#! /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:
#	Makefile
#	age.c
#	config.h
#	pwconv.c
#	pwent.c
#	pwpack.c
#	pwunconv.c
#	shadow.c
#	shadow.h
# This archive created: Fri Nov  9 10:22:06 1990
# By:	John F. Haugh II (River Parishes Programming, Austin TX)
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
#
# Copyright 1988,1989,1990, John F. Haugh II
# All rights reserved.
#
# Non-commercial distribution permitted.  You must provide this source
# code in any distribution.  This notice must remain intact.
#
#	%W%	%U%  - Shadow password system
#
#	%W%	%U%	%G%
#
SHELL = /bin/sh

#
# Set this flag to decide what level of code "get" returns.
# The base USENET release was release 1.  It is no longer supported.
# The unreleased version with the utilities added was release 2.
# The unreleased version with database-like file access is release 3.
RELEASE = 3
GFLAGS = -t -r$(RELEASE)

# Define the directory login is copied to.  BE VERY CAREFUL!!!
# LOGINDIR = /bin
LOGINDIR = /etc

# Pick your favorite C compiler and tags command
CC = cc
TAGS = ctags

# OS.  Currently only BSD and USG are defined.  If you don't use BSD,
# USG (System V) is assumed.
OS = -DUSG
# OS = -DBSD

# Do you have to do ranlib?  Sorry to hear that ...
RANLIB = ranlib
# RANLIB = echo

# Flags for SCO Xenix/386
CFLAGS = -O -M3 -g $(PWDEF) $(AL64DEF) $(OS)
LIBS = -lcrypt -ldbm
LDFLAGS = -M3 -g
LTFLAGS = 
# This should be Slibsec.a for small model, or Llibsec.a for
# large model or whatever.  MUST AGREE WITH CFLAGS!!!
LIBSEC = Slibsec.a

# Flags for normal machines
# CFLAGS = -O -g $(PWDEF) $(AL64DEF) $(OS)
# LIBS =
# LDFLAGS = -g
# LIBSEC = libsec.a

# Rules for .L (lint) files
.SUFFIXES: .L
LINT = lint
LINTFLAGS = $(OS)

.c.L:
	$(LINT) $(LINTFLAGS) $< > $*.L

LOBJS = lmain.o login.o env.o password.o entry.o valid.o setup.o shell.o age.o \
	pwent.o utmp.o sub.o mail.o motd.o log.o shadow.o dialup.o dialchk.o \
	ttytype.o failure.o port.o pwpack.o

LSRCS = lmain.c login.c env.c password.c entry.c valid.c setup.c shell.c age.c \
	pwent.c utmp.c sub.c mail.c motd.c log.c shadow.c dialup.c dialchk.c \
	ttytype.c failure.c port.c pwpack.c

SOBJS = smain.o env.o password.o entry.o suvalid.o susetup.o sushell.o \
	pwent.o susub.o mail.o motd.o sulog.o shadow.o suage.o pwpack.o

SSRCS = smain.c env.c password.c entry.c valid.c setup.c shell.c \
	pwent.c sub.c mail.c motd.c sulog.c shadow.c age.c pwpack.c

POBJS = pmain.o password.o entry.o valid.o pwage.o pwent.o obscure.o shadow.o \
	pwpack.o

PSRCS = pmain.c password.c entry.c valid.c age.c pwent.c obscure.c shadow.c \
	pwpack.c

GPSRCS = gpmain.c password.c grent.c

GPOBJS = gpmain.o password.o grent.o

PWOBJS = pwconv.o pwent.o shadow.o pwage.o pwpack.o

PWSRCS = pwconv.c pwent.c shadow.c age.c pwpack.c

PWUNOBJS = pwunconv.o pwent.o shadow.o pwage.o pwpack.o

PWUNSRCS = pwunconv.c pwent.c shadow.c age.c pwpack.c

SULOGOBJS = sulogin.o entry.o env.o password.o pwage.o pwent.o setup.o \
	shadow.o shell.o valid.o pwpack.o

SULOGSRCS = sulogin.c entry.c env.c password.c age.c pwent.c setup.c \
	shadow.c shell.c valid.c pwpack.c

DBOBJS = mkpasswd.o pwent.o pwpack.o

DBSRCS = mkpasswd.c pwent.c pwpack.c

NGSRCS = newgrp.c shadow.c password.c

NGOBJS = newgrp.o shadow.o password.o

CHFNSRCS = chfn.c pwent.c pwpack.c

CHFNOBJS = chfn.o pwent.o pwpack.o

CHSHSRCS = chsh.c pwent.c pwpack.c

CHSHOBJS = chsh.o pwent.o pwpack.o

CHAGEOBJS = chage.o pwent.o pwpack.o pwage.o shadow.o

CHAGESRCS = chage.c pwent.c pwpack.c age.c shadow.c

ALLSRCS = age.c dialchk.c dialup.c entry.c env.c lmain.c log.c login.c mail.c \
	motd.c obscure.c password.c pmain.c pwconv.c pwent.c pwunconv.c \
	setup.c shadow.c shell.c smain.c sub.c sulog.c sulogin.c ttytype.c \
	utmp.c valid.c port.c newgrp.c gpmain.c grent.c mkpasswd.c pwpack.c \
	chfn.c chsh.c chage.c

FILES1 = README newgrp.c Makefile config.h pwunconv.c obscure.c age.c \
	sub.c login.c shell.c lastlog.h

FILES2 = pmain.c port.c lmain.c mkpasswd.c sulogin.c pwpack.c dialup.c \
	sulog.c password.c env.c mail.c dialchk.c

FILES3 = chfn.c chsh.c smain.c faillog.c pwconv.c failure.c utmp.c shadow.c \
	log.c shadow.h faillog.h

FILES4 = gpmain.c chage.c pwent.c valid.c setup.c entry.c ttytype.c port.h \
	grent.c motd.c dialup.h

MAN_1 = chage.1 chfn.1 chsh.1 login.1 passwd.1 su.1
MAN_3 = shadow.3
MAN_4 = faillog.4 passwd.4 porttime.4 shadow.4
MAN_8 = faillog.8 pwconv.8 pwunconv.8 sulogin.8

DOCS = $(MAN_1) $(MAN_3) $(MAN_4) $(MAN_8)

BINS = su login pwconv pwunconv passwd sulogin faillog newgrp gpasswd \
	mkpasswd chfn chsh chage

all:	$(BINS) $(DOCS)

libsec: shadow.o
	ar rv $(LIBSEC) shadow.o
	$(RANLIB) $(LIBSEC)

install: all
	strip $(BINS)
	cp login $(LOGINDIR)/login
	cp mkpasswd pwconv pwunconv sulogin /etc
	cp su passwd gpasswd faillog newgrp chfn chsh /bin
	cp shadow.h /usr/include
	chown root $(LOGINDIR)/login /etc/pwconv /etc/pwunconv /etc/sulogin \
		/bin/su /bin/passwd /bin/gpasswd /bin/newgrp /etc/mkpasswd
	chgrp root $(LOGINDIR)/login /etc/pwconv /etc/pwunconv /etc/sulogin \
		/bin/su /bin/passwd /bin/gpasswd /bin/newgrp /etc/mkpasswd
	chown bin /bin/faillog /usr/include/shadow.h
	chgrp bin /bin/faillog /usr/include/shadow.h
	chmod 700 /etc/pwconv /etc/pwunconv /etc/sulogin /etc/mkpasswd
	chmod 4711 $(LOGINDIR)/login /bin/su /bin/passwd /bin/gpasswd \
		/bin/newgrp /bin/chfn
	chmod 711 /bin/faillog
	chmod 444 /usr/include/shadow.h

lint:	su.lint login.lint pwconv.lint pwunconv.lint passwd.lint sulogin.lint \
	faillog.lint newgrp.lint gpasswd.lint mkpasswd.lint chfn.lint \
	chsh.lint chage.lint $(ALLSRCS:.c=.L)

tags:	$(ALLSRCS)
	$(TAGS) $(ALLSRCS)

README:	s.README
	get -t -r$(RELEASE) s.README
	
$(DOCS):
	get -t -r$(RELEASE) s.$@

login:	$(LOBJS)
	$(CC) -o login $(LDFLAGS) $(LOBJS) $(LIBS)

login.lint: $(LSRCS)
	$(LINT) $(LINTFLAGS) $(LSRCS) > login.lint

su:	$(SOBJS)
	$(CC) -o su $(LDFLAGS) $(SOBJS) $(LIBS)

su.lint:	$(SSRCS)
	$(LINT) $(LINTFLAGS) -DSU $(SSRCS) > su.lint

passwd:	$(POBJS)
	$(CC) -o passwd $(LDFLAGS) $(POBJS) $(LIBS)

passwd.lint: $(PSRCS)
	$(LINT) $(LINTFLAGS) -DPASSWD $(PSRCS) > passwd.lint

gpasswd: $(GPOBJS)
	$(CC) -o gpasswd $(LDFLAGS) $(GPOBJS) $(LIBS)

gpasswd.lint: $(GPSRCS)
	$(LINT) $(LINTFLAGS) $(GPSRCS) > gpasswd.lint

pwconv:	$(PWOBJS) config.h
	$(CC) -o pwconv $(LDFLAGS) $(PWOBJS) $(LIBS)

pwconv.lint: $(PWSRCS) config.h
	$(LINT) $(LINTFLAGS) -DPASSWD $(PWSRCS) > pwconv.lint

pwunconv: $(PWUNOBJS)
	$(CC) -o pwunconv $(LDFLAGS) $(PWUNOBJS) $(LIBS)

pwunconv.lint: $(PWUNSRCS)
	$(LINT) $(LINTFLAGS) -DPASSWD $(PWUNSRCS) > pwunconv.lint

sulogin: $(SULOGOBJS)
	$(CC) -o sulogin $(LDFLAGS) $(SULOGOBJS) $(LIBS)

sulogin.lint: $(SULOGSRCS)
	$(LINT) $(LINTFLAGS) $(SULOGSRCS) > sulogin.lint

faillog: faillog.o
	$(CC) -o faillog $(LDFLAGS) faillog.o $(LIBS)

faillog.lint: faillog.c faillog.h config.h
	$(LINT) $(LINTFLAGS) faillog.c > faillog.lint

mkpasswd: $(DBOBJS)
	$(CC) -o mkpasswd $(LDFLAGS) $(DBOBJS) $(LIBS)

mkpasswd.lint: $(DBSRCS)
	$(LINT) $(LINTFLAGS) $(DBSRCS) > mkpasswd.lint

newgrp: $(NGOBJS)
	$(CC) -o newgrp $(LDFLAGS) $(NGOBJS) $(LIBS)

newgrp.lint: $(NGSRCS)
	$(LINT) $(LINTFLAGS) $(NGSRCS) > newgrp.lint

chfn:	$(CHFNOBJS)
	$(CC) -o chfn $(LDFLAGS) $(CHFNOBJS) $(LIBS)

chfn.lint:	$(CHFNSRCS)
	$(LINT) $(LINTFLAGS) $(CHFNSRCS) > chfn.lint

chsh:	$(CHSHOBJS)
	$(CC) -o chsh $(LDFLAGS) $(CHSHOBJS) $(LIBS)

chsh.lint: $(CHSHSRCS)
	$(LINT) $(LINTFLAGS) $(CHSHSRCS) > chsh.lint

chage:	$(CHAGEOBJS)
	$(CC) -o chage $(LDFLAGS) $(CHAGEOBJS) $(LIBS)

chage.lint: $(CHAGESRCS)
	$(LINT) $(LINTFLAGS) -DPASSWD $(CHAGESRCS) > chage.lint

sushell.c: shell.c
	cp shell.c sushell.c

sushell.o: config.h sushell.c
	$(CC) -c $(CFLAGS) -DSU sushell.c

susub.c: sub.c
	cp sub.c susub.c

susub.o: config.h susub.c
	$(CC) -c $(CFLAGS) -DSU susub.c

sulog.o: config.h

susetup.c: setup.c
	cp setup.c susetup.c

susetup.o: config.h setup.c
	$(CC) -c $(CFLAGS) -DSU susetup.c

suvalid.c: valid.c
	cp valid.c suvalid.c

suvalid.o: config.h valid.c
	$(CC) -c $(CFLAGS) -DSU suvalid.c

pmain.o: config.h lastlog.h shadow.h

pwage.o: age.c config.h
	cp age.c pwage.c
	$(CC) -c $(CFLAGS) -DPASSWD pwage.c
	rm pwage.c

suage.o: age.c config.h
	cp age.c suage.c
	$(CC) -c $(CFLAGS) -DSU suage.c
	rm suage.c

lmain.o: config.h lastlog.h faillog.h

smain.o: config.h lastlog.h

setup.o: config.h

utmp.o: config.h

mail.o: config.h

motd.o: config.h

age.o: config.h

log.o: config.h lastlog.h

shell.o: config.h

entry.o: config.h shadow.h

shadow.o: shadow.h

dialup.o: dialup.h

dialchk.o: dialup.h config.h

valid.o: config.h

failure.o: faillog.h config.h

faillog.o: faillog.h config.h

pwent.o: config.h

port.o: port.h

newgrp.o: config.h shadow.h

mkpasswd.o: config.h

gpmain.o: config.h

chfn.o: config.h

chsh.o: config.h

chage.o: config.h shadow.h

pwconv.o: config.h shadow.h

pwunconv.o: config.h shadow.h

clean:
	-rm -f *.o a.out core npasswd nshadow *.pag *.dir

clobber: clean
	-rm -f $(BINS) *.lint *.L sushell.c susetup.c susub.c suvalid.c

nuke:	clobber
	-for file in * ; do \
		if [ -f s.$$file -a ! -f p.$$file ] ; then \
			rm -f $$file ;\
		fi ;\
	done

shar:	login.sh.1 login.sh.2 login.sh.3 login.sh.4 login.sh.5

login.sh.1: $(FILES1)
	shar -a $(FILES1) > login.sh.1

login.sh.2: $(FILES2)
	shar -a $(FILES2) > login.sh.2

login.sh.3: $(FILES3)
	shar -a $(FILES3) > login.sh.3

login.sh.4: $(FILES4)
	shar -a $(FILES4) > login.sh.4

login.sh.5: $(DOCS)
	shar -a $(DOCS) > login.sh.5
SHAR_EOF
fi
if test -f 'age.c'
then
	echo shar: "will not over-write existing file 'age.c'"
else
cat << \SHAR_EOF > 'age.c'
/*
 * Copyright 1989, 1990, John F. Haugh II
 * All rights reserved.
 *
 * Use, duplication, and disclosure prohibited without
 * the express written permission of the author.
 */

#include <sys/types.h>
#include <stdio.h>
#include <pwd.h>
#include "config.h"

#ifndef	lint
static	char	_sccsid[] = "@(#)age.c	2.6	10:20:04	11/9/90";
#endif

#ifndef	PASSWD
extern	char	*newenvp[];
#endif

#ifndef	WARNAGE
#define	WARNAGE	10
#endif

time_t	time ();

int	c64i (c)
char	c;
{
	if (c == '.')
		return (0);

	if (c == '/')
		return (1);

	if (c >= '0' && c <= '9')
		return (c - '0' + 2);

	if (c >= 'A' && c <= 'Z')
		return (c - 'A' + 12);

	if (c >= 'a' && c <= 'z')
		return (c - 'a' + 38);
	else
		return (-1);
}

int	i64c (i)
int	i;
{
	if (i < 0)
		return ('.');
	else if (i > 63)
		return ('z');

	if (i == 0)
		return ('.');

	if (i == 1)
		return ('/');

	if (i >= 2 && i <= 11)
		return ('0' - 2 + i);

	if (i >= 12 && i <= 37)
		return ('A' - 12 + i);

	if (i >= 38 && i <= 63)
		return ('a' - 38 + i);

	return ('\0');
}

#ifdef	AGING
#ifdef	NEED_AL64
#ifdef	PASSWD
char	*l64a (l)
long	l;
{
	static	char	buf[8];
	int	i = 0;

	if (i < 0L)
		return ((char *) 0);

	do {
		buf[i++] = i64c ((int) (l % 64));
		buf[i] = '\0';
	} while (l /= 64L, l > 0 && i < 6);

	return (buf);
}
#endif

long	a64l (s)
char	*s;
{
	int	i;
	long	value;
	long	shift = 0;

	for (i = 0, value = 0L;i < 6 && *s;s++) {
		value += (c64i (*s) << shift);
		shift += 6;
	}
	return (value);
}
#endif
#ifndef	PASSWD
void	expire (name, last, min, max)
char	*name;
long	last;
int	min;
int	max;
{
	long	clock;
	long	week;
	long	expires;
	extern	int	errno;

	(void) time (&clock);
	clock /= (24L * 60L * 60L);

	if (min < 0)
		min = 0;

	if (max < 0)
		max = 10000;	/* 10000 is infinity */

	if (last <= 0L)
		expires = 0L;
	else
		expires = last + max;

	if (max < 10000 && (clock >= expires || min == max)) {
#ifndef	SU
		printf ("Your password has expired.");

		if (max < min) {
			puts ("  Contact the system administrator.\n");
			exit (1);
		}
		puts ("  Choose a new one.\n");

		execl ("/bin/passwd", "-passwd", name, (char *) 0);
		puts ("Can't execute /bin/passwd");
		exit (errno);
#else
		printf ("Your password has expired.\n");
#ifdef	SULOG
		sulog (0);
#endif
		exit (1);
#endif
	}
}

void	agecheck (last, min, max, warn)
long	last;
int	min;
int	max;
int	warn;
{
	long	clock = time ((long *) 0) / (24L * 3600);
	long	remain;

	if (last == 0)
		return;

	if ((remain = (last + max) - clock) <= warn)
		printf ("Your password will expire in %d %s.\n",
			remain, remain == 1 ? "day":"days");
}
#endif
#endif
SHAR_EOF
fi
if test -f 'config.h'
then
	echo shar: "will not over-write existing file 'config.h'"
else
cat << \SHAR_EOF > 'config.h'
/*
 * Copyright 1989, 1990, John F. Haugh II
 * All rights reserved.
 *
 * Use, duplication, and disclosure prohibited without
 * the express written permission of the author.
 */

/*
 * Configuration file for login.
 *
 *	@(#)config.h	2.6	08:26:28	8/20/90
 */

/*
 * Define DIALUP to use dialup password files.  Define PORTTIME
 * to use the port time restriction file, see port.h for more
 * information.
 */

#define	DIALUP
#define	PORTTIME

/*
 * Define SHADOWPWD to use shadow [ unreadable ] password file
 */

#define	SHADOWPWD

/*
 * Define DOUBLESIZE to use 16 character passwords
 */

#define DOUBLESIZE

/*
 * Define OBSCURE to include hard password testing code.
 */

#define	OBSCURE

/*
 * Define PASSLENGTH to be shortest legal password
 */

#define	PASSLENGTH	5

/*
 * Define NOBLANK if you want all passwords prompted for, including
 * empty ones.

#undef	NOBLANK

/*
 * Define MAXDAYS to be the default maximum number of days a password
 * is valid for when converting to shadow passwords.  Define MINDAYS
 * to be the minimum number of days before a password may be changed.
 * See pwconv.c for more details.
 */

#define	MAXDAYS	10000
#define	MINDAYS	0

/*
 * Define NDEBUG for production versions
 */

#define	NDEBUG

/*
 * Define HZ if login must set HZ value
 */

#define	HZ	"HZ=50"

/*
 * Define TZ if login must set timezone
 *
 * The first example sets the variable directly.  The
 * second example names a file which is read to determine
 * the proper value.  The file consists of a single line
 * of the form 'TZ=zone-name'
 */

/* #define	TZ	"TZ=CST6CDT" */
#define	TZ	"/etc/tzname"

/*
 * Define the default PATH and SUPATH here.  PATH is for non-privileged
 * users, SUPATH is for root.  The first pair are for real trusting
 * systems, the second pair are for the paranoid ...
 */

/* #define	PATH	"PATH=:/bin:/usr/bin"	*/
/* #define	SUPATH	"PATH=:/bin:/usr/bin:/etc" */
#define	PATH	"PATH=/bin:/usr/bin"
#define	SUPATH	"PATH=/bin:/usr/bin:/etc"

/*
 * Define the mailbox directory
 */

#define	MAILDIR	"/usr/spool/mail/"

/*
 * Define AGING if you want the password aging checks made.
 * Define WARNAGE to be the number of days notice a user receives
 * of a soon to expire password.
 */

#define	AGING
#define	WARNAGE	10

/*
 * Define MAILCHECK if you want the mailbox checked for new mail
 *
 * One of two messages are printed - `You have new mail.' or
 * `You have mail.'.
 */

#define	MAILCHECK

/*
 * Define CONSOLE if you want ROOT restricted to a particular terminal.
 *
 * Use the name of the tty line if you only want a single line, or use
 * the name of the file containing the permissible ports if you wish to
 * allow root logins on more than one port.
 */

/* #define	CONSOLE	"console"	/* root on /dev/console only */
#define	CONSOLE	"/etc/consoles"		/* check /etc/consoles for a list */

/*
 * Define NOLOGINS if you want to be able to deny non-root users logins.
 * Logins will not be permitted if this file exists.
 */

#define	NOLOGINS	"/etc/nologin"

/*
 * Define NOUSE if you want to be able to declare accounts which can't
 * be logged into.  Define NOLOGIN if you want it to be an su-only account.
 */

#define	NOUSE	"NOUSE"
#define	NOLOGIN	"NOLOGIN"

/*
 * Define MOTD if you want the message of the day (/etc/motd) printed
 * at login time.
 */

#define	MOTD

/*
 * Define HUSHLOGIN if you want the code added to avoid printing the
 * motd if a file $HOME/.hushlogin exists.  This obviously only matters
 * if any of MOTD, MAILCHECK or LASTLOG are #define'd.
 */

#define	HUSHLOGIN

/*
 * Define LASTLOG if you want a record made of logins in /usr/adm/lastlog.
 */

#define	LASTLOG

/*
 * Define FAILLOG if you want a record make of failed logins in
 * /usr/adm/faillog.  See faillog.h for more details.  See fail(1L)
 * for even still more details ...  Also, define FTMP to record utmp
 * style records for failed logins.  FTMP is the name of a utmp-like
 * file.  You can use who(1) instead of faillog(L), which is an
 * advantage.  Define UNKNOWNS if you do want unknown user names
 * recorded.  This can be a security hole since passwords are often
 * entered mistakenly as user names.
 */

#define	FAILLOG
#define	FTMP	"/etc/ftmp"
#define	UNKNOWNS

/*
 * Define TTYPERM to be the initial terminal permissions.  Defining
 * as 0600 will not allow messages, 0622 will.
 */

#define	TTYPERM	0600

/*
 * Define TTYTYPE to the be name of the port to terminal type
 * mapping file.  This is used to set the environmental variable
 * "TERM" to the correct terminal type.
 */

#define	TTYTYPE	"/etc/ttytype"

/*
 * Define QUOTAS if you want the code added in setup.c to support
 * file ulimit and nice [ and umask as well ] setting from the password
 * file.
 */

#define	QUOTAS

/*
 * Pick your version of DBM.  Only DBM is presently supported, NDBM will
 * follow.  You must also define the GETPWENT macro below.
 */

#define	DBM

/*
 * Define file name for sulog.  If SULOG is not defined, there will be
 * no logging.  This is NOT a good idea ...  We also define other file
 * names.
 */

#define	SULOG	"/usr/adm/sulog"
#define	SUCON	"/dev/console"
#define	PWDFILE	"/etc/passwd"
#define	OPWDFILE "/etc/-passwd"
#define	NPWDFILE "/etc/npasswd"
#define	OSHADOW "/etc/-shadow"
#define	NSHADOW "/etc/nshadow"
#define	GRPFILE	"/etc/group"
#define	OGRPFILE "/etc/-group"
#define	NGRPFILE "/etc/ngroup"

/*
 * Define PWDLOCK to be a locking semaphore for updating the password
 * file.  GRPLOCK is the same for the group file.
 */

#define	PWDLOCK	"/etc/.pwdlock"
#define	GRPLOCK "/etc/.grplock"

/*
 * Wierd stuff follows ...
 *
 *	The following macros exist solely to override stuff ...
 *	You will probably want to change their values to suit your
 *	fancy.
 */

#define	ERASECHAR	'\b'
#define	KILLCHAR	'\025'
#define	UMASK		022

#define	ULIMIT	(1L<<20) /* Define if your UNIX supports ulimit() */
#define	FGETPWENT	/* Define if library does not include FGETPWENT */
#define	GETPWENT	/* Define if you want my GETPWENT(3) routines */
#define	NEED_AL64	/* Define if library does not include a64l() */
SHAR_EOF
fi
if test -f 'pwconv.c'
then
	echo shar: "will not over-write existing file 'pwconv.c'"
else
cat << \SHAR_EOF > 'pwconv.c'
/*
 * Copyright 1989, 1990, John F. Haugh II
 * All rights reserved.
 *
 * Use, duplication, and disclosure prohibited without
 * the express written permission of the author.
 */

/*
 * pwconv - convert and update shadow password files
 *
 *	Pwconv copies the old password file information to a new shadow
 *	password file, merging entries from an optional existing shadow
 *	file.
 *
 *	The new password file is left in npasswd, the new shadow file is
 *	left in nshadow.  Existing shadow entries are copied as is.
 *	New entries are created with passwords which expire in MAXDAYS days,
 *	with a last changed date of today, unless password aging
 *	information was already present.  Likewise, the minimum number of
 *	days before which the password may be changed is controlled by
 *	MINDAYS.  The number of warning days is set to WARNAGE if that
 *	macro exists.  Entries with blank passwordsare not copied to the
 *	shadow file at all.
 */

#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <pwd.h>
#ifndef	BSD
#include <string.h>
#else
#define	strchr	index
#define	strrchr	rindex
#include <strings.h>
#endif
#include "config.h"
#include "shadow.h"

#ifndef	lint
static	char	_sccsid[] = "@(#)pwconv.c	3.1	08:21:33	11/9/90";
#endif

char	buf[BUFSIZ];

long	time ();
long	a64l ();

int	main ()
{
	long	today;
	struct	passwd	*pw;
	struct	passwd	*sgetpwent ();
	FILE	*pwd;
	FILE	*npwd;
	FILE	*shadow;
	struct	spwd	*spwd;
	struct	spwd	tspwd;
	int	fd;
	char	*cp;

	if (! (pwd = fopen (PWDFILE, "r"))) {
		perror (PWDFILE);
		exit (1);
	}
	unlink ("npasswd");
	if ((fd = open ("npasswd", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 ||
			! (npwd = fdopen (fd, "w"))) {
		perror ("npasswd");
		exit (1);
	}
	unlink  ("nshadow");
	if ((fd = open ("nshadow", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 ||
			! (shadow = fdopen (fd, "w"))) {
		perror ("nshadow");
		(void) unlink ("npasswd");
		(void) unlink ("nshadow");
		exit (1);
	}

	(void) time (&today);
	today /= (24L * 60L * 60L);

	while (fgets (buf, BUFSIZ, pwd) == buf) {
		if (cp = strrchr (buf, '\n'))
			*cp = '\0';

		if (buf[0] == '#') {	/* comment line */
			(void) fprintf (npwd, "%s\n", buf);
			continue;
		}
		if (! (pw = sgetpwent (buf))) { /* copy bad lines verbatim */
			(void) fprintf (npwd, "%s\n", buf);
			continue;
		}
		if (pw->pw_passwd[0] == '\0') { /* no password, skip */
			(void) fprintf (npwd, "%s\n", buf);
			continue;
		}
		setspent ();		/* rewind old shadow file */

		if (spwd = getspnam (pw->pw_name)) {
			if (putspent (spwd, shadow)) { /* copy old entry */
				perror ("nshadow");
				goto error;
			}
		} else {		/* need a new entry. */
			tspwd.sp_namp = pw->pw_name;
			tspwd.sp_pwdp = pw->pw_passwd;
			pw->pw_passwd = "x";

			if (pw->pw_age) { /* copy old password age stuff */
				if (strlen (pw->pw_age) >= 2) {
					tspwd.sp_min = c64i (pw->pw_age[1]);
					tspwd.sp_max = c64i (pw->pw_age[0]);
				} else {
					tspwd.sp_min = tspwd.sp_max = -1;
				}
				if (strlen (pw->pw_age) == 4)
					tspwd.sp_lstchg = a64l (&pw->pw_age[2]);
				else
					tspwd.sp_lstchg = -1;

				/*
				 * Convert weeks to days
				 */

				if (tspwd.sp_min != -1)
					tspwd.sp_min *= 7;

				if (tspwd.sp_max != -1)
					tspwd.sp_max *= 7;

				if (tspwd.sp_lstchg != -1)
					tspwd.sp_lstchg *= 7;
			} else {	/* fake up new password age stuff */
				tspwd.sp_max = MAXDAYS;
				tspwd.sp_min = MINDAYS;
				tspwd.sp_lstchg = today;
			}
#ifdef	WARNAGE
			tspwd.sp_warn = WARNAGE;
			tspwd.sp_inact = tspwd.sp_expire = tspwd.sp_flag = -1;
#else
			tspwd.sp_warn = tspwd.sp_inact = tspwd.sp_expire =
				tspwd.sp_flag = -1;
#endif
			if (putspent (&tspwd, shadow)) { /* output entry */
				perror ("nshadow");
				goto error;
			}
		}
		(void) fprintf (npwd, "%s:%s:%d:%d:%s:%s:",
				pw->pw_name, pw->pw_passwd,
				pw->pw_uid, pw->pw_gid,
				pw->pw_gecos, pw->pw_dir);

		if (fprintf (npwd, "%s\n",
				pw->pw_shell ? pw->pw_shell:"") == EOF) {
			perror ("npasswd");
			goto error;
		}
	}
	endspent ();

	if (ferror (npwd) || ferror (shadow)) {
		perror ("pwconv");
error:
		(void) unlink ("npasswd");
		(void) unlink ("nshadow");
		exit (1);
	}
	(void) fclose (pwd);
	(void) fclose (npwd);
	(void) fclose (shadow);

	exit (0);
}
SHAR_EOF
fi
if test -f 'pwent.c'
then
	echo shar: "will not over-write existing file 'pwent.c'"
else
cat << \SHAR_EOF > 'pwent.c'
/*
 * Copyright 1989, 1990, John F. Haugh II
 * All rights reserved.
 *
 * Use, duplication, and disclosure prohibited without
 * the express written permission of the author.
 *
 * Duplication is permitted for non-commercial [ profit making ]
 * purposes provided this and other copyright notices remain
 * intact.
 */

#include <stdio.h>
#include <pwd.h>
#include <string.h>
#include "config.h"

#ifdef	DBM
#include <dbm.h>
#endif

#ifndef	lint
static	char	_sccsid[] = "@(#)pwent.c	2.4	23:41:33	10/28/90";
#endif

#define	SBUFSIZ	64
#define	NFIELDS	7

static	FILE	*pwdfp;
static	char	pwdbuf[BUFSIZ];
static	char	*pwdfile = "/etc/passwd";
#ifdef	DBM
static	int	dbmopened;
static	int	dbmerror;
#endif
static	char	*pwdfields[NFIELDS];
static	struct	passwd	pwent;

/*
 * sgetpwent - convert a string to a (struct passwd)
 *
 * sgetpwent() parses a string into the parts required for a password
 * structure.  Strict checking is made for the UID and GID fields and
 * presence of the correct number of colons.  Any failing tests result
 * in a NULL pointer being returned.
 */

struct	passwd	*sgetpwent (buf)
char	*buf;
{
	int	i;
	char	*cp;

	/*
	 * Copy the string to a static buffer so the pointers into
	 * the password structure remain valid.
	 */

	strncpy (pwdbuf, buf, BUFSIZ);
	pwdbuf[BUFSIZ-1] = '\0';

	/*
	 * Save a pointer to the start of each colon separated
	 * field.  The fields are converted into NUL terminated strings.
	 */

	for (cp = pwdbuf, i = 0;i < NFIELDS && cp;i++) {
		pwdfields[i] = cp;
		if (cp = strchr (cp, ':'))
			*cp++ = 0;
	}

	/*
	 * There must be exactly NFIELDS colon separated fields or
	 * the entry is invalid.  Also, the UID and GID must be non-blank.
	 */

	if (i != NFIELDS || *pwdfields[2] == '\0' || *pwdfields[3] == '\0')
		return 0;

	/*
	 * Each of the fields is converted the appropriate data type
	 * and the result assigned to the password structure.  If the
	 * UID or GID does not convert to an integer value, a NULL
	 * pointer is returned.
	 */

	pwent.pw_name = pwdfields[0];
	pwent.pw_passwd = pwdfields[1];
	if ((pwent.pw_uid = strtol (pwdfields[2], &cp, 10)) == 0 && *cp)
		return 0;

	if ((pwent.pw_gid = strtol (pwdfields[3], &cp, 10)) == 0 && *cp)
		return 0;

	if (cp = strchr (pwent.pw_passwd, ',')) {
		pwent.pw_age = cp + 1;
		*cp = '\0';
	} else
		pwent.pw_age = "";

	pwent.pw_gecos = pwdfields[4];
	pwent.pw_dir = pwdfields[5];
	pwent.pw_shell = pwdfields[6];

	return (&pwent);
}
#ifdef FGETPWENT
/*
 * fgetpwent - get a password file entry from a stream
 *
 * fgetpwent() reads the next line from a password file formatted stream
 * and returns a pointer to the password structure for that line.
 */

struct	passwd	*fgetpwent (fp)
FILE	*fp;
{
	char	buf[BUFSIZ];

	while (fgets (buf, BUFSIZ, fp) != (char *) 0) {
		buf[strlen (buf) - 1] = '\0';
		return (sgetpwent (buf));
	}
	return 0;
}
#endif
#ifdef	GETPWENT

/*
 * endpwent - close a password file
 *
 * endpwent() closes the password file if open.
 */

int	endpwent ()
{
	if (pwdfp)
		if (fclose (pwdfp))
			return -1;

	return 0;
}

/*
 * getpwent - get a password entry from the password file
 *
 * getpwent() opens the password file, if not already opened, and reads
 * a single entry.  NULL is returned if any errors are encountered reading
 * the password file.
 */

struct	passwd	*getpwent ()
{
	if (! pwdfp && setpwent ())
		return 0;

	return fgetpwent (pwdfp);
}

/*
 * getpwuid - locate the password entry for a given UID
 *
 * getpwuid() locates the first password file entry for the given UID.
 * If there is a valid DBM file, the DBM files are queried first for
 * the entry.  Otherwise, a linear search is begun of the password file
 * searching for an entry which matches the provided UID.
 */

struct	passwd	*getpwuid (uid)
int	uid;
{
	struct	passwd	*pwd;
#ifdef	DBM
	datum	key;
	datum	content;

	/*
	 * Attempt to open the DBM files if they have never been opened
	 * and an error has never been returned.
	 */

	if (! dbmerror && ! dbmopened) {
		char	dbmfiles[BUFSIZ];

		strcpy (dbmfiles, pwdfile);
		strcat (dbmfiles, ".pag");

		if (access (dbmfiles, 0) || dbminit (pwdfile))
			dbmerror = 1;
		else
			dbmopened = 1;
	}

	/*
	 * If the DBM file are now open, create a key for this UID and
	 * try to fetch the entry from the database.  A matching record
	 * will be unpacked into a static structure and returned to
	 * the user.
	 */

	if (dbmopened) {
		pwent.pw_uid = uid;
		key.dsize = sizeof pwent.pw_uid;
		key.dptr = (char *) &pwent.pw_uid;
		content = fetch (key);
		if (content.dptr != 0) {
			memcpy (pwdbuf, content.dptr, content.dsize);
			pw_unpack (pwdbuf, content.dsize, &pwent);
			return &pwent;
		}
	}
#endif
	/*
	 * Rewind the database and begin searching for an entry which
	 * matches the UID.  Return the entry when a match is found.
	 */

	if (setpwent ())
		return 0;

	while (pwd = getpwent ())
		if (pwd->pw_uid == uid)
			return pwd;

	return 0;
}

struct	passwd	*getpwnam (name)
char	*name;
{
	struct	passwd	*pwd;
#ifdef	DBM
	datum	key;
	datum	content;

	/*
	 * Attempt to open the DBM files if they have never been opened
	 * and an error has never been returned.
	 */

	if (! dbmerror && ! dbmopened) {
		char	dbmfiles[BUFSIZ];

		strcpy (dbmfiles, pwdfile);
		strcat (dbmfiles, ".pag");

		if (access (dbmfiles, 0) || dbminit (pwdfile))
			dbmerror = 1;
		else
			dbmopened = 1;
	}

	/*
	 * If the DBM file are now open, create a key for this UID and
	 * try to fetch the entry from the database.  A matching record
	 * will be unpacked into a static structure and returned to
	 * the user.
	 */

	if (dbmopened) {
		key.dsize = strlen (name);
		key.dptr = name;
		content = fetch (key);
		if (content.dptr != 0) {
			memcpy (pwdbuf, content.dptr, content.dsize);
			pw_unpack (pwdbuf, content.dsize, &pwent);
			return &pwent;
		}
	}
#endif
	/*
	 * Rewind the database and begin searching for an entry which
	 * matches the name.  Return the entry when a match is found.
	 */

	if (setpwent ())
		return 0;

	while (pwd = getpwent ())
		if (strcmp (pwd->pw_name, name) == 0)
			return pwd;

	return 0;
}

/*
 * setpwent - open the password file
 *
 * setpwent() opens the system password file, and the DBM password files
 * if they are present.  The system password file is rewound if it was
 * open already.
 */

int	setpwent ()
{
	if (! pwdfp) {
		if (! (pwdfp = fopen (pwdfile, "r")))
			return -1;
	} else {
		if (fseek (pwdfp, 0L, 0) != 0)
			return -1;
	}
#ifdef	DBM
	/*
	 * Attempt to open the DBM files if they have never been opened
	 * and an error has never been returned.
	 */

	if (! dbmerror && ! dbmopened) {
		char	dbmfiles[BUFSIZ];

		strcpy (dbmfiles, pwdfile);
		strcat (dbmfiles, ".pag");

		if (access (dbmfiles, 0) || dbminit (pwdfile))
			dbmerror = 1;
		else
			dbmopened = 1;
	}
#endif
	return 0;
}
#endif
SHAR_EOF
fi
if test -f 'pwpack.c'
then
	echo shar: "will not over-write existing file 'pwpack.c'"
else
cat << \SHAR_EOF > 'pwpack.c'
/*
 * Copyright 1990, John F. Haugh II
 * All rights reserved.
 *
 * Use, duplication, and disclosure prohibited without
 * the express written permission of the author.
 *
 * Duplication is permitted for non-commercial [ profit making ]
 * purposes provided this and other copyright notices remain
 * intact.
 */

#include <stdio.h>
#include <pwd.h>
#ifdef	BSD
#include <strings.h>
#else
#include <string.h>
#endif

#ifndef	lint
static	char	sccsid[] = "@(#)pwpack.c	2.3	23:06:29	8/5/90";
#endif

int	pw_pack (passwd, buf)
struct	passwd	*passwd;
char	*buf;
{
	char	*cp;

	cp = buf;
	strcpy (cp, passwd->pw_name);
	cp += strlen (cp) + 1;

	strcpy (cp, passwd->pw_passwd);
	if (passwd->pw_age && passwd->pw_age[0]) {
		cp += strlen (cp);
		*cp++ = ',';
		strcpy (cp, passwd->pw_age);
	}
	cp += strlen (cp) + 1;

	memcpy (cp, (void *) &passwd->pw_uid, sizeof passwd->pw_uid);
	cp += sizeof passwd->pw_uid;

	memcpy (cp, (void *) &passwd->pw_gid, sizeof passwd->pw_gid);
	cp += sizeof passwd->pw_gid;

	strcpy (cp, passwd->pw_gecos);
	cp += strlen (cp) + 1;

	strcpy (cp, passwd->pw_dir);
	cp += strlen (cp) + 1;

	strcpy (cp, passwd->pw_shell);
		cp += strlen (cp) + 1;

	return cp - buf;
}

int	pw_unpack (buf, len, passwd)
char	*buf;
int	len;
struct	passwd	*passwd;
{
	char	*org = buf;
	char	*cp;

	passwd->pw_name = buf;
	buf += strlen (buf) + 1;
	if (buf - org > len)
		return -1;

	passwd->pw_passwd = buf;
	buf += strlen (buf) + 1;
	if (buf - org > len)
		return -1;

	if (cp = strchr (passwd->pw_passwd, ',')) {
		*cp++ = '\0';
		passwd->pw_age = cp;
	} else
		passwd->pw_age = "";

	memcpy ((void *) &passwd->pw_uid, (void *) buf, sizeof passwd->pw_uid);
	buf += sizeof passwd->pw_uid;
	if (buf - org > len)
		return -1;

	memcpy ((void *) &passwd->pw_gid, (void *) buf, sizeof passwd->pw_gid);
	buf += sizeof passwd->pw_gid;
	if (buf - org > len)
		return -1;

	passwd->pw_gecos = buf;
	buf += strlen (buf) + 1;
	if (buf - org > len)
		return -1;

	passwd->pw_dir = buf;
	buf += strlen (buf) + 1;
	if (buf - org > len)
		return -1;

	passwd->pw_shell = buf;
	buf += strlen (buf) + 1;
	if (buf - org > len)
		return -1;

	return 0;
}
SHAR_EOF
fi
if test -f 'pwunconv.c'
then
	echo shar: "will not over-write existing file 'pwunconv.c'"
else
cat << \SHAR_EOF > 'pwunconv.c'
/*
 * Copyright 1989, 1990, John F. Haugh II
 * All rights reserved.
 *
 * Use, duplication, and disclosure prohibited without
 * the express written permission of the author.
 */

/*
 * pwunconv - restore old password file from shadow password file.
 *
 *	Pwunconv copies the password file information from the shadow
 *	password file, merging entries from an optional existing shadow
 *	file.
 *
 *	The new password file is left in npasswd.  There is no new
 *	shadow file.  Password aging information is translated where
 *	possible.
 */

#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <pwd.h>
#include "config.h"
#include "shadow.h"

#ifndef	lint
static	char	_sccsid[] = "@(#)pwunconv.c	3.1	08:47:18	11/9/90";
#endif

char	buf[BUFSIZ];
char	*l64a ();

int	main ()
{
	struct	passwd	*pw;
	struct	passwd	*sgetpwent ();
	FILE	*pwd;
	FILE	*npwd;
	struct	spwd	*spwd;
	int	fd;
	char	newage[5];

	if (! (pwd = fopen (PWDFILE, "r"))) {
		perror (PWDFILE);
		return (1);
	}
	unlink ("npasswd");
	if ((fd = open ("npasswd", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 ||
			! (npwd = fdopen (fd, "w"))) {
		perror ("npasswd");
		return (1);
	}
	while (fgets (buf, BUFSIZ, pwd) == buf) {
		buf[strlen (buf) - 1] = '\0'; /* remove '\n' character */

		if (buf[0] == '#') {	/* comment line */
			(void) fprintf (npwd, "%s\n", buf);
			continue;
		}
		if (! (pw = sgetpwent (buf))) { /* copy bad lines verbatim */
			(void) fprintf (npwd, "%s\n", buf);
			continue;
		}
		setspent ();		/* rewind shadow file */

		if (! (spwd = getspnam (pw->pw_name))) {
			(void) fprintf (npwd, "%s\n", buf);
			continue;
		}
		pw->pw_passwd = spwd->sp_pwdp;

	/*
	 * Password aging works differently in the two different systems.
	 * With shadow password files you apparently must have some aging
	 * information.  The maxweeks or minweeks may not map exactly.
	 * In pwconv we set max == 10000, which is about 30 years.  Here
	 * we have to undo that kludge.  So, if maxdays == 10000, no aging
	 * information is put into the new file.  Otherwise, the days are
	 * converted to weeks and so on.
	 */

		if (spwd->sp_max > (63*7) && spwd->sp_max < 10000)
			spwd->sp_max = (63*7); /* 10000 is infinity this week */

		if (spwd->sp_min >= 0 && spwd->sp_min <= 63*7 &&
				spwd->sp_max >= 0 && spwd->sp_max <= 63*7) {
			if (spwd->sp_lstchg == -1)
				spwd->sp_lstchg = clock ((long *) 0) /
					(24L*60L*60L);

			spwd->sp_max /= 7;	/* turn it into weeks */
			spwd->sp_min /= 7;
			spwd->sp_lstchg /= 7;

			strncpy (newage, l64a (spwd->sp_lstchg * (64L*64L) +
				  spwd->sp_min * (64L) + spwd->sp_max), 5);
			pw->pw_age = newage;
		} else
			pw->pw_age = "";

		if (putpwent (pw, npwd)) {
			perror (stderr, "pwunconv: write error");
			exit (1);
		}
	}
	endspent ();

	if (ferror (npwd)) {
		perror ("pwunconv");
		(void) unlink ("npasswd");
	}
	(void) fclose (npwd);
	(void) fclose (pwd);
	return (0);
}
SHAR_EOF
fi
if test -f 'shadow.c'
then
	echo shar: "will not over-write existing file 'shadow.c'"
else
cat << \SHAR_EOF > 'shadow.c'
/*
 * Copyright 1989, 1990, John F. Haugh II
 * All rights reserved.
 *
 * Use, duplication, and disclosure prohibited without
 * the express written permission of the author.
 */

#include "shadow.h"
#include <stdio.h>
#ifndef	BSD
#include <string.h>
#include <memory.h>
#else
#include <strings.h>
#define	strchr	index
#define	strrchr	rindex
#endif

#ifndef	lint
static	char	_sccsid[] = "@(#)shadow.c	3.1	08:12:34	11/9/90";
#endif

static	FILE	*shadow;
#define	FIELDS	9
#define	OFIELDS	5

void
setspent ()
{
	if (shadow)
		rewind (shadow);
	else
		shadow = fopen (SHADOW, "r");
}

void
endspent ()
{
	if (shadow)
		(void) fclose (shadow);

	shadow = (FILE *) 0;
}

struct spwd *
sgetspent (string)
char	*string;
{
	static	char	buf[BUFSIZ];
	static	struct	spwd	spwd;
	char	*fields[FIELDS];
	char	*cp;
	char	*cpp;
	int	atoi ();
	long	atol ();
	int	i;

	strncpy (buf, string, BUFSIZ-1);
	buf[BUFSIZ-1] = '\0';

	if (cp = strrchr (buf, '\n'))
		*cp = '\0';

	for (cp = buf, i = 0;*cp && i < FIELDS;i++) {
		fields[i] = cp;
		while (*cp && *cp != ':')
			cp++;

		if (*cp)
			*cp++ = '\0';
	}
	if (*cp || (i != FIELDS && i != OFIELDS))
		return 0;

	spwd.sp_namp = fields[0];
	spwd.sp_pwdp = fields[1];

	if ((spwd.sp_lstchg = strtol (fields[2], &cpp, 10)) == 0 && *cpp)
		if (fields[2][0] == '\0')
			spwd.sp_lstchg = -1;
		else
			return 0;

	if ((spwd.sp_min = strtol (fields[3], &cpp, 10)) == 0 && *cpp)
		if (fields[3][0] == '\0')
			spwd.sp_min = -1;
		else
			return 0;

	if ((spwd.sp_max = strtol (fields[4], &cpp, 10)) == 0 && *cpp)
		if (fields[4][0] == '\0')
			spwd.sp_max = -1;
		else
			return 0;

	if (i == OFIELDS) {
		spwd.sp_warn = spwd.sp_inact = spwd.sp_expire =
			spwd.sp_flag = -1;

		return &spwd;
	}
	if ((spwd.sp_warn = strtol (fields[5], &cpp, 10)) == 0 && *cpp)
		if (fields[5][0] == '\0')
			spwd.sp_warn = -1;
		else
			return 0;

	if ((spwd.sp_inact = strtol (fields[6], &cpp, 10)) == 0 && *cpp)
		if (fields[6][0] == '\0')
			spwd.sp_inact = -1;
		else
			return 0;

	if ((spwd.sp_expire = strtol (fields[7], &cpp, 10)) == 0 && *cpp)
		if (fields[7][0] == '\0')
			spwd.sp_expire = -1;
		else
			return 0;

	if ((spwd.sp_flag = strtol (fields[8], &cpp, 10)) == 0 && *cpp)
		if (fields[8][0] == '\0')
			spwd.sp_flag = -1;
		else
			return 0;

	return (&spwd);
}

struct spwd
*fgetspent (fp)
FILE	*fp;
{
	char	buf[BUFSIZ];

	if (! fp)
		return (0);

	if (fgets (buf, BUFSIZ, fp) == (char *) 0)
		return (0);

	return sgetspent (buf);
}

struct spwd
*getspent ()
{
	if (! shadow)
		setspent ();

	return (fgetspent (shadow));
}

struct spwd
*getspnam (name)
char	*name;
{
	struct	spwd	*spwd;

	setspent ();

	while ((spwd = getspent ()) != (struct spwd *) 0) {
		if (strcmp (name, spwd->sp_namp) == 0)
			return (spwd);
	}
	return (0);
}

int
putspent (spwd, fp)
struct	spwd	*spwd;
FILE	*fp;
{
	int	errors = 0;

	if (! fp || ! spwd)
		return -1;

	if (fprintf (fp, "%s:%s:", spwd->sp_namp, spwd->sp_pwdp) < 0)
		errors++;

	if (spwd->sp_lstchg != -1) {
		if (fprintf (fp, "%ld:", spwd->sp_lstchg) < 0)
			errors++;
	} else if (putc (':', fp) == EOF)
		errors++;

	if (spwd->sp_min != -1) {
		if (fprintf (fp, "%ld:", spwd->sp_min) < 0)
			errors++;
	} else if (putc (':', fp) == EOF)
		errors++;

	if (spwd->sp_max != -1) {
		if (fprintf (fp, "%ld:", spwd->sp_max) < 0)
			errors++;
	} else if (putc (':', fp) == EOF)
		errors++;

	if (spwd->sp_warn != -1) {
		if (fprintf (fp, "%ld:", spwd->sp_warn) < 0)
			errors++;
	} else if (putc (':', fp) == EOF)
		errors++;

	if (spwd->sp_inact != -1) {
		if (fprintf (fp, "%ld:", spwd->sp_inact) < 0)
			errors++;
	} else if (putc (':', fp) == EOF)
		errors++;

	if (spwd->sp_expire != -1) {
		if (fprintf (fp, "%ld:", spwd->sp_expire) < 0)
			errors++;
	} else if (putc (':', fp) == EOF)
		errors++;

	if (spwd->sp_flag != -1) {
		if (fprintf (fp, "%ld:", spwd->sp_flag) < 0)
			errors++;
	} else if (putc (':', fp) == EOF)
		errors++;

	if (putc ('\n', fp) == EOF)
		errors++;

	if (errors)
		return -1;
	else
		return 0;
}
SHAR_EOF
fi
if test -f 'shadow.h'
then
	echo shar: "will not over-write existing file 'shadow.h'"
else
cat << \SHAR_EOF > 'shadow.h'
/*
 * Copyright 1988, 1989, 1990, John F. Haugh II
 * All rights reserved.
 *
 * Use, duplication, and disclosure prohibited without
 * the express written permission of the author.
 */

/*
 * This information is not derived from AT&T licensed sources.  Posted
 * to the USENET 11/88, and updated 11/90 with information from SVR4.
 *
 *	@(#)shadow.h	3.1	10:14:23	11/9/90
 */

/*
 * Shadow password security file structure.
 */

struct	spwd {
	char	*sp_namp;	/* login name */
	char	*sp_pwdp;	/* encrypted password */
	long	sp_lstchg;	/* date of last change */
	long	sp_min;		/* minimum number of days between changes */
	long	sp_max;		/* maximum number of days between changes */
	long	sp_warn;	/* number of days of warning before password
				   expires */
	long	sp_inact;	/* number of days after password expires
				   until the account becomes unusable. */
	long	sp_expire;	/* days since 1/1/70 until account expires */
	unsigned long	sp_flag; /* reserved for future use */
};

/*
 * Shadow password security file functions.
 */

struct	spwd	*getspent ();
struct	spwd	*getspnam ();
struct	spwd	*sgetspent ();
void	setspent ();
void	endspent ();
struct	spwd	*fgetspent ();
int	putspent ();

#define  SHADOW "/etc/shadow"
SHAR_EOF
fi
exit 0
#	End of shell archive