[alt.sources] Shadow login suite, patch 6

jfh@rpp386.cactus.org (John F Haugh II) (06/27/91)

This is getting close to the end of the current beta test cycle, so you
won't be seeing many more of these large patches.

There are three features to this patch.  The first is the continued
introduction of the SVR4 user administration commands.  Earlier I posted
the useradd, userdel and usermod clones.  This patch gives you the
groupadd, groupdel and groupmod clones.  The second round of changes
involves support code added to the libraries to perform deletions from
the DBM files.  Finally there are a number of bug fixes of the more
common "buggy code" variety.

There are two current patches in the pipeline.  The first ports the
code to SunOS.  It was performed by Dr. Michael Newberry "down under",
and I would like to welcome him to the group of people currently
working on this project.  The second provides for run-time configuration
of the programs [ as opposed to the current compile-time configuration ]
and was performed by Chip Rosenthal, who has been involved with this
project for several years now.  I don't know what the order will be
for posting them.
--
Prereq: "3.0.5"
Index: patchlevel.h
*** rel3/patchlevel.h	Tue Jun 25 09:38:24 1991
--- patchlevel.h	Wed Jun 26 09:43:23 1991
***************
*** 10,14 ****
   */
  
  #define	RELEASE		3
! #define	PATCHLEVEL	5
! #define	VERSION		"3.0.5"
--- 10,14 ----
   */
  
  #define	RELEASE		3
! #define	PATCHLEVEL	6
! #define	VERSION		"3.0.6"
Index: Makefile
*** rel3/Makefile	Tue Jun 25 09:38:24 1991
--- Makefile	Wed Jun 26 09:43:26 1991
***************
*** 8,16 ****
  # and conspicuously displayed on all copies of object code or
  # distribution media.
  #
! #	@(#)Makefile	3.15	20:52:45  - Shadow password system
  #
! #	@(#)Makefile	3.15	20:52:45	6/13/91
  #
  SHELL = /bin/sh
  
--- 8,16 ----
  # and conspicuously displayed on all copies of object code or
  # distribution media.
  #
! #	@(#)Makefile	3.17	09:41:38  - Shadow password system
  #
! #	@(#)Makefile	3.17	09:41:38	6/25/91
  #
  SHELL = /bin/sh
  
***************
*** 18,24 ****
  # Set this flag to decide what level of code "get" returns.
  # The base USENET release was release 1.  It is no longer supported.
  # The 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)
  
--- 18,24 ----
  # Set this flag to decide what level of code "get" returns.
  # The base USENET release was release 1.  It is no longer supported.
  # The version with the utilities added was release 2.
! # The version with database-like file access is release 3.
  RELEASE = 3
  GFLAGS = -t -r$(RELEASE)
  
***************
*** 141,150 ****
  	chfn.c chsh.c chage.c rad64.c encrypt.c chpasswd.c shadowio.c pwio.c \
  	newusers.c groupio.c fields.c pwdbm.c grpack.c grdbm.c sppack.c \
  	spdbm.c dpmain.c gshadow.c gsdbm.c gspack.c sgroupio.c useradd.c \
! 	userdel.c patchlevel.h usermod.c copydir.c mkrmdir.c
  
! FILES1 = README newgrp.c Makefile config.h pwunconv.c obscure.c age.c id.c \
! 	patchlevel.h
  
  FILES2 = passwd.c port.c lmain.c mkpasswd.c sulogin.c pwpack.c dialup.c \
  	sulog.c getpass.c
--- 141,151 ----
  	chfn.c chsh.c chage.c rad64.c encrypt.c chpasswd.c shadowio.c pwio.c \
  	newusers.c groupio.c fields.c pwdbm.c grpack.c grdbm.c sppack.c \
  	spdbm.c dpmain.c gshadow.c gsdbm.c gspack.c sgroupio.c useradd.c \
! 	userdel.c patchlevel.h usermod.c copydir.c mkrmdir.c groupadd.c \
! 	groupdel.c groupmod.c
  
! FILES1 = README patchlevel.h newgrp.c Makefile config.h pwunconv.c obscure.c \
! 	age.c id.c
  
  FILES2 = passwd.c port.c lmain.c mkpasswd.c sulogin.c pwpack.c dialup.c \
  	sulog.c getpass.c
***************
*** 164,169 ****
--- 165,172 ----
  
  FILES8 = useradd.c userdel.c usermod.c copydir.c mkrmdir.c
  
+ FILES9 = groupadd.c groupdel.c groupmod.c
+ 
  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
***************
*** 173,179 ****
  
  BINS = su login pwconv pwunconv passwd sulogin faillog newgrp gpasswd \
  	mkpasswd chfn chsh chage chpasswd newusers dpasswd id useradd \
! 	userdel usermod
  
  all:	$(BINS) $(DOCS)
  
--- 176,182 ----
  
  BINS = su login pwconv pwunconv passwd sulogin faillog newgrp gpasswd \
  	mkpasswd chfn chsh chage chpasswd newusers dpasswd id useradd \
! 	userdel usermod groupadd groupdel groupmod
  
  all:	$(BINS) $(DOCS)
  
***************
*** 209,229 ****
  install: all
  	strip $(BINS)
  	cp login $(LOGINDIR)/login
! 	cp mkpasswd pwconv pwunconv sulogin chpasswd newusers /etc
! 	cp su passwd gpasswd dpasswd faillog newgrp chfn chsh id /bin
  	cp dialup.h shadow.h pwd.h /usr/include
  	chown $(RUID) $(LOGINDIR)/login /etc/pwconv /etc/pwunconv /etc/sulogin \
  		/bin/su /bin/passwd /bin/gpasswd /bin/newgrp /etc/mkpasswd \
! 		/bin/dpasswd /bin/chsh /bin/chfn /bin/chage
  	chgrp $(RGID) $(LOGINDIR)/login /etc/pwconv /etc/pwunconv /etc/sulogin \
  		/bin/su /bin/passwd /bin/gpasswd /bin/newgrp /etc/mkpasswd \
! 		/bin/dpasswd /bin/chsh /bin/chfn /bin/chage
  	chown $(BUID) /bin/faillog /bin/id /usr/include/shadow.h \
  		/usr/include/dialup.h /usr/include/pwd.h
  	chgrp $(BGID) /bin/faillog /bin/id /usr/include/shadow.h \
  		/usr/include/dialup.h /usr/include/pwd.h
  	chmod 700 /etc/pwconv /etc/pwunconv /etc/sulogin /etc/mkpasswd \
! 		/etc/chpasswd /etc/newusers /bin/dpasswd /bin/chage
  	chmod 4711 $(LOGINDIR)/login /bin/su /bin/passwd /bin/gpasswd \
  		/bin/newgrp /bin/chfn /bin/chsh
  	chmod 711 /bin/faillog /bin/id
--- 212,239 ----
  install: all
  	strip $(BINS)
  	cp login $(LOGINDIR)/login
! 	cp mkpasswd pwconv pwunconv sulogin chpasswd newusers \
! 		useradd userdel usermod groupadd groupdel groupmod /etc
! 	cp su passwd gpasswd dpasswd faillog newgrp chfn chsh chage id /bin
  	cp dialup.h shadow.h pwd.h /usr/include
  	chown $(RUID) $(LOGINDIR)/login /etc/pwconv /etc/pwunconv /etc/sulogin \
  		/bin/su /bin/passwd /bin/gpasswd /bin/newgrp /etc/mkpasswd \
! 		/bin/dpasswd /bin/chsh /bin/chfn /bin/chage /etc/useradd \
! 		/etc/userdel /etc/usermod /etc/groupadd /etc/groupdel \
! 		/etc/groupmod
  	chgrp $(RGID) $(LOGINDIR)/login /etc/pwconv /etc/pwunconv /etc/sulogin \
  		/bin/su /bin/passwd /bin/gpasswd /bin/newgrp /etc/mkpasswd \
! 		/bin/dpasswd /bin/chsh /bin/chfn /bin/chage /etc/useradd \
! 		/etc/userdel /etc/usermod /etc/groupadd /etc/groupdel \
! 		/etc/groupmod
  	chown $(BUID) /bin/faillog /bin/id /usr/include/shadow.h \
  		/usr/include/dialup.h /usr/include/pwd.h
  	chgrp $(BGID) /bin/faillog /bin/id /usr/include/shadow.h \
  		/usr/include/dialup.h /usr/include/pwd.h
  	chmod 700 /etc/pwconv /etc/pwunconv /etc/sulogin /etc/mkpasswd \
! 		/etc/chpasswd /etc/newusers /bin/dpasswd /bin/chage \
! 		/etc/useradd /etc/userdel /etc/usermod /etc/groupadd \
! 		/etc/groupdel /etc/groupmod
  	chmod 4711 $(LOGINDIR)/login /bin/su /bin/passwd /bin/gpasswd \
  		/bin/newgrp /bin/chfn /bin/chsh
  	chmod 711 /bin/faillog /bin/id
***************
*** 233,248 ****
  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 dpasswd.lint id.lint useradd.lint userdel.lint \
! 	usermod.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) libshadow.a
  	$(CC) -o login $(LDFLAGS) $(LOBJS) libshadow.a $(LIBS)
--- 243,258 ----
  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 dpasswd.lint id.lint useradd.lint userdel.lint \
! 	usermod.lint groupadd.lint groupdel.lint groupmod.lint $(ALLSRCS:.c=.L)
  
  tags:	$(ALLSRCS)
  	$(TAGS) $(ALLSRCS)
  
! README:
! 	[ -f s.README ] && get -t -r$(RELEASE) s.README
  	
  $(DOCS):
! 	[ -f s.$@ ] && get -t -r$(RELEASE) s.$@
  
  login:	$(LOBJS) libshadow.a
  	$(CC) -o login $(LDFLAGS) $(LOBJS) libshadow.a $(LIBS)
***************
*** 367,372 ****
--- 377,400 ----
  usermod.lint: usermod.c copydir.c mkrmdir.c
  	$(LINT) $(LINTFLAGS) usermod.c copydir.c mkrmdir.c > usermod.lint
  
+ groupadd: groupadd.o libshadow.a
+ 	$(CC) -o groupadd $(LDFLAGS) groupadd.o libshadow.a $(LIBS)
+ 
+ groupadd.lint: groupadd.c
+ 	$(LINT) $(LINTFLAGS) groupadd.c > groupadd.lint
+ 
+ groupdel: groupdel.o libshadow.a
+ 	$(CC) -o groupdel $(LDFLAGS) groupdel.o libshadow.a $(LIBS)
+ 
+ groupdel.lint: groupdel.c
+ 	$(LINT) $(LINTFLAGS) groupdel.c > groupdel.lint
+ 
+ groupmod: groupmod.o libshadow.a
+ 	$(CC) -o groupmod $(LDFLAGS) groupmod.o libshadow.a $(LIBS)
+ 
+ groupmod.lint: groupmod.c
+ 	$(LINT) $(LINTFLAGS) groupmod.c > groupmod.lint
+ 
  sulog.o: config.h
  
  susetup.c: setup.c
***************
*** 437,442 ****
--- 465,474 ----
  dpmain.o: dialup.h
  useradd.o: config.h shadow.h pwd.h
  userdel.o: config.h shadow.h pwd.h
+ usermod.o: config.h shadow.h pwd.h
+ groupadd.o: config.h shadow.h
+ groupdel.o: config.h shadow.h
+ groupmod.o: config.h shadow.h
  
  clean:
  	-rm -f *.o a.out core npasswd nshadow *.pag *.dir
***************
*** 451,483 ****
  		fi ;\
  	done
  
! shar:	login.sh.1 login.sh.2 login.sh.3 login.sh.4 login.sh.5 login.sh.6 \
! 	login.sh.7 login.sh.8 login.sh.9
! 
! login.sh.1: $(FILES1) Makefile
! 	shar -a $(FILES1) > login.sh.1
! 
! login.sh.2: $(FILES2) Makefile
! 	shar -a $(FILES2) > login.sh.2
! 
! login.sh.3: $(FILES3) Makefile
! 	shar -a $(FILES3) > login.sh.3
! 
! login.sh.4: $(FILES4) Makefile
! 	shar -a $(FILES4) > login.sh.4
! 
! login.sh.5: $(FILES5) Makefile
! 	shar -a $(FILES5) > login.sh.5
! 
! login.sh.6: $(FILES6) Makefile
! 	shar -a $(FILES6) > login.sh.6
! 
! login.sh.7: $(FILES7) Makefile
! 	shar -a $(FILES7) > login.sh.7
! 
! login.sh.8: $(FILES8) Makefile
! 	shar -a $(FILES8) > login.sh.8
  
! login.sh.9: $(DOCS) Makefile
! 	shar -a $(DOCS) > login.sh.9
  
--- 483,517 ----
  		fi ;\
  	done
  
! shar:	login.sh.01 login.sh.02 login.sh.03 login.sh.04 login.sh.05 \
! 	login.sh.06 login.sh.07 login.sh.08 login.sh.09 login.sh.10
  
! login.sh.01: $(FILES1) Makefile
! 	shar -a $(FILES1) > login.sh.01
! 
! login.sh.02: $(FILES2) Makefile
! 	shar -a $(FILES2) > login.sh.02
! 
! login.sh.03: $(FILES3) Makefile
! 	shar -a $(FILES3) > login.sh.03
! 
! login.sh.04: $(FILES4) Makefile
! 	shar -a $(FILES4) > login.sh.04
! 
! login.sh.05: $(FILES5) Makefile
! 	shar -a $(FILES5) > login.sh.05
! 
! login.sh.06: $(FILES6) Makefile
! 	shar -a $(FILES6) > login.sh.06
! 
! login.sh.07: $(FILES7) Makefile
! 	shar -a $(FILES7) > login.sh.07
! 
! login.sh.08: $(FILES8) Makefile
! 	shar -a $(FILES8) > login.sh.08
! 
! login.sh.09: $(FILES9) Makefile
! 	shar -a $(FILES9) > login.sh.09
  
+ login.sh.10: $(DOCS) Makefile
+ 	shar -a $(DOCS) > login.sh.10
Index: grdbm.c
*** rel3/grdbm.c	Tue Jun 25 09:35:40 1991
--- grdbm.c	Wed Jun 26 09:43:28 1991
***************
*** 7,13 ****
   */
  
  #ifndef	lint
! static	char	sccsid[] = "@(#)grdbm.c	3.1	08:11:52	11/21/90";
  #endif
  
  #include <string.h>
--- 7,13 ----
   */
  
  #ifndef	lint
! static	char	sccsid[] = "@(#)grdbm.c	3.2	22:53:58	6/13/91";
  #endif
  
  #include <string.h>
***************
*** 104,108 ****
--- 104,187 ----
  		}
  	}
  	return 1;
+ }
+ 
+ /*
+  * gr_dbm_remove
+  *
+  * Deletes the DBM group file entries, if they exist.
+  */
+ 
+ int
+ gr_dbm_remove (gr)
+ struct	group	*gr;
+ {
+ 	datum	key;
+ 	datum	content;
+ 	char	data[BUFSIZ*8];
+ 	char	grpkey[60];
+ 	char	*cp;
+ 	int	len;
+ 	int	i;
+ 	int	cnt;
+ 	int	errors = 0;
+ 	static	int	once;
+ 
+ 	if (! once) {
+ 		if (! gr_dbm)
+ 			setgrent ();
+ 
+ 		once++;
+ 	}
+ 	if (! gr_dbm)
+ 		return 0;
+ 
+ 	key.dsize = strlen (gr->gr_name);
+ 	key.dptr = gr->gr_name;
+ 	content = dbm_fetch (gr_dbm, key);
+ 	if (content.dptr == 0)
+ 		++errors;
+ 	else {
+ 		if (content.dsize == sizeof (int)) {
+ 			memcpy (&cnt, content.dptr, sizeof cnt);
+ 
+ 			for (i = 0;i < cnt;i++) {
+ 				key.dsize = sizeof i + strlen (gr->gr_name);
+ 				key.dptr = grpkey;
+ 				memcpy (grpkey, &i, sizeof i);
+ 				strcpy (grpkey + sizeof i, gr->gr_name);
+ 				if (dbm_delete (gr_dbm, key))
+ 					++errors;
+ 			}
+ 		} else {
+ 			if (dbm_delete (gr_dbm, key))
+ 				++errors;
+ 		}
+ 	}
+ 	key.dsize = sizeof gr->gr_gid;
+ 	key.dptr = &gr->gr_gid;
+ 	content = dbm_fetch (gr_dbm, key);
+ 	if (content.dptr == 0)
+ 		++errors;
+ 	else {
+ 		if (content.dsize == sizeof (int)) {
+ 			memcpy (&cnt, content.dptr, sizeof cnt);
+ 
+ 			for (i = 0;i < cnt;i++) {
+ 				key.dsize = sizeof i + sizeof gr->gr_gid;
+ 				key.dptr = grpkey;
+ 				memcpy (grpkey, &i, sizeof i);
+ 				memcpy (grpkey + sizeof i,
+ 					&gr->gr_gid, sizeof gr->gr_gid);
+ 
+ 				if (dbm_delete (gr_dbm, key))
+ 					++errors;
+ 			}
+ 		} else {
+ 			if (dbm_delete (gr_dbm, key))
+ 				++errors;
+ 		}
+ 	}
+ 	return errors ? 0:1;
  }
  #endif
Index: gsdbm.c
*** rel3/gsdbm.c	Tue Jun 25 09:35:52 1991
--- gsdbm.c	Wed Jun 26 09:43:29 1991
***************
*** 10,16 ****
   */
  
  #ifndef	lint
! static	char	sccsid[] = "@(#)gsdbm.c	3.3	11:25:29	12/19/90";
  #endif
  
  #include <string.h>
--- 10,16 ----
   */
  
  #ifndef	lint
! static	char	sccsid[] = "@(#)gsdbm.c	3.4	22:55:17	6/13/91";
  #endif
  
  #include <string.h>
***************
*** 88,92 ****
--- 88,145 ----
  		}
  	}
  	return 1;
+ }
+ 
+ /*
+  * sgr_dbm_remove
+  *
+  * Deletes the DBM shadow group file entries, if they exist.
+  */
+ 
+ int
+ sgr_dbm_remove (name)
+ char	*name;
+ {
+ 	datum	key;
+ 	datum	content;
+ 	char	grpkey[60];
+ 	char	*cp;
+ 	int	i;
+ 	int	cnt;
+ 	int	errors = 0;
+ 	static	int	once;
+ 
+ 	if (! once) {
+ 		if (! sgr_dbm)
+ 			setsgent ();
+ 
+ 		once++;
+ 	}
+ 	if (! sgr_dbm)
+ 		return 0;
+ 
+ 	key.dsize = strlen (name);
+ 	key.dptr = name;
+ 	content = dbm_fetch (sgr_dbm, key);
+ 	if (content.dptr == 0)
+ 		++errors;
+ 	else {
+ 		if (content.dsize == sizeof (int)) {
+ 			memcpy (&cnt, content.dptr, sizeof cnt);
+ 
+ 			for (i = 0;i < cnt;i++) {
+ 				key.dsize = sizeof i + strlen (name);
+ 				key.dptr = grpkey;
+ 				memcpy (grpkey, &i, sizeof i);
+ 				strcpy (grpkey + sizeof i, name);
+ 				if (dbm_delete (sgr_dbm, key))
+ 					++errors;
+ 			}
+ 		} else {
+ 			if (dbm_delete (sgr_dbm, key))
+ 				++errors;
+ 		}
+ 	}
+ 	return errors ? 0:1;
  }
  #endif
Index: gshadow.c
*** rel3/gshadow.c	Tue Jun 25 09:38:10 1991
--- gshadow.c	Wed Jun 26 09:43:30 1991
***************
*** 32,38 ****
  
  
  #ifndef	lint
! static	char	sccsid[] = "@(#)gshadow.c	3.4	07:31:22	6/6/91";
  #endif
  
  #define	MAXMEM	1024
--- 32,38 ----
  
  
  #ifndef	lint
! static	char	sccsid[] = "@(#)gshadow.c	3.5	22:56:08	6/13/91";
  #endif
  
  #define	MAXMEM	1024
***************
*** 136,147 ****
  	if (cp = strrchr (sgrbuf, '\n'))
  		*cp = '\0';
  
! 	for (cp = sgrbuf, i = 0;*cp && i < FIELDS;i++) {
  		fields[i] = cp;
! 		while (*cp && *cp != ':')
! 			cp++;
! 
! 		if (*cp)
  			*cp++ = '\0';
  	}
  	if (*cp || i != FIELDS)
--- 136,144 ----
  	if (cp = strrchr (sgrbuf, '\n'))
  		*cp = '\0';
  
! 	for (cp = sgrbuf, i = 0;i < FIELDS && cp;i++) {
  		fields[i] = cp;
! 		if (cp = strchr (cp, ':'))
  			*cp++ = '\0';
  	}
  	if (*cp || i != FIELDS)
*** /dev/null	Wed Jun 26 09:26:31 1991
--- groupadd.c	Wed Jun 26 09:43:32 1991
***************
*** 0 ****
--- 1,390 ----
+ /*
+  * Copyright 1991, John F. Haugh II
+  * All rights reserved.
+  *
+  * Permission is granted to copy and create derivative works for any
+  * non-commercial purpose, provided this copyright notice is preserved
+  * in all copies of source code, or included in human readable form
+  * and conspicuously displayed on all copies of object code or
+  * distribution media.
+  */
+ 
+ #ifndef lint
+ static	char	sccsid[] = "@(#)groupadd.c	3.1	22:59:04	6/13/91";
+ #endif
+ 
+ #include <sys/types.h>
+ #include <stdio.h>
+ #include <grp.h>
+ #include <ctype.h>
+ #include <fcntl.h>
+ 
+ #ifdef	BSD
+ #include <strings.h>
+ #else
+ #include <string.h>
+ #endif
+ 
+ #include "config.h"
+ #include "shadow.h"
+ 
+ #ifdef	USE_SYSLOG
+ #include <syslog.h>
+ #endif
+ 
+ char	group_name[BUFSIZ];
+ int	group_id;
+ 
+ char	*Prog;
+ 
+ int	oflg;	/* permit non-unique group ID to be specified with -g         */
+ int	gflg;	/* ID value for the new group                                 */
+ 
+ #ifdef	NDBM
+ extern	int	gr_dbm_mode;
+ extern	int	sg_dbm_mode;
+ #endif
+ extern	char	*malloc();
+ 
+ extern	struct	group	*getgrnam();
+ extern	struct	group	*gr_next();
+ extern	int	gr_lock();
+ extern	int	gr_unlock();
+ extern	int	gr_rewind();
+ extern	int	gr_open();
+ 
+ #ifdef	SHADOWGRP
+ extern	int	sgr_lock();
+ extern	int	sgr_unlock();
+ extern	int	sgr_open();
+ #endif
+ 
+ /*
+  * usage - display usage message and exit
+  */
+ 
+ usage ()
+ {
+ 	fprintf (stderr, "usage: groupadd [-g gid [-o]] group\n");
+ 	exit (2);
+ }
+ 
+ /*
+  * new_grent - initialize the values in a group file entry
+  *
+  *	new_grent() takes all of the values that have been entered and
+  *	fills in a (struct group) with them.
+  */
+ 
+ void
+ new_grent (grent)
+ struct	group	*grent;
+ {
+ 	static	char	*empty_list = 0;
+ 
+ 	memset (grent, 0, sizeof *grent);
+ 	grent->gr_name = group_name;
+ 	grent->gr_passwd = "*";
+ 	grent->gr_gid = group_id;
+ 	grent->gr_mem = &empty_list;
+ }
+ 
+ #ifdef	SHADOWGRP
+ /*
+  * new_sgent - initialize the values in a shadow group file entry
+  *
+  *	new_sgent() takes all of the values that have been entered and
+  *	fills in a (struct sgrp) with them.
+  */
+ 
+ void
+ new_sgent (sgent)
+ struct	sgrp	*sgent;
+ {
+ 	static	char	*empty_list = 0;
+ 
+ 	memset (sgent, 0, sizeof *sgent);
+ 	sgent->sg_name = group_name;
+ 	sgent->sg_passwd = "!";
+ 	sgent->sg_adm = &empty_list;
+ 	sgent->sg_mem = &empty_list;
+ }
+ #endif	/* SHADOWGRP */
+ 
+ /*
+  * grp_update - add new group file entries
+  *
+  *	grp_update() writes the new records to the group files.
+  */
+ 
+ void
+ grp_update ()
+ {
+ 	int	i;
+ 	struct	group	grp;
+ #ifdef	SHADOWGRP
+ 	struct	sgrp	sgrp;
+ #endif	/* SHADOWGRP */
+ 
+ 	/*
+ 	 * Create the initial entries for this new group.
+ 	 */
+ 
+ 	new_grent (&grp);
+ #ifdef	SHADOWGRP
+ 	new_sgent (&sgrp);
+ #endif	/* SHADOWGRP */
+ 
+ 	/*
+ 	 * Write out the new group file entry.
+ 	 */
+ 
+ 	if (! gr_update (&grp)) {
+ 		fprintf (stderr, "%s: error adding new group entry\n", Prog);
+ 		exit (1);
+ 	}
+ #ifdef	NDBM
+ 
+ 	/*
+ 	 * Update the DBM group file with the new entry as well.
+ 	 */
+ 
+ 	if (! gr_dbm_update (&grp)) {
+ 		fprintf (stderr, "%s: cannot add new dbm group entry\n", Prog);
+ 		exit (1);
+ 	}
+ #endif	/* NDBM */
+ 
+ #ifdef	SHADOWGRP
+ 
+ 	/*
+ 	 * Write out the new shadow group entries as well.
+ 	 */
+ 
+ 	if (! sgr_update (&sgrp)) {
+ 		fprintf (stderr, "%s: error adding new group entry\n", Prog);
+ 		exit (1);
+ 	}
+ #ifdef	NDBM
+ 
+ 	/*
+ 	 * Update the DBM group file with the new entry as well.
+ 	 */
+ 
+ 	if (! sgr_dbm_update (&sgrp)) {
+ 		fprintf (stderr, "%s: cannot add new dbm group entry\n", Prog);
+ 		exit (1);
+ 	}
+ #endif	/* NDBM */
+ #endif	/* SHADOWGRP */
+ #ifdef	USE_SYSLOG
+ 	syslog (LOG_INFO, "new group: name=%s, gid=%d\n",
+ 		group_name, group_id);
+ #endif	/* USE_SYSLOG */
+ }
+ 
+ /*
+  * find_new_gid - find the next available GID
+  *
+  *	find_new_gid() locates the next highest unused GID in the group
+  *	file, or checks the given group ID against the existing ones for
+  *	uniqueness.
+  */
+ 
+ int
+ find_new_gid ()
+ {
+ 	struct	group	*grp;
+ 
+ 	/*
+ 	 * Start with some GID value if the user didn't provide us with
+ 	 * one already.
+ 	 */
+ 
+ 	if (! gflg)
+ 		group_id = 100;
+ 
+ 	/*
+ 	 * Search the entire group file, either looking for this
+ 	 * GID (if the user specified one with -g) or looking for the
+ 	 * largest unused value.
+ 	 */
+ 
+ 	for (gr_rewind (), grp = gr_next ();grp;grp = gr_next ()) {
+ 		if (strcmp (group_name, grp->gr_name) == 0) {
+ 			fprintf (stderr, "%s: name %s is not unique\n",
+ 				Prog, group_name);
+ 			exit (1);
+ 		}
+ 		if (gflg && group_id == grp->gr_gid) {
+ 			fprintf (stderr, "%s: gid %d is not unique\n",
+ 				Prog, group_id);
+ 			exit (1);
+ 		}
+ 		if (! gflg && grp->gr_gid >= group_id)
+ 			group_id = grp->gr_gid + 1;
+ 	}
+ }
+ 
+ /*
+  * process_flags - perform command line argument setting
+  *
+  *	process_flags() interprets the command line arguments and sets
+  *	the values that the user will be created with accordingly.  The
+  *	values are checked for sanity.
+  */
+ 
+ void
+ process_flags (argc, argv)
+ int	argc;
+ char	**argv;
+ {
+ 	extern	int	optind;
+ 	extern	char	*optarg;
+ 	struct	group	*grp;
+ 	char	*end;
+ 	int	anyflag = 0;
+ 	int	arg;
+ 
+ 	while ((arg = getopt (argc, argv, "og:")) != EOF) {
+ 		switch (arg) {
+ 			case 'g':
+ 				gflg++;
+ 				if (! isdigit (optarg[0]))
+ 					usage ();
+ 
+ 				group_id = strtol (optarg, &end, 10);
+ 				if (*end != '\0') {
+ 					fprintf (stderr, "%s: invalid group %s\n",
+ 						Prog, optarg);
+ 					exit (3);
+ 				}
+ 				break;
+ 			case 'o':
+ 				if (! gflg)
+ 					usage ();
+ 
+ 				oflg++;
+ 				break;
+ 			default:
+ 				usage ();
+ 		}
+ 		anyflag++;
+ 	}
+ 	if (optind == argc - 1)
+ 		strcpy (group_name, argv[argc - 1]);
+ 	else
+ 		usage ();
+ }
+ 
+ /*
+  * close_files - close all of the files that were opened
+  *
+  *	close_files() closes all of the files that were opened for this
+  *	new group.  This causes any modified entries to be written out.
+  */
+ 
+ close_files ()
+ {
+ 	if (! gr_close ()) {
+ 		fprintf (stderr, "%s: cannot rewrite group file\n", Prog);
+ 		exit (1);
+ 	}
+ 	(void) gr_unlock ();
+ #ifdef	SHADOWGRP
+ 	if (! sgr_close ()) {
+ 		fprintf (stderr, "%s: cannot rewrite shadow group file\n",
+ 			Prog);
+ 		exit (1);
+ 	}
+ 	(void) sgr_unlock ();
+ #endif	/* SHADOWGRP */
+ }
+ 
+ /*
+  * open_files - lock and open the group files
+  *
+  *	open_files() opens the two group files.
+  */
+ 
+ open_files ()
+ {
+ 	if (! gr_lock ()) {
+ 		fprintf (stderr, "%s: unable to lock group file\n", Prog);
+ 		exit (1);
+ 	}
+ 	if (! gr_open (O_RDWR)) {
+ 		fprintf (stderr, "%s: unable to open group file\n", Prog);
+ 		exit (1);
+ 	}
+ #ifdef	SHADOWGRP
+ 	if (! sgr_lock ()) {
+ 		fprintf (stderr, "%s: unable to lock shadow group file\n",
+ 			Prog);
+ 		exit (1);
+ 	}
+ 	if (! sgr_open (O_RDWR)) {
+ 		fprintf (stderr, "%s: unable to open shadow group file\n",
+ 			Prog);
+ 		exit (1);
+ 	}
+ #endif	/* SHADOWGRP */
+ }
+ 
+ /*
+  * main - useradd command
+  */
+ 
+ main (argc, argv)
+ int	argc;
+ char	**argv;
+ {
+ 
+ 	/*
+ 	 * Get my name so that I can use it to report errors.
+ 	 */
+ 
+ 	if (Prog = strrchr (argv[0], '/'))
+ 		Prog++;
+ 	else
+ 		Prog = argv[0];
+ 
+ #ifdef	USE_SYSLOG
+ 	openlog (Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH);
+ #endif	/* USE_SYSLOG */
+ 
+ 	/*
+ 	 * The open routines for the DBM files don't use read-write
+ 	 * as the mode, so we have to clue them in.
+ 	 */
+ 
+ #ifdef	NDBM
+ 	gr_dbm_mode = O_RDWR;
+ #ifdef	SHADOWGRP
+ 	sg_dbm_mode = O_RDWR;
+ #endif	/* SHADOWGRP */
+ #endif	/* NDBM */
+ 	process_flags (argc, argv);
+ 
+ 	/*
+ 	 * Start with a quick check to see if the group exists.
+ 	 */
+ 
+ 	if (getgrnam (group_name)) {
+ 		fprintf (stderr, "%s: group %s exists\n", Prog, group_name);
+ 		exit (9);
+ 	}
+ 
+ 	/*
+ 	 * Do the hard stuff - open the files, create the group entries,
+ 	 * then close and update the files.
+ 	 */
+ 
+ 	open_files ();
+ 
+ 	grp_update ();
+ 
+ 	close_files ();
+ 	exit (0);
+ 	/*NOTREACHED*/
+ }
*** /dev/null	Wed Jun 26 09:26:31 1991
--- groupdel.c	Wed Jun 26 09:43:33 1991
***************
*** 0 ****
--- 1,254 ----
+ /*
+  * Copyright 1991, John F. Haugh II
+  * All rights reserved.
+  *
+  * Permission is granted to copy and create derivative works for any
+  * non-commercial purpose, provided this copyright notice is preserved
+  * in all copies of source code, or included in human readable form
+  * and conspicuously displayed on all copies of object code or
+  * distribution media.
+  */
+ 
+ #ifndef lint
+ static	char	sccsid[] = "@(#)groupdel.c	3.1	22:59:09	6/13/91";
+ #endif
+ 
+ #include <sys/types.h>
+ #include <stdio.h>
+ #include <grp.h>
+ #include <ctype.h>
+ #include <fcntl.h>
+ 
+ #ifdef	BSD
+ #include <strings.h>
+ #else
+ #include <string.h>
+ #endif
+ 
+ #include "config.h"
+ #include "shadow.h"
+ 
+ #ifdef	USE_SYSLOG
+ #include <syslog.h>
+ #endif
+ 
+ char	group_name[BUFSIZ];
+ char	*Prog;
+ 
+ #ifdef	NDBM
+ extern	int	gr_dbm_mode;
+ extern	int	sg_dbm_mode;
+ #endif
+ extern	char	*malloc();
+ 
+ extern	struct	group	*getgrnam();
+ extern	struct	group	*gr_next();
+ extern	struct	group	*gr_locate();
+ extern	int	gr_lock();
+ extern	int	gr_unlock();
+ extern	int	gr_rewind();
+ extern	int	gr_open();
+ 
+ #ifdef	SHADOWGRP
+ extern	struct	sgrp	*sgr_locate();
+ extern	int	sgr_lock();
+ extern	int	sgr_unlock();
+ extern	int	sgr_open();
+ #endif
+ 
+ /*
+  * usage - display usage message and exit
+  */
+ 
+ usage ()
+ {
+ 	fprintf (stderr, "usage: groupmod group\n");
+ 	exit (2);
+ }
+ 
+ /*
+  * grp_update - update group file entries
+  *
+  *	grp_update() writes the new records to the group files.
+  */
+ 
+ void
+ grp_update ()
+ {
+ 	int	i;
+ 	struct	group	*ogrp;
+ 
+ 	if (! gr_remove (group_name)) {
+ 		fprintf (stderr, "%s: error removing group entry\n", Prog);
+ 		exit (1);
+ 	}
+ #ifdef	NDBM
+ 
+ 	/*
+ 	 * Update the DBM group file
+ 	 */
+ 
+ 	if (access ("/etc/group.pag", 0) == 0) {
+ 		if ((ogrp = getgrnam (group_name)) &&
+ 				! gr_dbm_remove (ogrp)) {
+ 			fprintf (stderr, "%s: error removing group dbm entry\n",
+ 				Prog);
+ 			exit (1);
+ 		}
+ 	}
+ #endif	/* NDBM */
+ 
+ #ifdef	SHADOWGRP
+ 
+ 	/*
+ 	 * Delete the shadow group entries as well.
+ 	 */
+ 
+ 	if (! sgr_remove (group_name)) {
+ 		fprintf (stderr, "%s: error removing shadow group entry\n",
+ 			Prog);
+ 		exit (1);
+ 	}
+ #ifdef	NDBM
+ 
+ 	/*
+ 	 * Update the DBM shadow group file
+ 	 */
+ 
+ 	if (access ("/etc/gshadow.pag", 0) == 0) {
+ 		if (! sgr_dbm_remove (group_name)) {
+ 			fprintf (stderr,
+ 				"%s: error removing shadow group dbm entry\n",
+ 				Prog);
+ 			exit (1);
+ 		}
+ 	}
+ #endif	/* NDBM */
+ #endif	/* SHADOWGRP */
+ #ifdef	USE_SYSLOG
+ 	syslog (LOG_INFO, "remove group `%s'\n", group_name);
+ #endif	/* USE_SYSLOG */
+ }
+ 
+ /*
+  * close_files - close all of the files that were opened
+  *
+  *	close_files() closes all of the files that were opened for this
+  *	new group.  This causes any modified entries to be written out.
+  */
+ 
+ close_files ()
+ {
+ 	if (! gr_close ()) {
+ 		fprintf (stderr, "%s: cannot rewrite group file\n", Prog);
+ 		exit (1);
+ 	}
+ 	(void) gr_unlock ();
+ #ifdef	SHADOWGRP
+ 	if (! sgr_close ()) {
+ 		fprintf (stderr, "%s: cannot rewrite shadow group file\n",
+ 			Prog);
+ 		exit (1);
+ 	}
+ 	(void) sgr_unlock ();
+ #endif	/* SHADOWGRP */
+ }
+ 
+ /*
+  * open_files - lock and open the group files
+  *
+  *	open_files() opens the two group files.
+  */
+ 
+ open_files ()
+ {
+ 	if (! gr_lock ()) {
+ 		fprintf (stderr, "%s: unable to lock group file\n", Prog);
+ 		exit (1);
+ 	}
+ 	if (! gr_open (O_RDWR)) {
+ 		fprintf (stderr, "%s: unable to open group file\n", Prog);
+ 		exit (1);
+ 	}
+ #ifdef	SHADOWGRP
+ 	if (! sgr_lock ()) {
+ 		fprintf (stderr, "%s: unable to lock shadow group file\n",
+ 			Prog);
+ 		exit (1);
+ 	}
+ 	if (! sgr_open (O_RDWR)) {
+ 		fprintf (stderr, "%s: unable to open shadow group file\n",
+ 			Prog);
+ 		exit (1);
+ 	}
+ #endif	/* SHADOWGRP */
+ }
+ 
+ /*
+  * main - groupdel command
+  *
+  *	The syntax of the groupdel command is
+  *	
+  *	groupdel group
+  *
+  *	The named group will be deleted.
+  */
+ 
+ main (argc, argv)
+ int	argc;
+ char	**argv;
+ {
+ 
+ 	/*
+ 	 * Get my name so that I can use it to report errors.
+ 	 */
+ 
+ 	if (Prog = strrchr (argv[0], '/'))
+ 		Prog++;
+ 	else
+ 		Prog = argv[0];
+ 
+ 	if (argc != 2)
+ 		usage ();
+ 
+ 	strncpy (group_name, argv[1], BUFSIZ);
+ 
+ #ifdef	USE_SYSLOG
+ 	openlog (Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH);
+ #endif	/* USE_SYSLOG */
+ 
+ 	/*
+ 	 * The open routines for the DBM files don't use read-write
+ 	 * as the mode, so we have to clue them in.
+ 	 */
+ 
+ #ifdef	NDBM
+ 	gr_dbm_mode = O_RDWR;
+ #ifdef	SHADOWGRP
+ 	sg_dbm_mode = O_RDWR;
+ #endif	/* SHADOWGRP */
+ #endif	/* NDBM */
+ 
+ 	/*
+ 	 * Start with a quick check to see if the group exists.
+ 	 */
+ 
+ 	if (! getgrnam (group_name)) {
+ 		fprintf (stderr, "%s: group %s does not exist\n",
+ 			Prog, group_name);
+ 		exit (9);
+ 	}
+ 
+ 	/*
+ 	 * Do the hard stuff - open the files, delete the group entries,
+ 	 * then close and update the files.
+ 	 */
+ 
+ 	open_files ();
+ 
+ 	grp_update ();
+ 
+ 	close_files ();
+ 	exit (0);
+ 	/*NOTREACHED*/
+ }
*** /dev/null	Wed Jun 26 09:26:31 1991
--- groupmod.c	Wed Jun 26 09:43:34 1991
***************
*** 0 ****
--- 1,421 ----
+ /*
+  * Copyright 1991, John F. Haugh II
+  * All rights reserved.
+  *
+  * Permission is granted to copy and create derivative works for any
+  * non-commercial purpose, provided this copyright notice is preserved
+  * in all copies of source code, or included in human readable form
+  * and conspicuously displayed on all copies of object code or
+  * distribution media.
+  */
+ 
+ #ifndef lint
+ static	char	sccsid[] = "@(#)groupmod.c	3.1	22:59:07	6/13/91";
+ #endif
+ 
+ #include <sys/types.h>
+ #include <stdio.h>
+ #include <grp.h>
+ #include <ctype.h>
+ #include <fcntl.h>
+ 
+ #ifdef	BSD
+ #include <strings.h>
+ #else
+ #include <string.h>
+ #endif
+ 
+ #include "config.h"
+ #include "shadow.h"
+ 
+ #ifdef	USE_SYSLOG
+ #include <syslog.h>
+ #endif
+ 
+ char	group_name[BUFSIZ];
+ char	group_newname[BUFSIZ];
+ int	group_id;
+ int	group_newid;
+ 
+ char	*Prog;
+ 
+ int	oflg;	/* permit non-unique group ID to be specified with -g         */
+ int	gflg;	/* new ID value for the group                                 */
+ int	nflg;	/* a new name has been specified for the group                */
+ 
+ #ifdef	NDBM
+ extern	int	gr_dbm_mode;
+ extern	int	sg_dbm_mode;
+ #endif
+ extern	char	*malloc();
+ 
+ extern	struct	group	*getgrnam();
+ extern	struct	group	*gr_next();
+ extern	struct	group	*gr_locate();
+ extern	int	gr_lock();
+ extern	int	gr_unlock();
+ extern	int	gr_rewind();
+ extern	int	gr_open();
+ 
+ #ifdef	SHADOWGRP
+ extern	struct	sgrp	*sgr_locate();
+ extern	int	sgr_lock();
+ extern	int	sgr_unlock();
+ extern	int	sgr_open();
+ #endif
+ 
+ /*
+  * usage - display usage message and exit
+  */
+ 
+ usage ()
+ {
+ 	fprintf (stderr, "usage: groupmod [-g gid [-o]] [-n name] group\n");
+ 	exit (2);
+ }
+ 
+ /*
+  * new_grent - updates the values in a group file entry
+  *
+  *	new_grent() takes all of the values that have been entered and
+  *	fills in a (struct group) with them.
+  */
+ 
+ void
+ new_grent (grent)
+ struct	group	*grent;
+ {
+ 	if (nflg)
+ 		grent->gr_name = strdup (group_newname);
+ 
+ 	if (gflg)
+ 		grent->gr_gid = group_newid;
+ }
+ 
+ #ifdef	SHADOWGRP
+ /*
+  * new_sgent - updates the values in a shadow group file entry
+  *
+  *	new_sgent() takes all of the values that have been entered and
+  *	fills in a (struct sgrp) with them.
+  */
+ 
+ void
+ new_sgent (sgent)
+ struct	sgrp	*sgent;
+ {
+ 	if (nflg)
+ 		sgent->sg_name = strdup (group_newname);
+ }
+ #endif	/* SHADOWGRP */
+ 
+ /*
+  * grp_update - update group file entries
+  *
+  *	grp_update() writes the new records to the group files.
+  */
+ 
+ void
+ grp_update ()
+ {
+ 	int	i;
+ 	struct	group	grp;
+ 	struct	group	*ogrp;
+ #ifdef	SHADOWGRP
+ 	struct	sgrp	sgrp;
+ #endif	/* SHADOWGRP */
+ 
+ 	/*
+ 	 * Create the initial entries for this new group.
+ 	 */
+ 
+ 	grp = *(gr_locate (group_name));
+ 	new_grent (&grp);
+ #ifdef	SHADOWGRP
+ 	sgrp = *(sgr_locate (group_name));
+ 	new_sgent (&sgrp);
+ #endif	/* SHADOWGRP */
+ 
+ 	/*
+ 	 * Write out the new group file entry.
+ 	 */
+ 
+ 	if (! gr_update (&grp)) {
+ 		fprintf (stderr, "%s: error adding new group entry\n", Prog);
+ 		exit (1);
+ 	}
+ 	if (nflg && ! gr_remove (group_name)) {
+ 		fprintf (stderr, "%s: error removing group entry\n", Prog);
+ 		exit (1);
+ 	}
+ #ifdef	NDBM
+ 
+ 	/*
+ 	 * Update the DBM group file with the new entry as well.
+ 	 */
+ 
+ 	if (access ("/etc/group.pag", 0) == 0) {
+ 		if (! gr_dbm_update (&grp)) {
+ 			fprintf (stderr, "%s: cannot add new dbm group entry\n",
+ 				Prog);
+ 			exit (1);
+ 		}
+ 		if (nflg && (ogrp = getgrnam (group_name)) &&
+ 				! gr_dbm_remove (ogrp)) {
+ 			fprintf (stderr, "%s: error removing group dbm entry\n",
+ 				Prog);
+ 			exit (1);
+ 		}
+ 	}
+ #endif	/* NDBM */
+ 
+ #ifdef	SHADOWGRP
+ 
+ 	/*
+ 	 * Write out the new shadow group entries as well.
+ 	 */
+ 
+ 	if (! sgr_update (&sgrp)) {
+ 		fprintf (stderr, "%s: error adding new group entry\n", Prog);
+ 		exit (1);
+ 	}
+ 	if (nflg && ! sgr_remove (group_name)) {
+ 		fprintf (stderr, "%s: error removing group entry\n", Prog);
+ 		exit (1);
+ 	}
+ #ifdef	NDBM
+ 
+ 	/*
+ 	 * Update the DBM shadow group file with the new entry as well.
+ 	 */
+ 
+ 	if (access ("/etc/gshadow.pag", 0) == 0) {
+ 		if (! sgr_dbm_update (&sgrp)) {
+ 			fprintf (stderr,
+ 				"%s: cannot add new dbm shadow group entry\n",
+ 				Prog);
+ 			exit (1);
+ 		}
+ 		if (nflg && ! sgr_dbm_remove (group_name)) {
+ 			fprintf (stderr,
+ 				"%s: error removing shadow group dbm entry\n",
+ 				Prog);
+ 			exit (1);
+ 		}
+ 	}
+ #endif	/* NDBM */
+ #endif	/* SHADOWGRP */
+ #ifdef	USE_SYSLOG
+ 	if (nflg)
+ 		syslog (LOG_INFO, "change group `%s' to `%s'\n",
+ 			group_name, group_newname);
+ 
+ 	if (gflg)
+ 		syslog (LOG_INFO, "change gid for `%s' to %d\n",
+ 			nflg ? group_name:group_newname, group_newid);
+ #endif	/* USE_SYSLOG */
+ }
+ 
+ /*
+  * check_new_gid - check the new GID value for uniqueness
+  *
+  *	check_new_gid() insures that the new GID value is unique.
+  */
+ 
+ int
+ check_new_gid ()
+ {
+ 	/*
+ 	 * First, the easy stuff.  If the ID can be duplicated, or if
+ 	 * the ID didn't really change, just return.  If the ID didn't
+ 	 * change, turn off those flags.  No sense doing needless work.
+ 	 */
+ 
+ 	if (oflg)
+ 		return 0;
+ 
+ 	if (group_id == group_newid) {
+ 		gflg = 0;
+ 		return 0;
+ 	}
+ 	if (getgrgid (group_newid))
+ 		return -1;
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * process_flags - perform command line argument setting
+  *
+  *	process_flags() interprets the command line arguments and sets
+  *	the values that the user will be created with accordingly.  The
+  *	values are checked for sanity.
+  */
+ 
+ void
+ process_flags (argc, argv)
+ int	argc;
+ char	**argv;
+ {
+ 	extern	int	optind;
+ 	extern	char	*optarg;
+ 	struct	group	*grp;
+ 	char	*end;
+ 	int	anyflag = 0;
+ 	int	arg;
+ 
+ 	while ((arg = getopt (argc, argv, "og:n:")) != EOF) {
+ 		switch (arg) {
+ 			case 'g':
+ 				gflg++;
+ 				group_newid = strtol (optarg, &end, 10);
+ 				if (*end != '\0') {
+ 					fprintf (stderr, "%s: invalid group %s\n",
+ 						Prog, optarg);
+ 					exit (3);
+ 				}
+ 				break;
+ 			case 'n':
+ 				if (strcmp (group_name, optarg)) {
+ 					nflg++;
+ 					strncpy (group_newname, optarg, BUFSIZ);
+ 				}
+ 				break;
+ 			case 'o':
+ 				if (! gflg)
+ 					usage ();
+ 
+ 				oflg++;
+ 				break;
+ 			default:
+ 				usage ();
+ 		}
+ 		anyflag++;
+ 	}
+ 	if (optind == argc - 1)
+ 		strcpy (group_name, argv[argc - 1]);
+ 	else
+ 		usage ();
+ }
+ 
+ /*
+  * close_files - close all of the files that were opened
+  *
+  *	close_files() closes all of the files that were opened for this
+  *	new group.  This causes any modified entries to be written out.
+  */
+ 
+ close_files ()
+ {
+ 	if (! gr_close ()) {
+ 		fprintf (stderr, "%s: cannot rewrite group file\n", Prog);
+ 		exit (1);
+ 	}
+ 	(void) gr_unlock ();
+ #ifdef	SHADOWGRP
+ 	if (! sgr_close ()) {
+ 		fprintf (stderr, "%s: cannot rewrite shadow group file\n",
+ 			Prog);
+ 		exit (1);
+ 	}
+ 	(void) sgr_unlock ();
+ #endif	/* SHADOWGRP */
+ }
+ 
+ /*
+  * open_files - lock and open the group files
+  *
+  *	open_files() opens the two group files.
+  */
+ 
+ open_files ()
+ {
+ 	if (! gr_lock ()) {
+ 		fprintf (stderr, "%s: unable to lock group file\n", Prog);
+ 		exit (1);
+ 	}
+ 	if (! gr_open (O_RDWR)) {
+ 		fprintf (stderr, "%s: unable to open group file\n", Prog);
+ 		exit (1);
+ 	}
+ #ifdef	SHADOWGRP
+ 	if (! sgr_lock ()) {
+ 		fprintf (stderr, "%s: unable to lock shadow group file\n",
+ 			Prog);
+ 		exit (1);
+ 	}
+ 	if (! sgr_open (O_RDWR)) {
+ 		fprintf (stderr, "%s: unable to open shadow group file\n",
+ 			Prog);
+ 		exit (1);
+ 	}
+ #endif	/* SHADOWGRP */
+ }
+ 
+ /*
+  * main - groupmod command
+  *
+  *	The syntax of the groupmod command is
+  *	
+  *	groupmod [ -g gid [ -o ]] [ -n name ] group
+  *
+  *	The flags are
+  *		-g - specify a new group ID value
+  *		-o - permit the group ID value to be non-unique
+  *		-n - specify a new group name
+  */
+ 
+ main (argc, argv)
+ int	argc;
+ char	**argv;
+ {
+ 
+ 	/*
+ 	 * Get my name so that I can use it to report errors.
+ 	 */
+ 
+ 	if (Prog = strrchr (argv[0], '/'))
+ 		Prog++;
+ 	else
+ 		Prog = argv[0];
+ 
+ #ifdef	USE_SYSLOG
+ 	openlog (Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH);
+ #endif	/* USE_SYSLOG */
+ 
+ 	/*
+ 	 * The open routines for the DBM files don't use read-write
+ 	 * as the mode, so we have to clue them in.
+ 	 */
+ 
+ #ifdef	NDBM
+ 	gr_dbm_mode = O_RDWR;
+ #ifdef	SHADOWGRP
+ 	sg_dbm_mode = O_RDWR;
+ #endif	/* SHADOWGRP */
+ #endif	/* NDBM */
+ 	process_flags (argc, argv);
+ 
+ 	/*
+ 	 * Start with a quick check to see if the group exists.
+ 	 */
+ 
+ 	if (! getgrnam (group_name)) {
+ 		fprintf (stderr, "%s: group %s does not exist\n",
+ 			Prog, group_name);
+ 		exit (9);
+ 	}
+ 
+ 	/*
+ 	 * Do the hard stuff - open the files, create the group entries,
+ 	 * then close and update the files.
+ 	 */
+ 
+ 	open_files ();
+ 
+ 	grp_update ();
+ 
+ 	close_files ();
+ 	exit (0);
+ 	/*NOTREACHED*/
+ }
Index: useradd.c
*** rel3/useradd.c	Tue Jun 25 09:38:28 1991
--- useradd.c	Wed Jun 26 09:43:37 1991
***************
*** 10,16 ****
   */
  
  #ifndef lint
! static	char	sccsid[] = "@(#)useradd.c	3.2	20:15:10	6/11/91";
  #endif
  
  #include <sys/types.h>
--- 10,16 ----
   */
  
  #ifndef lint
! static	char	sccsid[] = "@(#)useradd.c	3.4	09:39:58	6/26/91";
  #endif
  
  #include <sys/types.h>
***************
*** 80,93 ****
  int	eflg;	/* days after password changed before it becomes expired      */
  int	Dflg;	/* set/show new user default values                           */
  
! #if defined(DBM) || defined(NDBM)
  extern	int	pw_dbm_mode;
- #endif
- #ifdef	NDBM
  extern	int	sp_dbm_mode;
  extern	int	gr_dbm_mode;
  extern	int	sg_dbm_mode;
  #endif
  extern	FILE	*fopen();
  extern	int	fclose();
  extern	char	*malloc();
--- 80,93 ----
  int	eflg;	/* days after password changed before it becomes expired      */
  int	Dflg;	/* set/show new user default values                           */
  
! #ifdef NDBM
  extern	int	pw_dbm_mode;
  extern	int	sp_dbm_mode;
  extern	int	gr_dbm_mode;
+ #ifdef	SHADOWGRP
  extern	int	sg_dbm_mode;
  #endif
+ #endif
  extern	FILE	*fopen();
  extern	int	fclose();
  extern	char	*malloc();
***************
*** 372,378 ****
  			else if (grp = getgrnam (cp))
  				def_group = grp->gr_gid;
  			else
! 				fprintf (stderr, "%s: unknown group %s\n", cp);
  		}
  		
  		/*
--- 372,379 ----
  			else if (grp = getgrnam (cp))
  				def_group = grp->gr_gid;
  			else
! 				fprintf (stderr, "%s: unknown group %s\n",
! 					Prog, cp);
  		}
  		
  		/*
***************
*** 638,644 ****
  usage ()
  {
  	fprintf (stderr,
! 		"usage:\tuseradd [-u uid [-o]] [-g group] [-G group,...] \n");
  	fprintf (stderr,
  		"\t\t[-d home] [-s shell] [-c comment] [-m [-k template]]\n");
  	fprintf (stderr,
--- 639,645 ----
  usage ()
  {
  	fprintf (stderr,
! 		"usage:\t%s [-u uid [-o]] [-g group] [-G group,...] \n", Prog);
  	fprintf (stderr,
  		"\t\t[-d home] [-s shell] [-c comment] [-m [-k template]]\n");
  	fprintf (stderr,
***************
*** 645,651 ****
  		"\t\t[-f inactive] [-e expire] name\n");
  
  	fprintf (stderr,
! 		"\tuseradd -D [-g group] [-b base] [-f inactive] [-e expire]\n");
  
  	exit (1);
  }
--- 646,653 ----
  		"\t\t[-f inactive] [-e expire] name\n");
  
  	fprintf (stderr,
! 		"\t%s -D [-g group] [-b base] [-f inactive] [-e expire]\n",
! 			Prog);
  
  	exit (1);
  }
***************
*** 962,971 ****
  				if (! grp) {
  					fprintf (stderr,
  						"%s: unknown group %s\n",
! 						optarg);
  					exit (1);
  				}
! 				def_group = grp->gr_gid;
  				break;
  			case 'G':
  				Gflg++;
--- 964,973 ----
  				if (! grp) {
  					fprintf (stderr,
  						"%s: unknown group %s\n",
! 						Prog, optarg);
  					exit (1);
  				}
! 				user_gid = grp->gr_gid;
  				break;
  			case 'G':
  				Gflg++;
***************
*** 1061,1068 ****
--- 1063,1072 ----
  				Prog);
  			exit (1);
  		}
+ 		(void) sgr_unlock ();
  #endif
  	}
+ 	(void) spw_unlock ();
  	(void) pw_unlock ();
  }
  
Index: userdel.c
*** rel3/userdel.c	Tue Jun 25 09:38:29 1991
--- userdel.c	Wed Jun 26 09:43:39 1991
***************
*** 10,16 ****
   */
  
  #ifndef lint
! static	char	sccsid[] = "@(#)userdel.c	3.5	20:53:04	6/13/91";
  #endif
  
  #include <sys/types.h>
--- 10,16 ----
   */
  
  #ifndef lint
! static	char	sccsid[] = "@(#)userdel.c	3.7	09:40:05	6/26/91";
  #endif
  
  #include <sys/types.h>
***************
*** 64,73 ****
  char	*Prog;
  int	rflg;
  
- #if defined(DBM) || defined(NDBM)
- extern	int	pw_dbm_mode;
- #endif
  #ifdef	NDBM
  extern	int	sp_dbm_mode;
  extern	int	gr_dbm_mode;
  #ifdef	SHADOWGRP
--- 64,71 ----
  char	*Prog;
  int	rflg;
  
  #ifdef	NDBM
+ extern	int	pw_dbm_mode;
  extern	int	sp_dbm_mode;
  extern	int	gr_dbm_mode;
  #ifdef	SHADOWGRP
***************
*** 147,153 ****
  
  usage ()
  {
! 	fprintf (stderr, "usage: userdel [-r] name\n");
  	exit (2);
  }
  
--- 145,151 ----
  
  usage ()
  {
! 	fprintf (stderr, "usage: %s [-r] name\n", Prog);
  	exit (2);
  }
  
***************
*** 266,272 ****
  #endif
  #ifdef	USE_SYSLOG
  		syslog (LOG_INFO, "delete `%s' from shadow group `%s'\n",
! 			user_name, grp->gr_name);
  #endif
  	}
  #endif
--- 264,270 ----
  #endif
  #ifdef	USE_SYSLOG
  		syslog (LOG_INFO, "delete `%s' from shadow group `%s'\n",
! 			user_name, sgrp->sg_name);
  #endif
  	}
  #endif
***************
*** 304,309 ****
--- 302,308 ----
  	}
  	(void) sgr_unlock ();
  #endif
+ 	(void) spw_unlock ();
  	(void) pw_unlock ();
  }
  
Index: usermod.c
*** rel3/usermod.c	Tue Jun 25 09:38:29 1991
--- usermod.c	Wed Jun 26 09:43:42 1991
***************
*** 10,16 ****
   */
  
  #ifndef lint
! static	char	sccsid[] = "@(#)usermod.c	3.2	20:26:57	6/11/91";
  #endif
  
  #include <sys/types.h>
--- 10,16 ----
   */
  
  #ifndef lint
! static	char	sccsid[] = "@(#)usermod.c	3.3	09:29:57	6/26/91";
  #endif
  
  #include <sys/types.h>
***************
*** 57,63 ****
  char	user_shell[BUFSIZ];
  long	user_expire;
  long	user_inactive;
! int	user_ngroups;
  gid_t	user_groups[NGROUPS_MAX];
  struct	passwd	user_pwd;
  struct	spwd	user_spwd;
--- 57,63 ----
  char	user_shell[BUFSIZ];
  long	user_expire;
  long	user_inactive;
! int	user_ngroups = -1;
  gid_t	user_groups[NGROUPS_MAX];
  struct	passwd	user_pwd;
  struct	spwd	user_spwd;
***************
*** 76,89 ****
  int	eflg;	/* days after password changed before it becomes expired      */
  int	lflg;	/* new user name for user                                     */
  
- #if defined(DBM) || defined(NDBM)
- extern	int	pw_dbm_mode;
- #endif
  #ifdef	NDBM
  extern	int	sp_dbm_mode;
  extern	int	gr_dbm_mode;
  extern	int	sg_dbm_mode;
  #endif
  extern	FILE	*fopen();
  extern	int	fclose();
  extern	char	*malloc();
--- 76,89 ----
  int	eflg;	/* days after password changed before it becomes expired      */
  int	lflg;	/* new user name for user                                     */
  
  #ifdef	NDBM
+ extern	int	pw_dbm_mode;
  extern	int	sp_dbm_mode;
  extern	int	gr_dbm_mode;
+ #ifdef	SHADOWGRP
  extern	int	sg_dbm_mode;
  #endif
+ #endif
  extern	FILE	*fopen();
  extern	int	fclose();
  extern	char	*malloc();
***************
*** 848,854 ****
  				if (! grp) {
  					fprintf (stderr,
  						"%s: unknown group %s\n",
! 						optarg);
  					exit (1);
  				}
  				if (grp->gr_gid != user_gid) {
--- 848,854 ----
  				if (! grp) {
  					fprintf (stderr,
  						"%s: unknown group %s\n",
! 						Prog, optarg);
  					exit (1);
  				}
  				if (grp->gr_gid != user_gid) {
***************
*** 907,912 ****
--- 907,916 ----
  		}
  		anyflag++;
  	}
+ 	if (anyflag == 0) {
+ 		fprintf (stderr, "%s: no flags given\n", Prog);
+ 		exit (1);
+ 	}
  	if (optind != argc - 1)
  		usage ();
  
***************
*** 917,923 ****
  		uflg = oflg = 0;
  
  	if (lflg && getpwnam (user_newname)) {
! 		fprintf (stderr, "%s: user %s exists\n", user_newname);
  		exit (9);
  	}
  }
--- 921,927 ----
  		uflg = oflg = 0;
  
  	if (lflg && getpwnam (user_newname)) {
! 		fprintf (stderr, "%s: user %s exists\n", Prog, user_newname);
  		exit (9);
  	}
  }
***************
*** 940,946 ****
  			Prog);
  		exit (1);
  	}
! 	if (user_ngroups > 0) {
  		if (! gr_close ()) {
  			fprintf (stderr, "%s: cannot rewrite group file\n",
  				Prog);
--- 944,950 ----
  			Prog);
  		exit (1);
  	}
! 	if (user_ngroups >= 0) {
  		if (! gr_close ()) {
  			fprintf (stderr, "%s: cannot rewrite group file\n",
  				Prog);
***************
*** 953,960 ****
--- 957,966 ----
  				Prog);
  			exit (1);
  		}
+ 		(void) sgr_unlock ();
  #endif
  	}
+ 	(void) spw_unlock ();
  	(void) pw_unlock ();
  }
  
***************
*** 1009,1019 ****
  
  	if (lflg || uflg || gflg || cflg || dflg || sflg) {
  		if (! pw_update (&pwent)) {
! 			fprintf (stderr, "%s: error changing password entry\n");
  			exit (1);
  		}
  		if (lflg && ! pw_remove (user_name)) {
! 			fprintf (stderr, "%s: error removing password entry\n");
  			exit (1);
  		}
  #if defined(DBM) || defined(NDBM)
--- 1015,1027 ----
  
  	if (lflg || uflg || gflg || cflg || dflg || sflg) {
  		if (! pw_update (&pwent)) {
! 			fprintf (stderr, "%s: error changing password entry\n",
! 				Prog);
  			exit (1);
  		}
  		if (lflg && ! pw_remove (user_name)) {
! 			fprintf (stderr, "%s: error removing password entry\n",
! 				Prog);
  			exit (1);
  		}
  #if defined(DBM) || defined(NDBM)
Index: shadowio.c
*** rel3/shadowio.c	Tue Jun 25 09:37:59 1991
--- shadowio.c	Wed Jun 26 09:43:44 1991
***************
*** 24,30 ****
   */
  
  #ifndef	lint
! static	char	sccsid[] = "@(#)shadowio.c	3.5	09:08:15	5/28/91";
  #endif
  
  #include <sys/types.h>
--- 24,30 ----
   */
  
  #ifndef	lint
! static	char	sccsid[] = "@(#)shadowio.c	3.6	09:17:38	6/26/91";
  #endif
  
  #include <sys/types.h>
***************
*** 338,351 ****
  spw_close ()
  {
  	char	backup[BUFSIZ];
- 	int	fd;
  	int	mask;
  	int	c;
- 	int	i;
  	int	errors = 0;
  	FILE	*bkfp;
  	struct	spw_file_entry *spwf;
! 	struct	spw_file_entry *ospwf;
  
  	if (! isopen) {
  		errno = EINVAL;
--- 338,349 ----
  spw_close ()
  {
  	char	backup[BUFSIZ];
  	int	mask;
  	int	c;
  	int	errors = 0;
  	FILE	*bkfp;
  	struct	spw_file_entry *spwf;
! 	struct	stat	sb;
  
  	if (! isopen) {
  		errno = EINVAL;
***************
*** 361,372 ****
  	strcat (backup, "-");
  
  	if (open_modes == O_RDWR && sp_changed) {
! 		mask = umask (077);
  		if ((bkfp = fopen (backup, "w")) == 0) {
  			umask (mask);
  			return 0;
  		}
  		umask (mask);
  
  		rewind (spwfp);
  		while ((c = getc (spwfp)) != EOF) {
--- 359,372 ----
  	strcat (backup, "-");
  
  	if (open_modes == O_RDWR && sp_changed) {
! 		mask = umask (0377);
  		if ((bkfp = fopen (backup, "w")) == 0) {
  			umask (mask);
  			return 0;
  		}
  		umask (mask);
+ 		fstat (fileno (spwfp), &sb);
+ 		chown (backup, sb.st_uid, sb.st_gid);
  
  		rewind (spwfp);
  		while ((c = getc (spwfp)) != EOF) {
***************
*** 381,387 ****
  		isopen = 0;
  		(void) fclose (spwfp);
  
! 		mask = umask (077);
  		if (! (spwfp = fopen (spw_filename, "w"))) {
  			umask (mask);
  			return 0;
--- 381,387 ----
  		isopen = 0;
  		(void) fclose (spwfp);
  
! 		mask = umask (0377);
  		if (! (spwfp = fopen (spw_filename, "w"))) {
  			umask (mask);
  			return 0;
***************
*** 429,434 ****
--- 429,435 ----
  		free (spwf);
  	}
  	spwf_tail = 0;
+ 	isopen = 0;
  	return 1;
  }
  
Index: groupio.c
*** rel3/groupio.c	Tue Jun 25 09:37:51 1991
--- groupio.c	Wed Jun 26 09:43:47 1991
***************
*** 36,42 ****
  #endif
  
  #ifndef	lint
! static	char	sccsid[] = "@(#)groupio.c	3.7 09:07:28 5/28/91";
  #endif
  
  static	int	islocked;
--- 36,42 ----
  #endif
  
  #ifndef	lint
! static	char	sccsid[] = "@(#)groupio.c	3.8 09:03:34 6/26/91";
  #endif
  
  static	int	islocked;
***************
*** 365,370 ****
--- 365,371 ----
  	FILE	*bkfp;
  	struct	gr_file_entry *grf;
  	struct	gr_file_entry *ogrf;
+ 	struct	stat	sb;
  
  	if (! isopen) {
  		errno = EINVAL;
***************
*** 386,391 ****
--- 387,394 ----
  			return 0;
  		}
  		umask (mask);
+ 		fstat (fileno (grfp), &sb);
+ 		chown (backup, sb.st_uid, sb.st_gid);
  
  		rewind (grfp);
  		while ((c = getc (grfp)) != EOF) {
***************
*** 448,453 ****
--- 451,457 ----
  		free (grf);
  	}
  	grf_tail = 0;
+ 	isopen = 0;
  	return 1;
  }
  
Index: sgroupio.c
*** rel3/sgroupio.c	Tue Jun 25 09:38:10 1991
--- sgroupio.c	Wed Jun 26 09:43:49 1991
***************
*** 38,44 ****
  #include "shadow.h"
  
  #ifndef	lint
! static	char	sccsid[] = "@(#)sgroupio.c	3.3	07:06:36	6/6/91";
  #endif
  
  static	int	islocked;
--- 38,44 ----
  #include "shadow.h"
  
  #ifndef	lint
! static	char	sccsid[] = "@(#)sgroupio.c	3.4	09:11:25	6/26/91";
  #endif
  
  static	int	islocked;
***************
*** 369,382 ****
  sgr_close ()
  {
  	char	backup[BUFSIZ];
- 	int	fd;
  	int	mask;
  	int	c;
- 	int	i;
  	int	errors = 0;
  	FILE	*bkfp;
  	struct	sg_file_entry *sgrf;
! 	struct	sg_file_entry *osgrf;
  
  	if (! isopen) {
  		errno = EINVAL;
--- 369,380 ----
  sgr_close ()
  {
  	char	backup[BUFSIZ];
  	int	mask;
  	int	c;
  	int	errors = 0;
  	FILE	*bkfp;
  	struct	sg_file_entry *sgrf;
! 	struct	stat	sb;
  
  	if (! isopen) {
  		errno = EINVAL;
***************
*** 398,403 ****
--- 396,403 ----
  			return 0;
  		}
  		umask (mask);
+ 		fstat (fileno (sgrfp), &sb);
+ 		chown (backup, sb.st_uid, sb.st_gid);
  
  		rewind (sgrfp);
  		while ((c = getc (sgrfp)) != EOF) {
***************
*** 460,465 ****
--- 460,466 ----
  		free (sgrf);
  	}
  	sgr_tail = 0;
+ 	isopen = 0;
  	return 1;
  }
  
Index: pwio.c
*** rel3/pwio.c	Tue Jun 25 09:37:56 1991
--- pwio.c	Wed Jun 26 09:43:52 1991
***************
*** 37,43 ****
  #endif
  
  #ifndef lint
! static	char	sccsid[] = "@(#)pwio.c	3.7	09:08:02	5/28/91";
  #endif
  
  static	int	islocked;
--- 37,43 ----
  #endif
  
  #ifndef lint
! static	char	sccsid[] = "@(#)pwio.c	3.8	09:04:48	6/26/91";
  #endif
  
  static	int	islocked;
***************
*** 361,366 ****
--- 361,367 ----
  	FILE	*bkfp;
  	struct	pw_file_entry *pwf;
  	struct	pw_file_entry *opwf;
+ 	struct	stat	sb;
  
  	if (! isopen) {
  		errno = EINVAL;
***************
*** 376,387 ****
  	strcat (backup, "-");
  
  	if (open_modes == O_RDWR && pw_changed) {
! 		mask = umask (022);
  		if ((bkfp = fopen (backup, "w")) == 0) {
  			umask (mask);
  			return 0;
  		}
  		umask (mask);
  
  		rewind (pwfp);
  		while ((c = getc (pwfp)) != EOF) {
--- 377,390 ----
  	strcat (backup, "-");
  
  	if (open_modes == O_RDWR && pw_changed) {
! 		mask = umask (0222);
  		if ((bkfp = fopen (backup, "w")) == 0) {
  			umask (mask);
  			return 0;
  		}
  		umask (mask);
+ 		fstat (fileno (pwfp), &sb);
+ 		chown (backup, sb.st_uid, sb.st_gid);
  
  		rewind (pwfp);
  		while ((c = getc (pwfp)) != EOF) {
***************
*** 396,402 ****
  		isopen = 0;
  		(void) fclose (pwfp);
  
! 		mask = umask (022);
  		if (! (pwfp = fopen (pw_filename, "w"))) {
  			umask (mask);
  			return 0;
--- 399,405 ----
  		isopen = 0;
  		(void) fclose (pwfp);
  
! 		mask = umask (0222);
  		if (! (pwfp = fopen (pw_filename, "w"))) {
  			umask (mask);
  			return 0;
***************
*** 443,448 ****
--- 446,452 ----
  		free (pwf);
  	}
  	pwf_tail = 0;
+ 	isopen = 0;
  	return 1;
  }
  
Index: chage.c
*** rel3/chage.c	Tue Jun 25 09:38:02 1991
--- chage.c	Wed Jun 26 09:43:59 1991
***************
*** 17,23 ****
  #include <time.h>
  
  #ifndef	lint
! static	char	sccsid[] = "@(#)chage.c	3.7	06:35:00	5/29/91";
  #endif
  
  /*
--- 17,23 ----
  #include <time.h>
  
  #ifndef	lint
! static	char	sccsid[] = "@(#)chage.c	3.8	09:01:54	6/26/91";
  #endif
  
  /*
***************
*** 406,418 ****
  char	**argv;
  {
  	int	flag;
! 	int	lflg;
! 	int	mflg;
! 	int	Mflg;
! 	int	dflg;
! 	int	Wflg;
! 	int	Iflg;
! 	int	Eflg;
  	int	ruid = getuid ();
  	struct	passwd	*pw;
  	struct	passwd	pwent;
--- 406,418 ----
  char	**argv;
  {
  	int	flag;
! 	int	lflg = 0;
! 	int	mflg = 0;
! 	int	Mflg = 0;
! 	int	dflg = 0;
! 	int	Wflg = 0;
! 	int	Iflg = 0;
! 	int	Eflg = 0;
  	int	ruid = getuid ();
  	struct	passwd	*pw;
  	struct	passwd	pwent;
Index: obscure.c
*** rel3/obscure.c	Tue Jun 25 09:37:55 1991
--- obscure.c	Wed Jun 26 09:44:01 1991
***************
*** 21,27 ****
  #include "config.h"
  
  #ifndef	lint
! static	char	sccsid[] = "@(#)obscure.c	3.2	09:07:51	5/28/91";
  #endif
  
  #ifdef	NO_STRSTR
--- 21,27 ----
  #include "config.h"
  
  #ifndef	lint
! static	char	sccsid[] = "@(#)obscure.c	3.3	09:05:34	6/26/91";
  #endif
  
  #ifdef	NO_STRSTR
***************
*** 95,101 ****
  	if (similiar (newmono, oldmono))	/* jumbled version */
  		return (0);
  
! 	if (simple (new, old))			/* keyspace size */
  		return (0);
  
  	strcpy (wrapped, oldmono);
--- 95,101 ----
  	if (similiar (newmono, oldmono))	/* jumbled version */
  		return (0);
  
! 	if (simple (old, new))			/* keyspace size */
  		return (0);
  
  	strcpy (wrapped, oldmono);
-- 
John F. Haugh II        | Distribution to  | UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 255-8251 | GEnie PROHIBITED :-) |  Domain: jfh@rpp386.cactus.org
"UNIX signals are not interrupts.  Worse, SIGCHLD/SIGCLD is not even a UNIX
 signal, it's an abomination."  -- Doug Gwyn