home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume26
/
shadow
/
part09
< prev
next >
Wrap
Text File
|
1991-11-24
|
56KB
|
2,327 lines
Newsgroups: comp.sources.misc
From: jfh@rpp386.Cactus.ORG (John F Haugh II)
Subject: v26i062: shadow - Shadow Password Suite, Part09/11
Message-ID: <1991Nov24.185250.20627@sparky.imd.sterling.com>
X-Md4-Signature: def19317ec34a91d2c7d3e01ef3a2a48
Date: Sun, 24 Nov 1991 18:52:50 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: jfh@rpp386.Cactus.ORG (John F Haugh II)
Posting-number: Volume 26, Issue 62
Archive-name: shadow/part09
Environment: UNIX
Supersedes: shadow-2: Volume 06, Issue 22-24
#! /bin/sh
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# Contents: config.h dialup.c failure.c getpass.c groups.c gsdbm.c
# gspack.c id.c login.1 pwdbm.c pwpack.c pwunconv.c scologin.c
# shadow.3 shell.c usermod.1
# Wrapped by kent@sparky on Sun Nov 24 11:03:43 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo ' "shar: End of archive 9 (of 11)."'
if test -f 'config.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'config.h'\"
else
echo shar: Extracting \"'config.h'\" \(3169 characters\)
sed "s/^X//" >'config.h' <<'END_OF_FILE'
X/*
X * Copyright 1989, 1990, 1991, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X/*
X * Configuration file for login.
X *
X * @(#)config.h 3.13 08:27:18 10/31/91
X */
X
X
X/*
X * Pathname to the run-time configuration definitions file.
X */
X
X#define LOGINDEFS "/etc/login.defs"
X
X/*
X * Define SHADOWPWD to use shadow [ unreadable ] password file.
X * Release 3 has a requirement that SHADOWPWD always be defined.
X */
X
X#define SHADOWPWD
X
X/*
X * Define AUTOSHADOW to have root always copy sp_pwdp to pw_passwd
X * for getpwuid() and getpwnam(). This provides compatibility for
X * privileged applications which are shadow-ignorant. YOU ARE
X * ENCOURAGED TO NOT USE THIS OPTION UNLESS ABSOLUTELY NECESSARY.
X */
X
X#undef AUTOSHADOW
X
X/*
X * Define SHADOWGRP to user shadowed group files. This feature adds
X * the concept of a group administrator.
X */
X
X/* #define SHADOWGRP /**/
X
X/*
X * Define DOUBLESIZE to use 16 character passwords
X */
X
X#define DOUBLESIZE
X
X/*
X * Define AGING if you want the password aging checks made.
X * Release 3 has a requirement that AGING always be defined.
X */
X
X#define AGING
X
X/*
X * Pick your version of DBM. If you define either DBM or NDBM, you must
X * define GETPWENT. If you define NDBM you must define GETGRENT as well.
X */
X
X/* #define DBM /**/
X/* #define NDBM /**/
X
X/*
X * Define USE_SYSLOG if you want to have SYSLOG functions included in your code.
X */
X
X#define USE_SYSLOG
X
X/*
X * Enable RLOGIN to support the "-r" and "-h" options.
X * Also enable UT_HOST if your /etc/utmp provides for a host name.
X */
X
X#define RLOGIN
X#undef UT_HOST
X
X/*
X * Select one of the following
X */
X
X#define DIR_XENIX /* include <sys/ndir.h>, use (struct direct) */
X/* #define DIR_BSD /* include <ndir.h>, use (struct direct) */
X/* #define DIR_SYSV /* include <dirent.h>, use (struct dirent) */
X
X/*
X * Various system environment definitions.
X */
X
X#define HAVE_ULIMIT /* Define if your UNIX supports ulimit() */
X#define GETPWENT /* Define if you want my GETPWENT(3) routines */
X#define GETGRENT /* Define if you want my GETGRENT(3) routines */
X#define NEED_AL64 /* Define if library does not include a64l() */
X#define NEED_MKDIR /* Define if system does not have mkdir() */
X#define NEED_RMDIR /* Define if system does not have rmdir() */
X#define NEED_RENAME /* Define if system does not have rename() */
X#define NEED_STRSTR /* Define if library does not include strstr() */
X#define SIGTYPE int /* Type returned by signal() */
X
X/*
X * These definitions MUST agree with the values defined in <pwd.h>.
X */
X
X#undef BSD_QUOTA /* the pw_quota field exists */
X#define ATT_AGE /* the pw_age field exists */
X#define ATT_COMMENT /* the pw_comment field exists */
X
X/*
X * Define NDEBUG for production versions
X */
X
X#define NDEBUG
X
X/*
X * Define PWDFILE and GRPFILE to the names of the password and
X * group files.
X */
X
X#define PWDFILE "/etc/passwd"
X#define GRPFILE "/etc/group"
END_OF_FILE
if test 3169 -ne `wc -c <'config.h'`; then
echo shar: \"'config.h'\" unpacked with wrong size!
fi
# end of 'config.h'
fi
if test -f 'dialup.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'dialup.c'\"
else
echo shar: Extracting \"'dialup.c'\" \(2697 characters\)
sed "s/^X//" >'dialup.c' <<'END_OF_FILE'
X/*
X * Copyright 1989, 1990, 1991, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#include <stdio.h>
X#ifndef BSD
X#include <string.h>
X#else
X#include <strings.h>
X#define strchr index
X#define strrchr rindex
X#endif
X#include "dialup.h"
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)dialup.c 3.5 17:31:19 8/4/91";
X#endif
X
Xstatic FILE *dialpwd;
X
Xvoid
Xsetduent ()
X{
X if (dialpwd)
X rewind (dialpwd);
X else
X dialpwd = fopen (DIALPWD, "r");
X}
X
Xvoid
Xendduent ()
X{
X if (dialpwd)
X fclose (dialpwd);
X
X dialpwd = (FILE *) 0;
X}
X
Xstruct dialup *
Xfgetduent (fp)
XFILE *fp;
X{
X static struct dialup dialup; /* static structure to point to */
X static char shell[128]; /* some space for a login shell */
X static char passwd[128]; /* some space for dialup password */
X char buf[BUFSIZ];
X char *cp;
X char *cp2;
X
X if (! fp)
X return 0;
X
X if (! fp || feof (fp))
X return ((struct dialup *) 0);
X
X while (fgets (buf, BUFSIZ, fp) == buf && buf[0] == '#')
X ;
X
X if (feof (fp))
X return ((struct dialup *) 0);
X
X if (cp = strchr (buf, '\n'))
X *cp = '\0';
X
X if (! (cp = strchr (buf, ':')))
X return ((struct dialup *) 0);
X
X if (cp - buf > sizeof shell) /* something is fishy ... */
X return ((struct dialup *) 0);
X
X *cp++ = '\0';
X (void) strcpy (shell, buf);
X shell[cp - buf] = '\0';
X
X if (cp2 = strchr (cp, ':'))
X *cp2 = '\0';
X
X if (strlen (cp) + 1 > sizeof passwd) /* something is REALLY fishy */
X return ((struct dialup *) 0);
X
X (void) strcpy (passwd, cp);
X
X dialup.du_shell = shell;
X dialup.du_passwd = passwd;
X
X return (&dialup);
X}
X
Xstruct dialup *
Xgetduent ()
X{
X if (! dialpwd)
X setduent ();
X
X return fgetduent (dialpwd);
X}
X
Xstruct dialup *getdushell (shell)
Xchar *shell;
X{
X struct dialup *dialup;
X
X while (dialup = getduent ()) {
X if (strcmp (shell, dialup->du_shell) == 0)
X return (dialup);
X
X if (strcmp (dialup->du_shell, "*") == 0)
X return (dialup);
X }
X return ((struct dialup *) 0);
X}
X
Xint isadialup (tty)
Xchar *tty;
X{
X FILE *fp;
X char buf[BUFSIZ];
X int dialup = 0;
X
X if (! (fp = fopen (DIALUPS, "r")))
X return (0);
X
X while (fgets (buf, BUFSIZ, fp) == buf) {
X if (buf[0] == '#')
X continue;
X
X buf[strlen (buf) - 1] = '\0';
X
X if (strcmp (buf, tty) == 0) {
X dialup = 1;
X break;
X }
X }
X fclose (fp);
X
X return (dialup);
X}
X
Xint
Xputduent (dial, fp)
Xstruct dialup *dial;
XFILE *fp;
X{
X if (! fp || ! dial)
X return -1;
X
X if (fprintf (fp, "%s:%s\n", dial->du_shell, dial->du_passwd) == EOF)
X return -1;
X
X return 0;
X}
END_OF_FILE
if test 2697 -ne `wc -c <'dialup.c'`; then
echo shar: \"'dialup.c'\" unpacked with wrong size!
fi
# end of 'dialup.c'
fi
if test -f 'failure.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'failure.c'\"
else
echo shar: Extracting \"'failure.c'\" \(3164 characters\)
sed "s/^X//" >'failure.c' <<'END_OF_FILE'
X/*
X * Copyright 1989, 1990, 1991, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#include <sys/types.h>
X#include <fcntl.h>
X#include <time.h>
X#ifndef BSD
X#include <string.h>
X#include <memory.h>
X#else
X#include <strings.h>
X#define strchr index
X#define strrchr rindex
X#endif
X#include "faillog.h"
X#include "config.h"
X
X#include <utmp.h>
X
X#ifndef lint
Xstatic char _sccsid[] = "@(#)failure.c 3.1 08:26:45 9/17/91";
X#endif
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 ();
Xextern char *getdef_str();
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 (fail)
Xstruct faillog *fail;
X{
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
Xvoid
Xfailtmp (failent)
Xstruct utmp *failent;
X{
X int fd;
X char *ftmp;
X
X if ((ftmp = getdef_str ("FTMP_FILE")) == 0)
X return;
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}
END_OF_FILE
if test 3164 -ne `wc -c <'failure.c'`; then
echo shar: \"'failure.c'\" unpacked with wrong size!
fi
# end of 'failure.c'
fi
if test -f 'getpass.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'getpass.c'\"
else
echo shar: Extracting \"'getpass.c'\" \(3419 characters\)
sed "s/^X//" >'getpass.c' <<'END_OF_FILE'
X/*
X * Copyright 1990, 1991, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#include <signal.h>
X#include <stdio.h>
X#include "config.h"
X
X#ifdef BSD
X#include <sgtty.h>
X#include <strings.h>
X#else
X#include <termio.h>
X#include <string.h>
X#endif
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)getpass.c 3.7 08:27:22 10/31/91";
X#endif
X
X/*
X * limits.h may be kind enough to specify the length of a prompted
X * for password.
X */
X
X#if __STDC__ || _POSIX_SOURCE
X#include <limits.h>
X#endif
X
X/*
X * This is really a giant mess. On the one hand, it would be nice
X * if PASS_MAX were real big so that DOUBLESIZE isn't needed. But
X * if it is defined we must honor it because some idiot might use
X * this in a routine expecting some standard behavior.
X */
X
X#ifndef PASS_MAX
X#ifdef DOUBLESIZE
X#define PASS_MAX 16
X#else
X#define PASS_MAX 8
X#endif
X#endif
X
X#ifdef BSD
X#define STTY(fd,termio) stty(fd, termio)
X#define GTTY(fd,termio) gtty(fd, termio)
X#define TERMIO struct sgttyb
X#define INDEX index
X#else
X#define STTY(fd,termio) ioctl(fd, TCSETA, termio)
X#define GTTY(fd,termio) ioctl(fd, TCGETA, termio)
X#define TERMIO struct termio
X#define INDEX strchr
X#endif
X
Xstatic int sig_caught;
X
Xstatic void
Xsig_catch ()
X{
X sig_caught = 1;
X}
X
Xchar *
Xgetpass (prompt)
Xchar *prompt;
X{
X static char input[PASS_MAX+1];
X char *return_value = 0;
X char *cp;
X FILE *fp;
X int tty_opened = 0;
X SIGTYPE (*old_signal)();
X TERMIO new_modes;
X TERMIO old_modes;
X
X /*
X * set a flag so the SIGINT signal can be re-sent if it
X * is caught
X */
X
X sig_caught = 0;
X
X /*
X * if /dev/tty can't be opened, getpass() needs to read
X * from stdin instead.
X */
X
X if ((fp = fopen ("/dev/tty", "r")) == 0) {
X fp = stdin;
X setbuf (fp, (char *) 0);
X } else {
X tty_opened = 1;
X }
X
X /*
X * the current tty modes must be saved so they can be
X * restored later on. echo will be turned off, except
X * for the newline character (BSD has to punt on this)
X */
X
X if (GTTY (fileno (fp), &new_modes))
X return 0;
X
X old_modes = new_modes;
X old_signal = signal (SIGINT, sig_catch);
X
X#ifdef BSD
X new_modes.sg_flags &= ~ECHO ;
X#else
X new_modes.c_lflag &= ~(ECHO|ECHOE|ECHOK);
X new_modes.c_lflag |= ECHONL;
X#endif
X
X if (STTY (fileno (fp), &new_modes))
X goto out;
X
X /*
X * the prompt is output, and the response read without
X * echoing. the trailing newline must be removed. if
X * the fgets() returns an error, a NULL pointer is
X * returned.
X */
X
X if (fputs (prompt, stdout) == EOF)
X goto out;
X
X (void) fflush (stdout);
X
X if (fgets (input, sizeof input, fp) == input) {
X if (cp = INDEX (input, '\n'))
X *cp = '\0';
X else
X input[sizeof input - 1] = '\0';
X
X return_value = input;
X#ifdef BSD
X putc ('\n', stdout);
X#endif
X }
Xout:
X /*
X * the old SIGINT handler is restored after the tty
X * modes. then /dev/tty is closed if it was opened in
X * the beginning. finally, if a signal was caught it
X * is sent to this process for normal processing.
X */
X
X if (STTY (fileno (fp), &old_modes))
X return_value = 0;
X
X (void) signal (SIGINT, old_signal);
X
X if (tty_opened)
X (void) fclose (fp);
X
X if (sig_caught) {
X kill (getpid (), SIGINT);
X return_value = 0;
X }
X return return_value;
X}
END_OF_FILE
if test 3419 -ne `wc -c <'getpass.c'`; then
echo shar: \"'getpass.c'\" unpacked with wrong size!
fi
# end of 'getpass.c'
fi
if test -f 'groups.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'groups.c'\"
else
echo shar: Extracting \"'groups.c'\" \(2559 characters\)
sed "s/^X//" >'groups.c' <<'END_OF_FILE'
X/*
X * Copyright 1991, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
Xstatic char sccsid[] = "@(#)groups.c 3.1 08:50:47 11/3/91";
X
X#include "stdio.h"
X#include "pwd.h"
X#include "grp.h"
X
X/*
X * print_groups - print the groups which the named user is a member of
X *
X * print_groups() scans the groups file for the list of groups
X * which the user is listed as being a member of.
X */
X
Xprint_groups (member)
Xchar *member;
X{
X int i, groups = 0;
X struct group *grp;
X struct group *getgrent();
X
X setgrent ();
X
X while (grp = getgrent ()) {
X for (i = 0;grp->gr_mem[i];i++) {
X if (strcmp (grp->gr_mem[i], member) == 0) {
X if (groups++)
X putchar (' ');
X
X printf ("%s", grp->gr_name);
X }
X }
X }
X if (groups)
X putchar ('\n');
X}
X
X/*
X * groups - print out the groups a process is a member of
X */
X
Xmain (argc, argv)
Xint argc;
Xchar **argv;
X{
X int ngroups;
X#if NGROUPS > 0
X#if NGROUPS > 100
X gid_t *groups;
X#else
X gid_t groups[NGROUPS];
X#endif
X int i;
X#else
X char *logname;
X#endif
X struct group *gr;
X struct group *getgrgid();
X
X if (argc == 1) {
X
X /*
X * Called with no arguments - give the group set
X * for the current user.
X */
X
X#if NGROUPS > 0
X /*
X * This system supports concurrent group sets, so
X * I can ask the system to tell me which groups are
X * currently set for this process.
X */
X
X ngroups = getgroups (0, 0);
X#if NGROUPS > 100
X groups = (gid_t *) malloc (ngroups * sizeof (int *));
X#endif
X getgroups (ngroups, groups);
X
X /*
X * Print out the name of every group in the current
X * group set. Unknown groups are printed as their
X * decimal group ID values.
X */
X
X for (i = 0;i < ngroups;i++) {
X if (i)
X putchar (' ');
X
X if (gr = getgrgid (groups[i]))
X printf ("%s", gr->gr_name);
X else
X printf ("%d", groups[i]);
X }
X putchar ('\n');
X#else
X /*
X * This system does not have the getgroups() system
X * call, so I must check the groups file directly.
X */
X
X if (logname = getlogin ())
X print_groups (logname);
X else
X exit (1);
X#endif
X } else {
X
X /*
X * The invoker wanted to know about some other
X * user. Use that name to look up the groups instead.
X */
X
X if (getpwnam (argv[1]) == 0) {
X fprintf (stderr, "unknown user %s\n", argv[1]);
X exit (1);
X }
X print_groups (argv[1]);
X }
X exit (0);
X}
END_OF_FILE
if test 2559 -ne `wc -c <'groups.c'`; then
echo shar: \"'groups.c'\" unpacked with wrong size!
fi
# end of 'groups.c'
fi
if test -f 'gsdbm.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'gsdbm.c'\"
else
echo shar: Extracting \"'gsdbm.c'\" \(2700 characters\)
sed "s/^X//" >'gsdbm.c' <<'END_OF_FILE'
X/*
X * Copyright 1990, 1991, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)gsdbm.c 3.5 08:45:49 9/12/91";
X#endif
X
X#include <string.h>
X#include <stdio.h>
X#include "shadow.h"
X#include "config.h"
X
X#ifdef NDBM
X#include <ndbm.h>
XDBM *sgr_dbm;
X
X#define GRP_FRAG 256
X
X/*
X * sgr_dbm_update
X *
X * Updates the DBM password files, if they exist.
X */
X
Xint
Xsgr_dbm_update (sgr)
Xstruct sgrp *sgr;
X{
X datum key;
X datum content;
X char data[BUFSIZ*8];
X char sgrpkey[60];
X char *cp;
X int len;
X int i;
X int cnt;
X static int once;
X
X if (! once) {
X if (! sgr_dbm)
X setsgent ();
X
X once++;
X }
X if (! sgr_dbm)
X return 0;
X
X len = sgr_pack (sgr, data);
X
X if (len <= GRP_FRAG) {
X content.dsize = len;
X content.dptr = data;
X
X key.dsize = strlen (sgr->sg_name);
X key.dptr = sgr->sg_name;
X if (dbm_store (sgr_dbm, key, content, DBM_REPLACE))
X return 0;
X } else {
X content.dsize = sizeof cnt;
X content.dptr = (char *) &cnt;
X cnt = (len + (GRP_FRAG-1)) / GRP_FRAG;
X
X key.dsize = strlen (sgr->sg_name);
X key.dptr = sgr->sg_name;
X if (dbm_store (sgr_dbm, key, content, DBM_REPLACE))
X return 0;
X
X for (cp = data, i = 0;i < cnt;i++) {
X content.dsize = len > GRP_FRAG ? GRP_FRAG:len;
X len -= content.dsize;
X content.dptr = cp;
X cp += content.dsize;
X
X key.dsize = sizeof i + strlen (sgr->sg_name);
X key.dptr = sgrpkey;
X memcpy (sgrpkey, (char *) &i, sizeof i);
X strcpy (sgrpkey + sizeof i, sgr->sg_name);
X if (dbm_store (sgr_dbm, key, content, DBM_REPLACE))
X return 0;
X }
X }
X return 1;
X}
X
X/*
X * sgr_dbm_remove
X *
X * Deletes the DBM shadow group file entries, if they exist.
X */
X
Xint
Xsgr_dbm_remove (name)
Xchar *name;
X{
X datum key;
X datum content;
X char grpkey[60];
X int i;
X int cnt;
X int errors = 0;
X static int once;
X
X if (! once) {
X if (! sgr_dbm)
X setsgent ();
X
X once++;
X }
X if (! sgr_dbm)
X return 0;
X
X key.dsize = strlen (name);
X key.dptr = name;
X content = dbm_fetch (sgr_dbm, key);
X if (content.dptr == 0)
X ++errors;
X else {
X if (content.dsize == sizeof (int)) {
X memcpy ((char *) &cnt, content.dptr, sizeof cnt);
X
X for (i = 0;i < cnt;i++) {
X key.dsize = sizeof i + strlen (name);
X key.dptr = grpkey;
X memcpy (grpkey, (char *) &i, sizeof i);
X strcpy (grpkey + sizeof i, name);
X if (dbm_delete (sgr_dbm, key))
X ++errors;
X }
X } else {
X if (dbm_delete (sgr_dbm, key))
X ++errors;
X }
X }
X return errors ? 0:1;
X}
X#endif
END_OF_FILE
if test 2700 -ne `wc -c <'gsdbm.c'`; then
echo shar: \"'gsdbm.c'\" unpacked with wrong size!
fi
# end of 'gsdbm.c'
fi
if test -f 'gspack.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'gspack.c'\"
else
echo shar: Extracting \"'gspack.c'\" \(2890 characters\)
sed "s/^X//" >'gspack.c' <<'END_OF_FILE'
X/*
X * Copyright 1990, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#include <stdio.h>
X#include "shadow.h"
X#ifdef BSD
X#include <strings.h>
X#else
X#include <string.h>
X#endif
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)gspack.c 3.1 09:13:50 12/13/90";
X#endif
X
X/*
X * sgr_pack - convert a shadow group structure to a packed
X * shadow group record
X *
X * sgr_pack takes the shadow group structure and packs
X * the components in a record. this record will be
X * unpacked later by sgr_unpack.
X */
X
Xint
Xsgr_pack (sgrp, buf)
Xstruct sgrp *sgrp;
Xchar *buf;
X{
X char *cp;
X int i;
X
X /*
X * The name and password are both easy - append each string
X * to the buffer. These are always the first two strings
X * in a record.
X */
X
X cp = buf;
X strcpy (cp, sgrp->sg_name);
X cp += strlen (cp) + 1;
X
X strcpy (cp, sgrp->sg_passwd);
X cp += strlen (cp) + 1;
X
X /*
X * The arrays of administrators and members are slightly
X * harder. Each element is appended as a string, with a
X * final '\0' appended to serve as a blank string. The
X * number of elements is not known in advance, so the
X * entire collection of administrators must be scanned to
X * find the start of the members.
X */
X
X for (i = 0;sgrp->sg_adm[i];i++) {
X strcpy (cp, sgrp->sg_adm[i]);
X cp += strlen (cp) + 1;
X }
X *cp++ = '\0';
X
X for (i = 0;sgrp->sg_mem[i];i++) {
X strcpy (cp, sgrp->sg_mem[i]);
X cp += strlen (cp) + 1;
X }
X *cp++ = '\0';
X
X return cp - buf;
X}
X
X/*
X * sgr_unpack - convert a packed shadow group record to an
X * unpacked record
X *
X * sgr_unpack converts a record which was packed by sgr_pack
X * into the normal shadow group structure format.
X */
X
Xint
Xsgr_unpack (buf, len, sgrp)
Xchar *buf;
Xint len;
Xstruct sgrp *sgrp;
X{
X char *org = buf;
X int i;
X
X /*
X * The name and password are both easy - they are the first
X * two strings in the record.
X */
X
X sgrp->sg_name = buf;
X buf += strlen (buf) + 1;
X if (buf - org > len)
X return -1;
X
X sgrp->sg_passwd = buf;
X buf += strlen (buf) + 1;
X if (buf - org > len)
X return -1;
X
X /*
X * The administrators and members are slightly more difficult.
X * The arrays are lists of strings. Each list is terminated
X * by a string of length zero. This string is detected by
X * looking for an initial character of '\0'.
X */
X
X for (i = 0;*buf && i < 1024;i++) {
X sgrp->sg_adm[i] = buf;
X buf += strlen (buf) + 1;
X
X if (buf - org > len)
X return -1;
X }
X sgrp->sg_adm[i] = (char *) 0;
X if (! *buf)
X buf++;
X
X for (i = 0;*buf && i < 1024;i++) {
X sgrp->sg_mem[i] = buf;
X buf += strlen (buf) + 1;
X
X if (buf - org > len)
X return -1;
X }
X sgrp->sg_mem[i] = (char *) 0;
X
X return 0;
X}
END_OF_FILE
if test 2890 -ne `wc -c <'gspack.c'`; then
echo shar: \"'gspack.c'\" unpacked with wrong size!
fi
# end of 'gspack.c'
fi
if test -f 'id.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'id.c'\"
else
echo shar: Extracting \"'id.c'\" \(3225 characters\)
sed "s/^X//" >'id.c' <<'END_OF_FILE'
X/*
X * Copyright 1991, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X/*
X * id - print current process user identification information
X *
X * Print the current process identifiers. This includes the
X * UID, GID, effective-UID and effective-GID. Optionally print
X * the concurrent group set if the current system supports it.
X */
X
X#include <sys/types.h>
X#include <stdio.h>
X#include <grp.h>
X#include "pwd.h"
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)id.c 3.4 08:43:37 9/12/91";
X#endif
X
Xusage ()
X{
X#if NGROUPS > 0
X fprintf (stderr, "usage: id [ -a ]\n");
X#else
X fprintf (stderr, "usage: id\n");
X#endif
X exit (1);
X}
X
X/*ARGSUSED*/
Xmain (argc, argv)
Xint argc;
Xchar **argv;
X{
X int id;
X#if NGROUPS > 0
X#if NGROUPS > 100
X int *groups;
X#else
X int groups[NGROUPS];
X#endif
X int ngroups;
X int aflg = 0;
X#endif
X struct passwd *pw,
X *getpwuid();
X struct group *gr,
X *getgrgid();
X
X#if NGROUPS > 0
X /*
X * See if the -a flag has been given to print out the
X * concurrent group set.
X */
X
X if (argc > 1) {
X if (argc > 2 || strcmp (argv[1], "-a"))
X usage ();
X else
X aflg = 1;
X }
X#else
X if (argc > 1)
X usage ();
X#endif
X
X /*
X * Print out the real user ID and group ID. If the user or
X * group does not exist, just give the numerical value.
X */
X
X if (pw = getpwuid (id = getuid ()))
X printf ("uid=%d(%s)", id, pw->pw_name);
X else
X printf ("uid=%d", id);
X
X if (gr = getgrgid (id = getgid ()))
X printf (" gid=%d(%s)", id, gr->gr_name);
X else
X printf (" gid=%d", id);
X
X /*
X * Print out the effective user ID and group ID if they are
X * different from the real values.
X */
X
X if (getuid () != geteuid ()) {
X if (pw = getpwuid (id = geteuid ()))
X printf (" euid=%d(%s)", id, pw->pw_name);
X else
X printf (" euid=%d", id);
X }
X if (getgid () != getegid ()) {
X if (gr = getgrgid (id = getegid ()))
X printf (" egid=%d(%s)", id, gr->gr_name);
X else
X printf (" egid=%d", id);
X }
X#if NGROUPS > 0
X
X /*
X * Print out the concurrent group set if the user has requested
X * it. The group numbers will be printed followed by their
X * names.
X */
X
X if (aflg && (ngroups = getgroups (0, 0)) != -1) {
X
X#if NGROUPS > 100
X /*
X * The size of the group set is determined so an array
X * large enough to hold it can be allocated.
X */
X
X if (groups = (int *) malloc (ngroups * sizeof *groups)) {
X putchar ('\n');
X perror ("out of memory");
X exit (1);
X }
X#endif
X /*
X * Start off the group message. It will be of the format
X *
X * groups=###(aaa),###(aaa),###(aaa)
X *
X * where "###" is a numerical value and "aaa" is the
X * corresponding name for each respective numerical value.
X */
X
X getgroups (ngroups, groups);
X printf (" groups=");
X for (i = 0;i < ngroups;i++) {
X if (i)
X putchar (',');
X
X if (gr = getgrgid (groups[i]))
X printf ("%d(%s)", groups[i], gr->gr_name);
X else
X printf ("%d", groups[i]);
X }
X }
X#endif
X
X /*
X * Finish off the line.
X */
X
X putchar ('\n');
X exit (0);
X /*NOTREACHED*/
X}
END_OF_FILE
if test 3225 -ne `wc -c <'id.c'`; then
echo shar: \"'id.c'\" unpacked with wrong size!
fi
# end of 'id.c'
fi
if test -f 'login.1' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'login.1'\"
else
echo shar: Extracting \"'login.1'\" \(3344 characters\)
sed "s/^X//" >'login.1' <<'END_OF_FILE'
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.\" @(#)login.1 3.1 09:34:21 11/21/90
X.\"
X.TH LOGIN 1
X.SH NAME
Xlogin \- Begin session on the system
X.SH SYNOPSIS
X.B login
X[ username [ environmental-variables ] ]
X.SH DESCRIPTION
X.I login
Xis used to establish a new session with the system.
XIt is normally invoked automatically by responding to the
X.B login:
Xprompt on the user\'s terminal.
X.I login
Xmay be special to the shell and may not be invoked as a sub-process.
XTypically,
X.I login
Xis treated by the shell as \fBexec login\fR which causes the user
Xto exit from the current shell.
XAttempting to execute \fIlogin\fR from any shell but the login shell
Xwill produce an error message.
X.PP
XWhen invoked from the \fBlogin:\fR prompt, the user may enter
Xenvironmental variables after the username.
XThese variables are entered in the form \fBNAME=VALUE\fR.
XNot all variables may be set in the fashion, notably \fBPATH\fR,
X\fBHOME\fR and \fBSHELL\fR.
XAdditionally, \fBIFS\fR may be inhibited if the user\'s login
Xshell is \fB/bin/sh\fR.
X.PP
XThe user is then prompted for a password, where appropriate.
XEchoing is disabled to prevent revealing the password.
XOnly a small number of password failures are permitted before
X\fIlogin\fR exits and the communications link is severed.
X.PP
XIf password aging has been enabled for your account, you may be
Xprompted for a new password before proceeding.
XYou will be forced to provide your old password and the new
Xpassword before continuing.
XPlease refer to \fIpasswd(1)\fR for more information.
X.PP
XAfter a successful login,
Xyou will be informed of any system messages and the presence
Xof mail.
XYou may turn off the printing of the system message file,
X\fI/etc/motd\fR, by creating a zero-length file \fI.hushlogin\fR
Xin your login directory.
XThe mail message will be one of "\fIYou have new mail.\fR",
X"\fIYou have mail.\fR", or "\fINo Mail.\fR" according to
Xthe condition of your mailbox.
X.PP
XYour user and group ID will be set according to their values in
Xthe \fI/etc/passwd\fR file.
XThe value for \fB$HOME\fR, \fB$SHELL\fR, \fB$PATH\fR, \fB$LOGNAME\fR,
Xand \fB$MAIL\fR are set according to the appropriate fields in the
Xpassword entry.
XUlimit, umask and nice values may also be set according to
Xentries in the GECOS field.
X.PP
XOn some installations, the environmental variable \fB$TERM\fR will be
Xinitialize to the terminal type on your tty line, as specified in
X\fI/etc/ttytype\fR.
X.PP
XAn initialization script for your command interpreter may also be
Xexecuted.
XPlease see the appropriate manual section for more information on
Xthis function.
X.SH CAVEATS
X.PP
XThis version of \fIlogin\fR has many compilation options, only some of which
Xmay be in use at any particular site.
X.SH Files
X/etc/utmp \- list of current login sessions
X.br
X/etc/wtmp \- list of previous login sessions
X.br
X/etc/passwd \- user account information
X.br
X/etc/shadow \- encrypted passwords and age information
X.br
X/etc/motd \- system message file
X.br
X/etc/ttytype \- list of terminal types
X.br
X$HOME/.profile \- initialization script for default shell
X.br
X$HOME/.hushlogin \- suppress printing of system messages
X.br
X.SH See Also
X.PP
Xgetty(1M),
Xmail(1),
Xpasswd(1),
Xsh(1),
Xsu(1),
Xd_passwd(4),
Xpasswd(4)
END_OF_FILE
if test 3344 -ne `wc -c <'login.1'`; then
echo shar: \"'login.1'\" unpacked with wrong size!
fi
# end of 'login.1'
fi
if test -f 'pwdbm.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'pwdbm.c'\"
else
echo shar: Extracting \"'pwdbm.c'\" \(2489 characters\)
sed "s/^X//" >'pwdbm.c' <<'END_OF_FILE'
X/*
X * Copyright 1990, 1991, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)pwdbm.c 3.5 09:29:30 6/6/91";
X#endif
X
X#ifdef BSD
X#include <strings.h>
X#define strchr index
X#define strrchr rindex
X#else
X#include <string.h>
X#endif
X#include <stdio.h>
X#include "pwd.h"
X#include "config.h"
X
X#if defined(DBM) || defined(NDBM) /*{*/
X
X#ifdef DBM
X#include <dbm.h>
X#endif
X#ifdef NDBM
X#include <ndbm.h>
XDBM *pw_dbm;
X#endif
X
X/*
X * pw_dbm_update
X *
X * Updates the DBM password files, if they exist.
X */
X
Xint
Xpw_dbm_update (pw)
Xstruct passwd *pw;
X{
X datum key;
X datum content;
X char data[BUFSIZ];
X int len;
X static int once;
X
X if (! once) {
X#ifdef NDBM
X if (! pw_dbm)
X setpwent ();
X#else
X setpwent ();
X#endif
X once++;
X }
X#ifdef DBM
X strcpy (data, PWDFILE);
X strcat (data, ".pag");
X if (access (data, 0))
X return 0;
X#endif
X#ifdef NDBM
X if (! pw_dbm)
X return 0;
X#endif
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#ifdef DBM
X if (store (key, content))
X return 0;
X#endif
X#ifdef NDBM
X if (dbm_store (pw_dbm, key, content, DBM_REPLACE))
X return 0;
X#endif
X
X key.dsize = sizeof pw->pw_uid;
X key.dptr = (char *) &pw->pw_uid;
X#ifdef DBM
X if (store (key, content))
X return 0;
X#endif
X#ifdef NDBM
X if (dbm_store (pw_dbm, key, content, DBM_REPLACE))
X return 0;
X#endif
X return 1;
X}
X
X/*
X * pw_dbm_remove
X *
X * Removes the DBM password entry, if it exists.
X */
X
Xint
Xpw_dbm_remove (pw)
Xstruct passwd *pw;
X{
X datum key;
X static int once;
X
X if (! once) {
X#ifdef NDBM
X if (! pw_dbm)
X setpwent ();
X#else
X setpwent ();
X#endif
X once++;
X }
X#ifdef DBM
X strcpy (data, PWDFILE);
X strcat (data, ".pag");
X if (access (data, 0))
X return 0;
X#endif
X#ifdef NDBM
X if (! pw_dbm)
X return 0;
X#endif
X key.dsize = strlen (pw->pw_name);
X key.dptr = pw->pw_name;
X#ifdef DBM
X if (delete (key))
X return 0;
X#endif
X#ifdef NDBM
X if (dbm_delete (pw_dbm, key))
X return 0;
X#endif
X key.dsize = sizeof pw->pw_uid;
X key.dptr = (char *) &pw->pw_uid;
X#ifdef DBM
X if (delete (key))
X return 0;
X#endif
X#ifdef NDBM
X if (dbm_delete (pw_dbm, key))
X return 0;
X#endif
X return 1;
X}
X
X#endif /*} defined(NDBM) || defined(DBM) */
END_OF_FILE
if test 2489 -ne `wc -c <'pwdbm.c'`; then
echo shar: \"'pwdbm.c'\" unpacked with wrong size!
fi
# end of 'pwdbm.c'
fi
if test -f 'pwpack.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'pwpack.c'\"
else
echo shar: Extracting \"'pwpack.c'\" \(2994 characters\)
sed "s/^X//" >'pwpack.c' <<'END_OF_FILE'
X/*
X * Copyright 1990, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#include <stdio.h>
X#include "pwd.h"
X#ifdef BSD
X#include <strings.h>
X#define strchr index
X#define strrchr rindex
X#else
X#include <string.h>
X#endif
X#include "config.h"
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)pwpack.c 3.3 12:31:23 12/12/90";
X#endif
X
X/*
X * pw_pack - convert a (struct pwd) to a packed record
X */
X
Xint
Xpw_pack (passwd, buf)
Xstruct passwd *passwd;
Xchar *buf;
X{
X char *cp;
X
X cp = buf;
X strcpy (cp, passwd->pw_name);
X cp += strlen (cp) + 1;
X
X strcpy (cp, passwd->pw_passwd);
X#ifdef ATT_AGE
X if (passwd->pw_age[0]) {
X *cp++ = ',';
X strcat (cp, passwd->pw_age);
X }
X#endif
X cp += strlen (cp) + 1;
X
X memcpy (cp, (void *) &passwd->pw_uid, sizeof passwd->pw_uid);
X cp += sizeof passwd->pw_uid;
X
X memcpy (cp, (void *) &passwd->pw_gid, sizeof passwd->pw_gid);
X cp += sizeof passwd->pw_gid;
X#ifdef BSD_QUOTAS
X memcpy (cp, (void *) &passwd->pw_quota, sizeof passwd->pw_quota);
X cp += sizeof passwd->pw_quota;
X#endif
X#ifdef ATT_COMMENT
X if (passwd->pw_comment) {
X strcpy (cp, passwd->pw_comment);
X cp += strlen (cp) + 1;
X } else
X *cp++ = '\0';
X#endif
X strcpy (cp, passwd->pw_gecos);
X cp += strlen (cp) + 1;
X
X strcpy (cp, passwd->pw_dir);
X cp += strlen (cp) + 1;
X
X strcpy (cp, passwd->pw_shell);
X cp += strlen (cp) + 1;
X
X return cp - buf;
X}
X
X/*
X * pw_unpack - convert a packed (struct pwd) record to a (struct pwd)
X */
X
Xint
Xpw_unpack (buf, len, passwd)
Xchar *buf;
Xint len;
Xstruct passwd *passwd;
X{
X char *org = buf;
X char *cp;
X
X memset ((void *) passwd, 0, sizeof *passwd);
X
X passwd->pw_name = buf;
X buf += strlen (buf) + 1;
X if (buf - org > len)
X return -1;
X
X passwd->pw_passwd = buf;
X buf += strlen (buf) + 1;
X if (buf - org > len)
X return -1;
X
X#ifdef ATT_AGE
X if (cp = strchr (passwd->pw_passwd, ',')) {
X *cp++ = '\0';
X passwd->pw_age = cp;
X } else
X passwd->pw_age = "";
X#endif
X
X memcpy ((void *) &passwd->pw_uid, (void *) buf, sizeof passwd->pw_uid);
X buf += sizeof passwd->pw_uid;
X if (buf - org > len)
X return -1;
X
X memcpy ((void *) &passwd->pw_gid, (void *) buf, sizeof passwd->pw_gid);
X buf += sizeof passwd->pw_gid;
X if (buf - org > len)
X return -1;
X
X#ifdef BSD_QUOTAS
X memcpy ((void *) &passwd->pw_quota, (void *) buf,
X sizeof passwd->pw_quota);
X buf += sizeof passwd->pw_quota;
X if (buf - org > len)
X return -1;
X#endif
X#ifdef ATT_COMMENT
X passwd->pw_comment = buf;
X buf += strlen (buf) + 1;
X if (buf - org > len)
X return -1;
X#endif
X passwd->pw_gecos = buf;
X buf += strlen (buf) + 1;
X if (buf - org > len)
X return -1;
X
X passwd->pw_dir = buf;
X buf += strlen (buf) + 1;
X if (buf - org > len)
X return -1;
X
X passwd->pw_shell = buf;
X buf += strlen (buf) + 1;
X if (buf - org > len)
X return -1;
X
X return 0;
X}
END_OF_FILE
if test 2994 -ne `wc -c <'pwpack.c'`; then
echo shar: \"'pwpack.c'\" unpacked with wrong size!
fi
# end of 'pwpack.c'
fi
if test -f 'pwunconv.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'pwunconv.c'\"
else
echo shar: Extracting \"'pwunconv.c'\" \(3159 characters\)
sed "s/^X//" >'pwunconv.c' <<'END_OF_FILE'
X/*
X * Copyright 1989, 1990, 1991, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X *
X * pwunconv - restore old password file from shadow password file.
X *
X * Pwunconv copies the password file information from the shadow
X * password file, merging entries from an optional existing shadow
X * file.
X *
X * The new password file is left in npasswd. There is no new
X * shadow file. Password aging information is translated where
X * possible.
X */
X
X#include <sys/types.h>
X#include <stdio.h>
X#include <fcntl.h>
X#include "pwd.h"
X#include "config.h"
X#include "shadow.h"
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)pwunconv.c 3.3 09:08:06 5/28/91";
X#endif
X
X#ifdef ITI_AGING
X#define WEEK (7L*24L*3600L)
X#else
X#define WEEK (7)
X#endif
X
Xchar buf[BUFSIZ];
Xchar *l64a ();
X
Xint main ()
X{
X struct passwd *pw;
X struct passwd *sgetpwent ();
X FILE *pwd;
X FILE *npwd;
X struct spwd *spwd;
X int fd;
X char newage[5];
X
X if (! (pwd = fopen (PWDFILE, "r"))) {
X perror (PWDFILE);
X return (1);
X }
X unlink ("npasswd");
X if ((fd = open ("npasswd", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 ||
X ! (npwd = fdopen (fd, "w"))) {
X perror ("npasswd");
X return (1);
X }
X while (fgets (buf, BUFSIZ, pwd) == buf) {
X buf[strlen (buf) - 1] = '\0'; /* remove '\n' character */
X
X if (buf[0] == '#') { /* comment line */
X (void) fprintf (npwd, "%s\n", buf);
X continue;
X }
X if (! (pw = sgetpwent (buf))) { /* copy bad lines verbatim */
X (void) fprintf (npwd, "%s\n", buf);
X continue;
X }
X setspent (); /* rewind shadow file */
X
X if (! (spwd = getspnam (pw->pw_name))) {
X (void) fprintf (npwd, "%s\n", buf);
X continue;
X }
X pw->pw_passwd = spwd->sp_pwdp;
X
X /*
X * Password aging works differently in the two different systems.
X * With shadow password files you apparently must have some aging
X * information. The maxweeks or minweeks may not map exactly.
X * In pwconv we set max == 10000, which is about 30 years. Here
X * we have to undo that kludge. So, if maxdays == 10000, no aging
X * information is put into the new file. Otherwise, the days are
X * converted to weeks and so on.
X */
X
X#ifdef ATT_AGE
X if (spwd->sp_max > (63*WEEK) && spwd->sp_max < 10000)
X spwd->sp_max = (63*WEEK); /* 10000 is infinity */
X
X if (spwd->sp_min >= 0 && spwd->sp_min <= 63*7 &&
X spwd->sp_max >= 0 && spwd->sp_max <= 63*7) {
X if (spwd->sp_lstchg == -1)
X spwd->sp_lstchg = 0;
X
X spwd->sp_max /= WEEK; /* turn it into weeks */
X spwd->sp_min /= WEEK;
X spwd->sp_lstchg /= WEEK;
X
X strncpy (newage, l64a (spwd->sp_lstchg * (64L*64L) +
X spwd->sp_min * (64L) + spwd->sp_max), 5);
X pw->pw_age = newage;
X } else
X pw->pw_age = "";
X#endif /* ATT_AGE */
X if (putpwent (pw, npwd)) {
X perror ("pwunconv: write error");
X exit (1);
X }
X }
X endspent ();
X
X if (ferror (npwd)) {
X perror ("pwunconv");
X (void) unlink ("npasswd");
X }
X (void) fclose (npwd);
X (void) fclose (pwd);
X return (0);
X}
END_OF_FILE
if test 3159 -ne `wc -c <'pwunconv.c'`; then
echo shar: \"'pwunconv.c'\" unpacked with wrong size!
fi
# end of 'pwunconv.c'
fi
if test -f 'scologin.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'scologin.c'\"
else
echo shar: Extracting \"'scologin.c'\" \(1834 characters\)
sed "s/^X//" >'scologin.c' <<'END_OF_FILE'
X/*
X * Copyright 1991, John F. Haugh II and Chip Rosenthal
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)scologin.c 3.2 14:38:24 10/27/91";
X#endif
X
X#include <stdio.h>
X#include "pwd.h"
X
X#define USAGE "usage: %s [ -r remote_host remote_user local_user [ term_type ] ]\n"
X#define LOGIN "/etc/login"
X
Xextern int errno;
Xextern char *sys_errlist[];
Xextern char **environ;
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X char *rhost, *ruser, *luser;
X char term[1024], *nargv[8], *nenvp[2];
X int root_user, i;
X struct passwd *pw;
X
X if (argc == 1) {
X
X /*
X * Called from telnetd.
X */
X nargv[0] = "login";
X nargv[1] = "-p";
X nargv[2] = NULL;
X
X } else if (strcmp(argv[1], "-r") == 0 && argc >= 6) {
X
X /*
X * Called from rlogind.
X */
X
X rhost = argv[2];
X ruser = argv[3];
X luser = argv[4];
X root_user = ((pw = getpwnam(luser)) != NULL && pw->pw_uid == 0);
X
X i = 0;
X if ( argc == 6 ) {
X strcpy(term, "TERM=");
X strncat(term+sizeof("TERM=")-1,
X argv[5], sizeof(term)-sizeof("TERM="));
X term[sizeof(term)-1] = '\0';
X nenvp[i++] = term;
X }
X nenvp[i++] = NULL;
X environ = nenvp;
X
X i = 0;
X nargv[i++] = "login";
X nargv[i++] = "-p";
X nargv[i++] = "-h";
X nargv[i++] = rhost;
X if (ruserok(rhost, root_user, ruser, luser) == 0)
X nargv[i++] = "-f";
X nargv[i++] = luser;
X nargv[i++] = NULL;
X
X } else {
X
X fprintf(stderr, USAGE, argv[0]);
X exit(1);
X
X }
X
X (void) execv(LOGIN, nargv);
X fprintf(stderr, "%s: could not exec '%s' [%s]\n",
X argv[0], LOGIN, sys_errlist[errno]);
X exit(1);
X /*NOTREACHED*/
X}
END_OF_FILE
if test 1834 -ne `wc -c <'scologin.c'`; then
echo shar: \"'scologin.c'\" unpacked with wrong size!
fi
# end of 'scologin.c'
fi
if test -f 'shadow.3' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'shadow.3'\"
else
echo shar: Extracting \"'shadow.3'\" \(2801 characters\)
sed "s/^X//" >'shadow.3' <<'END_OF_FILE'
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.\" @(#)shadow.3 3.1 23:49:42 11/11/90
X.\"
X.TH SHADOW 3
X.SH NAME
Xshadow \- encrypted password file routines
X.SH Syntax
X.IP "" .5i
X#include <shadow.h>
X.IP "" .5i
Xstruct spwd *getspent();
X.br
Xstruct spwd *getspnam(char * name);
X.br
Xvoid setspent();
X.br
Xvoid endspent();
X.br
Xstruct spwd *fgetspent(FILE *fp);
X.br
Xstruct spwd *sgetspent(char *cp);
X.br
Xint putspent(struct spwd *p,FILE *fp);
X.SH DESCRIPTION
X.I shadow
Xmanipulates the contents of the shadow password file,
X\fB/etc/shadow\fR.
XThe structure in the \fI#include\fR file is
X.IP "" .5i
Xstruct spwd {
X.br
X char *sp_namp; /* user login name */
X.br
X char *sp_pwdp; /* encrypted password */
X.br
X long sp_lstchg; /* last password change */
X.br
X int sp_min; /* days until change allowed. */
X.br
X int sp_max; /* days before change required */
X.br
X int sp_warn; /* days warning for expiration */
X.br
X int sp_inact; /* days before account inactive */
X.br
X int sp_expire; /* date when account expires */
X.br
X int sp_flag; /* reserved for future use */
X.br
X}
X.PP
XThe meanings of each field are
X.IP "" .5i
Xsp_namp \- pointer to null-terminated user name.
X.IP "" .5i
Xsp_pwdp \- pointer to null-terminated password.
X.IP "" .5i
Xsp_lstchg \- days since Jan 1, 1970 password was last changed.
X.IP "" .5i
Xsp_min \- days before which password may not be changed.
X.IP "" .5i
Xsp_max \- days after which password must be changed.
X.IP "" .5i
Xsp_warn \- days before password is to expire that user is warned
Xof pending password expiration.
X.IP "" .5i
Xsp_inact \- days after password expires that account is considered
Xinactive and disabled.
X.IP "" .5i
Xsp_expire \- days since Jan 1, 1970 that account will be disabled.
X.IP "" .5i
Xsp_flag \- reserved for future use.
X.SH Description
X\fIgetspent\fR, \fIgetspname\fR, \fIfgetspent\fR, and \fIsgetspent\fR
Xeach return a pointer to a \fBstruct spwd\fR.
X\fIgetspent\fR returns the
Xnext entry from the file, and \fIfgetspent\fR returns the next
Xentry from the given stream, which is assumed to be a file of
Xthe proper format.
X\fIsgetspent\fR returns a pointer to a \fBstruct spwd\fR using the
Xprovided string as input.
X\fIgetspnam\fR searches from the current position in the file for
Xan entry matching \fIname\fR.
X.PP
X\fIsetspent\fR and \fIendspent\fR may be used to begin and end,
Xrespectively, access to the shadow password file.
X.SH Diagnostics
XRoutines return NULL if no more entries are available or if an
Xerror occurs during processing.
X.SH Caveats
XThese routines may only be used by the super user as access to
Xthe shadow password file is restricted.
X.SH Files
X/etc/shadow \- encrypted user passwords
X.SH See Also
Xgetpwent(3),
Xshadow(4)
END_OF_FILE
if test 2801 -ne `wc -c <'shadow.3'`; then
echo shar: \"'shadow.3'\" unpacked with wrong size!
fi
# end of 'shadow.3'
fi
if test -f 'shell.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'shell.c'\"
else
echo shar: Extracting \"'shell.c'\" \(2527 characters\)
sed "s/^X//" >'shell.c' <<'END_OF_FILE'
X/*
X * Copyright 1989, 1990, 1991, 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 <stdio.h>
X#include <errno.h>
X#ifndef BSD
X#include <string.h>
X#include <memory.h>
X#else
X#include <strings.h>
X#define strchr index
X#define strrchr rindex
X#endif
X#include "config.h"
X
X#ifndef lint
Xstatic char _sccsid[] = "@(#)shell.c 3.2 07:55:08 2/6/91";
X#endif
X
Xextern char *newenvp[];
X
X/*
X * shell - execute the named program
X *
X * shell begins by trying to figure out what argv[0] is going to
X * be for the named process. The user may pass in that argument,
X * or it will be the last pathname component of the file with a
X * '-' prepended. The first attempt is to just execute the named
X * file. If the errno comes back "ENOEXEC", the file is assumed
X * at first glance to be a shell script. The first two characters
X * must be "#!", in which case "/bin/sh" is executed to process
X * the file. If all that fails, give up in disgust ...
X */
X
Xvoid shell (file, arg)
Xchar *file;
Xchar *arg;
X{
X char arg0[BUFSIZ];
X FILE *fp;
X char *path;
X int err;
X
X if (file == (char *) 0)
X exit (1);
X
X /*
X * The argv[0]'th entry is usually the path name, but
X * for various reasons the invoker may want to override
X * that. So, we determine the 0'th entry only if they
X * don't want to tell us what it is themselves.
X */
X
X if (arg == (char *) 0) {
X if (path = strrchr (file, '/'))
X path++;
X else
X path = file;
X
X (void) strcpy (arg0 + 1, path);
X arg0[0] = '-';
X arg = arg0;
X }
X#ifndef NDEBUG
X printf ("Executing shell %s\n", file);
X#endif
X
X /*
X * First we try the direct approach. The system should be
X * able to figure out what we are up to without too much
X * grief.
X */
X
X execle (file, arg, (char *) 0, newenvp);
X err = errno;
X
X /*
X * It is perfectly OK to have a shell script for a login
X * shell, and this code attempts to support that. It
X * relies on the standard shell being able to make sense
X * of the "#!" magic number.
X */
X
X if (err == ENOEXEC) {
X if (fp = fopen (file, "r")) {
X if (getc (fp) == '#' && getc (fp) == '!') {
X fclose (fp);
X execle ("/bin/sh", "sh",
X file, (char *) 0, newenvp);
X err = errno;
X } else {
X fclose (fp);
X }
X }
X }
X
X /*
X * Obviously something is really wrong - I can't figure out
X * how to execute this stupid shell, so I might as well give
X * up in disgust ...
X */
X
X sprintf (arg0, "Cannot execute %s", file);
X errno = err;
X perror (arg0);
X exit (err);
X}
END_OF_FILE
if test 2527 -ne `wc -c <'shell.c'`; then
echo shar: \"'shell.c'\" unpacked with wrong size!
fi
# end of 'shell.c'
fi
if test -f 'usermod.1' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'usermod.1'\"
else
echo shar: Extracting \"'usermod.1'\" \(3224 characters\)
sed "s/^X//" >'usermod.1' <<'END_OF_FILE'
X.\" Copyright 1991, John F. Haugh II
X.\" All rights reserved.
X.\"
X.\" Permission is granted to copy and create derivative works for any
X.\" non-commercial purpose, provided this copyright notice is preserved
X.\" in all copies of source code, or included in human readable form
X.\" and conspicuously displayed on all copies of object code or
X.\" distribution media.
X.\"
X.\" @(#)usermod.1 3.1 07:46:06 7/13/91
X.\"
X.TH USERMOD 1M
X.SH NAME
Xusermod \- Modify a user account
X.SH SYNOPSIS
X.B usermod
X[ \fB-c\fI comment\fR ]
X[ \fB-d\fI home_dir \fR[ \fB-m\fR ] ]
X[ \fB-e\fI expire_date\fR ]
X[ \fB-f\fI inactive_time\fR ]
X[ \fB-g\fI initial_group\fR ]
X[ \fB-G\fI group[,...]\fR ]
X[ \fB-l\fI login_name \fR ]
X[ \fB-s\fI shell\fR ]
X[ \fB-u\fI uid \fR[ \fB-o\fR ]
X.I login
X.SH DESCRIPTION
XThe \fIusermod\fR command modifies the system account files to reflect
Xthe changes that are specified on the command line.
XThe options which apply to the \fIusermod\fR command are
X.IP "\fB-c \fIcomment\fR"
XThe new value of the user's password file comment field.
XIt is normally modified using the \fBchfn(1)\fR utility.
X.IP "\fB-d \fIhome_dir\fR"
XThe user's new login directory.
XIf the \fB-m\fR option is given the contents of the current home directory
Xwill be moved to the new home directory, which is created if it does not
Xalready exist.
X.IP "\fB-e \fIexpire_date\fR"
XThe date on which the user account will be disabled.
XThe date is specified in the format \fIMM/DD/YY\fR.
X.IP "\fB-f \fIinactive_days\fR"
XThe number of days after a password expires until the account
Xis permanently disabled.
XA value of 0 disables the account as soon as the password has
Xexpired, and a value of -1 disables the feature.
XThe default value is -1.
X.IP "\fB-g \fIinitial_group\fR"
XThe group name or number of the user's new initial login group.
XThe group name must exist. A group number must refer to an
Xalready existing group.
XThe default group number is 1.
X.IP "\fB-G \fIgroup,[...]\fR"
XA list of supplementary groups which the user is also a member
Xof.
XEach group is separated from the next by a comma, with no
Xintervening whitespace.
XThe groups are subject to the same restrictions as the group
Xgiven with the \fB-g\fR option.
XIf the user is currently a member of a group which is not listed,
Xthe user will be removed from the group
X.IP "\fB-l \fIlogin_name\fR"
XThe name of the user will be changed from \fIlogin\fR to
X\fIlogin_name\fR.
XNothing else is changed.
XIn particular, the user's home directory name should probably
Xbe changed to reflect the new login name.
X.IP "\fB-s \fIshell\fR"
XThe name of the user's new login shell.
XSetting this field to blank causes the system
Xto select the default login shell.
X.IP "\fB-u \fIuid\fR"
XThe numerical value of the user's ID.
XThis value must be unique, unless the \fI-o\fR option is used.
XThe value must be non-negative.
XValues between 0 and 99 are typically reserved for system accounts.
XAny files which the user owned must have the file user ID changed
Xmanually.
X.SH Files
X/etc/passwd \- user account information
X.br
X/etc/shadow \- secure user account information
X.br
X/etc/group \- group information
X.SH SEE ALSO
X\fBchfn(1), chsh(1), groupadd(1M), groupdel(1M), groupmod(1M),
Xpasswd(1), useradd(1M), userdel(1M)
END_OF_FILE
if test 3224 -ne `wc -c <'usermod.1'`; then
echo shar: \"'usermod.1'\" unpacked with wrong size!
fi
# end of 'usermod.1'
fi
echo shar: End of archive 9 \(of 11\).
cp /dev/null ark9isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 11 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still must unpack the following archives:
echo " " ${MISSING}
fi
exit 0
exit 0 # Just in case...