#! /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: # gpmain.c # chage.c # pwent.c # valid.c # setup.c # entry.c # ttytype.c # port.h # grent.c # motd.c # dialup.h # This archive created: Wed Dec 12 12:37:13 1990 # By: John F Haugh II (River Parishes Programming, Austin TX) export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'gpmain.c'" '(9373 characters)' if test -f 'gpmain.c' then echo shar: "will not over-write existing file 'gpmain.c'" else sed 's/^X//' << \SHAR_EOF > 'gpmain.c' X/* X * Copyright 1990, John F. Haugh II X * All rights reserved. X * X * Non-commercial distribution permitted. You must provide this source X * code in any distribution. This notice must remain intact. X */ X X#includeX#include X#include X#include X#include X#include X#include X#ifndef BSD X#include X#ifdef SYS3 X#include X#endif X#include X#ifndef SYS3 X#include X#endif X#else X#include X#include X#define strchr index X#define strrchr rindex X#endif X#include "config.h" X X#ifndef PASSLENGTH X#define PASSLENGTH 5 X#endif X X#ifndef lint Xstatic char _sccsid[] = "@(#)gpmain.c 2.1 00:44:03 11/28/90"; X#endif X Xchar name[BUFSIZ]; Xchar pass[BUFSIZ]; Xchar pass2[BUFSIZ]; X Xstruct group grent; X Xchar *myname; Xchar *user; Xchar *group; Xint aflg; Xint dflg; Xint rflg; 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 X/* X * usage - display usage message X */ X Xvoid Xusage () X{ X fprintf (stderr, "usage: %s [ -r ] group\n", myname); X fprintf (stderr, " %s [ -a user ] group\n", myname); X fprintf (stderr, " %s [ -d user ] group\n", myname); X exit (1); X} X Xchar ** Xadd_list (list, member) Xchar **list; Xchar *member; X{ X int i; X int found = 0; X char **tmp; X X for (i = 0;!found && list[i] != (char *) 0;i++) X if (strcmp (list[i], member) == 0) X found++; X X tmp = (char **) malloc ((i + 2) * sizeof member); X X for (i = 0;list[i] != (char *) 0;i++) X tmp[i] = list[i]; X X if (! found) { X tmp[i++] = strdup (member); X tmp[i] = (char *) 0; X } X return tmp; X} X Xchar ** Xdel_list (list, member) Xchar **list; Xchar *member; X{ X int i, j; X char **tmp; X X for (i = 0;list[i] != (char *) 0;i++) X ; X X tmp = (char **) malloc ((i + 1) * sizeof member); X X for (j = i = 0;list[i] != (char *) 0;i++) X if (strcmp (list[i], member) == 0) X tmp[j++] = list[i]; X X tmp[j] = (char *) 0; X X return tmp; X} X Xint Xmain (argc, argv) Xint argc; Xchar **argv; X{ X extern int optind; X extern char *optarg; X int flag; X int i; X void die (); X char *cp; X char *getlogin (); X int amroot; X int lockfd = -1; X int retries; X int ruid = getuid(); X int suid = geteuid(); X long salttime; X struct group *gr; X struct group *getgrnam (); X struct group *sgetgrent (); X struct passwd *pw; X struct passwd *getpwuid (); X struct passwd *getpwnam (); X FILE *ngrp; X FILE *ogrp; X char buf[BUFSIZ]; X char tmp[BUFSIZ]; X X amroot = getuid () == 0; X setuid (geteuid ()); X myname = argv[0]; X X if (! isatty (0) || ! isatty (1)) X exit (1); X X die (0); /* save tty modes */ X X signal (SIGHUP, die); X signal (SIGINT, die); X signal (SIGQUIT, die); X signal (SIGTERM, die); X X while ((flag = getopt (argc, argv, "a:d:gr")) != EOF) { X switch (flag) { X case 'a': /* add a user */ X aflg++; X user = optarg; X break; X case 'd': X dflg++; X user = optarg; X break; X case 'g': /* no-op from normal password */ X break; X case 'r': /* remove group password */ X rflg++; X break; X default: X usage (); X } X } X if (aflg + dflg + rflg > 1) X usage (); X X if ((cp = getlogin ()) && (pw = getpwnam (cp)) && pw->pw_uid == ruid) { X /* need user name */ X (void) strcpy (name, cp); X } else if (pw = getpwuid (ruid)) /* get it from password file */ X strcpy (name, pw->pw_name); X else { /* can't find user name! */ X fprintf (stderr, "Who are you?\n"); X exit (1); X } X if (! (pw = getpwnam (name))) X goto failure; /* can't get my name ... */ X X if (! (group = argv[optind])) X usage (); X X if (! (gr = getgrnam (group))) { X fprintf (stderr, "unknown group: %s\n", group); X exit (1); X } X grent = *gr; X grent.gr_name = strdup (gr->gr_name); X grent.gr_passwd = strdup (gr->gr_passwd); X X for (i = 0;gr->gr_mem[i];i++) X ; X grent.gr_mem = (char **) malloc ((i + 1) * sizeof (char *)); X for (i = 0;gr->gr_mem[i];i++) X grent.gr_mem[i] = strdup (gr->gr_mem[i]); X grent.gr_mem[i] = (char *) 0; X X if (! amroot) { X if (gr->gr_mem[0] == (char *) 0) X goto failure; X X if (strcmp (gr->gr_mem[0], name) != 0) X goto failure; X } X if (rflg) { X if (! amroot && (gr->gr_mem[0] && X strcmp (name, gr->gr_mem[0]) != 0)) X goto failure; X X gr->gr_passwd = ""; X goto output; X } X if (aflg) { X if (! amroot && (gr->gr_mem[0] == (char *) 0 || X strcmp (name, gr->gr_mem[0]) != 0)) X goto failure; X X printf ("Adding user %s to group %s\n", user, group); X grent.gr_mem = add_list (gr->gr_mem, user); X goto output; X } X if (dflg) { X if (! amroot && (gr->gr_mem[0] == (char *) 0 || X strcmp (name, gr->gr_mem[0]) != 0)) X goto failure; X X printf ("Removing user %s from group %s\n", user, group); X grent.gr_mem = del_list (gr->gr_mem, user); X goto output; X } X printf ("Changing password for group %s\n", group); X X printf ("Enter new password (minimum of %d characters)\n", PASSLENGTH); X retries = RETRIES; Xretry: X if (! password ("New Password:", pass)) X exit (1); X 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 (void) time (&salttime); X salttime = ((salttime & 07777) ^ ((salttime >> 12) & 07777)) & 07777; X grent.gr_passwd = tmp; X strcpy (grent.gr_passwd, crypt (pass, l64a (salttime))); X#ifdef DOUBLESIZE X if (strlen (pass) > 8) { X strcpy (grent.gr_passwd + 13, X crypt (pass + 8, l64a (salttime)) + 2); X } X#endif Xoutput: 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 (".grplock", O_RDONLY|O_CREAT|O_EXCL), 0444) == -1) X#else X for (retries = 0;retries < 30;retries++) { X if ((lockfd = open (GRPLOCK, O_RDONLY|O_CREAT|O_EXCL, 0)) != -1) X break; X X sleep (1); X } X if (lockfd == -1) X#endif /* NDEBUG */ X { X puts ("Can't get lock"); X exit (1); X } X umask (077); /* close security holes to come ... */ X if (access (NGRPFILE, 0) == 0 && unlink (NGRPFILE) == -1) X goto failure; X X#ifndef NDEBUG X if ((ngrp = fopen ("ngroup", "w")) == (FILE *) 0) X#else X umask (077); /* no permissions for non-roots */ X X if ((ngrp = fopen (NGRPFILE, "w")) == (FILE *) 0) X#endif /* NDEBUG */ X goto failure; X X#ifndef NDEBUG X chmod (NGRPFILE, 0444); /* lets have some security here ... */ X chown (NGRPFILE, 0, 0); /* ... and keep the bad guy away */ X#endif /* NDEBUG */ X if ((ogrp = fopen (GRPFILE, "r")) == (FILE *) 0) X goto failure; X X while (fgets (buf, sizeof buf, ogrp) != (char *) 0) { X if (buf[0] == '#' || ! (gr = sgetgrent (buf))) { X fputs (buf, ngrp); X } else if (strcmp (gr->gr_name, group) != 0) X fputs (buf, ngrp); X else X break; X } X if (gr) { X (void) fprintf (ngrp, "%s:%s:%d:", X grent.gr_name, grent.gr_passwd ? grent.gr_passwd:"x", X grent.gr_gid); X X for (i = 0;grent.gr_mem[i] != (char *) 0;i++) { X if (i) X fputc (',', ngrp); X fputs (grent.gr_mem[i], ngrp); X } X fputc ('\n', ngrp); X } X while (fgets (buf, BUFSIZ, ogrp) != (char *) 0) X fputs (buf, ngrp); X X if (ferror (ngrp)) { X perror (NGRPFILE); X if (unlink (NGRPFILE) || unlink (GRPLOCK)) X fputs ("Help!\n", stderr); X X exit (1); X } X fflush (ngrp); X fclose (ngrp); X#ifdef NDEBUG X chmod (NGRPFILE, 0644); X if (unlink (OGRPFILE) == -1) { X if (errno != ENOENT) { X puts ("Can't unlink backup file"); X goto unlock; X } X } X if (link (GRPFILE, OGRPFILE) || unlink (GRPFILE)) { X puts ("Can't save backup file"); X goto unlock; X } X#ifndef BSD X if (link (NGRPFILE, GRPFILE) || unlink (NGRPFILE)) X#else X if (rename (NGRPFILE, GRPFILE)) X#endif X { X puts ("Can't rename new file"); X goto unlock; X } X#endif /* NDEBUG */ X#ifndef NDEBUG X (void) unlink (".grplock"); X#else X (void) unlink (GRPLOCK); X#endif X exit (0); X /*NOTREACHED*/ X Xfailure: X puts ("Permission denied."); Xunlock: X if (lockfd >= 0) X (void) unlink (GRPLOCK); X X (void) unlink (NGRPFILE); 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 9373 -ne "`wc -c < 'gpmain.c'`" then echo shar: "error transmitting 'gpmain.c'" '(should have been 9373 characters)' fi fi echo shar: "extracting 'chage.c'" '(10464 characters)' if test -f 'chage.c' then echo shar: "will not over-write existing file 'chage.c'" else sed 's/^X//' << \SHAR_EOF > 'chage.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#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 SHADOWPWD X#include "shadow.h" X#endif X#ifdef DBM X#include X#endif X X#ifndef lint Xstatic char _sccsid[] = "@(#)chage.c 2.3 08:59:07 11/5/90"; X#endif X Xchar *myname; X Xtime_t today; Xchar name[BUFSIZ]; Xchar newage[10]; Xint lflg; Xint mflg; Xint Mflg; Xint dflg; X Xstruct passwd pwent; X#ifdef SHADOWPWD Xstruct spwd spwd; X#endif Xint mindays; Xint maxdays; Xlong lastday; X Xextern int errno; X Xchar Usage[] = X"Usage: %s [ -l ] [ -m min_days ] [ -M max_days ] [ -w week | -d day ] user\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 * 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 (val, prompt) Xint *val; Xchar *prompt; X{ X int newval; X char new[BUFSIZ]; X char *cp; X X while (1) { X if (*val == -1) X printf ("\t%s []: ", prompt); X else X printf ("\t%s [%d]: ", prompt, *val); X X fgets (new, BUFSIZ, stdin); X X if (cp = strchr (new, '\n')) X *cp = '\0'; X else X return; X X if (new[0] == '\0') X return; X X newval = strtol (new, &cp, 10); X if (cp != new && newval >= -1 && newval <= 10000) { X *val = newval; X return; X } X fprintf (stderr, "%s: illegal value: %s\n", myname, new); X } X} X X/* X * new_fields - change the user's password aging information interactively. X * X * prompt the user for the two password age values. set 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 (&mindays, "Minimum Password Age"); X change_field (&maxdays, "Maximum Password Age"); X change_field (&lastday, "Last Password Change"); X} X X/* X * list_fields - display the current values of the expiration fields X * X * display the mindays, maxdays, and lastday values. X */ X Xlist_fields () X{ X struct tm *tp; X char *cp; X long changed; X long expires; X X changed = lastday * (24L*60L*60L); X expires = maxdays * (24L*60L*60L) + changed; X X printf ("Minimum:\t%d\n", mindays); X printf ("Maximum:\t%d\n", maxdays); X X printf ("Last Change:\t"); X if (changed == 0) { X printf ("Never\n"); X } else { X tp = localtime (&changed); X cp = asctime (tp); X printf ("%6.6s, %4.4s\n", cp + 4, cp + 20); X } X X printf ("Expires:\t"); X if (expires == 0 || maxdays == 10000) { X printf ("Never\n"); X } else { X tp = localtime (&expires); X cp = asctime (tp); X printf ("%6.6s, %4.4s\n", cp + 4, cp + 20); X } 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#ifdef SHADOWPWD X struct spwd *sp; X#endif 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 if (myname = strchr (argv[0], '/')) X myname++; X else X myname = argv[0]; X X if (getuid () != 0) { X fprintf (stderr, "%s: permission denied\n", myname); X exit (1); X } X while ((flag = getopt (argc, argv, "lm:M:d:w:")) != EOF) { X switch (flag) { X case 'l': X lflg++; X break; X case 'm': X mflg++; X mindays = strtol (optarg, 0, 10); X break; X case 'M': X Mflg++; X maxdays = strtol (optarg, 0, 10); X break; X case 'd': X dflg++; X lastday = strtol (optarg, 0, 10); X break; X case 'w': X dflg++; X lastday = strtol (optarg, 0, 10) * 7; X break; X default: X usage (); X } X } 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 if (lflg && (mflg || Mflg || dflg)) { X fprintf (stderr, "%s: do not include \"l\" with other flags\n", X myname); X exit (1); X } X strcpy (name, pw->pw_name); X#ifdef SHADOWPWD X if (sp = getspnam (name)) { X spwd = *sp; X spwd.sp_namp = strdup (sp->sp_namp); X spwd.sp_pwdp = strdup (sp->sp_pwdp); X } X#endif X pwent = *pw; X pwent.pw_name = strdup (pw->pw_name); X pwent.pw_passwd = strdup (pw->pw_passwd); X pwent.pw_age = strdup (pw->pw_age); X pwent.pw_gecos = strdup (pw->pw_gecos); X pwent.pw_dir = strdup (pw->pw_dir); X pwent.pw_shell = strdup (pw->pw_shell); X X /* X * Set the fields that aren't being set from the command line X * from the password file. X */ X X#ifdef SHADOWPWD X if (sp) { X if (! Mflg) X maxdays = spwd.sp_max; X if (! mflg) X mindays = spwd.sp_min; X if (! dflg) X lastday = spwd.sp_lstchg; X } else X#endif X if (pwent.pw_age && strlen (pwent.pw_age) >= 2) { X if (! Mflg) X maxdays = c64i (pwent.pw_age[0]) * 7; X if (! mflg) X mindays = c64i (pwent.pw_age[1]) * 7; X if (! dflg && strlen (pwent.pw_age) == 4) X lastday = a64l (&pwent.pw_age[2]) * 7; X } X X /* X * Print out the expiration fields if the user has X * requested the list option. X */ X X if (lflg) { X list_fields (); X exit (0); 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 (! mflg && ! Mflg && ! dflg) { X printf ("Changing the aging information for %s\n", name); X new_fields (); X } X X /* X * Output the new password files. 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 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 SHADOWPWD X if (sp) { X spwd.sp_min = mindays; X spwd.sp_max = maxdays; X spwd.sp_lstchg = lastday; X 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 (sp = getspent ()) { X if (strcmp (sp->sp_namp, name) == 0) X break; X X if (putspent (sp, npwd)) X goto failure; X } X (void) putspent (&spwd, npwd); /* add the new entry */ X X while (sp = getspent ()) /* finish the other ones off */ X (void) putspent (sp, 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#ifndef NDEBUG X (void) unlink (".pwdlock"); X#else X (void) unlink (PWDLOCK); X#endif X exit (0); X /*NOTREACHED*/ X } X#endif X if (maxdays == -1 || mindays == -1 || lastday == -1) { X pwent.pw_age = ""; X } else { X if (maxdays > (63*7)) X maxdays = 63*7; X if (mindays > (63*7)) X mindays = 63*7; X X newage[0] = i64c (maxdays / 7); X newage[1] = i64c (mindays / 7); X strcpy (&newage[2], l64a (lastday / 7)); X pwent.pw_age = newage; 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 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} SHAR_EOF if test 10464 -ne "`wc -c < 'chage.c'`" then echo shar: "error transmitting 'chage.c'" '(should have been 10464 characters)' fi fi echo shar: "extracting 'pwent.c'" '(6808 characters)' if test -f 'pwent.c' then echo shar: "will not over-write existing file 'pwent.c'" else sed 's/^X//' << \SHAR_EOF > 'pwent.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 * 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#include X#include "config.h" X X#ifdef DBM X#include X#endif X X#ifndef lint Xstatic char _sccsid[] = "@(#)pwent.c 2.4 23:41:33 10/28/90"; X#endif X X#define SBUFSIZ 64 X#define NFIELDS 7 X Xstatic FILE *pwdfp; Xstatic char pwdbuf[BUFSIZ]; Xstatic char *pwdfile = "/etc/passwd"; X#ifdef DBM Xstatic int dbmopened; Xstatic int dbmerror; X#endif Xstatic char *pwdfields[NFIELDS]; Xstatic struct passwd pwent; X X/* X * sgetpwent - convert a string to a (struct passwd) X * X * sgetpwent() parses a string into the parts required for a password X * structure. Strict checking is made for the UID and GID fields and X * presence of the correct number of colons. Any failing tests result X * in a NULL pointer being returned. X */ X Xstruct passwd *sgetpwent (buf) Xchar *buf; X{ X int i; X char *cp; X X /* X * Copy the string to a static buffer so the pointers into X * the password structure remain valid. X */ X X strncpy (pwdbuf, buf, BUFSIZ); X pwdbuf[BUFSIZ-1] = '\0'; X X /* X * Save a pointer to the start of each colon separated X * field. The fields are converted into NUL terminated strings. X */ X X for (cp = pwdbuf, i = 0;i < NFIELDS && cp;i++) { X pwdfields[i] = cp; X if (cp = strchr (cp, ':')) X *cp++ = 0; X } X X /* X * There must be exactly NFIELDS colon separated fields or X * the entry is invalid. Also, the UID and GID must be non-blank. X */ X X if (i != NFIELDS || *pwdfields[2] == '\0' || *pwdfields[3] == '\0') X return 0; X X /* X * Each of the fields is converted the appropriate data type X * and the result assigned to the password structure. If the X * UID or GID does not convert to an integer value, a NULL X * pointer is returned. X */ X X pwent.pw_name = pwdfields[0]; X pwent.pw_passwd = pwdfields[1]; X if ((pwent.pw_uid = strtol (pwdfields[2], &cp, 10)) == 0 && *cp) X return 0; X X if ((pwent.pw_gid = strtol (pwdfields[3], &cp, 10)) == 0 && *cp) X return 0; X X if (cp = strchr (pwent.pw_passwd, ',')) { X pwent.pw_age = cp + 1; X *cp = '\0'; X } else X pwent.pw_age = ""; X X pwent.pw_gecos = pwdfields[4]; X pwent.pw_dir = pwdfields[5]; X pwent.pw_shell = pwdfields[6]; X X return (&pwent); X} X#ifdef FGETPWENT X/* X * fgetpwent - get a password file entry from a stream X * X * fgetpwent() reads the next line from a password file formatted stream X * and returns a pointer to the password structure for that line. X */ X Xstruct passwd *fgetpwent (fp) XFILE *fp; X{ X char buf[BUFSIZ]; X X while (fgets (buf, BUFSIZ, fp) != (char *) 0) { X buf[strlen (buf) - 1] = '\0'; X return (sgetpwent (buf)); X } X return 0; X} X#endif X#ifdef GETPWENT X X/* X * endpwent - close a password file X * X * endpwent() closes the password file if open. X */ X Xint endpwent () X{ X if (pwdfp) X if (fclose (pwdfp)) X return -1; X X return 0; X} X X/* X * getpwent - get a password entry from the password file X * X * getpwent() opens the password file, if not already opened, and reads X * a single entry. NULL is returned if any errors are encountered reading X * the password file. X */ X Xstruct passwd *getpwent () X{ X if (! pwdfp && setpwent ()) X return 0; X X return fgetpwent (pwdfp); X} X X/* X * getpwuid - locate the password entry for a given UID X * X * getpwuid() locates the first password file entry for the given UID. X * If there is a valid DBM file, the DBM files are queried first for X * the entry. Otherwise, a linear search is begun of the password file X * searching for an entry which matches the provided UID. X */ X Xstruct passwd *getpwuid (uid) Xint uid; X{ X struct passwd *pwd; X#ifdef DBM X datum key; X datum content; X X /* X * Attempt to open the DBM files if they have never been opened X * and an error has never been returned. X */ X X if (! dbmerror && ! dbmopened) { X char dbmfiles[BUFSIZ]; X X strcpy (dbmfiles, pwdfile); X strcat (dbmfiles, ".pag"); X X if (access (dbmfiles, 0) || dbminit (pwdfile)) X dbmerror = 1; X else X dbmopened = 1; X } X X /* X * If the DBM file are now open, create a key for this UID and X * try to fetch the entry from the database. A matching record X * will be unpacked into a static structure and returned to X * the user. X */ X X if (dbmopened) { X pwent.pw_uid = uid; X key.dsize = sizeof pwent.pw_uid; X key.dptr = (char *) &pwent.pw_uid; X content = fetch (key); X if (content.dptr != 0) { X memcpy (pwdbuf, content.dptr, content.dsize); X pw_unpack (pwdbuf, content.dsize, &pwent); X return &pwent; X } X } X#endif X /* X * Rewind the database and begin searching for an entry which X * matches the UID. Return the entry when a match is found. X */ X X if (setpwent ()) X return 0; X X while (pwd = getpwent ()) X if (pwd->pw_uid == uid) X return pwd; X X return 0; X} X Xstruct passwd *getpwnam (name) Xchar *name; X{ X struct passwd *pwd; X#ifdef DBM X datum key; X datum content; X X /* X * Attempt to open the DBM files if they have never been opened X * and an error has never been returned. X */ X X if (! dbmerror && ! dbmopened) { X char dbmfiles[BUFSIZ]; X X strcpy (dbmfiles, pwdfile); X strcat (dbmfiles, ".pag"); X X if (access (dbmfiles, 0) || dbminit (pwdfile)) X dbmerror = 1; X else X dbmopened = 1; X } X X /* X * If the DBM file are now open, create a key for this UID and X * try to fetch the entry from the database. A matching record X * will be unpacked into a static structure and returned to X * the user. X */ X X if (dbmopened) { X key.dsize = strlen (name); X key.dptr = name; X content = fetch (key); X if (content.dptr != 0) { X memcpy (pwdbuf, content.dptr, content.dsize); X pw_unpack (pwdbuf, content.dsize, &pwent); X return &pwent; X } X } X#endif X /* X * Rewind the database and begin searching for an entry which X * matches the name. Return the entry when a match is found. X */ X X if (setpwent ()) X return 0; X X while (pwd = getpwent ()) X if (strcmp (pwd->pw_name, name) == 0) X return pwd; X X return 0; X} X X/* X * setpwent - open the password file X * X * setpwent() opens the system password file, and the DBM password files X * if they are present. The system password file is rewound if it was X * open already. X */ X Xint setpwent () X{ X if (! pwdfp) { X if (! (pwdfp = fopen (pwdfile, "r"))) X return -1; X } else { X if (fseek (pwdfp, 0L, 0) != 0) X return -1; X } X#ifdef DBM X /* X * Attempt to open the DBM files if they have never been opened X * and an error has never been returned. X */ X X if (! dbmerror && ! dbmopened) { X char dbmfiles[BUFSIZ]; X X strcpy (dbmfiles, pwdfile); X strcat (dbmfiles, ".pag"); X X if (access (dbmfiles, 0) || dbminit (pwdfile)) X dbmerror = 1; X else X dbmopened = 1; X } X#endif X return 0; X} X#endif SHAR_EOF if test 6808 -ne "`wc -c < 'pwent.c'`" then echo shar: "error transmitting 'pwent.c'" '(should have been 6808 characters)' fi fi echo shar: "extracting 'valid.c'" '(3190 characters)' if test -f 'valid.c' then echo shar: "will not over-write existing file 'valid.c'" else sed 's/^X//' << \SHAR_EOF > 'valid.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[] = "@(#)valid.c 2.4 19:24:27 7/29/90"; X#endif X X/* X * valid - compare encrypted passwords X * X * Valid() compares the DES encrypted password from the password file X * against the password which the user has entered after it has been X * encrypted using the same salt as the original. X */ X Xint valid (password, entry) Xchar *password; Xstruct passwd *entry; X{ X char *encrypt; X char *salt; X char *crypt (); X char *shell; X#ifdef DOUBLESIZE X int firsthalf; X int longpass; X#endif X X#ifdef NOUSE X if (entry->pw_shell && strcmp (NOUSE, entry->pw_shell) == 0) X return (0); X#if defined(SU) && defined (NOLOGIN) X if (entry->pw_shell && strcmp (NOLOGIN, entry->pw_shell) == 0) { X if (! (shell = getenv ("SHELL"))) X return 0; X } X#endif X#if !defined(SU) && defined (NOLOGIN) X if (entry->pw_shell && strcmp (NOLOGIN, entry->pw_shell) == 0) X return 0; X#endif X#endif X /* X * Start with blank or empty password entries. Always encrypt X * a password if no such user exists. Only if the ID exists and X * the password is really empty do you return quickly. This X * routine is meant to waste CPU time. X */ X X if (entry->pw_name && X (entry->pw_passwd == (char *) 0 || X strlen (entry->pw_passwd) == 0)) { X if (strlen (password) == 0) X return (1); /* user entered nothing */ X else X return (0); /* user entered something! */ X } X X#ifdef DOUBLESIZE X longpass = entry->pw_passwd && strlen (entry->pw_passwd) > 13; X#endif X X /* X * If there is no entry then we need a salt to use. X */ X X if (entry->pw_passwd == (char *) 0 || entry->pw_passwd[0] == '\0') X salt = "xx"; X else X salt = entry->pw_passwd; X X /* X * Now, perform the encryption using the salt from before on X * the users input. Since we always encrypt the string, it X * should be very difficult to determine if the user exists by X * looking at execution time. X */ X X encrypt = crypt (password, salt); X#ifdef DOUBLESIZE X firsthalf = entry->pw_passwd X && strncmp (encrypt + 2, entry->pw_passwd + 2, 11) == 0; X X if (strlen (password) > 8) X encrypt = crypt (password + 8, salt); X else { X (void) crypt (password, salt); /* waste time ... */ X encrypt = ""; X } X#endif X /* X * One last time we must deal with there being no password file X * entry for the user. We use the pw_passwd == NULL idiom to X * cause non-existent users to not be validated. Even still, X * we are safe because if the string were == "", any encrypted X * string is not going to match - the output of crypt() begins X * with the salt, which is "xx", not "". X */ X X#ifndef DOUBLESIZE X if (entry->pw_passwd && strcmp (encrypt, entry->pw_passwd) == 0) X return (1); X else X return (0); X#else X if (! longpass) X return (firsthalf); X X if (entry->pw_passwd && firsthalf X && strncmp (encrypt + 2, entry->pw_passwd + 13) == 0) X return (1); X else X return (0); X#endif X} SHAR_EOF if test 3190 -ne "`wc -c < 'valid.c'`" then echo shar: "error transmitting 'valid.c'" '(should have been 3190 characters)' fi fi echo shar: "extracting 'setup.c'" '(2514 characters)' if test -f 'setup.c' then echo shar: "will not over-write existing file 'setup.c'" else sed 's/^X//' << \SHAR_EOF > 'setup.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[] = "@(#)setup.c 2.2 19:24:10 7/29/90"; X#endif X Xextern char home[]; Xextern char prog[]; Xextern char name[]; Xextern char mail[]; 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#ifndef MAILDIR X#define MAILDIR "/usr/spool/mail" X#endif X X#ifndef TTYPERM X#define TTYPERM 0622 X#endif X X#ifndef SU Xextern struct utmp utent; X#endif X X#ifdef QUOTAS Xlong strtol (); X#ifdef ULIMIT Xlong ulimit (); X#endif X#endif X Xvoid addenv (); X Xvoid setup (info) Xstruct passwd *info; X{ X extern int errno; X char logname[30]; X#ifndef SU X char tty[30]; X#endif X char *cp; X int i; X long l; X X#ifndef SU X (void) strcat (strcpy (tty, "/dev/"), utent.ut_line); X if (chown (tty, info->pw_uid, info->pw_gid) || X chmod (tty, TTYPERM)) X perror (tty); X#endif X if (chdir (info->pw_dir) == -1) { X (void) printf ("Unable to change directory to \"%s\"\n", info->pw_dir); X exit (errno); X } X#ifdef QUOTAS X for (cp = info->pw_gecos;cp != (char *) 0;cp = strchr (cp, ',')) { X if (*cp == ',') X cp++; X X if (strncmp (cp, "pri=", 4) == 0) { X i = atoi (cp + 4); X if (i >= -20 && i <= 20) X (void) nice (i); X X continue; X } X#ifdef ULIMIT X if (strncmp (cp, "ulimit=", 7) == 0) { X l = strtol (cp + 7, (char **) 0, 10); X (void) ulimit (2, l); X X continue; X } X#endif X if (strncmp (cp, "umask=", 6) == 0) { X i = strtol (cp + 6, (char **) 0, 8) & 0777; X (void) umask (i); X X continue; X } X } X#endif X if (setgid (info->pw_gid) == -1) { X puts ("Bad group id"); X exit (errno); X } X#ifndef BSD X if (setuid (info->pw_uid)) X#else X if (setreuid (info->pw_uid, info->pw_uid)) X#endif X { X puts ("Bad user id"); X exit (errno); X } X (void) strcat (strcpy (home, "HOME="), info->pw_dir); X addenv (home); X X if (info->pw_shell == (char *) 0) X info->pw_shell = "/bin/sh"; X X (void) strcat (strcpy (prog, "SHELL="), info->pw_shell); X addenv (prog); X X if (info->pw_uid == 0) X addenv (SUPATH); X else X addenv (PATH); X X (void) strcat (strcpy (logname, "LOGNAME="), name); X addenv (logname); X X (void) strcat (strcat (strcpy (mail, "MAIL="), MAILDIR), name); X addenv (mail); X} SHAR_EOF if test 2514 -ne "`wc -c < 'setup.c'`" then echo shar: "error transmitting 'setup.c'" '(should have been 2514 characters)' fi fi echo shar: "extracting 'entry.c'" '(2353 characters)' if test -f 'entry.c' then echo shar: "will not over-write existing file 'entry.c'" else sed 's/^X//' << \SHAR_EOF > 'entry.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#else X#include X#define strchr index X#define strrchr rindex X#endif X#include "config.h" X#ifdef SHADOWPWD X#include "shadow.h" X#endif X X#ifndef lint Xstatic char _sccsid[] = "@(#)entry.c 2.3 07:47:34 8/14/90"; X#endif X Xstruct passwd *fgetpwent (); Xchar *malloc (); X Xchar *strdup (s) Xchar *s; X{ X char *cp; X X if (s == (char *) 0) X return ((char *) 0); X X if (! (cp = malloc ((unsigned) strlen (s) + 1))) X return ((char *) 0); X X return (strcpy (cp, s)); X} X Xvoid entry (name, pwent) Xchar *name; Xstruct passwd *pwent; X{ X FILE *pwd; X struct passwd *passwd; X#ifdef SHADOWPWD X struct spwd *spwd; X char *l64a (); X#endif X char *cp; X X if ((pwd = fopen (PWDFILE, "r")) == (FILE *) 0) { X pwent->pw_passwd = (char *) 0; X return; X } X while (passwd = fgetpwent (pwd)) { X if (strcmp (name, passwd->pw_name) == 0) X break; X } X fclose (pwd); X X if (passwd == (struct passwd *) 0) { X pwent->pw_name = (char *) 0; X pwent->pw_passwd = (char *) 0; X } else { X pwent->pw_name = strdup (passwd->pw_name); X pwent->pw_uid = passwd->pw_uid; X pwent->pw_gid = passwd->pw_gid; X pwent->pw_comment = (char *) 0; X pwent->pw_gecos = strdup (passwd->pw_gecos); X pwent->pw_dir = strdup (passwd->pw_dir); X pwent->pw_shell = strdup (passwd->pw_shell); X#ifdef SHADOWPWD X setspent (); X if (spwd = getspnam (name)) { X pwent->pw_passwd = strdup (spwd->sp_pwdp); X X pwent->pw_age = malloc (5); X X if (spwd->sp_max > (63*7)) X spwd->sp_max = (63*7); X if (spwd->sp_min > (63*7)) X spwd->sp_min = (63*7); X X pwent->pw_age[0] = i64c (spwd->sp_max / 7); X pwent->pw_age[1] = i64c (spwd->sp_min / 7); X X cp = l64a (spwd->sp_lstchg / 7); X pwent->pw_age[2] = cp[0]; X pwent->pw_age[3] = cp[1]; X X pwent->pw_age[4] = '\0'; X X endspent (); X return; X } X endspent (); X passwd->pw_age = pwent->pw_age = (char *) 0; X#endif X if (passwd->pw_passwd) X pwent->pw_passwd = strdup (passwd->pw_passwd); X else X pwent->pw_passwd = (char *) 0; X X if (passwd->pw_age) { X pwent->pw_age = malloc (5); /* longest legal time */ X (void) strncpy (pwent->pw_age, passwd->pw_age, 5); X } else X pwent->pw_age = (char *) 0; X } X} SHAR_EOF if test 2353 -ne "`wc -c < 'entry.c'`" then echo shar: "error transmitting 'entry.c'" '(should have been 2353 characters)' fi fi echo shar: "extracting 'ttytype.c'" '(1125 characters)' if test -f 'ttytype.c' then echo shar: "will not over-write existing file 'ttytype.c'" else sed 's/^X//' << \SHAR_EOF > 'ttytype.c' X/* X * Copyright 1989, 1990, John F. Haugh II X * All rights reserved. X * X * Use, duplication, and disclosure prohibited without X * the express written permission of the author. X */ X X#include X#ifndef BSD X#include X#include X#else X#include X#define strchr index X#define strrchr rindex X#endif X#include "config.h" X X#ifdef TTYTYPE X#ifndef lint Xstatic char _sccsid[] = "@(#)ttytype.c 2.2 19:24:24 7/29/90"; X#endif X X/* X * ttytype - set ttytype from port to terminal type mapping database X */ X Xvoid ttytype (line) Xchar *line; X{ X FILE *fp; X char buf[BUFSIZ]; X char termvar[BUFSIZ]; X char *cp; X char *type; X char *port; X char *getenv (); X X if (getenv ("TERM")) X return; X X if (! (fp = fopen (TTYTYPE, "r"))) X return; X X while (fgets (buf, BUFSIZ, fp)) { X if (buf[0] == '#') X continue; X X if (cp = strchr (buf, '\n')) X *cp = '\0'; X X if ((type = strtok (buf, " \t")) X && (port = strtok ((char *) 0, " \t"))) { X if (strcmp (line, port) == 0) X break; X } X } X if (! feof (fp) && ! ferror (fp)) { X strcat (strcpy (termvar, "TERM="), type); X addenv (termvar); X } X fclose (fp); X} X#endif SHAR_EOF if test 1125 -ne "`wc -c < 'ttytype.c'`" then echo shar: "error transmitting 'ttytype.c'" '(should have been 1125 characters)' fi fi echo shar: "extracting 'port.h'" '(1459 characters)' if test -f 'port.h' then echo shar: "will not over-write existing file 'port.h'" else sed 's/^X//' << \SHAR_EOF > 'port.h' 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 X/* X * port.h - structure of /etc/porttime X * X * @(#)port.h 1.3 08:26:37 8/20/90 X * X * Each entry in /etc/porttime consists of a TTY device X * name or "*" to indicate all TTY devices, followed by X * a list of 1 or more user IDs or "*" to indicate all X * user names, followed by a list of zero or more valid X * login times. Login time entries consist of zero or X * more day names (Su, Mo, Tu, We, Th, Fr, Sa, Wk, Al) X * followed by a pair of time values in HHMM format X * separated by a "-". X */ X X/* X * PORTS - Name of system port access time file. X * PORT_IDS - Allowable number of IDs per entry. X * PORT_TIMES - Allowable number of time entries per entry. X * PORT_DAY - Day of the week to a bit value (0 = Sunday). X */ X X#define PORTS "/etc/porttime" X#define PORT_IDS 64 X#define PORT_TIMES 24 X#define PORT_DAY(day) (1<<(day)) X X/* X * pt_name - pointer to device name in /dev/ X * pt_users - pointer to array of applicable user IDs. X * pt_times - pointer to list of allowable time periods. X */ X Xstruct port { X char *pt_name; X char **pt_users; X struct pt_time *pt_times; X}; X X/* X * t_days - bit array for each day of the week (0 = Sunday) X * t_start - starting time for this entry X * t_end - ending time for this entry X */ X Xstruct pt_time { X short t_days; X short t_start; X short t_end; X}; SHAR_EOF if test 1459 -ne "`wc -c < 'port.h'`" then echo shar: "error transmitting 'port.h'" '(should have been 1459 characters)' fi fi echo shar: "extracting 'grent.c'" '(1297 characters)' if test -f 'grent.c' then echo shar: "will not over-write existing file 'grent.c'" else sed 's/^X//' << \SHAR_EOF > 'grent.c' X/* X * Copyright 1990, John F. Haugh II X * All rights reserved. X * X * Non-commercial distribution permitted. You must provide this source X * code in any distribution. This notice must remain intact. X */ X X#include X#include X#include X#include "config.h" X#ifdef DBM X#include X#endif X X#ifndef lint Xstatic char _sccsid[] = "@(#)grent.c 1.1 08:14:07 6/20/90"; X#endif X X#define NFIELDS 4 X#define MAXMEM 1024 X Xstatic char grpbuf[4*BUFSIZ]; Xstatic char *grpfields[NFIELDS]; Xstatic char *members[MAXMEM+1]; X Xstatic char ** Xlist (s) Xchar *s; X{ X int nmembers = 0; X X while (*s) { X members[nmembers++] = s; X if (s = strchr (s, ',')) X *s++ = '\0'; X } X members[nmembers] = (char *) 0; X return members; X} X Xstruct group *sgetgrent (buf) Xchar *buf; X{ X int i; X char *cp; X static struct group grent; X X strncpy (grpbuf, buf, sizeof grpbuf); X grpbuf[sizeof grpbuf - 1] = '\0'; X if (cp = strrchr (grpbuf, '\n')) X *cp = '\0'; X X for (cp = grpbuf, i = 0;i < NFIELDS && cp;i++) { X grpfields[i] = cp; X if (cp = strchr (cp, ':')) X *cp++ = 0; X } X if (i < (NFIELDS-1) || *grpfields[2] == '\0') X return ((struct group *) 0); X X grent.gr_name = grpfields[0]; X grent.gr_passwd = grpfields[1]; X grent.gr_gid = atoi (grpfields[2]); X grent.gr_mem = list (grpfields[3]); X X return (&grent); X} SHAR_EOF if test 1297 -ne "`wc -c < 'grent.c'`" then echo shar: "error transmitting 'grent.c'" '(should have been 1297 characters)' fi fi echo shar: "extracting 'motd.c'" '(750 characters)' if test -f 'motd.c' then echo shar: "will not over-write existing file 'motd.c'" else sed 's/^X//' << \SHAR_EOF > 'motd.c' X/* X * Copyright 1989, 1990, John F. Haugh II X * All rights reserved. X * X * Use, duplication, and disclosure prohibited without X * the express written permission of the author. X */ X X#include X#ifndef BSD X#include X#include X#else X#include X#define strchr index X#define strrchr rindex X#endif X#include "config.h" X X#ifndef lint Xstatic char _sccsid[] = "@(#)motd.c 2.2 19:23:58 7/29/90"; X#endif X Xextern char home[]; X#ifdef HUSHLOGIN Xextern int hushed; X#endif X X#ifdef MOTD Xvoid motd () X{ X FILE *fp; X register int c; X X#ifdef HUSHLOGIN X if (hushed) X return; X#endif X if ((fp = fopen ("/etc/motd", "r")) == (FILE *) 0) X return; X X while ((c = getc (fp)) != EOF) X putchar (c); X X fclose (fp); X fflush (stdout); X} X#endif SHAR_EOF if test 750 -ne "`wc -c < 'motd.c'`" then echo shar: "error transmitting 'motd.c'" '(should have been 750 characters)' fi fi echo shar: "extracting 'dialup.h'" '(928 characters)' if test -f 'dialup.h' then echo shar: "will not over-write existing file 'dialup.h'" else sed 's/^X//' << \SHAR_EOF > 'dialup.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 * Structure of d_passwd file X * X * The d_passwd file contains the names of login shells which require X * dialup passwords. Each line contains the fully qualified path name X * for the shell, followed by an optional password. Each field is X * separated by a ':'. X * X * Structure of the dialups file X * X * The dialups file contains the names of ports which may be dialup X * lines. Each line consists of the last component of the path X * name. Any leading directory names are removed. X * X * @(#)dialup.h 2.2 19:23:40 7/29/90 X */ X Xstruct dialup { X char *du_shell; X char *du_passwd; X}; X Xvoid setduent (); Xvoid endduent (); Xstruct dialup *getduent (); Xstruct dialup *getdushell (); X X#define DIALPWD "/etc/d_passwd" X#define DIALUPS "/etc/dialups" SHAR_EOF if test 928 -ne "`wc -c < 'dialup.h'`" then echo shar: "error transmitting 'dialup.h'" '(should have been 928 characters)' fi fi exit 0 # End of shell archive