[alt.sources] Group Password Command redux

jfh@rpp386.cactus.org (John F. Haugh II) (06/26/90)

Someone noted that I neglected to include config.h for people who
don't already have the shadow login stuff.  Also, there was a problem
with root setting passwords on other accounts.

This posting includes a fresh, new, gpasswd.c with the "root changes
password" bug fixed and a copy of the current config.h.

Shar and Enjoy!
--
#! /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
#	gpmain.c
#	grent.c
#	password.c
#	config.h
# This archive created: Tue Jun 26 09:19:37 1990
# By:	John F. Haugh II (River Parishes Programming, Austin TX)
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'Makefile'" '(6678 characters)'
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
X#
X# Copyright 1988,1989,1990, John F. Haugh II
X# All rights reserved.
X#
X# Non-commercial distribution permitted.  You must provide this source
X# code in any distribution.  This notice must remain intact.
X#
X#	@(#)Makefile	2.7	09:40:16  - Shadow password system
X#
X#	@(#)Makefile	2.7	09:40:16	6/22/90
X#
XSHELL = /bin/sh
X
X# Define the directory login is copied to.  BE VERY CAREFUL!!!
X# LOGINDIR = /bin
XLOGINDIR = /etc
X
X# Pick your favorite C compiler and tags command
XCC = cc
XTAGS = ctags
X
X# OS.  Currently only BSD and USG are defined.  If you don't use BSD,
X# USG (System V) is assumed.
X# OS = -DBSD
X
X# Do you have to do ranlib?  Sorry to hear that ...
XRANLIB = ranlib
X# RANLIB = echo
X
X# Flags for SCO Xenix/386
XCFLAGS = -O -M3 -g $(PWDEF) $(AL64DEF) $(OS)
XLIBS = -lcrypt
XLDFLAGS = -M3 -g
XLTFLAGS = 
X# This should be Slibsec.a for small model, or Llibsec.a for
X# large model or whatever.  MUST AGREE WITH CFLAGS!!!
XLIBSEC = Slibsec.a
X
X# Flags for normal machines
X# CFLAGS = -O -g $(PWDEF) $(AL64DEF) $(OS)
X# LIBS =
X# LDFLAGS = -g
X# LIBSEC = libsec.a
X
XLOBJS = lmain.o login.o env.o password.o entry.o valid.o setup.o shell.o age.o \
X	pwent.o utmp.o sub.o mail.o motd.o log.o shadow.o dialup.o dialchk.o \
X	ttytype.o failure.o port.o
X
XLSRCS = lmain.c login.c env.c password.c entry.c valid.c setup.c shell.c age.c \
X	pwent.c utmp.c sub.c mail.c motd.c log.c shadow.c dialup.c dialchk.c \
X	ttytype.c failure.c port.c
X
XSOBJS = smain.o env.o password.o entry.o suvalid.o susetup.o sushell.o \
X	pwent.o susub.o mail.o motd.o sulog.o shadow.o age.o
X
XSSRCS = smain.c env.c password.c entry.c valid.c setup.c shell.c \
X	pwent.c sub.c mail.c motd.c sulog.c shadow.c age.c
X
XPOBJS = pmain.o password.o entry.o valid.o pwage.o pwent.o obscure.o shadow.o
X
XPSRCS = pmain.c password.c entry.c valid.c age.c pwent.c obscure.c shadow.c
X
XGPSRCS = gpmain.c password.c grent.c
X
XGPOBJS = gpmain.o password.o grent.o
X
XPWOBJS = pwconv.o pwent.o shadow.o pwage.o
X
XPWSRCS = pwconv.c pwent.c shadow.c age.c
X
XPWUNOBJS = pwunconv.o pwent.o shadow.o pwage.o
X
XPWUNSRCS = pwunconv.c pwent.c shadow.c age.c
X
XSULOGOBJS = sulogin.o entry.o env.o password.o pwage.o pwent.o setup.o \
X	shadow.o shell.o valid.o
X
XSULOGSRCS = sulogin.c entry.c env.c password.c age.c pwent.c setup.c \
X	shadow.c shell.c valid.c
X
XDBOBJS = mkpasswd.o pwent.o
X
XDBSRCS = mkpasswd.c pwent.c
X
XNGSRCS = newgrp.c shadow.c password.c
X
XNGOBJS = newgrp.o shadow.o password.o
X
XALLSRCS = age.c dialchk.c dialup.c entry.c env.c lmain.c log.c login.c mail.c \
X	motd.c obscure.c password.c pmain.c pwconv.c pwent.c pwunconv.c \
X	setup.c shadow.c shell.c smain.c sub.c sulog.c sulogin.c ttytype.c \
X	utmp.c valid.c port.c newgrp.c gpmain.c grent.c
X
XFILES1 = README log.c mail.c shadow.h sulog.c Makefile entry.c obscure.c \
X	setup.c sub.c config.h pmain.c sulogin.c dialup.h ttytype.c \
X	port.c newgrp.c
X
XFILES2 = lastlog.h login.c motd.c password.c shell.c utmp.c age.c env.c \
X	pwent.c shadow.c valid.c lmain.c smain.c pwconv.c dialup.c dialchk.c \
X	pwunconv.c failure.c faillog.h faillog.c port.h gpmain.c grent.c
X
XDOCS = login.1 passwd.1 passwd.4 shadow.3 shadow.4 su.1 sulogin.8 pwconv.8 \
X	pwunconv.8 faillog.8 faillog.4
X
XBINS = su login pwconv pwunconv passwd sulogin faillog newgrp gpasswd \
X	mkpasswd
X
Xall:	$(BINS) $(DOCS)
X
Xlibsec: shadow.o
X	ar rv $(LIBSEC) shadow.o
X	$(RANLIB) $(LIBSEC)
X
Xinstall: all
X	strip $(BINS)
X	cp login $(LOGINDIR)/login
X	cp mkpasswd pwconv pwunconv sulogin /etc
X	cp su passwd gpasswd faillog newgrp /bin
X	cp shadow.h /usr/include
X	chown root $(LOGINDIR)/login /etc/pwconv /etc/pwunconv /etc/sulogin \
X		/bin/su /bin/passwd /bin/gpasswd /bin/newgrp /etc/mkpasswd
X	chgrp root $(LOGINDIR)/login /etc/pwconv /etc/pwunconv /etc/sulogin \
X		/bin/su /bin/passwd /bin/gpasswd /bin/newgrp /etc/mkpasswd
X	chown bin /bin/faillog /usr/include/shadow.h
X	chgrp bin /bin/faillog /usr/include/shadow.h
X	chmod 700 /etc/pwconv /etc/pwunconv /etc/sulogin /etc/mkpasswd
X	chmod 4711 $(LOGINDIR)/login /bin/su /bin/passwd /bin/gpasswd \
X		/bin/newgrp
X	chmod 711 /bin/faillog
X	chmod 444 /usr/include/shadow.h
X
Xlint:	su.L login.L pwconv.L pwunconv.L passwd.L sulogin.L faillog.L \
X	newgrp.L gpasswd.L
X
Xtags:	$(ALLSRCS)
X	$(TAGS) $(ALLSRCS)
X
XREADME:	s.README
X	get s.README
X	
X$(DOCS):
X	get s.$@
X
Xlogin:	$(LOBJS)
X	$(CC) -o login $(LDFLAGS) $(LOBJS) $(LIBS)
X
Xlogin.L: $(LSRCS)
X	lint $(LSRCS) > login.L
X
Xsu:	$(SOBJS)
X	$(CC) -o su $(LDFLAGS) $(SOBJS) $(LIBS)
X
Xsu.L:	$(SSRCS)
X	lint -DSU $(SSRCS) > su.L
X
Xpasswd:	$(POBJS)
X	$(CC) -o passwd $(LDFLAGS) $(POBJS) $(LIBS)
X
Xpasswd.L: $(PSRCS)
X	lint -DPASSWD $(PSRCS) > passwd.L
X
Xgpasswd: $(GPOBJS)
X	$(CC) -o gpasswd $(LDFLAGS) $(GPOBJS) $(LIBS)
X
Xgpasswd.L: $(GPSRCS)
X	lint $(GPSRCS) > gpasswd.L
X
Xpwconv:	$(PWOBJS)
X	$(CC) -o pwconv $(LDFLAGS) $(PWOBJS) $(LIBS)
X
Xpwconv.L: $(PWSRCS)
X	lint -DPASSWD $(PWSRCS) > pwconv.L
X
Xpwunconv: $(PWUNOBJS)
X	$(CC) -o pwunconv $(LDFLAGS) $(PWUNOBJS) $(LIBS)
X
Xpwunconv.L: $(PWUNSRCS)
X	lint -DPASSWD $(PWUNSRCS) > pwunconv.L
X
Xsulogin: $(SULOGOBJS)
X	$(CC) -o sulogin $(LDFLAGS) $(SULOGOBJS) $(LIBS)
X
Xsulogin.L: $(SULOGSRCS)
X	lint $(SULOGSRCS) > sulogin.L
X
Xfaillog: faillog.o
X	$(CC) -o faillog $(LDFLAGS) faillog.o $(LIBS)
X
Xfaillog.L: faillog.c faillog.h config.h
X	lint faillog.c > faillog.L
X
Xmkpasswd: $(DBOBJS)
X	$(CC) -o mkpasswd $(LDFLAGS) $(DBOBJS) $(LIBS) -ldbm
X
Xmkpasswd.L: $(DBSRCS)
X	lint $(DBSRCS) > mkpasswd.L
X
Xnewgrp: $(NGOBJS)
X	$(CC) -o newgrp $(LDFLAGS) $(NGOBJS) $(LIBS)
X
Xnewgrp.L: $(NGSRCS)
X	lint $(NGSRCS) > newgrp.L
X
Xsushell.o: config.h shell.c
X	$(CC) -c $(CFLAGS) -DSU shell.c
X	mv shell.o sushell.o
X
Xsusub.o: config.h sub.c
X	cp sub.c susub.c
X	$(CC) -c $(CFLAGS) -DSU susub.c
X	rm susub.c
X
Xsulog.o: config.h
X
Xsusetup.o: config.h setup.c
X	$(CC) -c $(CFLAGS) -DSU setup.c
X	mv setup.o susetup.o
X
Xsuvalid.o: config.h valid.c
X	cp valid.c suvalid.c
X	$(CC) -c $(CFLAGS) -DSU suvalid.c
X	rm suvalid.c
X
Xpmain.o: config.h lastlog.h shadow.h
X
Xpwage.o: age.c config.h
X	cp age.c pwage.c
X	$(CC) -c $(CFLAGS) -DPASSWD pwage.c
X	rm pwage.c
X
Xlmain.o: config.h lastlog.h faillog.h
X
Xsmain.o: config.h lastlog.h
X
Xsetup.o: config.h
X
Xutmp.o: config.h
X
Xmail.o: config.h
X
Xmotd.o: config.h
X
Xage.o: config.h
X
Xlog.o: config.h lastlog.h
X
Xshell.o: config.h
X
Xentry.o: config.h shadow.h
X
Xshadow.o: shadow.h
X
Xdialup.o: dialup.h
X
Xdialchk.o: dialup.h config.h
X
Xvalid.o: config.h
X
Xfailure.o: faillog.h config.h
X
Xfaillog.o: faillog.h config.h
X
Xpwent.o: config.h
X
Xport.o: port.h
X
Xnewgrp.o: config.h shadow.h
X
Xclean:
X	-rm -f *.o a.out core npasswd nshadow *.pag *.dir
X
Xclobber: clean
X	-rm -f $(BINS) *.L
X
Xshar:	login.sh.1 login.sh.2 login.sh.3
X
Xlogin.sh.1: $(FILES1)
X	shar -a $(FILES1) > login.sh.1
X
Xlogin.sh.2: $(FILES2)
X	shar -a $(FILES2) > login.sh.2
X
Xlogin.sh.3: $(DOCS)
X	shar -a $(DOCS) > login.sh.3
SHAR_EOF
if test 6678 -ne "`wc -c < 'Makefile'`"
then
	echo shar: "error transmitting 'Makefile'" '(should have been 6678 characters)'
fi
fi
echo shar: "extracting 'gpmain.c'" '(7286 characters)'
if test -f 'gpmain.c'
then
	echo shar: "will not over-write existing file 'gpmain.c'"
else
sed 's/^X//' << \SHAR_EOF > 'gpmain.c'
X/*
X * Copyright 1990, John F. Haugh II
X * All rights reserved.
X *
X * Non-commercial distribution permitted.  You must provide this source
X * code in any distribution.  This notice must remain intact.
X */
X
X#include <sys/types.h>
X#include <stdio.h>
X#include <pwd.h>
X#include <grp.h>
X#include <fcntl.h>
X#include <signal.h>
X#include <errno.h>
X#ifndef	BSD
X#include <termio.h>
X#ifdef SYS3
X#include <sys/ioctl.h>
X#endif
X#include <string.h>
X#ifndef	SYS3
X#include <memory.h>
X#endif
X#else
X#include <sgtty.h>
X#include <strings.h>
X#define	strchr	index
X#define	strrchr	rindex
X#endif
X#include "config.h"
X
X#ifndef	PASSLENGTH
X#define	PASSLENGTH	5
X#endif
X
X#ifndef	lint
Xstatic	char	_sccsid[] = "@(#)gpmain.c	1.3	09:19:10	6/26/90";
X#endif
X
Xchar	name[BUFSIZ];
Xchar	pass[BUFSIZ];
Xchar	pass2[BUFSIZ];
X
Xstruct	group	grent;
X
Xchar	*myname;
X
X#ifndef	RETRIES
X#define	RETRIES	3
X#endif
X
Xchar	*l64a ();
Xchar	*crypt ();
Xextern	int	errno;
Xlong	a64l ();
Xvoid	entry ();
Xtime_t	time ();
X
X/*
X * usage - display usage message
X */
X
Xvoid
Xusage ()
X{
X	fprintf (stderr, "usage: %s [ -r ] group\n", myname);
X	exit (1);
X}
X
Xint
Xmain (argc, argv)
Xint	argc;
Xchar	**argv;
X{
X	extern	int	optind;
X	extern	char	*optarg;
X	char	*group;
X	int	flag;
X	int	i;
X	void	die ();
X	char	*cp;
X	char	*getlogin ();
X	int	amroot;
X	int	lockfd = -1;
X	int	remove = 0;
X	int	retries;
X	int	ruid = getuid();
X	int	suid = geteuid();
X	long	salttime;
X	struct	group	*gr;
X	struct	group	*getgrnam ();
X	struct	group	*sgetgrent ();
X	struct	passwd	*pw;
X	struct	passwd	*getpwuid ();
X	struct	passwd	*getpwnam ();
X	FILE	*ngrp;
X	FILE	*ogrp;
X	char	buf[BUFSIZ];
X	char	tmp[BUFSIZ];
X
X	amroot = getuid () == 0;
X	setuid (geteuid ());
X	myname = argv[0];
X
X	if (! isatty (0) || ! isatty (1))
X		exit (1);
X
X	die (0);			/* save tty modes */
X
X	signal (SIGHUP, die);
X	signal (SIGINT, die);
X	signal (SIGQUIT, die);
X	signal (SIGTERM, die);
X
X	while ((flag = getopt (argc, argv, "gr")) != EOF) {
X		switch (flag) {
X			case 'g':	/* no-op from normal password */
X				break;
X			case 'r':	/* remove group password */
X				remove = 1;
X				break;
X			default:
X				usage ();
X		}
X	}
X	if (cp = getlogin ())		/* need user name */
X		(void) strcpy (name, cp);
X	else if (pw = getpwuid (ruid)) /* get it from password file */
X		strcpy (name, pw->pw_name);
X	else {				/* can't find user name! */
X		fprintf (stderr, "Who are you?\n");
X		exit (1);
X	}
X	if (! (pw = getpwnam (name)))
X		goto failure;		/* can't get my name ... */
X		
X	if (! (group = argv[optind]))
X		usage ();
X
X	if (! (gr = getgrnam (group))) {
X		fprintf (stderr, "unknown group: %s\n", group);
X		exit (1);
X	}
X	if (! amroot) {
X		if (gr->gr_mem[0] == (char *) 0)
X			goto failure;
X
X		if (strcmp (gr->gr_mem[0], name) != 0)
X			goto failure;
X	}
X	if (remove) {
X		if (! amroot && (gr->gr_mem[0] &&
X				strcmp (name, gr->gr_mem[0]) != 0))
X			goto failure;
X
X		gr->gr_passwd = "";
X		goto output;
X	}
X	printf ("Changing password for group %s\n", group);
X
X	printf ("Enter new password (minimum of %d characters)\n", PASSLENGTH);
X	retries = RETRIES;
Xretry:
X	if (! password ("New Password:", pass))
X		exit (1);
X
X	if (! password ("Re-enter new password:", pass2))
X		exit (1);
X
X	if (strcmp (pass, pass2) != 0) {
X		puts ("They don't match; try again");
X
X		if (retries-- > 0)
X			goto retry;
X		else
X			goto toomany;
X	}
X	(void) time (&salttime);
X	salttime = ((salttime & 07777) ^ ((salttime >> 12) & 07777)) & 07777;
X	grent.gr_passwd = tmp;
X	strcpy (grent.gr_passwd, crypt (pass, l64a (salttime)));
X#ifdef	DOUBLESIZE
X	if (strlen (pass) > 8) {
X		strcpy (grent.gr_passwd + 13,
X			crypt (pass + 8, l64a (salttime)) + 2);
X	}
X#endif
Xoutput:
X
X	/*
X	 * Now we get to race the bad guy.  I don't think he can get us.
X	 *
X	 * Ignore most reasonable signals.
X	 *	Maybe we should ignore more?  He can't hurt us until the end.
X	 *
X	 * Get a lock file.
X	 *
X	 * Copy first part of password file to new file.
X	 *	Illegal lines are copied verbatim.
X	 *	File permissions are r--r--r--, owner root, group root.
X	 *
X	 * Output the new entry.
X	 *	Only fields in struct passwd are output.
X	 *
X	 * Copy the rest of the file verbatim.
X	 *
X	 * Rename (link, unlink) password file to backup.
X	 *	Kill me now and nothing changes or no one gets in.
X	 *
X	 * Rename (link, unlink) temporary file to password file.
X	 *	Kill me now and no one gets in or lock is left.
X	 *
X	 * Remove locking file.
X	 *
X	 * That's all folks ...
X	 */
X
X	signal (SIGHUP, SIG_IGN);
X	signal (SIGINT, SIG_IGN);
X	signal (SIGQUIT, SIG_IGN);
X	signal (SIGTERM, SIG_IGN);
X
X	ulimit (30000);			/* prevent any funny business */
X	umask (0);			/* get new files modes correct */
X#ifndef	NDEBUG
X	if ((lockfd = open (".grplock", O_RDONLY|O_CREAT|O_EXCL), 0444) == -1)
X#else
X	if ((lockfd = open (GRPLOCK, O_RDONLY|O_CREAT|O_EXCL), 0444) == -1)
X#endif	/* NDEBUG */
X	{
X		puts ("Can't get lock");
X		exit (1);
X	}
X	umask (077);			/* close security holes to come ... */
X	if (access (NGRPFILE, 0) == 0 && unlink (NGRPFILE) == -1)
X		goto failure;
X
X#ifndef	NDEBUG
X	if ((ngrp = fopen ("ngroup", "w")) == (FILE *) 0)
X#else
X	umask (077);		/* no permissions for non-roots */
X
X	if ((ngrp = fopen (NGRPFILE, "w")) == (FILE *) 0)
X#endif	/* NDEBUG */
X		goto failure;
X
X#ifndef	NDEBUG
X	chmod (NGRPFILE, 0444);		/* lets have some security here ... */
X	chown (NGRPFILE, 0, 0);		/* ... and keep the bad guy away */
X#endif	/* NDEBUG */
X	if ((ogrp = fopen (GRPFILE, "r")) == (FILE *) 0)
X		goto failure;
X
X	while (fgets (buf, sizeof buf, ogrp) != (char *) 0) {
X		if (buf[0] == '#' || ! (gr = sgetgrent (buf))) {
X			fputs (buf, ngrp);
X		} else if (strcmp (gr->gr_name, group) != 0)
X			fputs (buf, ngrp);
X		else
X			break;
X	}
X	if (gr) {
X		(void) fprintf (ngrp, "%s:%s:%d%s",
X			gr->gr_name,
X				grent.gr_passwd ? grent.gr_passwd:"x",
X				gr->gr_gid, strrchr (buf, ':'));
X
X		while (fgets (buf, BUFSIZ, ogrp) != (char *) 0)
X			fputs (buf, ngrp);
X	}
X	if (ferror (ngrp)) {
X		perror (NGRPFILE);
X		if (unlink (NGRPFILE) || unlink (GRPLOCK))
X			fputs ("Help!\n", stderr);
X
X		exit (1);
X	}
X	fflush (ngrp);
X	fclose (ngrp);
X#ifdef	NDEBUG
X	chmod (NGRPFILE, 0644);
X	if (unlink (OGRPFILE) == -1) {
X		if (errno != ENOENT) {
X			puts ("Can't unlink backup file");
X			goto unlock;
X		}
X	}
X	if (link (GRPFILE, OGRPFILE) || unlink (GRPFILE)) {
X		puts ("Can't save backup file");
X		goto unlock;
X	}
X#ifndef	BSD
X	if (link (NGRPFILE, GRPFILE) || unlink (NGRPFILE))
X#else
X	if (rename (NGRPFILE, GRPFILE))
X#endif
X	{
X		puts ("Can't rename new file");
X		goto unlock;
X	}
X#endif	/* NDEBUG */
X#ifndef	NDEBUG
X	(void) unlink (".grplock");
X#else
X	(void) unlink (GRPLOCK);
X#endif
X	exit (0);
X	/*NOTREACHED*/
X
Xfailure:
X	puts ("Permission denied.");
Xunlock:
X	if (lockfd >= 0)
X		(void) unlink (GRPLOCK);
X
X	(void) unlink (NGRPFILE);
X	exit (1);
X	/*NOTREACHED*/
X
Xtoomany:
X	puts ("Too many tries; try again later.");
X	exit (1);
X	/*NOTREACHED*/
X}
X
X/*
X * die - set or reset termio modes.
X *
X *	die() is called before processing begins.  signal() is then
X *	called with die() as the signal handler.  If signal later
X *	calls die() with a signal number, the terminal modes are
X *	then reset.
X */
X
Xvoid	die (killed)
Xint	killed;
X{
X#ifdef	BSD
X	static	struct	sgtty	sgtty;
X
X	if (killed)
X		stty (0, &sgtty);
X	else
X		gtty (0, &sgtty);
X#else
X	static	struct	termio	sgtty;
X
X	if (killed)
X		ioctl (0, TCSETA, &sgtty);
X	else
X		ioctl (0, TCGETA, &sgtty);
X#endif
X	if (killed) {
X		putchar ('\n');
X		fflush (stdout);
X		exit (killed);
X	}
X}
SHAR_EOF
if test 7286 -ne "`wc -c < 'gpmain.c'`"
then
	echo shar: "error transmitting 'gpmain.c'" '(should have been 7286 characters)'
fi
fi
echo shar: "extracting 'grent.c'" '(1297 characters)'
if test -f 'grent.c'
then
	echo shar: "will not over-write existing file 'grent.c'"
else
sed 's/^X//' << \SHAR_EOF > 'grent.c'
X/*
X * Copyright 1990, John F. Haugh II
X * All rights reserved.
X *
X * Non-commercial distribution permitted.  You must provide this source
X * code in any distribution.  This notice must remain intact.
X */
X
X#include <stdio.h>
X#include <grp.h>
X#include <string.h>
X#include "config.h"
X#ifdef	DBM
X#include <dbm.h>
X#endif
X
X#ifndef	lint
Xstatic	char	_sccsid[] = "@(#)grent.c	1.1	08:14:07	6/20/90";
X#endif
X
X#define	NFIELDS	4
X#define	MAXMEM	1024
X
Xstatic	char	grpbuf[4*BUFSIZ];
Xstatic	char	*grpfields[NFIELDS];
Xstatic	char	*members[MAXMEM+1];
X
Xstatic char **
Xlist (s)
Xchar	*s;
X{
X	int	nmembers = 0;
X
X	while (*s) {
X		members[nmembers++] = s;
X		if (s = strchr (s, ','))
X			*s++ = '\0';
X	}
X	members[nmembers] = (char *) 0;
X	return members;
X}
X
Xstruct	group	*sgetgrent (buf)
Xchar	*buf;
X{
X	int	i;
X	char	*cp;
X	static	struct	group	grent;
X
X	strncpy (grpbuf, buf, sizeof grpbuf);
X	grpbuf[sizeof grpbuf - 1] = '\0';
X	if (cp = strrchr (grpbuf, '\n'))
X		*cp = '\0';
X
X	for (cp = grpbuf, i = 0;i < NFIELDS && cp;i++) {
X		grpfields[i] = cp;
X		if (cp = strchr (cp, ':'))
X			*cp++ = 0;
X	}
X	if (i < (NFIELDS-1) || *grpfields[2] == '\0')
X		return ((struct group *) 0);
X
X	grent.gr_name = grpfields[0];
X	grent.gr_passwd = grpfields[1];
X	grent.gr_gid = atoi (grpfields[2]);
X	grent.gr_mem = list (grpfields[3]);
X
X	return (&grent);
X}
SHAR_EOF
if test 1297 -ne "`wc -c < 'grent.c'`"
then
	echo shar: "error transmitting 'grent.c'" '(should have been 1297 characters)'
fi
fi
echo shar: "extracting 'password.c'" '(1939 characters)'
if test -f 'password.c'
then
	echo shar: "will not over-write existing file 'password.c'"
else
sed 's/^X//' << \SHAR_EOF > 'password.c'
X/*
X * Copyright 1988,1989,1990, John F. Haugh II
X * All rights reserved.
X *
X * Non-commercial distribution permitted.  You must provide this source
X * code in any distribution.  This notice must remain intact.
X */
X
X#include <stdio.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#ifndef	BSD
X#include <termio.h>
X#else
X#include <sgtty.h>
X#endif
X
X#include <fcntl.h>
X
X/*
X * password - prompt for password and return entry
X *
X *	Need to fake up getpass().  Returns TRUE if a password
X *	was successfully input, and FALSE otherwise, including
X *	EOF on input or ioctl() failure.  pass is not modified
X *	on failure.  The input length limit may be set by
X *	changing the value of PASSLIMIT.
X */
X
X#ifndef	lint
Xstatic	char	_sccsid[] = "@(#)password.c	2.2	09:38:59	6/22/90";
X#endif
X
X#define	PASSLIMIT	20
X
Xint	password (prompt, pass)
Xchar	*prompt;
Xchar	*pass;
X{
X	char	buf[BUFSIZ];
X	char	*cp;
X	int	eof;
X	int	ttyopened = 0;
X#ifndef	BSD
X	struct	termio	termio;
X	struct	termio	save;
X#else
X	struct	sgttyb	termio ;
X	struct	sgttyb	save ;
X#endif
X	FILE	*fp;
X
X	if ((fp = fopen ("/dev/tty", "r")) == (FILE *) 0)
X		fp = stdin;
X	else
X		ttyopened = 1;
X
X#ifndef	BSD
X	if (ioctl (fileno (fp), TCGETA, &termio))
X		return (0);
X#else
X	if ( gtty( fileno(fp), &termio ) )
X		return (0);
X#endif
X
X	save = termio;
X#ifndef	BSD
X	termio.c_lflag &= ~(ECHO|ECHOE|ECHOK);
X	ioctl (fileno (fp), TCSETAF, &termio);
X#else
X	termio.sg_flags &= ~ECHO ;
X	stty( fileno( fp ), termio ) ;
X#endif
X
X	fputs (prompt, stdout);
X	eof = fgets (buf, BUFSIZ, fp) == (char *) 0 || feof (fp) || ferror (fp);
X	putchar ('\n');
X
X#ifndef	BSD
X	ioctl (fileno (fp), TCSETAF, &save);
X#else
X	stty( fileno( fp ), save ) ;
X#endif
X
X	if (! eof) {
X		buf[PASSLIMIT] = '\0';
X		if ((cp = strchr (buf, '\n')) || (cp = strchr (buf, '\r')))
X			*cp = '\0'; 
X
X		(void) strcpy (pass, buf);
X	}
X	if (ttyopened)
X		fclose (fp);
X
X	return (! eof);
X}
SHAR_EOF
if test 1939 -ne "`wc -c < 'password.c'`"
then
	echo shar: "error transmitting 'password.c'" '(should have been 1939 characters)'
fi
fi
echo shar: "extracting 'config.h'" '(5246 characters)'
if test -f 'config.h'
then
	echo shar: "will not over-write existing file 'config.h'"
else
sed 's/^X//' << \SHAR_EOF > 'config.h'
X/*
X * Configuration file for login.
X *
X *	@(#)config.h	2.2	00:22:54	5/25/90
X */
X
X/*
X * Define DIALUP to use dialup password files
X */
X
X#define	DIALUP
X
X/*
X * Define SHADOWPWD to use shadow [ unreadable ] password file
X */
X
X#define	SHADOWPWD
X
X/*
X * Define DOUBLESIZE to use 16 character passwords
X */
X
X#define DOUBLESIZE
X
X/*
X * Define OBSCURE to include hard password testing code.
X */
X
X#define	OBSCURE
X
X/*
X * Define PASSLENGTH to be shortest legal password
X */
X
X#define	PASSLENGTH	5
X
X/*
X * Define NOBLANK if you want all passwords prompted for, including
X * empty ones.
X
X#undef	NOBLANK
X
X/*
X * Define MAXDAYS to be the default maximum number of days a password
X * is valid for when converting to shadow passwords.  Define MINDAYS
X * to be the minimum number of days before a password may be changed.
X * See pwconv.c for more details.
X */
X
X#define	MAXDAYS	10000
X#define	MINDAYS	0
X
X/*
X * Define NDEBUG for production versions
X */
X
X#define	NDEBUG
X
X/*
X * Define HZ if login must set HZ value
X */
X
X#define	HZ	"HZ=50"
X
X/*
X * Define TZ if login must set timezone
X *
X * The first example sets the variable directly.  The
X * second example names a file which is read to determine
X * the proper value.  The file consists of a single line
X * of the form 'TZ=zone-name'
X */
X
X/* #define	TZ	"TZ=CST6CDT" */
X#define	TZ	"/etc/tzname"
X
X/*
X * Define the default PATH and SUPATH here.  PATH is for non-privileged
X * users, SUPATH is for root.  The first pair are for real trusting
X * systems, the second pair are for the paranoid ...
X */
X
X/* #define	PATH	"PATH=:/bin:/usr/bin"	*/
X/* #define	SUPATH	"PATH=:/bin:/usr/bin:/etc" */
X#define	PATH	"PATH=/bin:/usr/bin"
X#define	SUPATH	"PATH=/bin:/usr/bin:/etc"
X
X/*
X * Define the mailbox directory
X */
X
X#define	MAILDIR	"/usr/spool/mail/"
X
X/*
X * Define AGING if you want the password aging checks made.
X */
X
X#define	AGING
X
X/*
X * Define MAILCHECK if you want the mailbox checked for new mail
X *
X * One of two messages are printed - `You have new mail.' or
X * `You have mail.'.
X */
X
X#define	MAILCHECK
X
X/*
X * Define CONSOLE if you want ROOT restricted to a particular terminal.
X *
X * Use the name of the tty line if you only want a single line, or use
X * the name of the file containing the permissible ports if you wish to
X * allow root logins on more than one port.
X */
X
X/* #define	CONSOLE	"console"	/* root on /dev/console only */
X#define	CONSOLE	"/etc/consoles"		/* check /etc/consoles for a list */
X
X/*
X * Define NOLOGINS if you want to be able to deny non-root users logins.
X * Logins will not be permitted if this file exists.
X */
X
X#define	NOLOGINS	"/etc/nologin"
X
X/*
X * Define NOUSE if you want to be able to declare accounts which can't
X * be logged into.  Define NOLOGIN if you want it to be an su-only account.
X */
X
X#define	NOUSE	"NOUSE"
X#define	NOLOGIN	"NOLOGIN"
X
X/*
X * Define MOTD if you want the message of the day (/etc/motd) printed
X * at login time.
X */
X
X#define	MOTD
X
X/*
X * Define HUSHLOGIN if you want the code added to avoid printing the
X * motd if a file $HOME/.hushlogin exists.  This obviously only matters
X * if any of MOTD, MAILCHECK or LASTLOG are #define'd.
X */
X
X#define	HUSHLOGIN
X
X/*
X * Define LASTLOG if you want a record made of logins in /usr/adm/lastlog.
X */
X
X#define	LASTLOG
X
X/*
X * Define FAILLOG if you want a record make of failed logins in
X * /usr/adm/faillog.  See faillog.h for more details.  See fail(1L)
X * for even still more details ...  Also, define FTMP to record utmp
X * style records for failed logins.  FTMP is the name of a utmp-like
X * file.  You can use who(1) instead of faillog(L), which is an
X * advantage.
X */
X
X#define	FAILLOG
X#define	FTMP	"/etc/ftmp"
X
X/*
X * Define TTYPERM to be the initial terminal permissions.  Defining
X * as 0600 will not allow messages, 0622 will.
X */
X
X#define	TTYPERM	0600
X
X/*
X * Define TTYTYPE to the be name of the port to terminal type
X * mapping file.  This is used to set the environmental variable
X * "TERM" to the correct terminal type.
X */
X
X#define	TTYTYPE	"/etc/ttytype"
X
X/*
X * Define QUOTAS if you want the code added in setup.c to support
X * file ulimit and nice [ and umask as well ] setting from the password
X * file.
X */
X
X#define	QUOTAS
X
X/*
X * Define file name for sulog.  If SULOG is not defined, there will be
X * no logging.  This is NOT a good idea ...  We also define other file
X * names.
X */
X
X#define	SULOG	"/usr/adm/sulog"
X#define	SUCON	"/dev/console"
X#define	PWDFILE	"/etc/passwd"
X#define	OPWDFILE "/etc/-passwd"
X#define	NPWDFILE "/etc/npasswd"
X#define	OSHADOW "/etc/-shadow"
X#define	NSHADOW "/etc/nshadow"
X#define	GRPFILE	"/etc/group"
X#define	OGRPFILE "/etc/-group"
X#define	NGRPFILE "/etc/ngroup"
X
X/*
X * Define PWDLOCK to be a locking semaphore for updating the password
X * file.  GRPLOCK is the same for the group file.
X */
X
X#define	PWDLOCK	"/etc/.pwdlock"
X#define	GRPLOCK "/etc/.grplock"
X
X/*
X * Wierd stuff follows ...
X *
X *	The following macros exist solely to override stuff ...
X *	You will probably want to change their values to suit your
X *	fancy.
X */
X
X#define	ERASECHAR	'\b'
X#define	KILLCHAR	'\025'
X#define	UMASK		022
X
X#define	ULIMIT	(1L<<20) /* Define if your UNIX supports ulimit() */
X#define	FGETPWENT	/* Define if library does not include FGETPWENT */
X#define	NEED_AL64	/* Define if library does not include a64l() */
SHAR_EOF
if test 5246 -ne "`wc -c < 'config.h'`"
then
	echo shar: "error transmitting 'config.h'" '(should have been 5246 characters)'
fi
fi
exit 0
#	End of shell archive
-- 
John F. Haugh II                             UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 832-8832                           Domain: jfh@rpp386.cactus.org

                                            Proud Pilot of RS/6000 Serial #1472