#! /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: # pmain.c # port.c # lmain.c # mkpasswd.c # sulogin.c # pwpack.c # dialup.c # sulog.c # password.c # env.c # mail.c # dialchk.c # This archive created: Wed Dec 12 12:36:45 1990 # By: John F Haugh II (River Parishes Programming, Austin TX) export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'pmain.c'" '(11779 characters)' if test -f 'pmain.c' then echo shar: "will not over-write existing file 'pmain.c'" else sed 's/^X//' << \SHAR_EOF > 'pmain.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#includeX#include X#include X#include X#include X#include X#ifndef BSD X#include X#include X#include X#else X#include X#include X#define strchr index X#define strrchr rindex X#endif X#include "config.h" X#include "lastlog.h" X#include "shadow.h" X X#ifdef SHADOW X# ifndef AGING X# define AGING X# endif X#endif X X#ifdef DBM X#include X#endif X X#ifndef PASSLENGTH X#define PASSLENGTH 5 X#endif X X#ifndef lint Xstatic char _sccsid[] = "@(#)pmain.c 2.8 07:55:00 11/8/90"; X#endif X Xchar name[BUFSIZ]; Xchar orig[BUFSIZ]; Xchar pass[BUFSIZ]; Xchar pass2[BUFSIZ]; X Xstruct passwd pwent; X X#ifndef RETRIES X#define RETRIES 3 X#endif X Xchar *l64a (); Xchar *crypt (); Xextern int errno; Xlong a64l (); Xvoid entry (); Xtime_t time (); X Xvoid Xusage () X{ X#ifdef OBSCURE X fprintf (stderr, "usage: passwd { [ -f ] user | -g [ -r ] group }\n"); X#else X fprintf (stderr, "usage: passwd { user | -g [ -r ] group }\n"); X#endif X exit (1); X} X X#ifdef DBM X/* X * update_dbm X * X * Updates the DBM password files, if they exist. X */ X Xupdate_dbm (pw) Xstruct passwd *pw; X{ X datum key; X datum content; X char data[BUFSIZ]; X int len; X X strcpy (data, PWDFILE); X strcat (data, ".pag"); X if (access (data, 0)) X return; X X len = pw_pack (pw, data); X content.dsize = len; X content.dptr = data; X X key.dsize = strlen (pw->pw_name); X key.dptr = pw->pw_name; X store (key, content); X X key.dsize = sizeof pw->pw_uid; X key.dptr = (char *) &pw->pw_uid; X store (key, content); X} X#endif X Xint Xmain (argc, argv) Xint argc; Xchar **argv; X{ X void die (); X char *cp; X char *getlogin (); X int amroot; X int lockfd = -1; X#ifdef OBSCURE X int force = 0; X#endif X int retries; X#ifdef AGING X long week; X long lastweek; X char newage[5]; X#endif X long salttime; X struct passwd *pw; X struct passwd *getpwuid (); X struct passwd *getpwnam (); X struct passwd *sgetpwent (); X FILE *npwd; X#ifdef SHADOWPWD X struct spwd *spwd; X struct spwd tspwd; X#else X FILE *pwd; X char buf[BUFSIZ]; X#endif X char tmp[BUFSIZ]; X X argc--; argv++; /* shift ... */ X X if (! isatty (0) || ! isatty (1)) X exit (1); X X die (0); /* save tty modes */ X X signal (SIGHUP, die); /* exit if SIGHUP */ X signal (SIGINT, die); /* exit if SIGINT */ X signal (SIGQUIT, die); /* exit if SIGQUIT */ X signal (SIGTERM, die); /* exit if SIGTERM */ X X if (argc > 0 && strcmp (argv[0], "-g") == 0) { X argv[0] = "gpasswd"; X execv ("/bin/gpasswd", &argv[0]); X perror ("/bin/gpasswd"); X fprintf (stderr, "Unable to change group passwords\n"); X exit (-1); X } X#ifdef OBSCURE X if (argc > 0 && strcmp (argv[0], "-f") == 0) { X force = 1; X argc--; argv++; /* shift ... */ X } X#endif X if (argc > 0 && argv[0][0] == '-') X usage (); X X if (argc > 0) X (void) strcpy (name, argv[0]); X else if (cp = getlogin ()) /* need user name */ X (void) strcpy (name, cp); X else { /* can't find user name! */ X fprintf (stderr, "unknown user: %s\n", argv[0]); X exit (1); X } X printf ("Changing password for %s\n", name); X X if (! (pw = getpwnam (name))) X goto failure; /* can't get my name ... */ X X amroot = getuid () == 0; /* currently am super user */ X#ifdef OBSCURE X if (! amroot) X force = 0; X#endif X if (! amroot && (getuid () != pw->pw_uid || X strcmp (name, getlogin ()))) X goto failure; X X entry (name, &pwent); /* get password file entry */ X X if (! pwent.pw_name) /* no entry for user??? */ X goto failure; X X if (! amroot) { X if (! password ("Old Password:", orig)) X exit (1); X X if (! valid (orig, &pwent)) { X puts ("Sorry."); X exit (1); X } X } X#ifdef AGING X if (! amroot && pwent.pw_age) { /* check out the age */ X#ifdef SHADOWPWD X (void) time (&week); X week /= (24L * 60L * 60L); /* days since epoch */ X if (spwd = getspnam (name)) { /* use entries in shadow */ X if (spwd->sp_min > spwd->sp_max) { X puts ("You may not change this password"); X exit (1); X } X if (spwd->sp_lstchg + spwd->sp_min > week) { X printf ("Sorry, less than %d days since the last change\n", spwd->sp_min); X exit (1); X } X } else { X#endif /* SHADOWPWD */ X (void) time (&week); X week /= (7L * 24L * 60L * 60L); /* weeks since epoch */ X lastweek = a64l (&pwent.pw_age[2]); X X if (c64i (pwent.pw_age[0]) < c64i (pwent.pw_age[1])) { X puts ("You may not change this password"); X exit (1); X } X if (c64i (pwent.pw_age[1]) + lastweek > week) { X printf ("Sorry, less than %d weeks since the last change\n", c64i (pwent.pw_age[1])); X exit (1); X } X#ifdef SHADOWPWD X } X#endif X } X#endif X printf ("Enter new password (minimum of %d characters)\n", PASSLENGTH); X#ifdef OBSCURE X puts ("Please use a combination of upper and lowercase letters and numbers"); X#endif X retries = RETRIES; Xretry: X if (! password ("New Password:", pass)) X exit (1); X X#ifndef OBSCURE X if (! obscure ()) { X puts ("Password not changed."); X exit (1); X } X#else X if (! force && ! obscure ()) { X if (retries-- > 0) { X puts ("Please try again."); X goto retry; X } else X goto toomany; X } X#endif X if (! password ("Re-enter new password:", pass2)) X exit (1); X X if (strcmp (pass, pass2) != 0) { X puts ("They don't match; try again"); X X if (retries-- > 0) X goto retry; X else X goto toomany; X } X#ifdef AGING X if (pwent.pw_age && strlen (pwent.pw_age) >= 2) { X strcpy (newage, pwent.pw_age); X pwent.pw_age = newage; X X cp = l64a (week); X X if (pwent.pw_age[0] == '.' && pwent.pw_age[1] == '.') X pwent.pw_age[0] = 'z'; X X pwent.pw_age[2] = cp[0]; X pwent.pw_age[3] = cp[1]; X pwent.pw_age[4] = '\0'; X } X#endif X (void) time (&salttime); X salttime = ((salttime & 07777) ^ ((salttime >> 14) & 07777)) & 07777; X pwent.pw_passwd = tmp; X strcpy (pwent.pw_passwd, crypt (pass, l64a (salttime))); X#ifdef DOUBLESIZE X if (strlen (pass) > 8) { X strcpy (pwent.pw_passwd + 13, X crypt (pass + 8, l64a (salttime)) + 2); X } X#endif X /* X * Now we get to race the bad guy. I don't think he can get us. X * X * Ignore most reasonable signals. X * Maybe we should ignore more? He can't hurt us until the end. X * X * Get a lock file. X * X * Copy first part of password file to new file. X * Illegal lines are copied verbatim. X * File permissions are r--r--r--, owner root, group root. X * X * Output the new entry. X * Only fields in struct passwd are output. X * X * Copy the rest of the file verbatim. X * X * Rename (link, unlink) password file to backup. X * Kill me now and nothing changes or no one gets in. X * X * Rename (link, unlink) temporary file to password file. X * Kill me now and no one gets in or lock is left. X * X * Remove locking file. X * X * That's all folks ... X */ X X signal (SIGHUP, SIG_IGN); X signal (SIGINT, SIG_IGN); X signal (SIGQUIT, SIG_IGN); X signal (SIGTERM, SIG_IGN); X X ulimit (30000); /* prevent any funny business */ X umask (0); /* get new files modes correct */ X#ifndef NDEBUG X if ((lockfd = open (".pwdlock", O_RDONLY|O_CREAT|O_EXCL), 0444) == -1) X#else X if ((lockfd = open (PWDLOCK, O_RDONLY|O_CREAT|O_EXCL), 0444) == -1) X#endif /* NDEBUG */ X { X puts ("Can't get lock"); X exit (1); X } X umask (077); /* close security holes to come ... */ X#ifdef SHADOWPWD X if (access (NSHADOW, 0) == 0 && unlink (NSHADOW) == -1) X goto failure; X X if ((npwd = fopen (NSHADOW, "w")) == (FILE *) 0) X goto failure; X X if (chmod (NSHADOW, 0400) || chown (NSHADOW, 0, 0)) X goto failure; X X setspent (); X X while (spwd = getspent ()) { X if (strcmp (spwd->sp_namp, name) == 0) X break; X X if (putspent (spwd, npwd)) X goto failure; X } X if (spwd == (struct spwd *) 0) { /* didn't find a match */ X spwd = &tspwd; /* use a local structure instead */ X spwd->sp_namp = pwent.pw_name; X spwd->sp_max = 10000; /* about as big as possible */ X spwd->sp_min = 0; /* about as small as possible */ X } X spwd->sp_pwdp = pwent.pw_passwd; /* fixup the password */ X X (void) time (&lastweek); /* get the current time ... */ X lastweek /= (24L*60L*60L); /* ... turn it into days. */ X spwd->sp_lstchg = lastweek; /* save it as date of last change */ X X if (spwd->sp_min == 0 && spwd->sp_max == 0) X spwd->sp_max = 10000; /* don't force another passwd */ X X (void) putspent (spwd, npwd); /* add the new entry */ X X while (spwd = getspent ()) /* finish the other ones off */ X (void) putspent (spwd, npwd); X X endspent (); X X if (ferror (npwd)) { X perror (NSHADOW); X if (unlink (NPWDFILE) || unlink (PWDLOCK)) X fputs ("Help!\n", stderr); X X exit (1); X } X fflush (npwd); X fclose (npwd); X X if (access (OSHADOW, 0) == 0) { X if (unlink (OSHADOW)) { X puts ("Can't remove backup file"); X goto unlock; X } X } X if (link (SHADOW, OSHADOW) || unlink (SHADOW)) { X puts ("Can't save backup file"); X goto unlock; X } X#ifndef BSD X if (link (NSHADOW, SHADOW) || unlink (NSHADOW)) X#else X if (rename (NSHADOW, SHADOW)) X#endif X { X (void) unlink (OSHADOW); X puts ("Can't rename new file"); X goto unlock; X } X if (unlink (OSHADOW)) { X puts ("Can't remove backup file"); X goto unlock; X } X#else /* ! SHADOWPWD */ X#ifdef DBM X update_dbm (&pwent); X#endif X if (access (NPWDFILE, 0) == 0 && unlink (NPWDFILE) == -1) X goto failure; X X#ifndef NDEBUG X if ((npwd = fopen ("npasswd", "w")) == (FILE *) 0) X#else X umask (077); /* no permissions for non-roots */ X X if ((npwd = fopen (NPWDFILE, "w")) == (FILE *) 0) X#endif /* NDEBUG */ X goto failure; X X#ifndef NDEBUG X chmod (NPWDFILE, 0444); /* lets have some security here ... */ X chown (NPWDFILE, 0, 0); /* ... and keep the bad guy away */ X#endif /* NDEBUG */ X if ((pwd = fopen (PWDFILE, "r")) == (FILE *) 0) X goto failure; X X while (fgets (buf, BUFSIZ, pwd) != (char *) 0) { X if (buf[0] == '#' || ! (pw = sgetpwent (buf))) { X fputs (buf, npwd); X } else if (strcmp (pw->pw_name, pwent.pw_name) != 0) X fputs (buf, npwd); X else X break; X } X (void) fprintf (npwd, "%s:", pw->pw_name); X if (pwent.pw_age && pwent.pw_age[0]) X (void) fprintf (npwd, "%s,%s:", pwent.pw_passwd, pwent.pw_age); X else X (void) fprintf (npwd, "%s:", pwent.pw_passwd); X X (void) fprintf (npwd, "%d:%d:%s:%s:%s\n", X pwent.pw_uid, pwent.pw_gid, pwent.pw_gecos, pwent.pw_dir, X pwent.pw_shell ? pwent.pw_shell:""); X X while (fgets (buf, BUFSIZ, pwd) != (char *) 0) X fputs (buf, npwd); X X if (ferror (npwd)) { X perror (NPWDFILE); X if (unlink (NPWDFILE) || unlink (PWDLOCK)) X fputs ("Help!\n", stderr); X X exit (1); X } X fflush (npwd); X fclose (npwd); X#ifdef NDEBUG X chmod (NPWDFILE, 0644); X if (unlink (OPWDFILE) == -1) { X if (errno != ENOENT) { X puts ("Can't unlink backup file"); X goto unlock; X } X } X if (link (PWDFILE, OPWDFILE) || unlink (PWDFILE)) { X puts ("Can't save backup file"); X goto unlock; X } X#ifndef BSD X if (link (NPWDFILE, PWDFILE) || unlink (NPWDFILE)) X#else X if (rename (NPWDFILE, PWDFILE)) X#endif X { X puts ("Can't rename new file"); X goto unlock; X } X#endif /* NDEBUG */ X#endif /* SHADOW */ X#ifndef NDEBUG X (void) unlink (".pwdlock"); X#else X (void) unlink (PWDLOCK); X#endif X exit (0); X /*NOTREACHED*/ X Xfailure: X puts ("Permission denied."); Xunlock: X if (lockfd >= 0) X (void) unlink (PWDLOCK); X X (void) unlink (NPWDFILE); X exit (1); X /*NOTREACHED*/ X Xtoomany: X puts ("Too many tries; try again later."); X exit (1); X /*NOTREACHED*/ X} X X/* X * die - set or reset termio modes. X * X * die() is called before processing begins. signal() is then X * called with die() as the signal handler. If signal later X * calls die() with a signal number, the terminal modes are X * then reset. X */ X Xvoid die (killed) Xint killed; X{ X#ifdef BSD X static struct sgtty sgtty; X X if (killed) X stty (0, &sgtty); X else X gtty (0, &sgtty); X#else X static struct termio sgtty; X X if (killed) X ioctl (0, TCSETA, &sgtty); X else X ioctl (0, TCGETA, &sgtty); X#endif X if (killed) { X putchar ('\n'); X fflush (stdout); X exit (killed); X } X} SHAR_EOF if test 11779 -ne "`wc -c < 'pmain.c'`" then echo shar: "error transmitting 'pmain.c'" '(should have been 11779 characters)' fi fi echo shar: "extracting 'port.c'" '(8322 characters)' if test -f 'port.c' then echo shar: "will not over-write existing file 'port.c'" else sed 's/^X//' << \SHAR_EOF > 'port.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 X#include X#ifndef BSD X#include X#else X#include X#define strchr index X#define strrchr rindex X#endif X#include "port.h" X X#ifndef lint Xstatic char _sccsid[] = "@(#)port.c 2.2 08:26:33 8/20/90"; X#endif X Xextern int errno; X Xstatic FILE *ports; X X/* X * setttyent - open /etc/porttime file or rewind X * X * the /etc/porttime file is rewound if already open, or X * opened for reading. X */ X Xvoid Xsetttyent () X{ X if (ports) X rewind (ports); X else X ports = fopen (PORTS, "r"); X} X X/* X * endttyent - close the /etc/porttime file X * X * the /etc/porttime file is closed and the ports variable set X * to NULL to indicate that the /etc/porttime file is no longer X * open. X */ X Xvoid Xendttyent () X{ X if (ports) X fclose (ports); X X ports = (FILE *) 0; X} X X/* X * getttyent - read a single entry from /etc/porttime X * X * the next line in /etc/porttime is converted to a (struct port) X * and a pointer to a static (struct port) is returned to the X * invoker. NULL is returned on either EOF or error. errno is X * set to EINVAL on error to distinguish the two conditions. X */ X Xstruct port * Xgetttyent () X{ X static struct port port; /* static struct to point to */ X static char buf[BUFSIZ]; /* some space for stuff */ X static char *users[PORT_IDS]; /* some pointers to user ids */ X static struct pt_time times[PORT_TIMES]; /* some time range things */ X char *cp; /* pointer into line */ X int time; /* scratch time of day */ X int i, j; X int saveerr = errno; /* errno value on entry */ X X /* X * If the ports file is not open, open the file. Do not rewind X * since we want to search from the beginning each time. X */ X X if (! ports) X setttyent (); X X if (! ports) { X errno = saveerr; X return 0; X } X X /* X * Common point for beginning a new line - X * X * - read a line, and NUL terminate X * - skip lines which begin with '#' X * - parse off the tty name X * - parse off a list of user names X * - parse off a list of days and times X */ X Xagain: X X /* X * Get the next line and remove the last character, which X * is a '\n'. Lines which begin with '#' are all ignored. X */ X X if (fgets (buf, BUFSIZ, ports) == 0) { X errno = saveerr; X return 0; X } X if (buf[0] == '#') X goto again; X X /* X * Get the name of the TTY device. It is the first colon X * separated field, and is the name of the TTY with no X * leading "/dev". The entry '*' is used to specify all X * TTY devices. X */ X X buf[strlen (buf) - 1] = 0; X X port.pt_name = buf; X if (! (cp = strchr (buf, ':'))) X goto again; X X *cp++ = 0; X X /* X * Get the list of user names. It is the second colon X * separated field, and is a comma separated list of user X * names. The entry '*' is used to specify all usernames. X * The last entry in the list is a (char *) 0 pointer. X */ X X if (*cp != ':') { X port.pt_users = users; X port.pt_users[0] = cp; X X for (j = 1;*cp != ':';cp++) { X if (*cp == ',' && j < (PORT_IDS-1)) { X *cp++ = 0; X port.pt_users[j++] = cp; X } X } X port.pt_users[j] = 0; X } else X port.pt_users = 0; X X if (*cp != ':') X goto again; X X *cp++ = 0; X X /* X * Get the list of valid times. The times field is the third X * colon separated field and is a list of days of the week and X * times during which this port may be used by this user. The X * valid days are 'Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', and 'Sa'. X * X * In addition, the value 'Al' represents all 7 days, and 'Wk' X * represents the 5 weekdays. X * X * Times are given as HHMM-HHMM. The ending time may be before X * the starting time. Days are presumed to wrap at 0000. X */ X X if (*cp == '\0') { X port.pt_times = 0; X return &port; X } X X port.pt_times = times; X X /* X * Get the next comma separated entry X */ X X for (j = 0;*cp && j < (PORT_TIMES-1);j++) { X X /* X * Start off with no days of the week X */ X X port.pt_times[j].t_days = 0; X X /* X * Check each two letter sequence to see if it is X * one of the abbreviations for the days of the X * week or the other two values. X */ X X for (i = 0;cp[i] && cp[i + 1] && isalpha (cp[i]);i += 2) { X switch ((cp[i] << 8) | (cp[i + 1])) { X case ('S' << 8) | 'u': X port.pt_times[j].t_days |= 01; X break; X case ('M' << 8) | 'o': X port.pt_times[j].t_days |= 02; X break; X case ('T' << 8) | 'u': X port.pt_times[j].t_days |= 04; X break; X case ('W' << 8) | 'e': X port.pt_times[j].t_days |= 010; X break; X case ('T' << 8) | 'h': X port.pt_times[j].t_days |= 020; X break; X case ('F' << 8) | 'r': X port.pt_times[j].t_days |= 040; X break; X case ('S' << 8) | 'a': X port.pt_times[j].t_days |= 0100; X break; X case ('W' << 8) | 'k': X port.pt_times[j].t_days |= 076; X break; X case ('A' << 8) | 'l': X port.pt_times[j].t_days |= 0177; X break; X default: X errno = EINVAL; X return 0; X } X } X X /* X * The default is 'Al' if no days were seen. X */ X X if (i == 0) X port.pt_times[j].t_days = 0177; X X /* X * The start and end times are separated from each X * other by a '-'. The times are four digit numbers X * representing the times of day. X */ X X for (time = 0;cp[i] && isdigit (cp[i]);i++) X time = time * 10 + cp[i] - '0'; X X if (cp[i] != '-' || time > 2400 || time % 100 > 59) X goto again; X port.pt_times[j].t_start = time; X cp = cp + i + 1; X X for (time = i = 0;cp[i] && isdigit (cp[i]);i++) X time = time * 10 + cp[i] - '0'; X X if ((cp[i] != ',' && cp[i]) || time > 2400 || time % 100 > 59) X goto again; X X port.pt_times[j].t_end = time; X cp = cp + i + 1; X } X X /* X * The end of the list is indicated by a pair of -1's for the X * start and end times. X */ X X port.pt_times[j].t_start = port.pt_times[j].t_end = -1; X X return &port; X} X X/* X * getttyuser - get ports information for user and tty X * X * getttyuser() searches the ports file for an entry with a TTY X * and user field both of which match the supplied TTY and X * user name. The file is searched from the beginning, so the X * entries are treated as an ordered list. X */ X Xstruct port * Xgetttyuser (tty, user) Xchar *tty; Xchar *user; X{ X int i; X struct port *port; X X setttyent (); X X while (port = getttyent ()) { X if (strcmp (port->pt_name, tty) != 0 && X strcmp (port->pt_name, "*") != 0) X continue; X X if (strcmp (*port->pt_users, "*") == 0) X break; X X for (i = 0;port->pt_users && port->pt_users[i];i++) { X if (strcmp (user, port->pt_users[i]) == 0) X break; X } X if (port->pt_users && port->pt_users[i]) X break; X } X endttyent (); X return port; X} X X/* X * isttytime - tell if a given user may login at a particular time X * X * isttytime searches the ports file for an entry which matches X * the user name and TTY given. X */ X Xint Xisttytime (id, port, clock) Xchar *id; Xchar *port; Xlong clock; X{ X int i; X int time; X struct port *pp; X struct tm *tm, X *localtime(); X X /* X * Try to find a matching entry for this user. Default to X * letting the user in - there are pleny of ways to have an X * entry to match all users. X */ X X if (! (pp = getttyuser (id, port))) X return 1; X X /* X * The entry is there, but has not time entries - don't X * ever let them login. X */ X X if (pp->pt_times == 0) X return 0; X X /* X * The current time is converted to HHMM format for X * comparision against the time values in the TTY entry. X */ X X tm = localtime (&clock); X time = tm->tm_hour * 100 + tm->tm_min; X X /* X * Each time entry is compared against the current X * time. For entries with the start after the end time, X * the comparision is made so that the time is between X * midnight and either the start or end time. X */ X X for (i = 0;pp->pt_times[i].t_start != -1;i++) { X if (! (pp->pt_times[i].t_days & PORT_DAY(tm->tm_wday))) X continue; X X if (pp->pt_times[i].t_start <= pp->pt_times[i].t_end) { X if (time >= pp->pt_times[i].t_start && X time <= pp->pt_times[i].t_end) X return 1; X } else { X if (time >= pp->pt_times[i].t_start || X time <= pp->pt_times[i].t_end) X return 1; X } X } X X /* X * No matching time entry was found, user shouldn't X * be let in right now. X */ X X return 0; X} SHAR_EOF if test 8322 -ne "`wc -c < 'port.c'`" then echo shar: "error transmitting 'port.c'" '(should have been 8322 characters)' fi fi echo shar: "extracting 'lmain.c'" '(8196 characters)' if test -f 'lmain.c' then echo shar: "will not over-write existing file 'lmain.c'" else sed 's/^X//' << \SHAR_EOF > 'lmain.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 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#ifndef BSD X#include X#else X#include X#endif X#include "config.h" X#include "lastlog.h" X#include "faillog.h" X#ifdef SHADOWPWD X#include "shadow.h" X#endif X X#ifndef lint Xstatic char _sccsid[] = "@(#)lmain.c 2.7 10:20:08 11/9/90"; X#endif X X#ifndef ERASECHAR X#define ERASECHAR '\b' /* backspace */ X#endif X X#ifndef KILLCHAR X#define KILLCHAR '\025' /* control U */ X#endif X Xchar name[BUFSIZ]; Xchar pass[BUFSIZ]; Xchar home[BUFSIZ]; Xchar prog[BUFSIZ]; Xchar mail[BUFSIZ]; X#ifdef HUSHLOGIN Xchar hush[BUFSIZ]; Xint hushed; X#endif X Xstruct passwd pwent; Xstruct utmp utent; Xstruct lastlog lastlog; X#ifndef BSD Xstruct termio termio; X#endif X X#ifndef MAXENV X#define MAXENV 64 X#endif X Xchar *newenvp[MAXENV]; Xint newenvc = 0; Xint maxenv = MAXENV; Xextern char **environ; X Xchar *getenv (); Xvoid checkutmp (); Xvoid addenv (); Xvoid setenv (); Xunsigned alarm (); Xvoid login (); Xvoid entry (); Xvoid setutmp (); Xvoid subsystem (); Xvoid log (); Xvoid setup (); Xvoid expire (); Xvoid motd (); Xvoid mailcheck (); Xvoid shell (); Xlong a64l (); Xint c64i (); X X#ifdef TZ XFILE *tzfile; Xchar tzbuf[32] = TZ; X#endif X X#ifndef ALARM X#define ALARM 60 X#endif X X#ifndef RETRIES X#define RETRIES 3 X#endif X X#ifdef FAILLOG Xstruct faillog faillog; X#endif X#ifdef FTMP Xstruct utmp failent; X#endif X#ifndef WARNAGE X#define WARNAGE 0 X#endif X Xint main (argc, argv, envp) Xint argc; Xchar **argv; Xchar **envp; X{ X int retries = RETRIES; X int failed; X#ifdef CONSOLE X int conflag; X char console[BUFSIZ]; X FILE *fp; X struct stat statbuf; X#endif X#ifdef SHADOWPWD X struct spwd *spwd; X struct spwd *getspnam(); X#endif X X checkutmp (); /* must be lowest level shell */ X X if (! isatty (0)) /* must be a terminal */ X exit (1); X X#ifndef BSD X (void) ioctl (0, TCGETA, &termio); /* get terminal characteristics */ X X /* X * Add your favorite terminal modes here ... X */ X X termio.c_lflag |= ISIG; X X termio.c_cc[VERASE] = ERASECHAR; X termio.c_cc[VKILL] = KILLCHAR; X (void) ioctl (0, TCSETAF, &termio); /* set erase and kill characters */ X#endif X#ifdef UMASK X umask (UMASK); /* override the default umask */ X#endif X#ifdef ULIMIT X ulimit (2, (long) ULIMIT); /* override the default ulimit */ X#endif X while (*envp) /* add inherited environment, */ X addenv (*envp++); /* some variables change later */ X X#ifdef TZ X if (tzbuf[0] == '/') { X if ((tzfile = fopen (tzbuf, "r")) != (FILE *) 0) { X if (fgets (tzbuf, sizeof tzbuf, tzfile)) { X tzbuf[strlen (tzbuf) - 1] = '\0'; X addenv (tzbuf); X } X fclose (tzfile); X } X } else { X addenv (tzbuf); X } X#endif X#ifdef HZ X addenv (HZ); /* set the default $HZ, if one */ X#endif X if (argc >= 2) { /* now set command line variables */ X setenv (argc - 2, &argv[2]); X (void) strncpy (name, argv[1], sizeof name); X } X (void) alarm (ALARM); /* only allow ALARM sec. for login */ X X while (1) { /* repeatedly get login/password pairs */ X if (! name[0]) { /* need to get a login id */ X login (name); X continue; X } X entry (name, &pwent); /* get entry from password file */ X failed = 0; /* hasn't failed validation yet */ X X /* X * Here we have a sticky situation. Some accounts may have no X * password entry in the password file. So, we don't ask for a X * password. Others, have a blank password entered - you be the X * judge. The conditional compilation NOBLANK requires even X * blank passwords to be prompted for. This may well break X * quite a few systems. Use with discretion. X */ X X#ifdef NOBLANK X /* get a password from user */ X if (! password ("Password:", pass)) X continue; X#else X if ((! pwent.pw_name || X (pwent.pw_passwd && strlen (pwent.pw_passwd) > 0)) X && ! password ("Password:", pass)) X continue; X#endif X if (! valid (pass, &pwent)) /* check encrypted passwords ... */ X failed = 1; X X#ifdef DIALUP X alarm (30); X if (! dialcheck (utent.ut_line, X pwent.pw_shell ? pwent.pw_shell:"/bin/sh")) X failed = 1; X#endif X#ifdef PORTTIME X if (pwent.pw_name && X ! isttytime (utent.ut_line, pwent.pw_name, X time ((long *) 0))) X failed = 1; X#endif X#ifdef CONSOLE X if (pwent.pw_uid == 0 && stat (CONSOLE, &statbuf) == 0) { X if ((statbuf.st_mode & S_IFMT) == S_IFREG) { X fp = fopen (CONSOLE, "r"); X while (fp && fgets (console, BUFSIZ, fp) X == console) { X console[strlen (console) - 1] = '\0'; X if (! strcmp (console, utent.ut_line)) X break; X } X if (! fp || feof (fp)) X failed = 1; X X fclose (fp); X } else { X if (strcmp (CONSOLE, utent.ut_line)) X failed = 1; X } X } X#endif X#ifdef FAILLOG X if (! failcheck (pwent.pw_uid, &faillog, failed)) X failed = 1; X#endif X if (! failed) X break; X X puts ("Login incorrect"); X#ifdef FAILLOG X if (pwent.pw_name) /* don't log non-existent users */ X failure (pwent.pw_uid, utent.ut_line, &faillog); X#endif X#ifdef FTMP X failent = utent; X X if (pwent.pw_name) X strncpy (failent.ut_name, X pwent.pw_name, sizeof failent.ut_name); X else X#ifdef UNKNOWNS X strcpy (failent.ut_name, name); X#else X strcpy (failent.ut_name, "UNKNOWN"); X#endif X failent.ut_time = time ((time_t *) 0); X failent.ut_type = USER_PROCESS; X X failtmp (&failent); X#endif /* FTMP */ X if (--retries <= 0) /* only allow so many failures */ X exit (1); X X#ifndef BSD X (void) memset (name, '\0', sizeof name); X (void) memset (pass, '\0', sizeof pass); X#else X bzero (name, sizeof name); X bzero (pass, sizeof pass); X#endif X } X (void) alarm (0); /* turn off alarm clock */ X#ifdef NOLOGINS X /* X * Check to see if system is turned off for non-root users. X * This would be useful to prevent users from logging in X * during system maintenance. X */ X X if (pwent.pw_uid != 0 && access (NOLOGINS, 0) == 0) { X printf ("\r\nSystem closed for routine maintenance\n"); X exit (0); X } X#endif X environ = newenvp; /* make new environment active */ X X if (getenv ("IFS")) /* don't export user IFS ... */ X addenv ("IFS= \t\n"); /* ... instead, set a safe IFS */ X X setutmp (); /* make entry in utmp & wtmp files */ X if (pwent.pw_shell && pwent.pw_shell[0] == '*') /* subsystem root */ X subsystem (); /* figure out what to execute */ X X#ifdef LASTLOG X log (); /* give last login and log this one */ X#endif X#ifdef SHADOWPWD X /* X * Need to get expiration information before changing UID X */ X X spwd = getspnam (pwent.pw_name); X#endif X setup (&pwent); /* set UID, GID, HOME, etc ... */ X#ifdef AGING X#ifdef SHADOWPWD X if (spwd) X expire (spwd->sp_namp, spwd->sp_lstchg, X spwd->sp_min, spwd->sp_max); X else X#endif X if (pwent.pw_age && pwent.pw_age[0]) { /* check for age of password */ X expire (pwent.pw_name, (strlen (pwent.pw_age) == 4 ? X a64l (pwent.pw_age + 2):0L) * 7, X c64i (pwent.pw_age[1]) * 7, X c64i (pwent.pw_age[0]) * 7); X } X#endif X#ifdef HUSHLOGIN X sprintf (hush, "%s/.hushlogin", strchr (home, '=') + 1); X hushed = access (hush, 0) != -1; X#endif X#ifdef MOTD X motd (); /* print the message of the day */ X#endif X#ifdef FAILLOG X if (faillog.fail_cnt != 0) X failprint (pwent.pw_uid, &faillog); X#endif X#ifdef LASTLOG X if (lastlog.ll_time != 0 && ! hushed) X printf ("Last login: %.19s on %s\n", X ctime (&lastlog.ll_time), lastlog.ll_line); X#endif X#ifdef AGING X#ifdef SHADOWPWD X if (spwd) X agecheck (spwd->sp_lstchg, X spwd->sp_min, spwd->sp_max, 1); X else X#endif X agecheck (strlen (pwent.pw_age) == 4 ? X a64l (pwent.pw_age + 2):0L, X c64i (pwent.pw_age[1]), c64i (pwent.pw_age[0]), 7); X#endif X#ifdef MAILCHECK X mailcheck (); /* report on the status of mail */ X#endif X#ifdef TTYTYPE X ttytype (utent.ut_line); X#endif X signal (SIGINT, SIG_DFL); /* default interrupt signal */ X signal (SIGQUIT, SIG_DFL); /* default quit signal */ X signal (SIGTERM, SIG_DFL); /* default terminate signal */ X signal (SIGALRM, SIG_DFL); /* default alarm signal */ X X shell (pwent.pw_shell); /* exec the shell finally. */ X /*NOTREACHED*/ X} SHAR_EOF if test 8196 -ne "`wc -c < 'lmain.c'`" then echo shar: "error transmitting 'lmain.c'" '(should have been 8196 characters)' fi fi echo shar: "extracting 'mkpasswd.c'" '(6587 characters)' if test -f 'mkpasswd.c' then echo shar: "will not over-write existing file 'mkpasswd.c'" else sed 's/^X//' << \SHAR_EOF > 'mkpasswd.c' X/* X * Copyright 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 * Duplication is permitted for non-commercial [ profit making ] X * purposes provided this and other copyright notices remain X * intact. X */ X X#include "config.h" X#include X#include X#include X#ifdef BSD X#include X#else X#include X#endif X X#if !defined(DBM) X#error "What you are trying to do? You have to have a DBM of some kind ..." X#endif X X#ifdef DBM X#include X#endif X X#ifndef lint Xstatic char sccsid[] = "@(#)mkpasswd.c 2.3 08:56:25 11/5/90"; Xstatic char copyright[] = "Copyright 1990, John F. Haugh II"; X#endif X Xchar *CANT_OPEN = "%s: cannot open file %s\n"; Xchar *CANT_OVERWRITE = "%s: cannot overwrite file %s\n"; Xchar *CANT_CREATE = "%s: cannot create %s\n"; Xchar *DBM_OPEN_ERR = "%s: cannot open DBM files for %s\n"; Xchar *PARSE_ERR = "%s: error parsing line\n\"%s\"\n"; Xchar *LINE_TOO_LONG = "%s: the beginning with \"%.16s ...\" is too long\n"; Xchar *ADD_NAME = "adding key for name \"%s\"\n"; Xchar *ADD_NAME_ERR = "%s: error adding entry for \"%s\"\n"; Xchar *ADD_UID = "adding key for uid %d, name \"%s\"\n"; Xchar *ADD_UID_ERR = "%s: error adding entry for uid %d, name \"%s\"\n"; Xchar *INFO = "added %d entries, longest was %d\n"; Xchar *USAGE = "Usage: %s [ -v ] [ -f ] file\n"; X Xchar *Progname; Xint vflg = 0; Xint fflg = 0; X Xvoid usage(); X Xextern char *malloc(); Xextern struct passwd *sgetpwent(); X X/* X * mkpasswd - create DBM files for /etc/passwd-like input file X * X * mkpasswd takes an an argument the name of a file in /etc/passwd format X * and creates a DBM file keyed by user ID and name. The output files have X * the same name as the input file, with .dir and .pag appended. X */ X Xint Xmain (argc, argv) Xint argc; Xchar **argv; X{ X extern int optind; X extern char *optarg; X FILE *pwfp; /* File pointer for password file */ X char *pwfile; /* Name of password file */ X char *pwdir; /* Name of .dir file */ X char *pwpag; /* Name of .pag file */ X char *cp; /* Temporary character pointer */ X int flag; /* Flag for command line option */ X int fd; /* File descriptor of open DBM file */ X int cnt = 0; /* Number of entries in database */ X int longest = 0; /* Longest entry in database */ X int errors = 0; /* Count of errors processing file */ X char buf[BUFSIZ]; /* Input line from password file */ X char dbmbuf[BUFSIZ]; /* Place to build DBM record */ X struct passwd *passwd; /* Pointer to password file entry */ X datum key; /* Info for DBM key data */ X datum content; /* Info for DBM record data */ X X /* X * Figure out what my name is. I will use this later ... X */ X X if (Progname = strrchr (argv[0], '/')) X Progname++; X else X Progname = argv[0]; X X /* X * Figure out what the flags might be ... X */ X X while ((flag = getopt (argc, argv, "fv")) != EOF) { X switch (flag) { X case 'v': X vflg++; X break; X case 'f': X fflg++; X break; X default: X usage (); X } X } X X /* X * The last and only remaining argument must be the file name X */ X X if (argc - 1 != optind) X usage (); X X pwfile = argv[optind]; X X if (! (pwfp = fopen (pwfile, "r"))) { X fprintf (stderr, CANT_OPEN, Progname, pwfile); X exit (1); X } X X /* X * Make the filenames for the two DBM files. X */ X X pwdir = malloc (strlen (pwfile) + 5); /* space for .dir file */ X strcat (strcpy (pwdir, pwfile), ".dir"); X X pwpag = malloc (strlen (pwfile) + 5); /* space for .pag file */ X strcat (strcpy (pwpag, pwfile), ".pag"); X X /* X * Remove existing files if requested. X */ X X if (fflg) { X (void) unlink (pwdir); X (void) unlink (pwpag); X } X X /* X * Create the two DBM files - it is an error for these files X * to have existed already. X */ X X if (access (pwdir, 0) == 0) { X fprintf (stderr, CANT_OVERWRITE, Progname, pwdir); X exit (1); X } X if (access (pwpag, 0) == 0) { X fprintf (stderr, CANT_OVERWRITE, Progname, pwpag); X exit (1); X } X X umask (0); X if ((fd = open (pwdir, O_RDWR|O_CREAT|O_EXCL, 0644)) == -1) { X fprintf (stderr, CANT_CREATE, Progname, pwdir); X exit (1); X } else X close (fd); X X if ((fd = open (pwpag, O_RDWR|O_CREAT|O_EXCL, 0644)) == -1) { X fprintf (stderr, CANT_CREATE, Progname, pwpag); X unlink (pwdir); X exit (1); X } else X close (fd); X X /* X * Now the DBM database gets initialized X */ X X#ifdef DBM X if (dbminit (pwfile) == -1) { X fprintf (stderr, DBM_OPEN_ERR, Progname, pwfile); X exit (1); X } X#endif X X /* X * Read every line in the password file and convert it into a X * data structure to be put in the DBM database files. X */ X X while (fgets (buf, BUFSIZ, pwfp) != NULL) { X X /* X * Get the next line and strip off the trailing newline X * character. Very long lines are fatal errors. X */ X X buf[BUFSIZ-1] = '\0'; X if (! (cp = strchr (buf, '\n'))) { X fprintf (stderr, LINE_TOO_LONG, Progname, buf); X exit (1); X } X *cp = '\0'; X X /* X * Parse the password file line into a (struct passwd). X * Erroneous lines cause error messages, but that's X * all. YP lines are ignored completely. X */ X X if (buf[0] == '-' || buf[0] == '+') X continue; X X if (! (passwd = sgetpwent (buf))) { X fprintf (stderr, PARSE_ERR, Progname, buf); X errors++; X continue; X } X X /* X * Pack the (struct passwd) into a buffer and build X * the content structure for the DBM. X */ X X content.dsize = pw_pack (passwd, dbmbuf); X content.dptr = dbmbuf; X X /* X * Store the record using the name as the key X */ X X key.dsize = strlen (passwd->pw_name); X key.dptr = passwd->pw_name; X if (vflg) X printf (ADD_NAME, passwd->pw_name); X#ifdef DBM X if (store (key, content)) { X fprintf (stderr, ADD_NAME_ERR, Progname, X passwd->pw_name); X errors++; X } X#endif X X /* X * Store the record using the UID as the key X */ X X key.dsize = sizeof passwd->pw_uid; X key.dptr = (char *) &passwd->pw_uid; X if (vflg) X printf (ADD_UID, passwd->pw_uid, passwd->pw_name); X#ifdef DBM X if (store (key, content)) { X fprintf (stderr, ADD_UID_ERR, Progname, X passwd->pw_uid, passwd->pw_name); X errors++; X } X#endif X /* X * Update the longest record and record count X */ X X if (content.dsize > longest) X longest = content.dsize; X cnt++; X } X X /* X * Tell the user how things went ... X */ X X if (vflg) X printf (INFO, cnt, longest); X X exit (errors); X /*NOTREACHED*/ X} X X/* X * usage - print error message and exit X */ X Xvoid Xusage () X{ X fprintf (stderr, USAGE, Progname); X exit (1); X /*NOTREACHED*/ X} SHAR_EOF if test 6587 -ne "`wc -c < 'mkpasswd.c'`" then echo shar: "error transmitting 'mkpasswd.c'" '(should have been 6587 characters)' fi fi echo shar: "extracting 'sulogin.c'" '(3193 characters)' if test -f 'sulogin.c' then echo shar: "will not over-write existing file 'sulogin.c'" else sed 's/^X//' << \SHAR_EOF > 'sulogin.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 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[] = "@(#)sulogin.c 2.3.1.1 08:28:36 12/5/90"; X#endif X Xchar name[BUFSIZ]; Xchar pass[BUFSIZ]; Xchar home[BUFSIZ]; Xchar prog[BUFSIZ]; Xchar mail[BUFSIZ]; X Xstruct passwd pwent; Xstruct utmp utent; X X#ifdef TZ XFILE *tzfile; Xchar tzbuf[16] = TZ; X#endif X X#ifndef MAXENV X#define MAXENV 64 X#endif X Xchar *newenvp[MAXENV]; Xint newenvc = 0; Xint maxenv = MAXENV; Xextern char **environ; X X#ifndef ALARM X#define ALARM 60 X#endif X X#ifndef RETRIES X#define RETRIES 3 X#endif X Xint main (argc, argv, envp) Xint argc; Xchar **argv; Xchar **envp; X{ X char *getenv (); X char *ttyname (); X char *cp; X X if (access (PWDFILE, 0) == -1) { /* must be a password file! */ X printf ("No password file\n"); X exit (1); X } X#ifdef NDEBUG X if (getppid () != 1) /* parent must be INIT */ X exit (1); X#endif X if (! isatty (0)) /* must be a terminal */ X exit (1); X X while (*envp) /* add inherited environment, */ X addenv (*envp++); /* some variables change later */ X X#ifdef TZ X if (tzbuf[0] == '/') { X if ((tzfile = fopen (tzbuf, "r")) != (FILE *) 0) { X if (fgets (tzbuf, sizeof tzbuf, tzfile)) { X tzbuf[strlen (tzbuf) - 1] = '\0'; X addenv (tzbuf); X } X fclose (tzfile); X } X } else { X addenv (tzbuf); X } X#endif X#ifdef HZ X addenv (HZ); /* set the default $HZ, if one */ X#endif X (void) strcpy (name, "root"); /* KLUDGE!!! */ X X alarm (ALARM); X while (1) { /* repeatedly get login/password pairs */ X entry (name, &pwent); /* get entry from password file */ X if (pwent.pw_name == (char *) 0) { X printf ("No password entry for 'root'\n"); X exit (1); X } X X /* X * Here we prompt for the root password, or if no password is X * given we just exit. X */ X X /* get a password for root */ X if (! password ("Type control-d for normal startup,\n\ X(or give root password for system maintenance):", pass)) X exit (0); X X if (valid (pass, &pwent)) /* check encrypted passwords ... */ X break; /* ... encrypted passwords matched */ X X puts ("Login incorrect"); X } X alarm (0); X environ = newenvp; /* make new environment active */ X X puts ("Entering System Maintenance Mode"); X X /* X * Normally there would be a utmp entry for login to mung on X * to get the tty name, date, etc. from. We don't need all that X * stuff because we won't update the utmp or wtmp files. BUT!, X * we do need the tty name so we can set the permissions and X * ownership. X */ X X if (cp = ttyname (0)) { /* found entry in /dev/ */ X if (strrchr (cp, '/') != (char *) 0) X strcpy (utent.ut_line, strrchr (cp, '/') + 1); X else X strcpy (utent.ut_line, cp); X } X if (getenv ("IFS")) /* don't export user IFS ... */ X addenv ("IFS= \t\n"); /* ... instead, set a safe IFS */ X X setup (&pwent); /* set UID, GID, HOME, etc ... */ X X shell (pwent.pw_shell); /* exec the shell finally. */ X /*NOTREACHED*/ X} SHAR_EOF if test 3193 -ne "`wc -c < 'sulogin.c'`" then echo shar: "error transmitting 'sulogin.c'" '(should have been 3193 characters)' fi fi echo shar: "extracting 'pwpack.c'" '(2139 characters)' if test -f 'pwpack.c' then echo shar: "will not over-write existing file 'pwpack.c'" else sed 's/^X//' << \SHAR_EOF > 'pwpack.c' X/* X * Copyright 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 * Duplication is permitted for non-commercial [ profit making ] X * purposes provided this and other copyright notices remain X * intact. X */ X X#include X#include X#ifdef BSD X#include X#else X#include X#endif X X#ifndef lint Xstatic char sccsid[] = "@(#)pwpack.c 2.3 23:06:29 8/5/90"; X#endif X Xint pw_pack (passwd, buf) Xstruct passwd *passwd; Xchar *buf; X{ X char *cp; X X cp = buf; X strcpy (cp, passwd->pw_name); X cp += strlen (cp) + 1; X X strcpy (cp, passwd->pw_passwd); X if (passwd->pw_age && passwd->pw_age[0]) { X cp += strlen (cp); X *cp++ = ','; X strcpy (cp, passwd->pw_age); X } X cp += strlen (cp) + 1; X X memcpy (cp, (void *) &passwd->pw_uid, sizeof passwd->pw_uid); X cp += sizeof passwd->pw_uid; X X memcpy (cp, (void *) &passwd->pw_gid, sizeof passwd->pw_gid); X cp += sizeof passwd->pw_gid; X X strcpy (cp, passwd->pw_gecos); X cp += strlen (cp) + 1; X X strcpy (cp, passwd->pw_dir); X cp += strlen (cp) + 1; X X strcpy (cp, passwd->pw_shell); X cp += strlen (cp) + 1; X X return cp - buf; X} X Xint pw_unpack (buf, len, passwd) Xchar *buf; Xint len; Xstruct passwd *passwd; X{ X char *org = buf; X char *cp; X X passwd->pw_name = buf; X buf += strlen (buf) + 1; X if (buf - org > len) X return -1; X X passwd->pw_passwd = buf; X buf += strlen (buf) + 1; X if (buf - org > len) X return -1; X X if (cp = strchr (passwd->pw_passwd, ',')) { X *cp++ = '\0'; X passwd->pw_age = cp; X } else X passwd->pw_age = ""; X X memcpy ((void *) &passwd->pw_uid, (void *) buf, sizeof passwd->pw_uid); X buf += sizeof passwd->pw_uid; X if (buf - org > len) X return -1; X X memcpy ((void *) &passwd->pw_gid, (void *) buf, sizeof passwd->pw_gid); X buf += sizeof passwd->pw_gid; X if (buf - org > len) X return -1; X X passwd->pw_gecos = buf; X buf += strlen (buf) + 1; X if (buf - org > len) X return -1; X X passwd->pw_dir = buf; X buf += strlen (buf) + 1; X if (buf - org > len) X return -1; X X passwd->pw_shell = buf; X buf += strlen (buf) + 1; X if (buf - org > len) X return -1; X X return 0; X} SHAR_EOF if test 2139 -ne "`wc -c < 'pwpack.c'`" then echo shar: "error transmitting 'pwpack.c'" '(should have been 2139 characters)' fi fi echo shar: "extracting 'dialup.c'" '(2171 characters)' if test -f 'dialup.c' then echo shar: "will not over-write existing file 'dialup.c'" else sed 's/^X//' << \SHAR_EOF > 'dialup.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#else X#include X#define strchr index X#define strrchr rindex X#endif X#include "dialup.h" X X#ifndef lint Xstatic char _sccsid[] = "@(#)dialup.c 2.2 19:23:38 7/29/90"; X#endif X Xstatic FILE *dialpwd; X Xvoid setduent () X{ X if (dialpwd) X rewind (dialpwd); X else X dialpwd = fopen (DIALPWD, "r"); X} X Xvoid endduent () X{ X if (dialpwd) X fclose (dialpwd); X X dialpwd = (FILE *) 0; X} X Xstruct dialup *getduent () X{ X static struct dialup dialup; /* static structure to point to */ X static char shell[64]; /* some space for a login shell */ X static char passwd[16]; /* some space for dialup password */ X char buf[BUFSIZ]; X char *cp; X X if (! dialpwd) X setduent (); X X if (! dialpwd || feof (dialpwd)) X return ((struct dialup *) 0); X X while (fgets (buf, BUFSIZ, dialpwd) == buf && buf[0] == '#') X ; X X if (feof (dialpwd)) X return ((struct dialup *) 0); X X cp = strchr (buf, ':'); X if (cp - buf > sizeof shell) /* something is fishy ... */ X return ((struct dialup *) 0); X X (void) strncpy (shell, buf, cp - buf); X shell[cp - buf] = '\0'; X X if (strlen (cp + 1) > sizeof passwd) /* something is REALLY fishy */ X return ((struct dialup *) 0); X X (void) strcpy (passwd, cp + 1); X passwd[strlen (passwd) - 1] = '\0'; X if (cp = strchr (passwd, ':')) X *cp = '\0'; X X dialup.du_shell = shell; X dialup.du_passwd = passwd; X X return (&dialup); X} X Xstruct dialup *getdushell (shell) Xchar *shell; X{ X struct dialup *dialup; X X while (dialup = getduent ()) { X if (strcmp (shell, dialup->du_shell) == 0) X return (dialup); X X if (strcmp (dialup->du_shell, "*") == 0) X return (dialup); X } X return ((struct dialup *) 0); X} X Xint isadialup (tty) Xchar *tty; X{ X FILE *fp; X char buf[BUFSIZ]; X int dialup = 0; X X if (! (fp = fopen (DIALUPS, "r"))) X return (0); X X while (fgets (buf, BUFSIZ, fp) == buf) { X if (buf[0] == '#') X continue; X X buf[strlen (buf) - 1] = '\0'; X X if (strcmp (buf, tty) == 0) { X dialup = 1; X break; X } X } X fclose (fp); X X return (dialup); X} SHAR_EOF if test 2171 -ne "`wc -c < 'dialup.c'`" then echo shar: "error transmitting 'dialup.c'" '(should have been 2171 characters)' fi fi echo shar: "extracting 'sulog.c'" '(1172 characters)' if test -f 'sulog.c' then echo shar: "will not over-write existing file 'sulog.c'" else sed 's/^X//' << \SHAR_EOF > 'sulog.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#include "config.h" X X#ifndef lint Xstatic char sccsid[] = "@(#)sulog.c 2.2.1.1 09:09:55 11/26/90"; X#endif X Xextern char name[]; Xextern char oldname[]; X Xtime_t time (); X Xvoid sulog (success) Xint success; X{ X#ifdef SULOG X char *tty; X char *cp; X char *ttyname (); X time_t clock; X struct tm *tm; X struct tm *localtime (); X FILE *fp; X X if ((fp = fopen (SULOG, "a+")) == (FILE *) 0) X return; /* can't open or create logfile */ X X (void) time (&clock); X tm = localtime (&clock); X X if (isatty (0) && (cp = ttyname (0))) { X if (tty = strrchr (cp, '/')) X tty++; X else X tty = cp; X } else X tty = "???"; X X (void) fprintf (fp, "SU %.02d/%0.2d %.02d:%.02d %c %.6s %s-%s\n", X tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, X success ? '+':'-', tty, oldname, name); X X fflush (fp); X fclose (fp); X#endif X} SHAR_EOF if test 1172 -ne "`wc -c < 'sulog.c'`" then echo shar: "error transmitting 'sulog.c'" '(should have been 1172 characters)' fi fi echo shar: "extracting 'password.c'" '(1939 characters)' if test -f 'password.c' then echo shar: "will not over-write existing file 'password.c'" else sed 's/^X//' << \SHAR_EOF > 'password.c' 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 X#include X#ifndef BSD X#include X#include X#else X#include X#define strchr index X#define strrchr rindex X#endif X#ifndef BSD X#include X#else X#include X#endif X X#include X X/* X * password - prompt for password and return entry X * X * Need to fake up getpass(). Returns TRUE if a password X * was successfully input, and FALSE otherwise, including X * EOF on input or ioctl() failure. pass is not modified X * on failure. The input length limit may be set by X * changing the value of PASSLIMIT. X */ X X#ifndef lint Xstatic char _sccsid[] = "@(#)password.c 2.2 09:38:59 6/22/90"; X#endif X X#define PASSLIMIT 20 X Xint password (prompt, pass) Xchar *prompt; Xchar *pass; X{ X char buf[BUFSIZ]; X char *cp; X int eof; X int ttyopened = 0; X#ifndef BSD X struct termio termio; X struct termio save; X#else X struct sgttyb termio ; X struct sgttyb save ; X#endif X FILE *fp; X X if ((fp = fopen ("/dev/tty", "r")) == (FILE *) 0) X fp = stdin; X else X ttyopened = 1; X X#ifndef BSD X if (ioctl (fileno (fp), TCGETA, &termio)) X return (0); X#else X if ( gtty( fileno(fp), &termio ) ) X return (0); X#endif X X save = termio; X#ifndef BSD X termio.c_lflag &= ~(ECHO|ECHOE|ECHOK); X ioctl (fileno (fp), TCSETAF, &termio); X#else X termio.sg_flags &= ~ECHO ; X stty( fileno( fp ), termio ) ; X#endif X X fputs (prompt, stdout); X eof = fgets (buf, BUFSIZ, fp) == (char *) 0 || feof (fp) || ferror (fp); X putchar ('\n'); X X#ifndef BSD X ioctl (fileno (fp), TCSETAF, &save); X#else X stty( fileno( fp ), save ) ; X#endif X X if (! eof) { X buf[PASSLIMIT] = '\0'; X if ((cp = strchr (buf, '\n')) || (cp = strchr (buf, '\r'))) X *cp = '\0'; X X (void) strcpy (pass, buf); X } X if (ttyopened) X fclose (fp); X X return (! eof); X} SHAR_EOF if test 1939 -ne "`wc -c < 'password.c'`" then echo shar: "error transmitting 'password.c'" '(should have been 1939 characters)' fi fi echo shar: "extracting 'env.c'" '(1788 characters)' if test -f 'env.c' then echo shar: "will not over-write existing file 'env.c'" else sed 's/^X//' << \SHAR_EOF > 'env.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#else X#define strchr index X#define strrchr rindex X#include X#endif X X#ifndef lint Xstatic char _sccsid[] = "@(#)env.c 2.2 19:23:43 7/29/90"; X#endif X Xextern char **environ; Xextern char *newenvp[]; Xextern int newenvc; Xextern int maxenv; X Xchar *strdup (); Xvoid free (); X Xstatic char *forbid[] = { X "HOME", X "IFS", X "PATH", X "SHELL", X (char *) 0 X}; X Xvoid addenv (entry) Xchar *entry; X{ X char *cp; X int i; X int len; X X if (cp = strchr (entry, '=')) X len = cp - entry; X else X return; X X for (i = 0;i < newenvc;i++) X if (strncmp (entry, newenvp[i], len) == 0 && X (newenvp[i][len] == '=' || newenvp[i][len] == '\0')) X break; X X if (i == maxenv) { X puts ("Environment overflow"); X return; X } X if (i == newenvc) { X newenvp[newenvc++] = strdup (entry); X } else { X free (newenvp[i]); X newenvp[i] = strdup (entry); X } X} X Xvoid setenv (argc, argv) Xint argc; Xchar **argv; X{ X int i; X int n; X int noname = 1; X char variable[BUFSIZ]; X char *cp; X X for (i = 0;i < argc;i++) { X if ((n = strlen (argv[i])) >= BUFSIZ) X continue; /* ignore long entries */ X X if (! (cp = strchr (argv[i], '='))) { X (void) strcpy (variable, argv[i]); X } else { X (void) strncpy (variable, argv[i], cp - argv[i]); X variable[cp - argv[i]] = '\0'; X } X for (n = 0;forbid[n] != (char *) 0;n++) X if (strcmp (variable, forbid[n]) == 0) X break; X X if (forbid[n] != (char *) 0) { X printf ("You may not change $%s\n", forbid[n]); X continue; X } X if (cp) { X addenv (argv[i]); X } else { X sprintf (variable, "L%d=%s", noname++, argv[i]); X addenv (variable); X } X } X} SHAR_EOF if test 1788 -ne "`wc -c < 'env.c'`" then echo shar: "error transmitting 'env.c'" '(should have been 1788 characters)' fi fi echo shar: "extracting 'mail.c'" '(912 characters)' if test -f 'mail.c' then echo shar: "will not over-write existing file 'mail.c'" else sed 's/^X//' << \SHAR_EOF > 'mail.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#include "config.h" X X#ifndef lint Xstatic char _sccsid[] = "@(#)mail.c 2.2 19:23:56 7/29/90"; X#endif X Xextern char mail[]; X X#ifdef HUSHLOGIN Xextern int hushed; X#endif X X#ifdef MAILCHECK Xvoid mailcheck () X{ X struct stat statbuf; X char *mailbox; X X#ifdef HUSHLOGIN X if (hushed) X return; X#endif X if (mailbox = strchr (mail, '=')) X mailbox++; X else X return; X X if (stat (mailbox, &statbuf) == -1 || statbuf.st_size == 0) X puts ("No mail."); X else if (statbuf.st_atime > statbuf.st_mtime) X puts ("You have mail."); X else X puts ("You have new mail."); X} X#endif SHAR_EOF if test 912 -ne "`wc -c < 'mail.c'`" then echo shar: "error transmitting 'mail.c'" '(should have been 912 characters)' fi fi echo shar: "extracting 'dialchk.c'" '(1008 characters)' if test -f 'dialchk.c' then echo shar: "will not over-write existing file 'dialchk.c'" else sed 's/^X//' << \SHAR_EOF > 'dialchk.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 "config.h" X#include "dialup.h" X X#ifndef lint Xstatic char _sccsid[] = "@(#)dialchk.c 2.2 19:23:36 7/29/90"; X#endif X X/* X * Check for dialup password X * X * dialcheck tests to see if tty is listed as being a dialup X * line. If so, a dialup password may be required if the shell X * is listed as one which requires a second password. X */ X X#ifdef DIALUP Xint dialcheck (tty, shell) Xchar *tty; Xchar *shell; X{ X char *crypt (); X char *getpass (); X struct dialup *dialup; X char *pass; X char *cp; X X if (! isadialup (tty)) X return (1); X X if (! (dialup = getdushell (shell))) X return (1); X X endduent (); X X if (dialup->du_passwd[0] == '\0') X return (1); X X if (! (pass = getpass ("Dialup Password:"))) X return (0); X X cp = crypt (pass, dialup->du_passwd); X return (strcmp (cp, dialup->du_passwd) == 0); X} X#endif SHAR_EOF if test 1008 -ne "`wc -c < 'dialchk.c'`" then echo shar: "error transmitting 'dialchk.c'" '(should have been 1008 characters)' fi fi exit 0 # End of shell archive