#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	README
#	newgrp.c
#	Makefile
#	config.h
#	pwunconv.c
#	obscure.c
#	age.c
#	sub.c
#	login.c
#	shell.c
#	lastlog.h
# This archive created: Wed Dec 12 12:36:30 1990
# By:	John F Haugh II (River Parishes Programming, Austin TX)
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'README'" '(12258 characters)'
if test -f 'README'
then
	echo shar: "will not over-write existing file 'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
XThis is the explanatory document for John F. Haugh II's login replacement.
XThis document is for version 2, last modified on 11/26/90.
X
XThis software is copyright 1988, 1989, 1990, John F. Haugh II.  All rights
Xreserved.  Use, duplication and disclosure is permitted according to the
Xguidelines listed below.
X
XThis software is being provided as a freely redistributable login clone.
XYou may distribute this software provided you do not charge for other than
Xtransmission costs.  You are free to copy this software provided you
Xdo not restrict the rights of the recipients to further copy this software.
X
XTHIS SOFTWARE IS BEING DISTRIBUTED AS-IS.  THE AUTHORS DISCLAIM ALL
XLIABILITY FOR ANY CONSEQUENCES OF USE.  THE USER IS SOLELY RESPONSIBLE
XFOR THE MAINTENANCE OF THIS SOFTWARE PACKAGE.  THE AUTHORS ARE UNDER NO
XOBLIGATION TO PROVIDE MODIFICATIONS OR IMPROVEMENTS.  THE USER IS
XENCOURAGE TO TAKE ANY AND ALL STEPS NEEDED TO PROTECT AGAINST ACCIDENTAL
XLOSE OF INFORMATION OR MACHINE RESOURCES.
X
XSpecial thanks are due to Chip Rosenthal for his fine testing efforts;
Xto Steve Simmons for his work in porting this code to BSD; and to Bill
XKennedy for his contributions of LaserJet printer time and energies.
X
XBegin by reading and editing the config.h file.  All options are selected
Xby using #define's.  A brief description for each available option appears
Xbelow.  You may want to print this file out as it is LONG and you will
Xneed to refer to it while editting config.h.  You will also have to edit
Xthe Makefile.  The possible differences are documented there.  Pay close
Xattention to the install: rule.  DO NOT MAIL ME DIFFERENCES FOR VARIOUS
XINSTALLATION PROBLEMS.  If you must share your experiences, do so on the
Xnet.  Login now runs on about 30 different varieties of UNIX that I have
Xbeen made aware of.
X
XNote that there are MANY options.  As distributed most options are turned
Xon, which produces a really nice package.  This is the system as used on
Xthe authors' machines.
X
XDialup Password Files -
X	This option permits individual ports to have an additional
X	password prompted for on a by-shell basis.  /etc/dialups
X	contains a list of dialup ports, d_passwd contains the
X	password for each shell requiring a dialup password.
X
X	Select this option by defining the DIALUP macro.
X
XPort Access Times File -
X	This option permits individual ports to have restrictions
X	based on user name and time of day and week.
X
X	Select this option by defining the PORTTIME macro.
X
XShadow [ unreadable ] Password Files -
X	This option utilizes an alternate, non-readable file to
X	contain the actual encrypted passwords.  This is presumed
X	to increase system security by increasing the difficulty
X	with which system crackers obtain encrypted passwords.
X
X	Select this option by defining the SHADOWPWD macro.
X
XDBM Password Files -
X	This option utilizes the DBM database access routines to
X	increase the performance of user name and ID lookups in the
X	password file.
X
X	Select this option by defining both the DBM and GETPWENT
X	macros.  The FGETPWENT macro must also be defined or the
X	fgetpwent() library routine must be present.
X
XDouble Length Passwords -
X	This option extends the maximum length of a user password
X	to 16 characters from eight.
X
X	Select this option by defining the DOUBLESIZE macro.
X	Credit for this option is due Jonathan Bayer.
X
XObscure Password Testing -
X	This option includes code to test user passwords for
X	complexity.  The programmer is encouraged to edit the
X	file obscure.c to add additional methods for detecting
X	simplistic passwords.
X
X	Select this option by defining the OBSCURE macro.
X
X	Additionally, the PASSLENGTH macro must be defined to
X	control the minimum length for a legal password.
X
XMandatory Password Prompting -
X	This option requires all passwords, including null ones,
X	to be prompted for.  Traditionally an account with a
X	password field of '::' does not require prompting for.
X	This option modifies this behavior to require even
X	null passwords be prompted for.
X
X	Select this option by defining the NOBLANK macro.
X
XPassword Aging Defaults -
X	You may select the default number of days during which a
X	password is valid.  The pwconv command adds aging
X	information to accounts which do not include it already.
X
X	The MINDAYS macro must be defined to be the minimum
X	number of days which must pass before a password may be
X	changed.  The MAXDAYS macro must be defined to be the
X	maximum number of days which a password will remain
X	valid during.
X
X	The WARNDAYS macro controls how many days warning a user
X	is given that their password is about to expire.  The
X	default is 10.
X
XHZ Environmental Variable -
X	This option pre-defines the HZ environmental variable.
X	Certain systems require this variable be defined for
X	system time reporting functions to work properly.
X
X	Select this option by defining the HZ macro to have
X	the desired environmental variable value.
X
XTZ Environmental Variable -
X	This option pre-defines the TZ environmental variable.
X	This provides a default timezone variable for use by
X	various utilities.
X
X	Select this option by defining the TZ macro to have
X	the desired environmental variable value, or the name
X	of the file containing the desired value.
X
XPassword Aging -
X	This option includes code to perform password aging.
X	Password aging is presumed to increase system security
X	by forcing users to change passwords on a regular
X	basis.  The resolution on password age is in weeks for
X	non-shadow password systems and in days otherwise.
X
X	Select this option by defining the AGING macro.
X
XMailbox Checking -
X	This option includes code to check the status of the
X	user's mailbox.  One of three messages are produced
X	depending on the status of the user's mailbox.
X
X	Select this option by defining the MAILCHECK macro.
X
XConsole Restricted Root Logins -
X	This option restricts the port which root may legally
X	login on.  This option presumably increases system
X	security by preventing outside attacks against the root
X	account.
X
X	Select this option by defining the CONSOLE macro to
X	have the desired port name.  If this file is a regular
X	file, it is considered to contain a list of legal port
X	names, one per line.  Note that the port names DO NOT
X	begin with "/dev/" and that a file name would have to
X	be fully qualified.  See config.h for a pair of
X	examples.
X
XRestricted User Logins -
X	This option permits you to specify a file which disables
X	user logins.  This options permits you to keep normal
X	users off of the system while performing maintenance
X	functions.
X
X	Select this option by defining NOLOGINS to be the name
X	of the file to use.
X
XRestricted Use Accounts -
X	This option permits certain accounts to be used for
X	identification purposes only.  This options associates
X	login ID's with UID's, such as for disk space accounting
X	or anonymous FTP accounts.  Passwords for these accounts
X	may only be changed by root.
X
X	Select this option by defining NOUSE to be the string
X	to include in the password file in place of the user's
X	shell.
X
XMessage of the Day Printing -
X	This option causes the message of the day to be
X	printed at login time.
X
X	Select this option by defining the MOTD macro.
X
X	If you wish this feature to be overriden on a per-user
X	basis, define the macro HUSHLOGIN and users may then
X	turn off the /etc/motd message by creating a file
X	'.hushlogin' in their home directories.
X
XLast Login Time Logging -
X	This option causes a record to be made of successful
X	logins in /usr/adm/lastlog.  The format of the
X	structure is defined in lastlog.h.
X
X	Select this option by defining the LASTLOG macro.
X
X	You will need to determine if you system already has
X	a lastlog.h file and use that file if present.
X
XFailed Login Logging -
X	This option causes a record to be kept of the most
X	recent login failure by date and port.  A cummulative
X	count of failures is maintained and compared against
X	an allowable limit.
X
X	Select this option by defining the FAILLOG macro.
X
X	An additional option is provided which will create
X	utmp-like entries for each failed login.  Because of
X	security concerns, only valid account names will be
X	logged.
X
X	Select this option by defining the FTMP macro to be
X	the name of a utmp-like file.  You may control the
X	recording of unknown login names by defining the
X	UNKNOWNS macro.  This prevents possible passwords from
X	being entered into the FTMP file.
X
X	See the file faillog.h and config.h for more details.
X
XTerminal Permissions - 
X	This option allows the terminal modes to be set at
X	login time.  This is particularly useful to disable
X	messages on user's terminals.
X
X	Select this option by defining the TTYPERM macro as
X	having the desired mode.
X
XTerminal Type Setup -
X	This option allows the terminal type to be set at
X	login time.  The environmental variable TERM will be
X	set from the specified terminal to port mapping
X	file.
X
X	Select this option by defining the TTYTYPE macro as
X	having the value of the name of the type to port
X	mapping file.  Credit for this option is due Chip
X	Rosenthal.
X
XFile Size Setting -
X	This option includes code to set the user's ulimit
X	at login time.  Additional code to set the umask and
X	nice value is also included.
X
X	Select this option by defining the QUOTAS macro.
X
XSwitch-User Logging -
X	This option causes su(1) to log attempts to switch
X	users.  Su(1) will log all attempt, giving the old
X	and new user ID's, tty port, and time.  It also
X	indicates if the attempt was successful.
X
X	Select this option by defining the SULOG macro to
X	have the value of the name of the file you want
X	attempts logged to.
X
XConfigurable Editing Keys -
X	This options allows the erase and kill characters to
X	be selected.  A default value is provided.  By default
X	ERASE will be ^H and KILL will be ^U.
X
X	Select this option by defining the ERASECHAR macro
X	to be the desired erase character and the KILLCHAR 
X	macro to be the desired KILL character.
X
XDefault ulimit and umask Values -
X	This option allows you to select the default values
X	for ulimit and umask, allowing you to avoid
X	regenerating your system kernel.  These values may be
X	overriden with appropriate entries in the GECOS field.
X
X	Select the default ulimit by defining the ULIMIT
X	macro, and the default umask by defining the UMASK
X	macro.
X	
X	Warning: These values will not apply to processes
X	executed by /etc/cron or any of their children.
X
XBSD Notes:	Steve Simmons	s...@iti.org
X
XThe full port of the shadow package to BSD is not complete; but some
Xof the issues have been worked out.  These notes describe the current
Xstate of things:
X
XIn order to make use of password aging under BSD, minor changes to
X/usr/include/pwd.h and getpwent() are needed.  These changes are to
Xkeep the password age from messing up the encrypted password when not
Xusing shadow passwords, and involve placing a new field in the password
Xdata structure.  To use this, you should apply the following two patches:
X	pwd.h.patch
X	getpwent.c.patch
Xto the BSD /usr/include/pwd.h and /usr/src/lib/libc/gen/getpwent.c,
Xrespectively.  After applying the patches, rebuild your standard C
Xlibrary with the new getpwent.  Programs which use the old getpwent
Xwill fail on password checking if they do a strcmp rather than a strncmp.
X[ I do not seem to have these two patches.  I have provided an entire
Xgetpwent collection of code which may be useful instead. -jfh ]
X
XThese changes are based on BSD4.3, not Tahoe
X
XToDo BSD:
X
XI'm working on this in my copious spare time (hah!); any help would
Xbe appreciated.  If you decide to help, do these independantly rather
Xthan rework BSD code!  Keep it redistributable!
X
XNo dbm functions have been put in place.  Dbm functionality is needed
Xfor both /etc/password and /etc/shadow management.  [ It is now possible
Xto create /etc/passwd.dir and /etc/passwd.pag using the new mkpasswd
Xcommand.  getpwuid and getpwnam both use these files.   Also, the 
Xcommands chfn, chsh, and chage all update the DBM files. -jfh ]
X
XThe BSD GECOS field gets used for lots more stuff than the USG.  At a
Xminimum this functionality should be duplicated under BSD; better is to put
Xit into USG as well; still better would be to make the chfn command for
Xboth systems; best would be site-configurable data to be put into GECOS/chfn.
X[ this is now possible using chfn and the -o option. - jfh ]
SHAR_EOF
if test 12258 -ne "`wc -c < 'README'`"
then
	echo shar: "error transmitting 'README'" '(should have been 12258 characters)'
fi
fi
echo shar: "extracting 'newgrp.c'" '(8415 characters)'
if test -f 'newgrp.c'
then
	echo shar: "will not over-write existing file 'newgrp.c'"
else
sed 's/^X//' << \SHAR_EOF > 'newgrp.c'
X/*
X * Copyright 1990, John F. Haugh II
X * All rights reserved.
X *
X * Non-commercial distribution permitted.  You must provide this source
X * code in any distribution.  This notice must remain intact.
X */
X
X#include 
X#include 
X#include 
X#include 
X#include 
X#include 
X#ifdef SYS3
X#include 
X#endif
X#include "config.h"
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)newgrp.c	1.2	14:01:27	7/22/90";
X#endif
X
X#ifdef	NGROUPS
Xint	ngroups;
Xgid_t	groups[NGROUPS];
X#endif
X
Xstruct	passwd	*pwd;
Xstruct	passwd	*getpwuid();
Xstruct	passwd	*getpwnam();
X
X#ifdef	SHADOWPWD
X#include "shadow.h"
Xstruct	spwd	*spwd;
Xstruct	spwd	*getspnam();
X#endif
Xstruct	group	*grp;
Xstruct	group	*getgrgid();
Xstruct	group	*getgrnam();
X
Xchar	*getlogin();
Xchar	*crypt();
X
Xchar	*name;
Xchar	*group;
Xint	gid;
X
Xchar	*myname;
Xchar	shell[BUFSIZ];
Xchar	base[BUFSIZ];
Xchar	passwd[BUFSIZ];
Xchar	*cpasswd;
Xchar	*salt;
X
X/*
X * usage - print command usage message
X */
X
Xusage ()
X{
X	fprintf (stderr, "usage: newgrp [ - ] [ group ]\n");
X	exit (1);
X}
X
X/*
X * newgrp - change the invokers current real and effective group id
X */
X
Xmain (argc, argv)
Xint	argc;
Xchar	**argv;
X{
X	int	initflag = 0;
X	int	needspasswd = 0;
X	int	i;
X	char	*cp;
X#ifdef	DOUBLESIZE
X	int	longpass;
X#endif
X
X	/*
X	 * let me parse the command line first.  the only legal flag
X	 * is a "-", which indicates the shell is to perform the same
X	 * initialization it does at login time.  the remaining
X	 * optional argument is the name of a new group.  if it isn't
X	 * present i just use the login group id of this user.
X	 */
X
X	if (argc > 1 && strcmp (argv[1], "-") == 0) {
X		initflag = 1;
X		argc--; argv++;
X	}
X	if (argc > 2)
X		usage ();
X
X#ifdef	NGROUPS
X
X	/*
X	 * get the current users groupset.  the new group will be
X	 * added to the concurrent groupset if there is room, otherwise
X	 * you get a nasty message but at least your real and effective
X	 * group id's are set.
X	 */
X
X	ngroups = getgroups (groups);
X#endif
X
X	/*
X	 * save my name for error messages and save my real gid incase
X	 * of errors.  if there is an error i have to exec a new login
X	 * shell for the user since her old shell won't have fork'd to
X	 * create the process.
X	 */
X
X	myname = argv[0];
X	gid = getgid ();
X
X	/*
X	 * now i get to determine my current name.  i do this to validate
X	 * my access to the requested group.  the validation works like
X	 * this -
X	 *	1) get the name associated with my current user id
X	 *	2) get my login name, as told by getlogin().
X	 *	3) if they match, my name is the login name
X	 *	4) if they don't match, my name is the name in the
X	 *	   password file.
X	 *
X	 * this isn't perfect, but it works more often then not.
X	 */
X
X	pwd = getpwuid (getuid ());
X
X	if (! (name = getlogin ()) || strcmp (name, pwd->pw_name) != 0)
X		name = pwd->pw_name;
X
X	if (! (pwd = getpwnam (name))) {
X		fprintf (stderr, "unknown user: %s\n", name);
X		exit (1);
X	}
X
X	/*
X	 * now we determine the name of the new group which she wishes
X	 * to become a member of.  the password file entry for her
X	 * current user id has been gotten.  if there is no optional
X	 * group argument she will have her real and effective group id
X	 * set to the value from her password file entry.  otherwise
X	 * we validate her access to the specified group.
X	 */
X
X	if (argv[1] != (char *) 0) {
X
X		/*
X		 * start by getting the entry for the requested group.
X		 */
X
X		if (! (grp = getgrnam (group = argv[1]))) {
X			fprintf (stderr, "unknown group: %s\n", group);
X			goto failure;
X		}
X
X		/*
X		 * see if she is a member of this group.
X		 */
X
X		for (i = 0;grp->gr_mem[i];i++)
X			if (strcmp (name, grp->gr_mem[i]) == 0)
X				break;
X
X		/*
X		 * if she isn't a member, she needs to provide the
X		 * group password.  if there is no group password, she
X		 * will be denied access anyway.
X		 */
X
X		if (grp->gr_mem[i] == (char *) 0)
X			needspasswd = 1;
X#ifdef	SHADOWPWD
X
X		/*
X		 * if she does not have either a shadowed password,
X		 * or a regular password, and the group has a password,
X		 * she needs to give the group password.
X		 */
X
X		if (spwd = getspnam (name)) {
X			if (spwd->sp_pwdp[0] == '\0' && grp->gr_passwd[0])
X				needspasswd = 1;
X		} else {
X			if (pwd->pw_passwd[0] == '\0' && grp->gr_passwd[0])
X				needspasswd = 1;
X		}
X#else
X
X		/*
X		 * if she does not have a regular password she will have
X		 * to give the group password, if one exists.
X		 */
X
X		if (pwd->pw_passwd[0] == '\0' && grp->gr_passwd[0])
X			needspasswd = 1;
X#endif
X	} else {
X
X		/*
X		 * get the group file entry for her login group id.
X		 * the entry must exist, simply to be annoying.
X		 */
X
X		if (! (grp = getgrgid (pwd->pw_gid))) {
X			fprintf (stderr, "unknown gid: %d\n", pwd->pw_gid);
X			goto failure;
X		}
X	}
X
X	/*
X	 * now i see about letting her into the group she requested.
X	 * if she is the root user, i'll let her in without having to
X	 * prompt for the password.  otherwise i ask for a password
X	 * if she flunked one of the tests above.  note that she
X	 * won't have to provide the password to her login group even
X	 * if she isn't listed as a member.
X	 */
X
X	if (getuid () != 0 && needspasswd) {
X		if (grp->gr_passwd[0]) {
X
X		/*
X		 * get the password from her, and set the salt for
X		 * the decryption from the group file.
X		 */
X
X			password ("Password:", passwd);
X			salt = grp->gr_passwd;
X		} else {
X
X		/*
X		 * there is no password, print out "Sorry" and give up
X		 */
X
X			fputs ("Sorry\n", stderr);
X			goto failure;
X		}
X
X		/*
X		 * encrypt the key she gave us using the salt from
X		 * the password in the group file.  the result of
X		 * this encryption must match the previously
X		 * encrypted value in the file.
X		 *
X		 * each chunk of encrypted string is 11 characters
X		 * long, plus 2 characters for the salt.  each
X		 * group of 11 characters represents 8 characters
X		 * of cleartext.
X		 */
X
X		cpasswd = crypt (passwd, salt);
X
X		if (strncmp (cpasswd, grp->gr_passwd, 13) != 0) {
X			fputs ("Sorry\n", stderr);
X			goto failure;
X		}
X#ifdef	DOUBLESIZE
X		if (strlen (grp->gr_passwd) > 13) {
X			cpasswd = crypt (passwd + 8, salt);
X
X			if (strcmp (cpasswd + 2, grp->gr_passwd + 13) != 0) {
X				fputs ("Sorry\n", stderr);
X				goto failure;
X			}
X		}
X#endif
X	}
X
X	/*
X	 * all successful validations pass through this point.  the
X	 * group id will be set, and the group added to the concurrent
X	 * groupset.
X	 */
X
X	gid = grp->gr_gid;
X#ifdef	NGROUPS
X
X	/*
X	 * i am going to try to add her new group id to her concurrent
X	 * group set.  if the group id is already present i'll just
X	 * skip this part.  if the group doesn't fit, i'll complain
X	 * loudly and skip this part ...
X	 */
X
X	for (i = 0;i < ngroups;i++) {
X		if (gid == groups[i])
X			break;
X	}
X	if (i == ngroups) {
X		if (ngroups == NGROUPS) {
X			fprintf (stderr, "too many groups\n");
X		} else {
X			groups[ngroups++] = gid;
X			if (setgroups (ngroups, groups))
X				perror (myname);
X		}
X	}
X#endif
X
X	/*
X	 * this is where all failures land.  the group id will not
X	 * have been set, so the setgid() below will set me to the
X	 * original group id i had when i was invoked.
X	 */
X
Xfailure:
X
X	/*
X	 * i set her group id either to the value she requested, or
X	 * to the original value.  i have to go back to the original
X	 * be she no longer has a shell running.
X	 */
X
X	if (setgid (gid))
X		perror ("setgid");
X
X	if (setuid (getuid ()))
X		perror ("setuid");
X
X	/*
X	 * i have to get the pathname of her login shell.  as a favor
X	 * i'll try her environment for a $SHELL value first, and
X	 * then try the password file entry.
X	 */
X
X	if ((cp = getenv ("SHELL")) && ! initflag)
X		strncpy (shell, cp, sizeof shell);
X	else if (pwd->pw_shell && pwd->pw_shell[0])
X		strncpy (shell, pwd->pw_shell, sizeof shell);
X	else
X		strcpy (shell, "/bin/sh");
X
X	/*
X	 * now i try to find the basename of the login shell.  this
X	 * will become argv[0] of the spawned command.
X	 */
X
X	if (cp = strrchr (shell, '/'))
X		cp++;
X	else
X		cp = shell;
X
X	/*
X	 * to have the shell perform login processing i will set the
X	 * first character in the first argument to a "-".
X	 */
X
X	if (initflag)
X		strcat (strcpy (base, "-"), cp);
X	else
X		strcpy (base, cp);
X
X#ifdef	SHADOWPWD
X	endspent ();
X#endif
X	endpwent ();
X	endgrent ();
X
X	/*
X	 * switch back to her home directory if i am doing login
X	 * initialization.
X	 */
X
X	if (initflag)
X		chdir (pwd->pw_dir);
X
X	/*
X	 * exec the login shell and report and error if the exec
X	 * fails.  not much i can do after that ...
X	 */
X
X	execl (shell, base, (char *) 0);
X	perror (shell);
X	exit (1);
X}
SHAR_EOF
if test 8415 -ne "`wc -c < 'newgrp.c'`"
then
	echo shar: "error transmitting 'newgrp.c'" '(should have been 8415 characters)'
fi
fi
echo shar: "extracting 'Makefile'" '(8384 characters)'
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
X#
X# Copyright 1988,1989,1990, John F. Haugh II
X# All rights reserved.
X#
X# Non-commercial distribution permitted.  You must provide this source
X# code in any distribution.  This notice must remain intact.
X#
X#	@(#)Makefile	2.16	08:41:16  - Shadow password system
X#
X#	@(#)Makefile	2.16	08:41:16	11/8/90
X#
XSHELL = /bin/sh
X
X#
X# Set this flag to decide what level of code "get" returns.
X# The base USENET release was release 1.  It is no longer supported.
X# The unreleased version with the utilities added is release 2.
XRELEASE = 2
XGFLAGS = -t -r$(RELEASE)
X
X# Define the directory login is copied to.  BE VERY CAREFUL!!!
X# LOGINDIR = /bin
XLOGINDIR = /etc
X
X# Pick your favorite C compiler and tags command
XCC = cc
XTAGS = ctags
X
X# OS.  Currently only BSD and USG are defined.  If you don't use BSD,
X# USG (System V) is assumed.
X# OS = -DBSD
X
X# Do you have to do ranlib?  Sorry to hear that ...
XRANLIB = ranlib
X# RANLIB = echo
X
X# Flags for SCO Xenix/386
XCFLAGS = -O -M3 -g $(PWDEF) $(AL64DEF) $(OS)
XLIBS = -lcrypt -ldbm
XLDFLAGS = -M3 -g
XLTFLAGS = 
X# This should be Slibsec.a for small model, or Llibsec.a for
X# large model or whatever.  MUST AGREE WITH CFLAGS!!!
XLIBSEC = Slibsec.a
X
X# Flags for normal machines
X# CFLAGS = -O -g $(PWDEF) $(AL64DEF) $(OS)
X# LIBS =
X# LDFLAGS = -g
X# LIBSEC = libsec.a
X
XLOBJS = lmain.o login.o env.o password.o entry.o valid.o setup.o shell.o age.o \
X	pwent.o utmp.o sub.o mail.o motd.o log.o shadow.o dialup.o dialchk.o \
X	ttytype.o failure.o port.o pwpack.o
X
XLSRCS = lmain.c login.c env.c password.c entry.c valid.c setup.c shell.c age.c \
X	pwent.c utmp.c sub.c mail.c motd.c log.c shadow.c dialup.c dialchk.c \
X	ttytype.c failure.c port.c pwpack.c
X
XSOBJS = smain.o env.o password.o entry.o suvalid.o susetup.o sushell.o \
X	pwent.o susub.o mail.o motd.o sulog.o shadow.o suage.o pwpack.o
X
XSSRCS = smain.c env.c password.c entry.c valid.c setup.c shell.c \
X	pwent.c sub.c mail.c motd.c sulog.c shadow.c age.c pwpack.c
X
XPOBJS = pmain.o password.o entry.o valid.o pwage.o pwent.o obscure.o shadow.o \
X	pwpack.o
X
XPSRCS = pmain.c password.c entry.c valid.c age.c pwent.c obscure.c shadow.c \
X	pwpack.c
X
XGPSRCS = gpmain.c password.c grent.c
X
XGPOBJS = gpmain.o password.o grent.o
X
XPWOBJS = pwconv.o pwent.o shadow.o pwage.o pwpack.o
X
XPWSRCS = pwconv.c pwent.c shadow.c age.c pwpack.c
X
XPWUNOBJS = pwunconv.o pwent.o shadow.o pwage.o pwpack.o
X
XPWUNSRCS = pwunconv.c pwent.c shadow.c age.c pwpack.c
X
XSULOGOBJS = sulogin.o entry.o env.o password.o pwage.o pwent.o setup.o \
X	shadow.o shell.o valid.o pwpack.o
X
XSULOGSRCS = sulogin.c entry.c env.c password.c age.c pwent.c setup.c \
X	shadow.c shell.c valid.c pwpack.c
X
XDBOBJS = mkpasswd.o pwent.o pwpack.o
X
XDBSRCS = mkpasswd.c pwent.c pwpack.c
X
XNGSRCS = newgrp.c shadow.c password.c
X
XNGOBJS = newgrp.o shadow.o password.o
X
XCHFNSRCS = chfn.c pwent.c pwpack.c
X
XCHFNOBJS = chfn.o pwent.o pwpack.o
X
XCHSHSRCS = chsh.c pwent.c pwpack.c
X
XCHSHOBJS = chsh.o pwent.o pwpack.o
X
XCHAGEOBJS = chage.o pwent.o pwpack.o pwage.o shadow.o
X
XCHAGESRCS = chage.c pwent.c pwpack.c age.c shadow.c
X
XALLSRCS = age.c dialchk.c dialup.c entry.c env.c lmain.c log.c login.c mail.c \
X	motd.c obscure.c password.c pmain.c pwconv.c pwent.c pwunconv.c \
X	setup.c shadow.c shell.c smain.c sub.c sulog.c sulogin.c ttytype.c \
X	utmp.c valid.c port.c newgrp.c gpmain.c grent.c mkpasswd.c pwpack.c \
X	chfn.c chsh.c chage.c
X
XFILES1 = README newgrp.c Makefile config.h pwunconv.c obscure.c age.c \
X	sub.c login.c shell.c lastlog.h
X
XFILES2 = pmain.c port.c lmain.c mkpasswd.c sulogin.c pwpack.c dialup.c \
X	sulog.c password.c env.c mail.c dialchk.c
X
XFILES3 = chfn.c chsh.c smain.c faillog.c pwconv.c failure.c utmp.c shadow.c \
X	log.c shadow.h faillog.h
X
XFILES4 = gpmain.c chage.c pwent.c valid.c setup.c entry.c ttytype.c port.h \
X	grent.c motd.c dialup.h
X
XMAN_1 = chage.1 chfn.1 chsh.1 login.1 passwd.1 su.1
XMAN_3 = shadow.3
XMAN_4 = faillog.4 passwd.4 porttime.4 shadow.4
XMAN_8 = faillog.8 pwconv.8 pwunconv.8 sulogin.8
X
XDOCS = $(MAN_1) $(MAN_3) $(MAN_4) $(MAN_8)
X
XBINS = su login pwconv pwunconv passwd sulogin faillog newgrp gpasswd \
X	mkpasswd chfn chsh chage
X
Xall:	$(BINS) $(DOCS)
X
Xlibsec: shadow.o
X	ar rv $(LIBSEC) shadow.o
X	$(RANLIB) $(LIBSEC)
X
Xinstall: all
X	strip $(BINS)
X	cp login $(LOGINDIR)/login
X	cp mkpasswd pwconv pwunconv sulogin /etc
X	cp su passwd gpasswd faillog newgrp chfn chsh /bin
X	cp shadow.h /usr/include
X	chown root $(LOGINDIR)/login /etc/pwconv /etc/pwunconv /etc/sulogin \
X		/bin/su /bin/passwd /bin/gpasswd /bin/newgrp /etc/mkpasswd
X	chgrp root $(LOGINDIR)/login /etc/pwconv /etc/pwunconv /etc/sulogin \
X		/bin/su /bin/passwd /bin/gpasswd /bin/newgrp /etc/mkpasswd
X	chown bin /bin/faillog /usr/include/shadow.h
X	chgrp bin /bin/faillog /usr/include/shadow.h
X	chmod 700 /etc/pwconv /etc/pwunconv /etc/sulogin /etc/mkpasswd
X	chmod 4711 $(LOGINDIR)/login /bin/su /bin/passwd /bin/gpasswd \
X		/bin/newgrp /bin/chfn
X	chmod 711 /bin/faillog
X	chmod 444 /usr/include/shadow.h
X
Xlint:	su.L login.L pwconv.L pwunconv.L passwd.L sulogin.L faillog.L \
X	newgrp.L gpasswd.L mkpasswd.L chfn.L chsh.L chage.L
X
Xtags:	$(ALLSRCS)
X	$(TAGS) $(ALLSRCS)
X
XREADME:	s.README
X	get -t -r$(RELEASE) s.README
X	
X$(DOCS):
X	get -t -r$(RELEASE) s.$@
X
Xlogin:	$(LOBJS)
X	$(CC) -o login $(LDFLAGS) $(LOBJS) $(LIBS)
X
Xlogin.L: $(LSRCS)
X	lint $(LSRCS) > login.L
X
Xsu:	$(SOBJS)
X	$(CC) -o su $(LDFLAGS) $(SOBJS) $(LIBS)
X
Xsu.L:	$(SSRCS)
X	lint -DSU $(SSRCS) > su.L
X
Xpasswd:	$(POBJS)
X	$(CC) -o passwd $(LDFLAGS) $(POBJS) $(LIBS)
X
Xpasswd.L: $(PSRCS)
X	lint -DPASSWD $(PSRCS) > passwd.L
X
Xgpasswd: $(GPOBJS)
X	$(CC) -o gpasswd $(LDFLAGS) $(GPOBJS) $(LIBS)
X
Xgpasswd.L: $(GPSRCS)
X	lint $(GPSRCS) > gpasswd.L
X
Xpwconv:	$(PWOBJS)
X	$(CC) -o pwconv $(LDFLAGS) $(PWOBJS) $(LIBS)
X
Xpwconv.L: $(PWSRCS)
X	lint -DPASSWD $(PWSRCS) > pwconv.L
X
Xpwunconv: $(PWUNOBJS)
X	$(CC) -o pwunconv $(LDFLAGS) $(PWUNOBJS) $(LIBS)
X
Xpwunconv.L: $(PWUNSRCS)
X	lint -DPASSWD $(PWUNSRCS) > pwunconv.L
X
Xsulogin: $(SULOGOBJS)
X	$(CC) -o sulogin $(LDFLAGS) $(SULOGOBJS) $(LIBS)
X
Xsulogin.L: $(SULOGSRCS)
X	lint $(SULOGSRCS) > sulogin.L
X
Xfaillog: faillog.o
X	$(CC) -o faillog $(LDFLAGS) faillog.o $(LIBS)
X
Xfaillog.L: faillog.c faillog.h config.h
X	lint faillog.c > faillog.L
X
Xmkpasswd: $(DBOBJS)
X	$(CC) -o mkpasswd $(LDFLAGS) $(DBOBJS) $(LIBS)
X
Xmkpasswd.L: $(DBSRCS)
X	lint $(DBSRCS) > mkpasswd.L
X
Xnewgrp: $(NGOBJS)
X	$(CC) -o newgrp $(LDFLAGS) $(NGOBJS) $(LIBS)
X
Xnewgrp.L: $(NGSRCS)
X	lint $(NGSRCS) > newgrp.L
X
Xchfn:	$(CHFNOBJS)
X	$(CC) -o chfn $(LDFLAGS) $(CHFNOBJS) $(LIBS)
X
Xchfn.L:	$(CHFNSRCS)
X	lint $(CHFNSRCS) > chfn.L
X
Xchsh:	$(CHSHOBJS)
X	$(CC) -o chsh $(LDFLAGS) $(CHSHOBJS) $(LIBS)
X
Xchsh.L: $(CHSHSRCS)
X	lint $(CHSHSRCS) > chsh.L
X
Xchage:	$(CHAGEOBJS)
X	$(CC) -o chage $(LDFLAGS) $(CHAGEOBJS) $(LIBS)
X
Xchage.L: $(CHAGESRCS)
X	lint -DPASSWD $(CHAGESRCS) > chage.L
X
Xsushell.c: shell.c
X	cp shell.c sushell.c
X
Xsushell.o: config.h sushell.c
X	$(CC) -c $(CFLAGS) -DSU sushell.c
X
Xsusub.c: sub.c
X	cp sub.c susub.c
X
Xsusub.o: config.h susub.c
X	$(CC) -c $(CFLAGS) -DSU susub.c
X
Xsulog.o: config.h
X
Xsusetup.c: setup.c
X	cp setup.c susetup.c
X
Xsusetup.o: config.h setup.c
X	$(CC) -c $(CFLAGS) -DSU susetup.c
X
Xsuvalid.c: valid.c
X	cp valid.c suvalid.c
X
Xsuvalid.o: config.h valid.c
X	$(CC) -c $(CFLAGS) -DSU suvalid.c
X
Xpmain.o: config.h lastlog.h shadow.h
X
Xpwage.o: age.c config.h
X	cp age.c pwage.c
X	$(CC) -c $(CFLAGS) -DPASSWD pwage.c
X	rm pwage.c
X
Xsuage.o: age.c config.h
X	cp age.c suage.c
X	$(CC) -c $(CFLAGS) -DSU suage.c
X	rm suage.c
X
Xlmain.o: config.h lastlog.h faillog.h
X
Xsmain.o: config.h lastlog.h
X
Xsetup.o: config.h
X
Xutmp.o: config.h
X
Xmail.o: config.h
X
Xmotd.o: config.h
X
Xage.o: config.h
X
Xlog.o: config.h lastlog.h
X
Xshell.o: config.h
X
Xentry.o: config.h shadow.h
X
Xshadow.o: shadow.h
X
Xdialup.o: dialup.h
X
Xdialchk.o: dialup.h config.h
X
Xvalid.o: config.h
X
Xfailure.o: faillog.h config.h
X
Xfaillog.o: faillog.h config.h
X
Xpwent.o: config.h
X
Xport.o: port.h
X
Xnewgrp.o: config.h shadow.h
X
Xmkpasswd.o: config.h
X
Xgpmain.o: config.h
X
Xchfn.o: config.h
X
Xchsh.o: config.h
X
Xchage.o: config.h shadow.h
X
Xclean:
X	-rm -f *.o a.out core npasswd nshadow *.pag *.dir
X
Xclobber: clean
X	-rm -f $(BINS) *.L sushell.c susetup.c susub.c suvalid.c
X
Xshar:	login.sh.1 login.sh.2 login.sh.3 login.sh.4 login.sh.5
X
Xlogin.sh.1: $(FILES1)
X	shar -a $(FILES1) > login.sh.1
X
Xlogin.sh.2: $(FILES2)
X	shar -a $(FILES2) > login.sh.2
X
Xlogin.sh.3: $(FILES3)
X	shar -a $(FILES3) > login.sh.3
X
Xlogin.sh.4: $(FILES4)
X	shar -a $(FILES4) > login.sh.4
X
Xlogin.sh.5: $(DOCS)
X	shar -a $(DOCS) > login.sh.5
SHAR_EOF
if test 8384 -ne "`wc -c < 'Makefile'`"
then
	echo shar: "error transmitting 'Makefile'" '(should have been 8384 characters)'
fi
fi
echo shar: "extracting 'config.h'" '(6050 characters)'
if test -f 'config.h'
then
	echo shar: "will not over-write existing file 'config.h'"
else
sed 's/^X//' << \SHAR_EOF > 'config.h'
X/*
X * Copyright 1989, 1990, John F. Haugh II
X * All rights reserved.
X *
X * Use, duplication, and disclosure prohibited without
X * the express written permission of the author.
X */
X
X/*
X * Configuration file for login.
X *
X *	@(#)config.h	2.6	08:26:28	8/20/90
X */
X
X/*
X * Define DIALUP to use dialup password files.  Define PORTTIME
X * to use the port time restriction file, see port.h for more
X * information.
X */
X
X#define	DIALUP
X#define	PORTTIME
X
X/*
X * Define SHADOWPWD to use shadow [ unreadable ] password file
X */
X
X#define	SHADOWPWD
X
X/*
X * Define DOUBLESIZE to use 16 character passwords
X */
X
X#define DOUBLESIZE
X
X/*
X * Define OBSCURE to include hard password testing code.
X */
X
X#define	OBSCURE
X
X/*
X * Define PASSLENGTH to be shortest legal password
X */
X
X#define	PASSLENGTH	5
X
X/*
X * Define NOBLANK if you want all passwords prompted for, including
X * empty ones.
X
X#undef	NOBLANK
X
X/*
X * Define MAXDAYS to be the default maximum number of days a password
X * is valid for when converting to shadow passwords.  Define MINDAYS
X * to be the minimum number of days before a password may be changed.
X * See pwconv.c for more details.
X */
X
X#define	MAXDAYS	10000
X#define	MINDAYS	0
X
X/*
X * Define NDEBUG for production versions
X */
X
X#define	NDEBUG
X
X/*
X * Define HZ if login must set HZ value
X */
X
X#define	HZ	"HZ=50"
X
X/*
X * Define TZ if login must set timezone
X *
X * The first example sets the variable directly.  The
X * second example names a file which is read to determine
X * the proper value.  The file consists of a single line
X * of the form 'TZ=zone-name'
X */
X
X/* #define	TZ	"TZ=CST6CDT" */
X#define	TZ	"/etc/tzname"
X
X/*
X * Define the default PATH and SUPATH here.  PATH is for non-privileged
X * users, SUPATH is for root.  The first pair are for real trusting
X * systems, the second pair are for the paranoid ...
X */
X
X/* #define	PATH	"PATH=:/bin:/usr/bin"	*/
X/* #define	SUPATH	"PATH=:/bin:/usr/bin:/etc" */
X#define	PATH	"PATH=/bin:/usr/bin"
X#define	SUPATH	"PATH=/bin:/usr/bin:/etc"
X
X/*
X * Define the mailbox directory
X */
X
X#define	MAILDIR	"/usr/spool/mail/"
X
X/*
X * Define AGING if you want the password aging checks made.
X * Define WARNAGE to be the number of days notice a user receives
X * of a soon to expire password.
X */
X
X#define	AGING
X#define	WARNAGE	10
X
X/*
X * Define MAILCHECK if you want the mailbox checked for new mail
X *
X * One of two messages are printed - `You have new mail.' or
X * `You have mail.'.
X */
X
X#define	MAILCHECK
X
X/*
X * Define CONSOLE if you want ROOT restricted to a particular terminal.
X *
X * Use the name of the tty line if you only want a single line, or use
X * the name of the file containing the permissible ports if you wish to
X * allow root logins on more than one port.
X */
X
X/* #define	CONSOLE	"console"	/* root on /dev/console only */
X#define	CONSOLE	"/etc/consoles"		/* check /etc/consoles for a list */
X
X/*
X * Define NOLOGINS if you want to be able to deny non-root users logins.
X * Logins will not be permitted if this file exists.
X */
X
X#define	NOLOGINS	"/etc/nologin"
X
X/*
X * Define NOUSE if you want to be able to declare accounts which can't
X * be logged into.  Define NOLOGIN if you want it to be an su-only account.
X */
X
X#define	NOUSE	"NOUSE"
X#define	NOLOGIN	"NOLOGIN"
X
X/*
X * Define MOTD if you want the message of the day (/etc/motd) printed
X * at login time.
X */
X
X#define	MOTD
X
X/*
X * Define HUSHLOGIN if you want the code added to avoid printing the
X * motd if a file $HOME/.hushlogin exists.  This obviously only matters
X * if any of MOTD, MAILCHECK or LASTLOG are #define'd.
X */
X
X#define	HUSHLOGIN
X
X/*
X * Define LASTLOG if you want a record made of logins in /usr/adm/lastlog.
X */
X
X#define	LASTLOG
X
X/*
X * Define FAILLOG if you want a record make of failed logins in
X * /usr/adm/faillog.  See faillog.h for more details.  See fail(1L)
X * for even still more details ...  Also, define FTMP to record utmp
X * style records for failed logins.  FTMP is the name of a utmp-like
X * file.  You can use who(1) instead of faillog(L), which is an
X * advantage.  Define UNKNOWNS if you do want unknown user names
X * recorded.  This can be a security hole since passwords are often
X * entered mistakenly as user names.
X */
X
X#define	FAILLOG
X#define	FTMP	"/etc/ftmp"
X#define	UNKNOWNS
X
X/*
X * Define TTYPERM to be the initial terminal permissions.  Defining
X * as 0600 will not allow messages, 0622 will.
X */
X
X#define	TTYPERM	0600
X
X/*
X * Define TTYTYPE to the be name of the port to terminal type
X * mapping file.  This is used to set the environmental variable
X * "TERM" to the correct terminal type.
X */
X
X#define	TTYTYPE	"/etc/ttytype"
X
X/*
X * Define QUOTAS if you want the code added in setup.c to support
X * file ulimit and nice [ and umask as well ] setting from the password
X * file.
X */
X
X#define	QUOTAS
X
X/*
X * Pick your version of DBM.  Only DBM is presently supported, NDBM will
X * follow.  You must also define the GETPWENT macro below.
X */
X
X#define	DBM
X
X/*
X * Define file name for sulog.  If SULOG is not defined, there will be
X * no logging.  This is NOT a good idea ...  We also define other file
X * names.
X */
X
X#define	SULOG	"/usr/adm/sulog"
X#define	SUCON	"/dev/console"
X#define	PWDFILE	"/etc/passwd"
X#define	OPWDFILE "/etc/-passwd"
X#define	NPWDFILE "/etc/npasswd"
X#define	OSHADOW "/etc/-shadow"
X#define	NSHADOW "/etc/nshadow"
X#define	GRPFILE	"/etc/group"
X#define	OGRPFILE "/etc/-group"
X#define	NGRPFILE "/etc/ngroup"
X
X/*
X * Define PWDLOCK to be a locking semaphore for updating the password
X * file.  GRPLOCK is the same for the group file.
X */
X
X#define	PWDLOCK	"/etc/.pwdlock"
X#define	GRPLOCK "/etc/.grplock"
X
X/*
X * Wierd stuff follows ...
X *
X *	The following macros exist solely to override stuff ...
X *	You will probably want to change their values to suit your
X *	fancy.
X */
X
X#define	ERASECHAR	'\b'
X#define	KILLCHAR	'\025'
X#define	UMASK		022
X
X#define	ULIMIT	(1L<<20) /* Define if your UNIX supports ulimit() */
X#define	FGETPWENT	/* Define if library does not include FGETPWENT */
X#define	GETPWENT	/* Define if you want my GETPWENT(3) routines */
X#define	NEED_AL64	/* Define if library does not include a64l() */
SHAR_EOF
if test 6050 -ne "`wc -c < 'config.h'`"
then
	echo shar: "error transmitting 'config.h'" '(should have been 6050 characters)'
fi
fi
echo shar: "extracting 'pwunconv.c'" '(3123 characters)'
if test -f 'pwunconv.c'
then
	echo shar: "will not over-write existing file 'pwunconv.c'"
else
sed 's/^X//' << \SHAR_EOF > 'pwunconv.c'
X/*
X * Copyright 1989, 1990, John F. Haugh II
X * All rights reserved.
X *
X * Use, duplication, and disclosure prohibited without
X * the express written permission of the author.
X */
X
X/*
X * pwunconv - restore old password file from shadow password file.
X *
X *	Pwunconv copies the password file information from the shadow
X *	password file, merging entries from an optional existing shadow
X *	file.
X *
X *	The new password file is left in npasswd.  There is no new
X *	shadow file.  Password aging information is translated where
X *	possible.
X */
X
X#include 
X#include 
X#include 
X#include 
X#include "config.h"
X#include "shadow.h"
X
X#ifndef	lint
Xstatic	char	_sccsid[] = "@(#)pwunconv.c	2.2	19:24:08	7/29/90";
X#endif
X
Xchar	buf[BUFSIZ];
Xchar	*l64a ();
X
Xint	main ()
X{
X	struct	passwd	*pw;
X	struct	passwd	*sgetpwent ();
X	FILE	*pwd;
X	FILE	*npwd;
X	struct	spwd	*spwd;
X	int	fd;
X
X	if (! (pwd = fopen (PWDFILE, "r"))) {
X		perror (PWDFILE);
X		return (1);
X	}
X	unlink ("npasswd");
X	if ((fd = open ("npasswd", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 ||
X			! (npwd = fdopen (fd, "w"))) {
X		perror ("npasswd");
X		return (1);
X	}
X	while (fgets (buf, BUFSIZ, pwd) == buf) {
X		buf[strlen (buf) - 1] = '\0'; /* remove '\n' character */
X
X		if (buf[0] == '#') {	/* comment line */
X			(void) fprintf (npwd, "%s\n", buf);
X			continue;
X		}
X		if (! (pw = sgetpwent (buf))) { /* copy bad lines verbatim */
X			(void) fprintf (npwd, "%s\n", buf);
X			continue;
X		}
X		setspent ();		/* rewind shadow file */
X
X		if (! (spwd = getspnam (pw->pw_name))) {
X			(void) fprintf (npwd, "%s\n", buf);
X			continue;
X		}
X		pw->pw_passwd = spwd->sp_pwdp;
X
X	/*
X	 * Password aging works differently in the two different systems.
X	 * With shadow password files you apparently must have some aging
X	 * information.  The maxweeks or minweeks may not map exactly.
X	 * In pwconv we set max == 10000, which is about 30 years.  Here
X	 * we have to undo that kludge.  So, if maxdays == 10000, no aging
X	 * information is put into the new file.  Otherwise, the days are
X	 * converted to weeks and so on.
X	 */
X
X		if (spwd->sp_max > (63*7) && spwd->sp_max < 10000)
X			spwd->sp_max = (63*7); /* 10000 is infinity this week */
X
X		if (spwd->sp_min >= 0 && spwd->sp_min <= 63*7 &&
X				spwd->sp_max >= 0 && spwd->sp_max <= 63*7) {
X			spwd->sp_max /= 7;	/* turn it into weeks */
X			spwd->sp_min /= 7;
X			spwd->sp_lstchg /= 7;
X			pw->pw_age = l64a ((long) spwd->sp_lstchg * (64L*64L) +
X						  spwd->sp_min * (64L) +
X						  spwd->sp_max);
X		} else
X			pw->pw_age = (char *) 0;
X
X		if (pw->pw_age)
X			(void) fprintf (npwd, "%s:%s,%s:%d:%d:%s:%s:%s\n",
X				pw->pw_name, pw->pw_passwd ? pw->pw_passwd:"",
X				pw->pw_age, pw->pw_uid, pw->pw_gid,
X				pw->pw_gecos, pw->pw_dir,
X				pw->pw_shell ? pw->pw_shell:"");
X		else
X			(void) fprintf (npwd, "%s:%s:%d:%d:%s:%s:%s\n",
X				pw->pw_name, pw->pw_passwd ? pw->pw_passwd:"",
X				pw->pw_uid, pw->pw_gid,
X				pw->pw_gecos, pw->pw_dir,
X				pw->pw_shell ? pw->pw_shell:"");
X	}
X	endspent ();
X
X	if (ferror (npwd)) {
X		perror ("pwunconv");
X		(void) unlink ("npasswd");
X	}
X	(void) fclose (npwd);
X	(void) fclose (pwd);
X	return (0);
X}
SHAR_EOF
if test 3123 -ne "`wc -c < 'pwunconv.c'`"
then
	echo shar: "error transmitting 'pwunconv.c'" '(should have been 3123 characters)'
fi
fi
echo shar: "extracting 'obscure.c'" '(2817 characters)'
if test -f 'obscure.c'
then
	echo shar: "will not over-write existing file 'obscure.c'"
else
sed 's/^X//' << \SHAR_EOF > 'obscure.c'
X/*
X * Copyright 1989, 1990, John F. Haugh II
X * All rights reserved.
X *
X * Use, duplication, and disclosure prohibited without
X * the express written permission of the author.
X */
X
X#include 
X#ifndef	BSD
X#include 
X#include 
X#else
X#include 
X#define	strchr	index
X#define	strrchr	rindex
X#endif
X#include "config.h"
X
X#ifndef	lint
Xstatic	char	_sccsid[] = "@(#)obscure.c	2.3	08:58:09	11/5/90";
X#endif
X
X/*
X * Obscure - see if password is obscure enough.
X *
X *	The programmer is encouraged to add as much complexity to this
X *	routine as desired.  Included are some of my favorite ways to
X *	check passwords.
X */
X
Xextern	char	pass[];			/* the new password */
Xextern	char	orig[];			/* the original password */
X#ifdef	OBSCURE
Xchar	mono[32];			/* a monocase version of pass */
X#endif
Xint	obscure ()
X{
X#ifdef	OBSCURE
X	int	i;
X#endif
X	if (orig[0] == '\0')
X		return (1);
X
X	if (strlen (pass) < PASSLENGTH) { /* too short */
X		printf ("Too short.  ");
X		return (0);
X	}
X#ifdef	OBSCURE
X	for (i = 0;pass[i];i++)
X		mono[i] = tolower (pass[i]);
X
X	if (strcmp (pass, orig) == 0)	/* the same */
X		return (0);
X
X	if (palindrome ())		/* a palindrome */
X		return (0);
X
X	if (caseshift ())		/* upper/lower case changes only */
X		return (0);
X
X	if (similiar ())		/* jumbled version of original */
X		return (0);
X
X	if (simple ())			/* keyspace size */
X		return (0);
X#endif
X	return (1);
X}
X
X#ifdef	OBSCURE
X
X/*
X * can't be a palindrome - like `R A D A R' or `M A D A M'
X */
X
Xint	palindrome ()
X{
X	int	i, j;
X
X	i = strlen (pass);
X
X	for (j = 0;j < i;j++)
X		if (pass[i - j - 1] != pass[j])
X			return (0);
X
X	printf ("No palindromes.  ");
X	return (1);
X}
X
X/*
X * may not be a shifted version of original
X */
X
Xint	caseshift ()
X{
X	int	i;
X
X	for (i = 0;pass[i] && orig[i];i++) {
X		if (tolower (pass[i]) == tolower (orig[i]))
X			continue;
X		else
X			return (0);
X	}
X	printf ("May not be case-shifted.  ");
X	return (1);
X}
X
X/*
X * more than half of the characters are different ones.
X */
X
Xint	similiar ()
X{
X	int	i, j;
X	char	*strchr ();
X
X	for (i = j = 0;pass[i] && orig[i];i++)
X		if (strchr (mono, tolower (orig[i])))
X			j++;
X
X	if (i >= j * 2)
X		return (0);
X
X	printf ("Too similiar.  ");
X	return (1);
X}
X
X/*
X * a nice mix of characters.
X */
X
Xint	simple ()
X{
X	int	digits = 0;
X	int	uppers = 0;
X	int	lowers = 0;
X	int	others = 0;
X	int	size;
X	int	i;
X	double	complexity;
X
X	for (i = 0;pass[i];i++) {
X		if (isdigit (pass[i]))
X			digits++;
X		else if (isupper (pass[i]))
X			uppers++;
X		else if (islower (pass[i]))
X			lowers++;
X		else
X			others++;
X	}
X
X	/*
X	 * The scam is this - a password of only one character type
X	 * must be 8 letters long.  Two types, 7, and so on.
X	 */
X
X	size = 9;
X	if (digits) size--;
X	if (uppers) size--;
X	if (lowers) size--;
X	if (others) size--;
X
X	if (size <= i)
X		return 0;
X
X	printf ("Too Simple.  ");
X	return 1;
X}
X#endif
SHAR_EOF
if test 2817 -ne "`wc -c < 'obscure.c'`"
then
	echo shar: "error transmitting 'obscure.c'" '(should have been 2817 characters)'
fi
fi
echo shar: "extracting 'age.c'" '(2588 characters)'
if test -f 'age.c'
then
	echo shar: "will not over-write existing file 'age.c'"
else
sed 's/^X//' << \SHAR_EOF > 'age.c'
X/*
X * Copyright 1989, 1990, John F. Haugh II
X * All rights reserved.
X *
X * Use, duplication, and disclosure prohibited without
X * the express written permission of the author.
X */
X
X#include 
X#include 
X#include 
X#include "config.h"
X
X#ifndef	lint
Xstatic	char	_sccsid[] = "@(#)age.c	2.6	10:20:04	11/9/90";
X#endif
X
X#ifndef	PASSWD
Xextern	char	*newenvp[];
X#endif
X
X#ifndef	WARNAGE
X#define	WARNAGE	10
X#endif
X
Xtime_t	time ();
X
Xint	c64i (c)
Xchar	c;
X{
X	if (c == '.')
X		return (0);
X
X	if (c == '/')
X		return (1);
X
X	if (c >= '0' && c <= '9')
X		return (c - '0' + 2);
X
X	if (c >= 'A' && c <= 'Z')
X		return (c - 'A' + 12);
X
X	if (c >= 'a' && c <= 'z')
X		return (c - 'a' + 38);
X	else
X		return (-1);
X}
X
Xint	i64c (i)
Xint	i;
X{
X	if (i < 0)
X		return ('.');
X	else if (i > 63)
X		return ('z');
X
X	if (i == 0)
X		return ('.');
X
X	if (i == 1)
X		return ('/');
X
X	if (i >= 2 && i <= 11)
X		return ('0' - 2 + i);
X
X	if (i >= 12 && i <= 37)
X		return ('A' - 12 + i);
X
X	if (i >= 38 && i <= 63)
X		return ('a' - 38 + i);
X
X	return ('\0');
X}
X
X#ifdef	AGING
X#ifdef	NEED_AL64
X#ifdef	PASSWD
Xchar	*l64a (l)
Xlong	l;
X{
X	static	char	buf[8];
X	int	i = 0;
X
X	if (i < 0L)
X		return ((char *) 0);
X
X	do {
X		buf[i++] = i64c ((int) (l % 64));
X		buf[i] = '\0';
X	} while (l /= 64L, l > 0 && i < 6);
X
X	return (buf);
X}
X#endif
X
Xlong	a64l (s)
Xchar	*s;
X{
X	int	i;
X	long	value;
X	long	shift = 0;
X
X	for (i = 0, value = 0L;i < 6 && *s;s++) {
X		value += (c64i (*s) << shift);
X		shift += 6;
X	}
X	return (value);
X}
X#endif
X#ifndef	PASSWD
Xvoid	expire (name, last, min, max)
Xchar	*name;
Xlong	last;
Xint	min;
Xint	max;
X{
X	long	clock;
X	long	week;
X	long	expires;
X	extern	int	errno;
X
X	(void) time (&clock);
X	clock /= (24L * 60L * 60L);
X
X	if (min < 0)
X		min = 0;
X
X	if (max < 0)
X		max = 10000;	/* 10000 is infinity */
X
X	if (last <= 0L)
X		expires = 0L;
X	else
X		expires = last + max;
X
X	if (max < 10000 && (clock >= expires || min == max)) {
X#ifndef	SU
X		printf ("Your password has expired.");
X
X		if (max < min) {
X			puts ("  Contact the system administrator.\n");
X			exit (1);
X		}
X		puts ("  Choose a new one.\n");
X
X		execl ("/bin/passwd", "-passwd", name, (char *) 0);
X		puts ("Can't execute /bin/passwd");
X		exit (errno);
X#else
X		printf ("Your password has expired.\n");
X#ifdef	SULOG
X		sulog (0);
X#endif
X		exit (1);
X#endif
X	}
X}
X
Xvoid	agecheck (last, min, max, warn)
Xlong	last;
Xint	min;
Xint	max;
Xint	warn;
X{
X	long	clock = time ((long *) 0) / (24L * 3600);
X	long	remain;
X
X	if (last == 0)
X		return;
X
X	if ((remain = (last + max) - clock) <= warn)
X		printf ("Your password will expire in %d %s.\n",
X			remain, remain == 1 ? "day":"days");
X}
X#endif
X#endif
SHAR_EOF
if test 2588 -ne "`wc -c < 'age.c'`"
then
	echo shar: "error transmitting 'age.c'" '(should have been 2588 characters)'
fi
fi
echo shar: "extracting 'sub.c'" '(1671 characters)'
if test -f 'sub.c'
then
	echo shar: "will not over-write existing file 'sub.c'"
else
sed 's/^X//' << \SHAR_EOF > 'sub.c'
X/*
X * Copyright 1989, 1990, John F. Haugh II
X * All rights reserved.
X *
X * Use, duplication, and disclosure prohibited without
X * the express written permission of the author.
X */
X
X#include 
X#include 
X#include 
X#ifndef	BSD
X#include 
X#include 
X#else
X#include 
X#define	strchr	index
X#define	strrchr	rindex
X#endif
X
X#ifndef	lint
Xstatic	char	_sccsid[] = "@(#)sub.c	2.2	19:24:19	7/29/90";
X#endif
X
Xextern	struct	passwd	pwent;
X#ifndef	SU
Xextern	struct	utmp	utent;
X#endif
X
Xvoid	setutmp ();
X
X/*
X * I have heard of two different types of behavior with subsystem roots.
X * One has you execute login no matter what.  The other has you execute
X * the command [ if one exists ] after the '*' in the shell name.  The
X * macro SUBLOGIN says to execute /bin/login [ followed by /etc/login ]
X * regardless.  Otherwise, pwent.pw_shell is fixed up and that command
X * is executed [ by returning to the caller ].  I prefer the latter since
X * it doesn't require having a "login" on the new root filesystem.
X */
X
Xvoid	subsystem ()
X{
X	char	*strdup ();
X
X	if (pwent.pw_dir[0] != '/')
X		exit (1);
X
X	if (chdir (pwent.pw_dir) || chroot (pwent.pw_dir)) {
X		printf ("Can't change to \"%s\"\n", pwent.pw_dir);
X		exit (1);
X	}
X#ifndef	SU
X	(void) strcpy (utent.ut_line, "");
X
X	setutmp ();
X#endif
X#ifdef	SUBLOGIN
X	execl ("/bin/login", "login", name, (char *) 0);
X	execl ("/etc/login", "login", name, (char *) 0);
X	puts ("No /bin/login or /etc/login on root");
X	exit (1);
X#else
X	if (! pwent.pw_shell || strlen (pwent.pw_shell) == 1)
X		pwent.pw_shell = "/bin/sh";	/* default shell */
X	else
X		pwent.pw_shell++;		/* skip over '*' */
X#endif
X}
SHAR_EOF
if test 1671 -ne "`wc -c < 'sub.c'`"
then
	echo shar: "error transmitting 'sub.c'" '(should have been 1671 characters)'
fi
fi
echo shar: "extracting 'login.c'" '(1164 characters)'
if test -f 'login.c'
then
	echo shar: "will not over-write existing file 'login.c'"
else
sed 's/^X//' << \SHAR_EOF > 'login.c'
X/*
X * Copyright 1989, 1990, John F. Haugh II
X * All rights reserved.
X *
X * Use, duplication, and disclosure prohibited without
X * the express written permission of the author.
X */
X
X#include 
X#include 
X#ifndef	BSD
X#include 
X#include 
X#else
X#include 
X#define	strchr	index
X#define	strrchr	rindex
X#endif
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)login.c	2.3	19:23:55	7/29/90";
X#endif
X
Xvoid	setenv ();
X
Xvoid	login (name)
Xchar	*name;
X{
X	char	buf[BUFSIZ];
X	char	*envp[32];
X	int	envc;
X	char	*cp;
X	int	i;
X
X#ifndef	BSD
X	(void) memset (buf, '\0', sizeof buf);
X#else
X	bzero (buf, sizeof buf);
X#endif
X	fputs ("login: ", stdout);
X
X	if (fgets (buf, BUFSIZ, stdin) != buf)
X		exit (1);
X
X	buf[strlen (buf) - 1] = '\0';	/* remove \n [ must be there ] */
X
X	for (cp = buf;*cp == ' ' || *cp == '\t';cp++)
X		;
X
X	for (i = 0;i < BUFSIZ - 1 && isgraph (*cp);name[i++] = *cp++)
X		;
X
X	if (*cp)
X		cp++;
X
X	name[i] = '\0';
X
X	if (*cp != '\0') {		/* process new variables */
X		for (envc = 0;envc < 32;envc++) {
X			envp[envc] = strtok (envc == 0 ? cp:(char *) 0, " \t,");
X
X			if (envp[envc] == (char *) 0)
X				break;
X		}
X		setenv (envc, envp);
X	}
X}
SHAR_EOF
if test 1164 -ne "`wc -c < 'login.c'`"
then
	echo shar: "error transmitting 'login.c'" '(should have been 1164 characters)'
fi
fi
echo shar: "extracting 'shell.c'" '(854 characters)'
if test -f 'shell.c'
then
	echo shar: "will not over-write existing file 'shell.c'"
else
sed 's/^X//' << \SHAR_EOF > 'shell.c'
X/*
X * Copyright 1989, 1990, John F. Haugh II
X * All rights reserved.
X *
X * Use, duplication, and disclosure prohibited without
X * the express written permission of the author.
X */
X
X#include 
X#ifndef	BSD
X#include 
X#include 
X#else
X#include 
X#define	strchr	index
X#define	strrchr	rindex
X#endif
X#include "config.h"
X
X#ifndef	lint
Xstatic	char	_sccsid[] = "@(#)shell.c	2.2	19:24:15	7/29/90";
X#endif
X
Xextern	char	*newenvp[];
X
Xvoid	shell (file)
Xchar	*file;
X{
X	char	arg0[BUFSIZ];
X	char	*path;
X	extern	int	errno;
X
X	if (file == (char *) 0)
X		exit (1);
X
X	if (path = strrchr (file, '/'))
X		path++;
X	else
X		path = file;
X
X	(void) strcpy (arg0 + 1, path);
X	arg0[0] = '-';
X#ifndef	NDEBUG
X	printf ("Executing shell %s\n", file);
X#endif
X	execle (file, arg0, (char *) 0, newenvp);
X	printf ("Can't execute %s\n", file);
X	exit (errno);
X}
SHAR_EOF
if test 854 -ne "`wc -c < 'shell.c'`"
then
	echo shar: "error transmitting 'shell.c'" '(should have been 854 characters)'
fi
fi
echo shar: "extracting 'lastlog.h'" '(511 characters)'
if test -f 'lastlog.h'
then
	echo shar: "will not over-write existing file 'lastlog.h'"
else
sed 's/^X//' << \SHAR_EOF > 'lastlog.h'
X/*
X * Copyright 1989, 1990, John F. Haugh II
X * All rights reserved.
X *
X * Use, duplication, and disclosure prohibited without
X * the express written permission of the author.
X */
X
X/*
X * lastlog.h - structure of lastlog file
X *
X *	@(#)lastlog.h	2.3	19:23:49	7/29/90
X *
X *	This file defines a lastlog file structure which should be sufficient
X *	to hold the information required by login.  It should only be used if
X *	there is no real lastlog.h file.
X */
X
Xstruct	lastlog	{
X	time_t	ll_time;
X	char	ll_line[8];
X};
SHAR_EOF
if test 511 -ne "`wc -c < 'lastlog.h'`"
then
	echo shar: "error transmitting 'lastlog.h'" '(should have been 511 characters)'
fi
fi
exit 0
#	End of shell archive