#! /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: # chfn.c # chsh.c # smain.c # faillog.c # pwconv.c # failure.c # utmp.c # shadow.c # log.c # shadow.h # faillog.h # This archive created: Wed Dec 12 12:36:59 1990 # By: John F Haugh II (River Parishes Programming, Austin TX) export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'chfn.c'" '(10514 characters)' if test -f 'chfn.c' then echo shar: "will not over-write existing file 'chfn.c'" else sed 's/^X//' << \SHAR_EOF > 'chfn.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#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#ifdef DBM X#include X#endif X X#ifndef lint Xstatic char _sccsid[] = "@(#)chfn.c 2.2 19:17:28 8/4/90"; X#endif X Xchar *myname; X Xchar user[BUFSIZ]; Xchar fullnm[BUFSIZ]; Xchar roomno[BUFSIZ]; Xchar workph[BUFSIZ]; Xchar homeph[BUFSIZ]; Xchar slop[BUFSIZ]; Xint fflg; Xint rflg; Xint wflg; Xint hflg; Xint oflg; X Xstruct passwd pwent; X Xextern int errno; X Xchar Usage[] = X"Usage: %s [ -f full_name ] [ -r room_no ] [ -w work_ph ] [ -h home_ph ]\n"; X Xchar Usage_root[] = X"Usage: %s [ -f full_name ] [ -r room_no ] [ -w work_ph ]\n\ X [ -h home_ph ] [ -o other ] [ user ]\n"; X X/* X * usage - print command line syntax and exit X */ X Xvoid Xusage () X{ X fprintf (stderr, getuid () == 0 ? Usage_root:Usage, myname); X exit (1); X} X X/* X * valid_field - insure that a field contains all legal characters X * X * The supplied field is scanned for non-printing and other illegal X * characters. If any illegal characters are found, valid_field X * prints a message and exits. X */ X Xvoid Xvalid_field (field, illegal) Xchar *field; Xchar *illegal; X{ X char *cp; X X for (cp = field;*cp && isprint (*cp) && ! strchr (illegal, *cp);cp++) X ; X X if (*cp) { X fprintf (stderr, "%s: invalid field: %s\n", myname, field); X exit (1); X } X} X X/* X * change_field - change a single field if a new value is given. X * X * prompt the user with the name of the field being changed and the X * current value. X */ X Xvoid Xchange_field (buf, prompt) Xchar *buf; Xchar *prompt; X{ X char new[BUFSIZ]; X char *cp; X X printf ("\t%s [%s]: ", prompt, buf); X fgets (new, BUFSIZ, stdin); X X if (cp = strchr (new, '\n')) X *cp = '\0'; X else X return; X X if (new[0]) X strcpy (buf, new); X} X X/* X * new_fields - change the user's GECOS information interactively X * X * prompt the user for each of the four fields and fill in the fields X * from the user's response, or leave alone if nothing was entered. X */ X Xnew_fields () X{ X printf ("Enter the new value, or press return for the default\n\n"); X X change_field (fullnm, "Full Name"); X change_field (roomno, "Room Number"); X change_field (workph, "Work Phone"); X change_field (homeph, "Home Phone"); X X if (getuid () == 0) X change_field (slop, "Other"); X} X X/* X * copy_field - get the next field from the gecos field X * X * copy_field copies the next field from the gecos field, returning a X * pointer to the field which follows, or NULL if there are no more X * fields. X */ X Xchar * Xcopy_field (in, out, extra) Xchar *in; /* the current GECOS field */ Xchar *out; /* where to copy the field to */ Xchar *extra; /* fields with '=' get copied here */ X{ X char *cp; X X while (in) { X if (cp = strchr (in, ',')) X *cp++ = '\0'; X X if (! strchr (in, '=')) X break; X X if (extra) { X if (extra[0]) X strcat (extra, ","); X X strcat (extra, in); X } X in = cp; X } X if (in && out) X strcpy (out, in); X X return cp; 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 extern int optind; X extern char *optarg; X void die (); X char *cp; X char *getlogin (); X int amroot; X int lockfd = -1; X int flag; X struct passwd *pw; X struct passwd *getpwuid (); X struct passwd *getpwnam (); X struct passwd *sgetpwent (); X FILE *npwd; X FILE *pwd; X char buf[BUFSIZ]; X char tmp[BUFSIZ]; X X amroot = getuid () == 0; X if (myname = strchr (argv[0], '/')) X myname++; X else X myname = argv[0]; X X while ((flag = getopt (argc, argv, "f:r:w:h:o:")) != EOF) { X switch (flag) { X case 'f': X fflg++; X strcpy (fullnm, optarg); X break; X case 'r': X rflg++; X strcpy (roomno, optarg); X break; X case 'w': X wflg++; X strcpy (workph, optarg); X break; X case 'h': X hflg++; X strcpy (homeph, optarg); X break; X case 'o': X if (getuid () == 0) { X oflg++; X strcpy (slop, optarg); X break; X } X fprintf (stderr, "%s: permission denied\n", X myname); X exit (1); X default: X usage (); X } X } X if (argc > optind) { X if (argc > optind + 1) X usage (); X X if (! (pw = getpwnam (argv[optind]))) { X fprintf (stderr, "%s: unknown user: %s\n", X myname, argv[optind]); X exit (1); X } X } else { X if (cp = getlogin ()) { X if (! (pw = getpwnam (cp))) { X fprintf (stderr, "%s: unknown user: %s\n", X myname, cp); X exit (1); X } X } else if (! (pw = getpwuid (getuid ()))) { X fprintf (stderr, "%s: who are you?\n", X myname); X exit (1); X } X } X if (! amroot && pw->pw_uid != getuid ()) { X fprintf (stderr, "%s: permission denied\n", X myname); X exit (1); X } X strcpy (user, pw->pw_name); X X pwent = *pw; X pwent.pw_name = strdup (pw->pw_name); X pwent.pw_passwd = strdup (pw->pw_passwd); X pwent.pw_dir = strdup (pw->pw_dir); X pwent.pw_shell = strdup (pw->pw_shell); X X /* X * Now get the full name. It is the first comma separated field X * in the GECOS field. X */ X X strcpy (buf, pw->pw_gecos); X cp = copy_field (buf, fflg ? (char *) 0:fullnm, slop); X X /* X * Now get the room number. It is the next comma separated field, X * if there is indeed one. X */ X X if (cp) X cp = copy_field (cp, rflg ? (char *) 0:roomno, slop); X X /* X * Now get the work phone number. It is the third field. X */ X X if (cp) X cp = copy_field (cp, wflg ? (char *) 0:workph, slop); X X /* X * Now get the home phone number. It is the fourth field. X */ X X if (cp) X cp = copy_field (cp, hflg ? (char *) 0:homeph, slop); X X /* X * Anything left over is "slop". X */ X X if (cp) { X if (slop[0]) X strcat (slop, ","); X X strcat (slop, cp); X } X X /* X * If none of the fields were changed from the command line, X * let the user interactively change them. X */ X X if (! fflg && ! rflg && ! wflg && ! hflg && ! oflg) { X printf ("Changing the user information for %s\n", user); X new_fields (); X } X X /* X * Check all of the fields for valid information X */ X X valid_field (fullnm, ":,="); X valid_field (roomno, ":,="); X valid_field (workph, ":,="); X valid_field (homeph, ":,="); X valid_field (slop, ":"); X X /* X * Build the new GECOS field by plastering all the pieces together, X * if they will fit ... X */ X X if (strlen (fullnm) + strlen (roomno) + strlen (workph) + X strlen (homeph) + strlen (slop) > 80) { X fprintf (stderr, "%s: fields too long\n", myname); X exit (1); X } X sprintf (tmp, "%s,%s,%s,%s", fullnm, roomno, workph, homeph); X if (slop[0]) { X strcat (tmp, ","); X strcat (tmp, slop); X } X pwent.pw_gecos = tmp; X 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 X#ifdef DBM X update_dbm (&pwent); X#endif X if (access (NPWDFILE, 0) == 0 && unlink (NPWDFILE) == -1) { X perror (NPWDFILE); X exit (1); 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 { X perror (NPWDFILE); X exit (1); 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 perror (NPWDFILE); X exit (1); 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) 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#ifndef NDEBUG X (void) unlink (".pwdlock"); X#else X (void) unlink (PWDLOCK); X#endif X exit (0); X /*NOTREACHED*/ X Xunlock: X if (lockfd >= 0) X (void) unlink (PWDLOCK); X X (void) unlink (NPWDFILE); X exit (1); X /*NOTREACHED*/ X} SHAR_EOF if test 10514 -ne "`wc -c < 'chfn.c'`" then echo shar: "error transmitting 'chfn.c'" '(should have been 10514 characters)' fi fi echo shar: "extracting 'chsh.c'" '(9052 characters)' if test -f 'chsh.c' then echo shar: "will not over-write existing file 'chsh.c'" else sed 's/^X//' << \SHAR_EOF > 'chsh.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#include "config.h" X X#ifdef DBM X#include X#endif X X#ifndef lint Xstatic char _sccsid[] = "@(#)chsh.c 2.2 12:54:39 10/22/90"; X#endif X Xchar *myname; Xint amroot; X Xchar user[BUFSIZ]; Xchar loginsh[BUFSIZ]; Xint sflg; X Xstruct passwd pwent; X Xextern int errno; X Xchar Usage[] = X"Usage: %s [ -s login_shell ] [ user_name ]\n"; X X/* X * usage - print command line syntax and exit X */ X Xvoid Xusage () X{ X fprintf (stderr, Usage, myname); X exit (1); X} X X/* X * valid_field - insure that a field contains all legal characters X * X * The supplied field is scanned for non-printing and other illegal X * characters. If any illegal characters are found, valid_field X * prints a message and exits. X */ X Xvoid Xvalid_field (field, illegal) Xchar *field; Xchar *illegal; X{ X char *cp; X X for (cp = field;*cp && isprint (*cp) && ! strchr (illegal, *cp);cp++) X ; X X if (*cp) { X fprintf (stderr, "%s: invalid field: %s\n", myname, field); X exit (1); X } X} X X/* X * change_field - change a single field if a new value is given. X * X * prompt the user with the name of the field being changed and the X * current value. X */ X Xvoid Xchange_field (buf, prompt) Xchar *buf; Xchar *prompt; X{ X char new[BUFSIZ]; X char *cp; X X printf ("\t%s [%s]: ", prompt, buf); X fgets (new, BUFSIZ, stdin); X X if (cp = strchr (new, '\n')) X *cp = '\0'; X else X return; X X if (new[0]) X strcpy (buf, new); X} X X/* X * new_fields - change the user's login shell information interactively X * X * prompt the user for the login shell and change it according to the X * response, or leave it alone if nothing was entered. X */ X Xnew_fields () X{ X printf ("Enter the new value, or press return for the default\n\n"); X X change_field (loginsh, "Login Shell"); X} X X/* X * check_shell - see if the user's login shell is listed in /etc/shells X * X * The /etc/shells file is read for valid names of login shells. If the X * /etc/shells file does not exist the user cannot set any shell unless X * they are root. X */ X Xcheck_shell (shell) Xchar *shell; X{ X char buf[BUFSIZ]; X char *cp; X int found = 0; X FILE *fp; X X if (amroot) X return 1; X X if ((fp = fopen ("/etc/shells", "r")) == (FILE *) 0) X return 0; X X while (fgets (buf, BUFSIZ, fp) && ! found) { X if (cp = strrchr (buf, '\n')) X *cp = '\0'; X X if (strcmp (buf, shell) == 0) X found = 1; X } X fclose (fp); X X return found; X} X X/* X * restricted_shell - return true if the named shell begins with 'r' or 'R' X * X * If the first letter of the filename is 'r' or 'R', the shell is X * considered to be restricted. X */ X Xint Xrestricted_shell (shell) Xchar *shell; X{ X char *cp; X X if (cp = strrchr (shell, '/')) X cp++; X else X cp = shell; X X return *cp == 'r' || *cp == 'R'; 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 extern int optind; X extern char *optarg; X void die (); X char *cp; X char *getlogin (); X int lockfd = -1; X int flag; X struct passwd *pw; X struct passwd *getpwuid (); X struct passwd *getpwnam (); X struct passwd *sgetpwent (); X FILE *npwd; X FILE *pwd; X char buf[BUFSIZ]; X char tmp[BUFSIZ]; X X amroot = getuid () == 0; X if (myname = strchr (argv[0], '/')) X myname++; X else X myname = argv[0]; X X while ((flag = getopt (argc, argv, "s:")) != EOF) { X switch (flag) { X case 's': X sflg++; X strcpy (loginsh, optarg); X break; X default: X usage (); X } X } X if (argc > optind) { X if (argc > optind + 1) X usage (); X X if (! (pw = getpwnam (argv[optind]))) { X fprintf (stderr, "%s: unknown user: %s\n", X myname, argv[optind]); X exit (1); X } X } else { X if (cp = getlogin ()) { X if (! (pw = getpwnam (cp))) { X fprintf (stderr, "%s: unknown user: %s\n", X myname, cp); X exit (1); X } X } else if (! (pw = getpwuid (getuid ()))) { X fprintf (stderr, "%s: who are you?\n", X myname); X exit (1); X } X } X if (! amroot && pw->pw_uid != getuid ()) { X fprintf (stderr, "%s: permission denied\n", X myname); X exit (1); X } X if (! amroot && restricted_shell (pw->pw_shell)) { X fprintf (stderr, "%s: permission denied\n", X myname); X exit (1); X } X strcpy (user, pw->pw_name); X X pwent = *pw; X pwent.pw_name = strdup (pw->pw_name); X pwent.pw_passwd = strdup (pw->pw_passwd); X pwent.pw_dir = strdup (pw->pw_dir); X pwent.pw_gecos = strdup (pw->pw_gecos); X X /* X * Now get the login shell. Either get it from the password X * file, or use the value from the command line. X */ X X if (! sflg) X strcpy (loginsh, pw->pw_shell); X X /* X * If the login shell was not set on the command line, X * let the user interactively change it. X */ X X if (! sflg) { X printf ("Changing the login shell for %s\n", user); X new_fields (); X } X X /* X * Check all of the fields for valid information X */ X X valid_field (loginsh, ":,="); X if (! check_shell (loginsh)) { X fprintf (stderr, "%s: %s is an invalid shell\n", X myname, loginsh); X exit (1); X } X pwent.pw_shell = loginsh; X 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 X#ifdef DBM X update_dbm (&pwent); X#endif X if (access (NPWDFILE, 0) == 0 && unlink (NPWDFILE) == -1) { X perror (NPWDFILE); X exit (1); 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 { X perror (NPWDFILE); X exit (1); 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 perror (NPWDFILE); X exit (1); 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); 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#ifndef NDEBUG X (void) unlink (".pwdlock"); X#else X (void) unlink (PWDLOCK); X#endif X exit (0); X /*NOTREACHED*/ X Xunlock: X if (lockfd >= 0) X (void) unlink (PWDLOCK); X X (void) unlink (NPWDFILE); X exit (1); X /*NOTREACHED*/ X} SHAR_EOF if test 9052 -ne "`wc -c < 'chsh.c'`" then echo shar: "error transmitting 'chsh.c'" '(should have been 9052 characters)' fi fi echo shar: "extracting 'smain.c'" '(6591 characters)' if test -f 'smain.c' then echo shar: "will not over-write existing file 'smain.c'" else sed 's/^X//' << \SHAR_EOF > 'smain.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#include X#else X#include X#include X#define strchr index X#define strrchr rindex X#endif X#include X#include "config.h" X#include "lastlog.h" X X#ifdef SHADOWPWD X#include "shadow.h" X#endif X X#ifndef lint Xstatic char _sccsid[] = "@(#)smain.c 2.7 10:20:06 11/9/90"; X#endif X X#ifndef MAXENV X#define MAXENV 64 X#endif X X#ifndef PATH X#define PATH ":/bin:/usr/bin" X#endif X X#ifndef SUPATH X#define SUPATH ":/bin:/usr/bin:/etc" X#endif X X#ifdef HUSHLOGIN Xchar hush[BUFSIZ]; Xint hushed; X#endif X Xchar name[BUFSIZ]; Xchar pass[BUFSIZ]; Xchar home[BUFSIZ]; Xchar prog[BUFSIZ]; Xchar mail[BUFSIZ]; Xchar oldname[BUFSIZ]; Xchar *newenvp[MAXENV]; Xint newenvc = 0; Xint maxenv = MAXENV; Xstruct passwd pwent; X X#ifdef TZ XFILE *tzfile; Xchar tzbuf[16] = TZ; X#endif X Xvoid addenv (); Xvoid entry (); Xvoid sulog (); Xvoid subsystem (); Xvoid setup (); Xvoid motd (); Xvoid mailcheck (); Xvoid shell (); Xvoid expire (); X Xextern char **environ; X Xint main (argc, argv, envp) Xint argc; Xchar **argv; Xchar **envp; X{ X void die (); X char *getenv (); X char *cp; X int doshell; X int fakelogin = 0; X int amroot; X struct passwd *pw; X struct passwd *getpwuid (); X#ifdef SHADOWPWD X struct spwd *spwd; X struct spwd *getspnam(); X#endif 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 argc--; argv++; /* shift out command name */ X X if (argc > 0 && argv[0][0] == '-' && argv[0][1] == '\0') { X fakelogin = 1; X argc--; argv++; /* shift ... */ X } X if (argc > 0 && argv[0][0] != '-') { X (void) strcpy (name, argv[0]); /* use this login id */ X argc--; argv++; /* shift ... */ X } X doshell = argc == 0; /* any arguments remaining? */ X X if (pw = getpwuid (getuid ())) /* need old user name */ X (void) strcpy (oldname, pw->pw_name); X else /* user ID MUST exist */ X goto failure; X X amroot = getuid () == 0; /* currently am super user */ X X if (! name[0]) /* use default user ID */ X (void) strcpy (name, "root"); X X entry (name, &pwent); /* get password file entry */ X if (pwent.pw_shell == (char *) 0 || pwent.pw_shell[0] == '\0') X pwent.pw_shell = "/bin/sh"; X X if (pwent.pw_name == (char *) 0) { /* unknown user */ X (void) fprintf (stderr, "Unknown id: %s\n", name); X exit (1); X } X#ifdef NOUSE X if (strcmp (pwent.pw_shell, NOUSE) == 0) X goto failure; X#endif X#ifdef NOLOGIN X if (strcmp (pwent.pw_shell, NOLOGIN) == 0) X if (! (pwent.pw_shell = getenv ("SHELL"))) X pwent.pw_shell = "/bin/sh"; X#endif 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 die (0); X X signal (SIGHUP, die); X signal (SIGINT, die); X signal (SIGQUIT, die); X signal (SIGTERM, die); X X#ifdef NOBLANK X if (! amroot && ! password ("Password:", pass)) X goto failure; X#else X if (! amroot && (pwent.pw_name == (char *) 0 || *pwent.pw_passwd) X && ! password ("Password:", pass)) X goto failure; X#endif X /* check encrypted passwords ... */ X if (! amroot && ! valid (pass, &pwent)) { Xfailure: sulog (0); /* log failed attempt */ X puts ("Sorry."); X exit (1); X } X signal (SIGHUP, SIG_DFL); X signal (SIGINT, SIG_DFL); X signal (SIGQUIT, SIG_DFL); X signal (SIGTERM, SIG_DFL); X X#ifdef SHADOWPWD X /* X * Need to get expiration information before changing UID X */ X X setspent (); X spwd = getspnam (pwent.pw_name); X endspent (); X#endif X#ifdef AGING X X /* X * Check to see if the account is expired. root gets to X * ignore any expired accounts, but normal users can't become X * a user with an expired password. X */ X X if (! amroot && X pwent.pw_age && pwent.pw_age[0]) { 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 expire (pwent.pw_name, (strlen (pwent.pw_age) == 4 ? X a64l (pwent.pw_age + 2):0L) * 7, X c64i (pwent.pw_age[1]), c64i (pwent.pw_age[0])); X } X#endif X#ifdef SULOG X sulog (1); /* save SU information */ X#endif X if (pwent.pw_uid == 0) X addenv (SUPATH); X else X addenv (PATH); X 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 if (doshell && pwent.pw_shell[0] == '*') /* subsystem root required */ X subsystem (); /* figure out what to execute */ X X if (fakelogin) X setup (&pwent); /* set UID, GID, HOME, etc ... */ X else { X if (setgid (pwent.pw_gid) || setuid (pwent.pw_uid)) { X perror ("Can't set ID"); X exit (1); X } X } X if (! doshell) { /* execute arguments as command */ X if (cp = getenv ("SHELL")) X pwent.pw_shell = cp; X argv[-1] = pwent.pw_shell; X (void) execv (pwent.pw_shell, &argv[-1]); X (void) fprintf (stderr, "No shell\n"); X exit (1); X } X if (fakelogin) { 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 MAILCHECK X mailcheck (); /* report on the status of mail */ X#endif X shell (pwent.pw_shell); /* exec the shell finally. */ X } else { X if (cp = strrchr (pwent.pw_shell, '/')) X cp++; X else X cp = pwent.pw_shell; X X execl (pwent.pw_shell, cp, (char *) 0); X perror (pwent.pw_shell); X exit (1); X } 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 exit (killed); X} SHAR_EOF if test 6591 -ne "`wc -c < 'smain.c'`" then echo shar: "error transmitting 'smain.c'" '(should have been 6591 characters)' fi fi echo shar: "extracting 'faillog.c'" '(4833 characters)' if test -f 'faillog.c' then echo shar: "will not over-write existing file 'faillog.c'" else sed 's/^X//' << \SHAR_EOF > 'faillog.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#include X#else X#include X#define strchr index X#define strrchr rindex X#endif X#include "config.h" X#include "faillog.h" X X#ifndef lint Xstatic char _sccsid[] = "@(#)faillog.c 2.2 19:23:44 7/29/90"; X#endif X XFILE *fail; /* failure file stream */ Xoff_t user; /* one single user, specified on command line */ Xint days; /* number of days to consider for print command */ Xtime_t seconds; /* that number of days in seconds */ Xint max; /* maximum failure count for fail_max */ X Xint mflg; /* set fail_max for a given user */ Xint rflg; /* reset fail_cnt for user or all user's */ Xint uflg; /* set if user is a valid user id */ Xint tflg; /* print is restricted to most recent days */ Xstruct faillog faillog; /* scratch structure to play with ... */ Xstruct stat statbuf; /* fstat buffer for file size */ X Xextern int optind; Xextern char *optarg; Xextern char *asctime (); Xextern struct passwd *getpwuid (); Xextern struct passwd *getpwnam (); Xextern struct passwd *getpwent (); Xextern struct tm *localtime (); X X#define DAY (24L*3600L) X#define NOW (time ((time_t *) 0)) X Xmain (argc, argv) Xint argc; Xchar **argv; X{ X char *mode; X int uid = 0; X int c; X struct passwd *pwent; X X if (getuid () == 0) /* only root can update anything */ X mode = "r+"; X else /* all others can only look */ X mode = "r"; X X if ((fail = fopen (FAILFILE, mode)) == (FILE *) 0) { X perror (FAILFILE); X exit (1); X } X while ((c = getopt (argc, argv, "m:pru:t:")) != EOF) { X switch (c) { X case 'm': X max = atoi (optarg); X setmax (); X break; X case 'p': X print (); X break; X case 'r': X reset (); X break; X case 'u': X pwent = getpwnam (optarg); X if (! pwent) { X fprintf (stderr, "Unknown User: %s\n", optarg); X exit (1); X } X uflg++; X user = pwent->pw_uid; X break; X case 't': X days = atoi (optarg); X seconds = days * DAY; X tflg++; X break; X } X } X fclose (fail); X exit (0); X} X Xprint () X{ X int uid; X off_t offset; X X if (uflg) { X offset = user * sizeof faillog; X fstat (fileno (fail), &statbuf); X if (offset >= statbuf.st_size) X return; X X fseek (fail, (off_t) user * sizeof faillog, 0); X if (fread ((char *) &faillog, sizeof faillog, 1, fail) == 1) X print_one (&faillog, user); X else X perror (FAILFILE); X } else { X for (uid = 0; X fread ((char *) &faillog, sizeof faillog, 1, fail) == 1; X uid++) { X X if (faillog.fail_cnt == 0) X continue; X X if (tflg && NOW - faillog.fail_time > seconds) X continue; X X print_one (&faillog, uid); X } X } X} X Xprint_one (faillog, uid) Xstruct faillog *faillog; X{ X static int once; X char *cp; X struct tm *tm; X struct passwd *pwent; X X if (! once) { X printf ("Username Failures Maximum Latest\n"); X once++; X } X pwent = getpwuid (uid); X tm = localtime (&faillog->fail_time); X cp = asctime (tm); X cp[24] = '\0'; X X if (pwent) { X printf ("%-16s %4d %4d", X pwent->pw_name, faillog->fail_cnt, faillog->fail_max); X if (faillog->fail_time) X printf (" %s on %s\n", cp, faillog->fail_line); X else X putchar ('\n'); X } X} X Xreset () X{ X int uid = 0; X X if (uflg) X reset_one (user); X else X for (uid = 0;reset_one (uid);uid++) X ; X} X Xreset_one (uid) Xint uid; X{ X off_t offset; X X offset = uid * sizeof faillog; X fstat (fileno (fail), &statbuf); X if (offset >= statbuf.st_size) X return (0); X X if (fseek (fail, offset, 0) != 0) { X perror (FAILFILE); X return (0); X } X if (fread ((char *) &faillog, sizeof faillog, 1, fail) != 1) { X if (! feof (fail)) X perror (FAILFILE); X X return (0); X } X if (faillog.fail_cnt == 0) X return (1); /* don't fill in no holes ... */ X X faillog.fail_cnt = 0; X X if (fseek (fail, offset, 0) == 0 X && fwrite ((char *) &faillog, sizeof faillog, 1, fail) == 1) { X fflush (fail); X return (1); X } else { X perror (FAILFILE); X } X return (0); X} X Xsetmax () X{ X int uid = 0; X struct passwd *pwent; X X if (uflg) { X setmax_one (user); X } else { X setpwent (); X while (pwent = getpwent ()) X setmax_one (pwent->pw_uid); X } X} X Xsetmax_one (uid) Xint uid; X{ X off_t offset; X X offset = uid * sizeof faillog; X X if (fseek (fail, offset, 0) != 0) { X perror (FAILFILE); X return; X } X if (fread ((char *) &faillog, sizeof faillog, 1, fail) != 1) { X if (! feof (fail)) X perror (FAILFILE); X } else { X#ifndef BSD X memset ((char *) &faillog, '\0', sizeof faillog); X#else X bzero ((char *) &faillog, sizeof faillog); X#endif X } X faillog.fail_max = max; X X if (fseek (fail, offset, 0) == 0 X && fwrite ((char *) &faillog, sizeof faillog, 1, fail) == 1) X fflush (fail); X else X perror (FAILFILE); X} SHAR_EOF if test 4833 -ne "`wc -c < 'faillog.c'`" then echo shar: "error transmitting 'faillog.c'" '(should have been 4833 characters)' fi fi echo shar: "extracting 'pwconv.c'" '(3767 characters)' if test -f 'pwconv.c' then echo shar: "will not over-write existing file 'pwconv.c'" else sed 's/^X//' << \SHAR_EOF > 'pwconv.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 * pwconv - convert and update shadow password files X * X * Pwconv copies the old password file information to a new shadow X * password file, merging entries from an optional existing shadow X * file. X * X * The new password file is left in npasswd, the new shadow file is X * left in nshadow. Existing shadow entries are copied as is. X * New entries are created with passwords which expire in MAXDAYS days, X * with a last changed date of today, unless password aging X * information was already present. Likewise, the minimum number of X * days before which the password may be changed is controlled by X * MINDAYS. Entries with blank passwordsare not copied to the shadow X * file at all. X */ X X#include X#include X#include X#include X#ifndef BSD X#include X#else X#define strchr index X#define strrchr rindex X#include X#endif X#include "config.h" X#include "shadow.h" X X#ifndef lint Xstatic char _sccsid[] = "@(#)pwconv.c 2.6 08:01:45 11/9/90"; X#endif X Xchar buf[BUFSIZ]; X Xlong time (); Xlong a64l (); X Xint main () X{ X long today; X struct passwd *pw; X struct passwd *sgetpwent (); X FILE *pwd; X FILE *npwd; X FILE *shadow; X struct spwd *spwd; X struct spwd tspwd; X int fd; X char *cp; X X if (! (pwd = fopen (PWDFILE, "r"))) { X perror (PWDFILE); X exit (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 exit (1); X } X unlink ("nshadow"); X if ((fd = open ("nshadow", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 || X ! (shadow = fdopen (fd, "w"))) { X perror ("nshadow"); X (void) unlink ("npasswd"); X (void) unlink ("nshadow"); X exit (1); X } X X (void) time (&today); X today /= (24L * 60L * 60L); X X while (fgets (buf, BUFSIZ, pwd) == buf) { X if (cp = strrchr (buf, '\n')) X *cp = '\0'; 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 if (pw->pw_passwd[0] == '\0') { /* no password, skip */ X (void) fprintf (npwd, "%s\n", buf); X continue; X } X setspent (); /* rewind old shadow file */ X X if (spwd = getspnam (pw->pw_name)) { X if (putspent (spwd, shadow)) { /* copy old entry */ X perror ("nshadow"); X goto error; X } X } else { /* need a new entry. */ X tspwd.sp_namp = pw->pw_name; X tspwd.sp_pwdp = pw->pw_passwd; X pw->pw_passwd = "x"; X X if (pw->pw_age) { /* copy old password age stuff */ X tspwd.sp_min = c64i (pw->pw_age[1]); X tspwd.sp_max = c64i (pw->pw_age[0]); X if (strlen (pw->pw_age) == 4) X tspwd.sp_lstchg = a64l (&pw->pw_age[2]); X else X tspwd.sp_lstchg = 0L; X X /* X * Convert weeks to days X */ X X tspwd.sp_min *= 7; X tspwd.sp_max *= 7; X tspwd.sp_lstchg *= 7; X } else { /* fake up new password age stuff */ X tspwd.sp_max = MAXDAYS; X tspwd.sp_min = MINDAYS; X tspwd.sp_lstchg = today; X } X if (putspent (&tspwd, shadow)) { /* output entry */ X perror ("nshadow"); X goto error; X } X } X (void) fprintf (npwd, "%s:%s:%d:%d:%s:%s:", X pw->pw_name, pw->pw_passwd, X pw->pw_uid, pw->pw_gid, X pw->pw_gecos, pw->pw_dir); X X if (fprintf (npwd, "%s\n", X pw->pw_shell ? pw->pw_shell:"") == EOF) { X perror ("npasswd"); X goto error; X } X } X endspent (); X X if (ferror (npwd) || ferror (shadow)) { X perror ("pwconv"); Xerror: X (void) unlink ("npasswd"); X (void) unlink ("nshadow"); X exit (1); X } X (void) fclose (pwd); X (void) fclose (npwd); X (void) fclose (shadow); X X exit (0); X} SHAR_EOF if test 3767 -ne "`wc -c < 'pwconv.c'`" then echo shar: "error transmitting 'pwconv.c'" '(should have been 3767 characters)' fi fi echo shar: "extracting 'failure.c'" '(2948 characters)' if test -f 'failure.c' then echo shar: "will not over-write existing file 'failure.c'" else sed 's/^X//' << \SHAR_EOF > 'failure.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 "faillog.h" X#include "config.h" X X#ifdef FTMP X#include X#endif X X#ifndef lint Xstatic char _sccsid[] = "@(#)failure.c 2.3 19:23:48 7/29/90"; X#endif X X#ifdef FAILLOG X X#define DAY (24L*3600L) X#define YEAR (365L*DAY) X#define NOW (time ((time_t *) 0)) X Xextern struct tm *localtime (); Xextern char *asctime (); Xextern void failprint (); X X/* X * failure - make failure entry X */ X Xvoid Xfailure (uid, tty, faillog) Xint uid; Xchar *tty; Xstruct faillog *faillog; X{ X int fd; X X if ((fd = open (FAILFILE, O_RDWR)) < 0) X return; X X lseek (fd, (off_t) (sizeof *faillog) * uid, 0); X if (read (fd, (char *) faillog, sizeof *faillog) X != sizeof *faillog) X#ifndef BSD X memset ((void *) faillog, '\0', sizeof *faillog); X#else X bzero ((char *) faillog, sizeof *faillog); X#endif X X if (faillog->fail_max == 0 || faillog->fail_cnt < faillog->fail_max) X faillog->fail_cnt++; X X strncpy (faillog->fail_line, tty, sizeof faillog->fail_line); X faillog->fail_time = time ((time_t *) 0); X X lseek (fd, (off_t) (sizeof *faillog) * uid, 0); X write (fd, (char *) faillog, sizeof *faillog); X close (fd); X} X X/* X * failcheck - check for failures > allowable X * X * failcheck() is called AFTER the password has been validated. X */ X Xint Xfailcheck (uid, faillog, failed) Xint uid; Xstruct faillog *faillog; X{ X int fd; X int okay = 1; X struct faillog fail; X X if ((fd = open (FAILFILE, O_RDWR)) < 0) X return (1); X X lseek (fd, (off_t) (sizeof *faillog) * uid, 0); X if (read (fd, (char *) faillog, sizeof *faillog) == sizeof *faillog) { X if (faillog->fail_max != 0 X && faillog->fail_cnt >= faillog->fail_max) X okay = 0; X } X if (!failed && okay) { X fail = *faillog; X fail.fail_cnt = 0; X X lseek (fd, (off_t) sizeof fail * uid, 0); X write (fd, (char *) &fail, sizeof fail); X } X close (fd); X X return (okay); X} X X/* X * failprint - print line of failure information X */ X Xvoid Xfailprint (uid, fail) Xstruct faillog *fail; X{ X int fd; X struct tm *tp; X char *lasttime; X X if (fail->fail_cnt == 0) X return; X X tp = localtime (&fail->fail_time); X lasttime = asctime (tp); X lasttime[24] = '\0'; X X if (NOW - fail->fail_time < YEAR) X lasttime[19] = '\0'; X if (NOW - fail->fail_time < DAY) X lasttime = lasttime + 11; X X if (*lasttime == ' ') X lasttime++; X X printf ("%d %s since last login. Last was %s on %s.\n", X fail->fail_cnt, fail->fail_cnt > 1 ? "failures":"failure", X lasttime, fail->fail_line); X} X#endif X X#ifdef FTMP X Xvoid Xfailtmp (failent) Xstruct utmp *failent; X{ X int fd; X X if ((fd = open (FTMP, O_WRONLY|O_APPEND)) == -1) X return; X X write (fd, (char *) failent, sizeof *failent); X close (fd); X} X#endif SHAR_EOF if test 2948 -ne "`wc -c < 'failure.c'`" then echo shar: "error transmitting 'failure.c'" '(should have been 2948 characters)' fi fi echo shar: "extracting 'utmp.c'" '(1596 characters)' if test -f 'utmp.c' then echo shar: "will not over-write existing file 'utmp.c'" else sed 's/^X//' << \SHAR_EOF > 'utmp.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 X#include "config.h" X X#ifndef lint Xstatic char sccsid[] = "@(#)utmp.c 2.3 19:24:26 7/29/90"; X#endif X Xextern struct utmp utent; Xextern char name[]; X Xstruct utmp *getutent (); Xvoid setutent (); Xvoid endutent (); Xvoid pututline (); Xtime_t time (); X Xvoid checkutmp () X{ X struct utmp *ut; X#ifndef NDEBUG X int pid = getppid (); X#else X int pid = getpid (); X#endif X setutent (); X X while (ut = getutent ()) X if (ut->ut_pid == pid) X break; X X if (ut) X utent = *ut; X X endutent (); X X if (ut && utent.ut_pid == pid) X return; X X puts ("No utmp entry. You must exec \"login\" from the lowest level \"sh\""); X exit (1); X} X Xvoid setutmp () X{ X FILE *wtmp; X char tty[sizeof utent.ut_line + 1]; X char *line; X X setutent (); X X (void) strncpy (utent.ut_user, name, sizeof utent.ut_user); X X utent.ut_type = USER_PROCESS; X X if (line = strrchr (utent.ut_line, '/')) { X (void) strcpy (tty, line + 1); X#ifndef BSD X (void) memset (utent.ut_line, '\0', sizeof utent.ut_line); X#else X bzero (utent.ut_line, sizeof utent.ut_line); X#endif X (void) strcpy (utent.ut_line, tty); X } X (void) time (&utent.ut_time); X X pututline (&utent); X endutent (); X X if ((wtmp = fopen (WTMP_FILE, "a+"))) { X fwrite (&utent, sizeof utent, 1, wtmp); X fclose (wtmp); X } X} SHAR_EOF if test 1596 -ne "`wc -c < 'utmp.c'`" then echo shar: "error transmitting 'utmp.c'" '(should have been 1596 characters)' fi fi echo shar: "extracting 'shadow.c'" '(2147 characters)' if test -f 'shadow.c' then echo shar: "will not over-write existing file 'shadow.c'" else sed 's/^X//' << \SHAR_EOF > 'shadow.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 "shadow.h" 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[] = "@(#)shadow.c 2.6.1.1 08:13:12 11/9/90"; X#endif X Xstatic FILE *shadow; X#define FIELDS 5 X Xvoid setspent () X{ X if (shadow) X rewind (shadow); X else X shadow = fopen (SHADOW, "r"); X} X Xvoid endspent () X{ X if (shadow) X (void) fclose (shadow); X X shadow = (FILE *) 0; X} X Xstruct spwd * Xsgetspent (string) Xchar *string; X{ X static char buf[BUFSIZ]; X static struct spwd spwd; X char *fields[FIELDS]; X char *cp; X char *cpp; X int atoi (); X long atol (); X int i; X X strncpy (buf, string, BUFSIZ-1); X buf[BUFSIZ-1] = '\0'; X X if (cp = strrchr (buf, '\n')) X *cp = '\0'; X X for (cp = buf, i = 0;*cp && i < FIELDS;i++) { X fields[i] = cp; X while (*cp && *cp != ':') X cp++; X X if (*cp) X *cp++ = '\0'; X } X if (*cp || i != FIELDS) X return 0; X X spwd.sp_namp = fields[0]; X spwd.sp_pwdp = fields[1]; X X if ((spwd.sp_lstchg = strtol (fields[2], &cpp, 10)) == 0 && *cpp) X return 0; X X if ((spwd.sp_min = strtol (fields[3], &cpp, 10)) == 0 && *cpp) X return 0; X X if ((spwd.sp_max = strtol (fields[4], &cpp, 10)) == 0 && *cpp) X return 0; X X return (&spwd); X} X Xstruct spwd *fgetspent (fp) XFILE *fp; X{ X char buf[BUFSIZ]; X X if (! fp) X return (0); X X if (fgets (buf, BUFSIZ, fp) == (char *) 0) X return (0); X X return sgetspent (buf); X} X Xstruct spwd *getspent () X{ X if (! shadow) X setspent (); X X return (fgetspent (shadow)); X} X Xstruct spwd *getspnam (name) Xchar *name; X{ X struct spwd *spwd; X X setspent (); X X while ((spwd = getspent ()) != (struct spwd *) 0) { X if (strcmp (name, spwd->sp_namp) == 0) X return (spwd); X } X return (0); X} X Xint putspent (spwd, fp) Xstruct spwd *spwd; XFILE *fp; X{ X if (! fp) X return -1; X X fprintf (fp, "%s:%s:%ld:%ld:%ld\n", X spwd->sp_namp, spwd->sp_pwdp, X spwd->sp_lstchg, spwd->sp_min, spwd->sp_max); X X if (ferror (fp)) X return -1; X else X return 0; X} SHAR_EOF if test 2147 -ne "`wc -c < 'shadow.c'`" then echo shar: "error transmitting 'shadow.c'" '(should have been 2147 characters)' fi fi echo shar: "extracting 'log.c'" '(1353 characters)' if test -f 'log.c' then echo shar: "will not over-write existing file 'log.c'" else sed 's/^X//' << \SHAR_EOF > 'log.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#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[] = "@(#)log.c 2.2 19:23:53 7/29/90"; X#endif X X#ifdef LASTLOG X X#include "lastlog.h" X Xextern struct utmp utent; Xextern struct passwd pwent; Xextern struct lastlog lastlog; Xextern char **environ; X Xlong lseek (); Xtime_t time (); X Xvoid log () X{ X int fd; X off_t offset; X struct lastlog newlog; X X if ((fd = open ("/usr/adm/lastlog", O_RDWR)) == -1) X return; X X offset = pwent.pw_uid * sizeof lastlog; X X if (lseek (fd, offset, 0) != offset) { X (void) close (fd); X return; X } X if (read (fd, (char *) &lastlog, sizeof lastlog) != sizeof lastlog) X#ifndef BSD X memset ((char *) &lastlog, sizeof lastlog, 0); X#else X bzero ((char *) &lastlog, sizeof lastlog); X#endif X newlog = lastlog; X X (void) time (&newlog.ll_time); X (void) strncpy (newlog.ll_line, utent.ut_line, sizeof newlog.ll_line); X (void) lseek (fd, offset, 0); X (void) write (fd, (char *) &newlog, sizeof newlog); X (void) close (fd); X} X#endif SHAR_EOF if test 1353 -ne "`wc -c < 'log.c'`" then echo shar: "error transmitting 'log.c'" '(should have been 1353 characters)' fi fi echo shar: "extracting 'shadow.h'" '(879 characters)' if test -f 'shadow.h' then echo shar: "will not over-write existing file 'shadow.h'" else sed 's/^X//' << \SHAR_EOF > 'shadow.h' X/* X * Copyright 1988, 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 * This information is not derived from AT&T licensed sources. Posted X * to the USENET 11/88. X * X * @(#)shadow.h 2.3 16:34:15 11/2/90 X */ X X/* X * Shadow password security file structure. X */ X Xstruct spwd { X char *sp_namp; /* login name */ X char *sp_pwdp; /* encrypted password */ X long sp_lstchg; /* date of last change */ X long sp_max; /* maximum number of days between changes */ X long sp_min; /* minimum number of days between changes */ X}; X X/* X * Shadow password security file functions. X */ X Xstruct spwd *getspent (); Xstruct spwd *getspnam (); Xstruct spwd *sgetspent (); Xvoid setspent (); Xvoid endspent (); Xstruct spwd *fgetspent (); Xint putspent (); X X#define SHADOW "/etc/shadow" SHAR_EOF if test 879 -ne "`wc -c < 'shadow.h'`" then echo shar: "error transmitting 'shadow.h'" '(should have been 879 characters)' fi fi echo shar: "extracting 'faillog.h'" '(715 characters)' if test -f 'faillog.h' then echo shar: "will not over-write existing file 'faillog.h'" else sed 's/^X//' << \SHAR_EOF > 'faillog.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 * faillog.h - login failure logging file format X * X * @(#)faillog.h 2.2 19:23:46 7/29/90 X * X * The login failure file is maintained by login(1) and fail(1L) X * Each record in the file represents a separate UID and the file X * is indexed in that fashion. X */ X X#define FAILFILE "/usr/adm/faillog" X Xstruct faillog { X short fail_cnt; /* failures since last success */ X short fail_max; /* failures before turning account off */ X char fail_line[12]; /* last failure occured here */ X time_t fail_time; /* last failure occured then */ X}; SHAR_EOF if test 715 -ne "`wc -c < 'faillog.h'`" then echo shar: "error transmitting 'faillog.h'" '(should have been 715 characters)' fi fi exit 0 # End of shell archive