Shadow password file library

Hans H. Huebner pengo at tmpmbx.UUCP
Sat Nov 19 02:52:08 AEST 1988


Hello,

here is my shadow password file library.  It should be System V R3.2
compatible.  I haven't seen the original manual pages, thus there might be
some discrepancies.  Please let me know if you have compatibility
suggestions.

I have written and tested this on XENIX System V.  There is a raw XENIX
Makefile included.  There should be no problems in getting this to run on
BSD systems.  Correct me, if I'm wrong.

	Thanks,
		Hans

#! /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 the files:
#	README
#	Article
#	Makefile
#	Makefile.xenix
#	shadow.h
#	getsp.c
#	getspent.c
#	fgetspent.c
#	putspent.c
#	getspnam.c
#	pwconv.c
#	pwunconv.c
#	getspent.3
#	putspent.3
#	pwconv.8
#	shadow.4
# This archive created: Fri Nov 18 17:43:09 1988
export PATH; PATH=/bin:$PATH
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
cat << \SHAR_EOF > 'README'

	This is the shadow password file library as desribed by Dennis
	Mumaugh in comp.unix.wizards recently.  It should work similar to
	the AT&T version used in Sys V3.2.  If you detect any
	discrepancies, please tell me.

	Sorry, no manual pages yet.  I'll do them later (maybe ;-) ).

	Also included are the two program "pwconf" and "pwunconf" with the
	functionality described by Dennis.  You'll find his description in
	the file "Article".

	Have fun,
			Hans

--
Hans H. Huebner, netmbx     | PSIMail: PSI%026245300043100::PENGO
Woerther Str. 36            | DOMAIN:  pengo at garp.mit.edu
D-1000 Berlin 20, W.Germany | Bang:    ..!{pyramid,unido}!tmpmbx!pengo
Phone: (+49 30) 882 54 29   | BITNET:  huebner at db0tui6
SHAR_EOF
fi # end of overwriting check
if test -f 'Article'
then
	echo shar: will not over-write existing file "'Article'"
else
cat << \SHAR_EOF > 'Article'
>From tub!unido!mcvax!uunet!attcan!utgpu!watmath!clyde!att!cuuxb!dlm Mon Nov 14 00:16:59 MET 1988
Path: tmpmbx!tub!unido!mcvax!uunet!attcan!utgpu!watmath!clyde!att!cuuxb!dlm
>From: dlm at cuuxb.ATT.COM (Dennis L. Mumaugh)
Newsgroups: comp.unix.wizards
Subject: /etc/shadow
Summary: See release notes for SVR3.2
Keywords: shadow password
Message-ID: <2189 at cuuxb.ATT.COM>
Date: 11 Nov 88 21:33:37 GMT
References: <16722 at agate.BERKELEY.EDU> <2178 at cuuxb.ATT.COM> <16768 at agate.BERKELEY.EDU> <17828 at glacier.STANFORD.EDU> <2182 at cuuxb.ATT.COM> <8
Reply-To: dlm at cuuxb.UUCP (Dennis L. Mumaugh)
Organization: ATT Data Systems Group, Lisle, Ill.
Lines: 60
Posted: Fri Nov 11 22:33:37 1988

In article <8861 at smoke.BRL.MIL> gwyn at brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>It would be a great service to the community if specifications for
>this feature were posted or at least sent to developers who want
>to enable a similar feature on their (typically BSD-based) systems.
>For example, what is the shadow file called, what is its format,
>what sort of stuff is left in the password field in /etc/passwd,
>what facilities are there to validate a password against the
>shadow encrypted password file?

The documentation is scattered in the Release Notes for System V
Release 3.2.  Of course they don't have a page shadow(4) but:

The file is /etc/shadow and is owned by root and mode 400.
It contains one line per login.  Fields are separated by colons:
	username \- users login name
	password \- A 13 character encrypted password or a lock string to
		    indicater the login is not accessible
	lastchanged \- number of days since January 1, 1970 that the password
	               has been modified
	min \- the number of days required between password changes
	max \- the maximum number of days the password is valid.

Routines to work with /etc/shadow:
	#include <shadow.h>
	struct spwd *getspent();
	struct spwd *getspnam(char * name);
	void setspent();
	void endspent();
	struct spwd *fgetspent(FILE *fp);
	int putspent(struct spwd *p,FILE *fp);

Programs allied with this are 
	pwconv \- install and/or update /etc/shadow with information
		  from /etc/passwd
	pwunconv \- restore /etc/password from /etc/shadown 
 
Programs like login, su and passwd work with  either  /etc/passwd
ONLY  or  with  the  added  /etc/shadow.  If there is no entry in
/etc/shadow we accept the /etc/passwd as gospel [in case  someone
forgot to run /usr/lib/pwconv after adding a user.]

Also /usr/include/shadow.h:

struct spwd {
	char	*sp_namp; /* users login name */
	char	*sp_pwdp; /* encrypted password */
	long	sp_lstchg; /* number of days since January 1, 1970 
			      that the password has been modified */
	int	sp_max; /* the number of days required between password changes */
	int	sp_min; /* the maximum number of days the password is valid. */
}
#define  SHADOW "/etc/shadow"

ATT doesn't provide any of the functions or the  header  file  as
part  of  its  product.  It  is in the source but not the binary.
Thus developers who need the  routines  must  contact  their  ATT
person [not me!] to obtain the shadow password security library
-- 
=Dennis L. Mumaugh
 Lisle, IL       ...!{att,lll-crg}!cuuxb!dlm  OR cuuxb!dlm at arpa.att.com


SHAR_EOF
fi # end of overwriting check
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
# Makefile for the shadow password file library

SHELL=		/bin/sh

# uncomment next line for Berserkeley systems
#DEFINES=	-Dstrchr=index

# Compiler configuration
CFLAGS=		-I. -g $(DEFINES)
LINTFLAGS=	-I.
LDFLAGS=	-g -i
SHAR=		shar

# File definition
LIB=		libshadow.a
PROGRAMS=	pwconv pwunconv
LIBOBJ=		$(LIB)(fgetspent.o) $(LIB)(getsp.o) \
			$(LIB)(getspent.o) $(LIB)(getspnam.o) \
			$(LIB)(putspent.o)
SOURCES=	getsp.c getspent.c fgetspent.c putspent.c getspnam.c
PSOURCES=	pwconv.c pwunconv.c
HFILES=		shadow.h
MISCFILES=	README Article Makefile Makefile.xenix
MANUALS=	getspent.3 putspent.3 pwconv.8 shadow.4

all:		$(PROGRAMS) $(LIB)

pwunconv:	pwunconv.o $(LIB)
		cc -o pwunconv $(LDFLAGS) pwunconv.o $(LIB)

pwconv:		pwconv.o $(LIB)
		cc -o pwconv $(LDFLAGS) pwconv.o $(LIB)

$(LIB):
		ranlib $(LIB)

lint:
		lint $(LINTFLAGS) $(SOURCES)

tags:		$(SOURCES) $(HFILES)
		ctags $(SOURCES) $(HFILES)

clean:
		rm -f *.o $(LIB) $(PROGRAMS)

shadow.sh:	$(MISCFILES) $(HFILES) $(SOURCES) $(PSOURCES) $(MANUALS)
		$(SHAR) $(MISCFILES) $(HFILES) $(SOURCES) $(PSOURCES) $(MANUALS) > shadow.sh

$(LIB):			$(LIBOBJ)

$(LIBOBJ):		$(HFILES)
pwunconv.o pwconv.o:	$(HFILES)
SHAR_EOF
fi # end of overwriting check
if test -f 'Makefile.xenix'
then
	echo shar: will not over-write existing file "'Makefile.xenix'"
else
cat << \SHAR_EOF > 'Makefile.xenix'
# ex:set ts=8 sw=8:

CFLAGS=		-I. -g $(CMODEL)
LINTFLAGS=	-I.
LDFLAGS=	-g -i

RANLIB=		ranlib

LIB=		libshadow.a
LIBOBJ=		$(MODEL)$(LIB)(fgetspent.o) $(MODEL)$(LIB)(getsp.o) \
			$(MODEL)$(LIB)(getspent.o) $(MODEL)$(LIB)(getspnam.o) \
			$(MODEL)$(LIB)(putspent.o)
SOURCES=	getsp.c getspent.c fgetspent.c putspent.c getspnam.c
HFILES=		shadow.h
MISCFILES=	Makefile

all:		small pwconv pwunconv

pwunconv:	pwunconv.o Slibshadow.a
		cc -o pwunconv $(LDFLAGS) pwunconv.o Slibshadow.a

pwconv:		pwconv.o Slibshadow.a
		cc -o pwconv $(LDFLAGS) pwconv.o Slibshadow.a

small:
		make lib MODEL=S CMODEL=-Mes2

middle:
		make lib MODEL=M CMODEL=-Mem2

large:
		make lib MODEL=L CMODEL=-Mel2

lib:	$(MODEL)$(LIB)
	$(RANLIB) $(MODEL)$(LIB)

lint:
	lint $(LINTFLAGS) $(SOURCES)

install: large middle small
	cp ?$(LIB) /usr/lib
	chmod +r /usr/lib/?$(LIB)
	cp $(HFILES) /usr/include

tags:	$(SOURCES) $(HFILES)
	ctags $(SOURCES) $(HFILES)

clean:
	rm -f *.o ?$(LIB)

tar:	clean

$(MODEL)$(LIB):	$(LIBOBJ)

$(LIBOBJ):	$(HFILES)
pwconv.o:	$(HFILES)
SHAR_EOF
fi # end of overwriting check
if test -f 'shadow.h'
then
	echo shar: will not over-write existing file "'shadow.h'"
else
cat << \SHAR_EOF > 'shadow.h'

/* shadow.h	Shadow passwd stuff					*/

struct spwd {
		char	*sp_namp;	/* users login name */
		char	*sp_pwdp;	/* encrypted password */
		long	sp_lstchg;	/* number of days since January 1, 1970 
				      	  that the password has been modified */
		int	sp_max;		/* the number of days required between
							     password changes */
		int	sp_min;		/* the maximum number of days the
							   password is valid. */
};

#define  SHADOW "/etc/shadow"

extern	struct	spwd	*getspent();
extern	struct	spwd	*getspnam();
extern	void		setspent();
extern	void		endspent();
extern	struct	spwd	*fgetspent();
extern	int		putspent();
SHAR_EOF
fi # end of overwriting check
if test -f 'getsp.c'
then
	echo shar: will not over-write existing file "'getsp.c'"
else
cat << \SHAR_EOF > 'getsp.c'

/*
 *	getsp.c		Shadow passwd file -- common functions
 *
 *	Written by Hans Huebner, netmbx Berlin		(pengo at tmpmbx.UUCP)
 *
 *	This code may be freely distributed, provided this copyright notice
 *	remains intact.
 *
 */

#include <stdio.h>
#include <shadow.h>

FILE	*_spfile = NULL;

/*
 *	setspent()	searches start position of shadow passwd file
 *
 */

void
setspent()

{	extern	FILE	*fopen();

	if (!_spfile) {
		_spfile = fopen(SHADOW, "r");
	} else {
		(void) fseek(_spfile, 0l, 0);
	}
}

/*
 *	endspent()	close shadow passwd file
 *
 */

void
endspent()

{
	if (_spfile) {
		(void) fclose(_spfile);
	}
}
SHAR_EOF
fi # end of overwriting check
if test -f 'getspent.c'
then
	echo shar: will not over-write existing file "'getspent.c'"
else
cat << \SHAR_EOF > 'getspent.c'

/*
 *	getspent.c	Shadow passwd file -- get next entry
 *
 *	Written by Hans Huebner, netmbx Berlin		(pengo at tmpmbx.UUCP)
 *
 *	This code may be freely distributed, provided this copyright notice
 *	remains intact.
 *
 */


#include <stdio.h>
#include <shadow.h>

/*
 *	getspent()	get next entry of the shadow passwd file
 *
 *			returns a pointer to the spwd entry read, or NULL
 *			upon end of file or error.
 *
 */

struct spwd *
getspent()

{	extern	FILE	*_spfile;

	if (!_spfile)
		setspent();

	if (_spfile)
		return(fgetspent(_spfile));
	else
		return(NULL);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'fgetspent.c'
then
	echo shar: will not over-write existing file "'fgetspent.c'"
else
cat << \SHAR_EOF > 'fgetspent.c'

/*
 *	fgetspent.c	Shadow passwd file -- get spwd entry from a given
 *			file
 *
 *	Written by Hans Huebner, netmbx Berlin		(pengo at tmpmbx.UUCP)
 *
 *	This code may be freely distributed, provided this copyright notice
 *	remains intact.
 *
 */

#include <stdio.h>
#include <shadow.h>

/*
 *	fgetspent()	get next spwd entry from a given file, returns
 *			pointer to spwd upon success, NULL on error or
 *			end of file.
 *
 */

#define	SBUF	255			/* max. line length		*/

struct spwd *
fgetspent(fp)

		FILE		*fp;
{	static	char		_buf[SBUF];
	static	struct	spwd	_retval;
	extern	char		*strchr();
		char		*colon;

	if (!fgets(_buf, sizeof(_buf), fp))
		return(NULL);
	
	_retval.sp_namp = _buf;
	if (!(colon = strchr(_buf, ':')))
		return(NULL);		/* incorrect file format	*/
	else
		*colon++ = '\0';

	_retval.sp_pwdp = colon;
	if (!(colon = strchr(colon, ':')))
		return(NULL);		/* incorrect file format	*/
	else
		*colon++ = '\0';

	if (sscanf(colon, "%ld:%d:%d", &_retval.sp_lstchg,
				&_retval.sp_max, &_retval.sp_min) != 3)
		return(NULL);		/* incorrect file format	*/
	else
		return(&_retval);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'putspent.c'
then
	echo shar: will not over-write existing file "'putspent.c'"
else
cat << \SHAR_EOF > 'putspent.c'

/*
 *	putspent.c	Shadow passwd file -- put an entry to the shadow
 *			passwd file.
 *
 *	Written by Hans Huebner, netmbx Berlin		(pengo at tmpmbx.UUCP)
 *
 *	This code may be freely distributed, provided this copyright notice
 *	remains intact.
 *
 */

#include <stdio.h>
#include <shadow.h>

/*
 *	putspent()	put an entry to the shadow passwd file
 *
 *			returns -1 on error, 0 on success
 *
 */

int
putspent(sp, fp)

	struct	spwd	*sp;
	FILE		*fp;
{
	if (!fp)
		return(-1);	/* you never know */

	return(fprintf(fp, "%s:%s:%ld:%d:%d\n", sp->sp_namp, sp->sp_pwdp,
			sp->sp_lstchg, sp->sp_max, sp->sp_min) > 0 ? 0 : -1);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'getspnam.c'
then
	echo shar: will not over-write existing file "'getspnam.c'"
else
cat << \SHAR_EOF > 'getspnam.c'

/*
 *	getspnam.c	Shadow passwd file -- get spwd entry by name
 *
 *	Written by Hans Huebner, netmbx Berlin		(pengo at tmpmbx.UUCP)
 *
 *	This code may be freely distributed, provided this copyright notice
 *	remains intact.
 *
 */

#include <stdio.h>
#include <shadow.h>

/*
 *	getspnam()	get the spwd entry for the user given as argument
 *
 *			returns a pointer to the spwd entry, or NULL if
 *			the user wasn't found or an error was encountered.
 *
 */

struct spwd *
getspnam(name)

	char		*name;
{	struct	spwd	*sp;

	setspent();

	while (sp = getspent())
		if (!strcmp(sp->sp_namp, name))
			return(sp);
	
	return(NULL);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'pwconv.c'
then
	echo shar: will not over-write existing file "'pwconv.c'"
else
cat << \SHAR_EOF > 'pwconv.c'

/*
 *	pconv.c		Shadow passwd file -- convert /etc/passwd to /etc/shadow
 *
 *	Written by Hans Huebner, netmbx Berlin		(pengo at tmpmbx.UUCP)
 *
 *	This code may be freely distributed, provided this copyright notice
 *	remains intact.
 *
 */

#include <stdio.h>
#include <shadow.h>
#include <pwd.h>


extern	struct	passwd	*getpwent();
extern	FILE		*fopen();
extern	char		*strchr();
extern	struct	spwd	*getspnam();

char	*agecode =
	"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

#define	weeks(code)	((int) (strchr(agecode, code) - agecode))

main()

{	FILE		*out;
	struct	passwd	*pw;
	struct	spwd	spwbuf;
	struct	spwd	*spw;

	umask(0277);

	if (!(out = fopen(SHADOW, "a"))) {
		perror(SHADOW);
		exit(1);
	}

	setpwent();

	while (pw = getpwent()) {
		if (!(spw = getspnam(pw->pw_name))) {
			char	*age = pw->pw_age ? pw->pw_age : "";
			spwbuf.sp_namp = pw->pw_name;
			spwbuf.sp_pwdp = pw->pw_passwd;
			spwbuf.sp_max = spwbuf.sp_min = 0;
			spwbuf.sp_lstchg = 0l;
			if (*age)
				spwbuf.sp_max = weeks(*age++);
			if (*age)
				spwbuf.sp_min = weeks(*age++);
			if (*age)
				spwbuf.sp_lstchg = (long) weeks(age[0])
						+ 64l * (long) weeks(age[1]);
			if (putspent(&spwbuf, out) == -1) {
				perror("write error");
				exit(1);
			}
		}
	}

	endpwent();
	fclose(out);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'pwunconv.c'
then
	echo shar: will not over-write existing file "'pwunconv.c'"
else
cat << \SHAR_EOF > 'pwunconv.c'

/*
 *	pwunconv.c	Shadow passwd file -- convert /etc/shadow to /etc/passwd
 *
 *	Written by Hans Huebner, netmbx Berlin		(pengo at tmpmbx.UUCP)
 *
 *	This code may be freely distributed, provided this copyright notice
 *	remains intact.
 *
 *	BUGS:	no file locking is supported.
 *
 */

#include <stdio.h>
#include <shadow.h>
#include <pwd.h>

#define TEMPFILE	"/etc/passwd.new"
#define OLDFILE		"/etc/passwd.old"
#define PASSWD		"/etc/passwd"

char	*agecode =
	"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

extern	struct	passwd	*getpwent();
extern	struct	spwd	*getspnam();

main()

{	FILE		*out;
	struct	passwd	*pw;
	struct	spwd	*spw;
	char		age[5];

	if (!(out = fopen(TEMPFILE, "w"))) {
		perror(TEMPFILE);
		exit(1);
	}

	setpwent();

	while (pw = getpwent()) {
		if (spw = getspnam(pw->pw_name)) {
			pw->pw_passwd = spw->sp_pwdp;
			if (spw->sp_max) {
				pw->pw_age = age;
				age[0] = agecode[spw->sp_max];
				age[1] = agecode[spw->sp_min];
				if (spw->sp_lstchg) {
					age[2] = agecode[spw->sp_lstchg % 64];
					age[3] = agecode[spw->sp_lstchg / 64];
					age[4] = '\0';
				} else
					age[2] = '\0';
			}
		}
		if (putpwent(pw, out)) {
			perror("write error");
			exit(1);
		}
	}

	endpwent();
	fclose(out);

	(void) unlink(OLDFILE);
	if (link(PASSWD, OLDFILE) == -1) {
		fprintf(stderr, "cannot link %s to %s", PASSWD, OLDFILE);
		perror("");
		exit(1);
	}
	if (unlink(PASSWD) == -1) {
		fprintf(stderr, "cannot unlink %s", PASSWD);
		perror("");
		exit(1);
	}
	if (link(TEMPFILE, PASSWD) == -1) {
		fprintf(stderr, "cannot link %s to %s", TEMPFILE, PASSWD);
		perror("");
		(void) link(OLDFILE, PASSWD);
		exit(1);
	}
	(void) unlink(TEMPFILE);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'getspent.3'
then
	echo shar: will not over-write existing file "'getspent.3'"
else
cat << \SHAR_EOF > 'getspent.3'
.TH GETSPENT 3 LOCAL
.SH NAME
getspent, getspnam, setspent, endspent \- Gets shadow password file entry
.SH SYNOPSIS
.B "#include <shadow.h>"
.P
.B "struct spwd *getspent()"
.P
.B "struct spwd *getspnam()"
.P
.B "int setspent()"
.P
.B "int endspent()"
.SH DESCRIPTION
.I getspent, fgetspent
and
.I getspnam
each returns a pointer to a structure containing a shadow password entry.
The structure of these entries is described in /usr/include/shadow.h.
.P
The meaning of the fields are described in shadow(4).
.P
.I getspent
and
.I fgetspent
read the next entry in the file, so successive calls
may be
used to search through the entire file.
.I fgetspent
allows to specify a file opened by the calling routine.
.I getspent
searches from the beginning of the file until a matching user
name is found or EOF is encountered.
.P
.I setspent
rewinds the shadow password file.
.I endspent
may be called to close the file.
.SH FILES
/etc/shadow
.SH "SEE ALSO"
putspent(3), shadow(4)
.SH DIAGNOSTICS
.I getspent, fgetspent
and
.I getspnam
return a pointer to the record read, or NULL if an error or EOF has been
encountered.
.SH NOTES
The pointers returned point to static data so it must be copied
by the calling program if it is to be saved.
SHAR_EOF
fi # end of overwriting check
if test -f 'putspent.3'
then
	echo shar: will not over-write existing file "'putspent.3'"
else
cat << \SHAR_EOF > 'putspent.3'
.TH PUTSPENT 3 LOCAL
.SH NAME
putspent \- Writes shadow password file entry
.SH SYNOPSIS
.B "#include <shadow.h>"
.P
.B "int putspent(*spwd, *fp)"
.br
.B "struct spwd *spwd;"
.br
.B "FILE *fp"
.SH DESCRIPTION
.I putspent
is the inverse of getspent(3).
It puts the shadow password structure pointed to by spwd to the
stream fp.
The line matches the format of /etc/shadow. 
.SH FILES
/etc/shadow
.SH "SEE ALSO"
getspent(3), shadow(4)
.SH DIAGNOSTICS
.I putspent
returns 0 on successful completion, nonzero upon error.
SHAR_EOF
fi # end of overwriting check
if test -f 'pwconv.8'
then
	echo shar: will not over-write existing file "'pwconv.8'"
else
cat << \SHAR_EOF > 'pwconv.8'
.TH PWCONV 8 LOCAL
.SH NAME
pwconv, pwunconv \- convert password entries between /etc/passwd and
/etc/shadow
.SH SYNOPSIS
.B "/usr/lib/pwconv"
.P
.B "/usr/lib/pwunconv"
.SH DESCRIPTION
.I pwconv
converts password entries from /etc/passwd to /etc/shadow.
For all login names which are found in /etc/passwd but have no entry in
/etc/shadow, a new entry is created.
This is used to upgrade systems to a higher security level or to create
an entry in /etc/shadow for a newsly created account.
.P
.I pwunconv
converts entries in /etc/shadow back into /etc/passwd.
It's not normally useful.
.SH FILES
/etc/shadow
.br
/etc/passwd
.SH "SEE ALSO"
shadow(4)
.SH DIAGNOSTICS
.I pwconv
and
.I pwunconv
exit, if they have no permissions to access /etc/passwd and /etc/shadow.
SHAR_EOF
fi # end of overwriting check
if test -f 'shadow.4'
then
	echo shar: will not over-write existing file "'shadow.4'"
else
cat << \SHAR_EOF > 'shadow.4'
.TH SHADOW 4 LOCAL
.SH NAME
shadow \- The shadow password file.
.SH DESCRIPTION
.I shadow
contains password information for users of the system.
This file is not world-readable, and as such it improves the systems'
security a bit.
.P
Each line in the shadow file contain the following information:
.P
\-Login name - The users' login name.
.P
\-Password - The 13 character encrypted password.
.P
\-Last change - Number of days since January 1. 1970 that the password
has been modified.
.P
\-Minimum change period \- The number of days required between password
changes.
.P
\-Maximum change period \- The maximum number of days th password is
valid.
.SH FILES
/etc/shadow
.SH "SEE ALSO"
getspent(3), putspent(3), pwconv(8)
SHAR_EOF
fi # end of overwriting check
#	End of shell archive
exit 0



More information about the Alt.sources mailing list