home *** CD-ROM | disk | FTP | other *** search
- Xref: sparky alt.hackers:1295 alt.sources:1874
- Newsgroups: alt.hackers,alt.sources
- Path: sparky!uunet!decwrl!csus.edu!netcom.com!jef
- From: jef@netcom.com (Jef Poskanzer)
- Subject: libsmpw - self-maintaining passwd indexer
- Message-ID: <_g8mf6n.jef@netcom.com>
- Date: Sun, 16 Aug 92 07:52:11 GMT
- Organization: Paratheo-Anametamystikhood Of Eris Esoteric
- Followup-To: alt.sources.d
- Reply-To: Jef Poskanzer <jef@netcom.com>
- Approved: :pa^ojddV
- Lines: 920
-
- This is kind of weird/cool. It's a library for indexed access to
- /etc/passwd, but the unusual thing is that it's self-maintaining.
- Why bother with something like this, when dbm/dbz works just fine?
- Well, back in January the sysadmins at the WELL turned off yp,
- which is good, but they didn't replace it with any other sort
- of indexed access to /etc/passwd, which, considering that the WELL
- has about 7000 users, is not so good.
-
- After eight months of waiting for them to do something about it
- (they've tried one CPU upgrade and have scheduled another, but
- gosh, things are still slow), I had a brainflash that I could
- do it myself. Make the index files world-writable, and have
- the library incrementally update with new entries whenever it
- has to fall back on linear search. Add lots of checking in case
- someone trashes the files. Then relink ls, finger, and whatever
- else does getpwuid()/getpwnam(). I'll leave relinking login
- for the sysadmins.
- ---
- Jef
-
- Jef Poskanzer jef@netcom.com jef@well.sf.ca.us
- "Republicans understand the importance of bondage between a mother and
- child." -- J. Danforth Quayle
-
- #! /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
- # libsmpw.3
- # smpw.c
- # Makefile
- # This archive created: Sun Aug 16 00:38:01 1992
- # By: Jef Poskanzer (Paratheo-Anametamystikhood Of Eris Esoteric)
- export PATH; PATH=/bin:$PATH
- echo shar: extracting "'README'" '(1034 characters)'
- if test -f 'README'
- then
- echo shar: will not over-write existing file "'README'"
- else
- sed 's/^X//' << \SHAR_EOF > 'README'
- X libsmpw - self-maintaining indexed access to /etc/passwd
- X Version 1.0 of 16aug92
- X Previous release NONE
- X
- Xlibsmpw is a drop-in replacement for getpwuid()/getpwnam(). Like many
- Xversions of these routines it uses external index files for faster
- Xaccess. Unlike other versions, the index files are "self-maintained".
- XThis means they are world-writable, and every time any user runs a
- Xprogram that accesses these routines, the indexes get updated as
- Xnecessary.
- X
- XThis is mainly to avoid the need for root privs to get fast /etc/passwd
- Xaccess - although even sysadmins may wish to install these routines to
- Xavoid maintenance headaches and delays in password changing.
- X
- X
- XFiles in this distribution:
- X README this
- X Makefile guess
- X smpw.c source code
- X libsmpw.3 man page
- X
- XTo install:
- X Unpack the files.
- X Edit the Makefile to change the configuration options if necessary.
- X Make.
- X Make install.
- X
- XComments to:
- X Jef Poskanzer jef@netcom.com jef@well.sf.ca.us
- SHAR_EOF
- if test 1034 -ne "`wc -c < 'README'`"
- then
- echo shar: error transmitting "'README'" '(should have been 1034 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'libsmpw.3'" '(1179 characters)'
- if test -f 'libsmpw.3'
- then
- echo shar: will not over-write existing file "'libsmpw.3'"
- else
- sed 's/^X//' << \SHAR_EOF > 'libsmpw.3'
- X.TH libsmpw 3 "13 August 1992"
- X.SH NAME
- Xlibsmpw - self-maintaining indexed access to /etc/passwd
- X.SH SYNOPSIS
- X-L/usr/public/lib -lsmpw
- X.SH DESCRIPTION
- X.B libsmpw
- Xis a drop-in replacement for getpwuid()/getpwnam().
- XLike many versions of these routines it uses external index files
- Xfor faster access.
- XUnlike other versions, the index files are "self-maintained".
- XThis means they are world-writable, and every time any user runs
- Xa program that accesses these routines, the indexes get updated
- Xas necessary.
- X.PP
- XThis is mainly to avoid the need for root privs to get fast /etc/passwd
- Xaccess - although even sysadmins may wish to install these
- Xroutines to avoid maintenance headaches and delays in password changing.
- X.SH "SEE ALSO"
- Xgetpwent(3)
- X.SH AUTHOR
- XCopyright (C) 1992 by Jef Poskanzer.
- X.\" Permission to use, copy, modify, and distribute this software and its
- X.\" documentation for any purpose and without fee is hereby granted, provided
- X.\" that the above copyright notice appear in all copies and that both that
- X.\" copyright notice and this permission notice appear in supporting
- X.\" documentation. This software is provided "as is" without express or
- X.\" implied warranty.
- SHAR_EOF
- if test 1179 -ne "`wc -c < 'libsmpw.3'`"
- then
- echo shar: error transmitting "'libsmpw.3'" '(should have been 1179 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'smpw.c'" '(15518 characters)'
- if test -f 'smpw.c'
- then
- echo shar: will not over-write existing file "'smpw.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'smpw.c'
- X/* smpw.c - self-maintaining indexed access to /etc/passwd
- X**
- X** Copyright (C) 1992 by Jef Poskanzer.
- X**
- X** Permission to use, copy, modify, and distribute this software and its
- X** documentation for any purpose and without fee is hereby granted, provided
- X** that the above copyright notice appear in all copies and that both that
- X** copyright notice and this permission notice appear in supporting
- X** documentation. This software is provided "as is" without express or
- X** implied warranty.
- X**
- X**
- X** Parts of this file are:
- X** Copyright 1989, 1990, 1991 John F. Haugh II
- X** All rights reserved.
- X**
- X** Permission is granted to copy and create derivative works for any
- X** non-commercial purpose, provided this copyright notice is preserved
- X** in all copies of source code, or included in human readable form
- X** and conspicuously displayed on all copies of object code or
- X** distribution media.
- X*/
- X
- X#include <stdio.h>
- X#include <pwd.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <sys/file.h>
- X
- X#ifdef SYSV
- X#include <string.h>
- X#define index strchr
- X#else /*SYSV*/
- X#include <strings.h>
- X#endif /*SYSV*/
- X
- Xextern off_t lseek();
- X
- X#ifndef PWDFILE
- X#define PWDFILE "/etc/passwd"
- X#endif
- X#ifndef PWDUFILE
- X#define PWDUFILE "/etc/passwd.u"
- X#endif
- X#ifndef PWDNFILE
- X#define PWDNFILE "/etc/passwd.n"
- X#endif
- X#ifndef PWDSFILE
- X#define PWDSFILE "/etc/passwd.s"
- X#endif
- X
- X#define NAMEHASHMULT 50021
- X
- X#define NO_OFF 2147483647
- X#define NO_UID 65535
- X
- X#define NEARBY_ENTRIES 30
- X#define BYTES_PER_ENTRY 74 /* approximately */
- X
- X#define NFIELDS 7
- X
- Xstatic uid_t maxuid;
- Xstatic off_t namehashsize;
- X
- Xstatic FILE* pwdfp = (FILE*) 0;
- Xstatic int pwufd = -1;
- Xstatic int pwnfd = -1;
- X
- Xstatic char pwdbuf[BUFSIZ];
- Xstatic char* pwdfields[NFIELDS];
- Xstatic struct passwd pwent;
- X
- X/* smpw_init - initialize the library */
- Xstatic void
- Xsmpw_init()
- X {
- X static int firstTime = 1;
- X FILE* fp;
- X int i1, i2;
- X
- X if ( firstTime )
- X {
- X firstTime = 0;
- X
- X /* Read maxuid and namehashsize from the file. The reason we do
- X ** this instead of just compiling them in is so that if you ever
- X ** need to change them, you don't have to recompile every program
- X ** in the world.
- X */
- X maxuid = 0;
- X fp = fopen( PWDSFILE, "r" );
- X if ( fp != (FILE*) 0 )
- X {
- X if ( fscanf( fp, "%d %d", &i1, &i2 ) == 2 )
- X {
- X maxuid = i1;
- X namehashsize = i2;
- X }
- X (void) fclose( fp );
- X }
- X }
- X }
- X
- X/* sgetpwent - convert a string to a (struct passwd)
- X**
- X** sgetpwent() parses pwdbuf into the parts required for a password
- X** structure. Strict checking is made for the uid and gid fields and
- X** presence of the correct number of colons. Any failing tests result
- X** in a NULL pointer being returned.
- X**/
- Xstatic struct passwd*
- Xsgetpwent()
- X {
- X int i;
- X char* cp;
- X
- X /* Save a pointer to the start of each colon separated
- X ** field. The fields are converted into NUL terminated strings.
- X */
- X for ( cp = pwdbuf, i = 0; i < NFIELDS && cp; ++i )
- X {
- X pwdfields[i] = cp;
- X cp = index( cp, ':' );
- X if ( cp )
- X *cp++ = 0;
- X }
- X
- X /* There must be exactly NFIELDS colon separated fields or
- X ** the entry is invalid. Also, the uid and gid must be non-blank.
- X */
- X if ( i != NFIELDS || *pwdfields[2] == '\0' || *pwdfields[3] == '\0' )
- X return (struct passwd*) 0;
- X
- X /* Each of the fields is converted the appropriate data type
- X ** and the result assigned to the password structure. If the
- X ** uid or gid does not convert to an integer value, a NULL
- X ** pointer is returned.
- X */
- X pwent.pw_name = pwdfields[0];
- X pwent.pw_passwd = pwdfields[1];
- X if ( sscanf( pwdfields[2], "%d", &i ) != 1 )
- X return (struct passwd*) 0;
- X pwent.pw_uid = i;
- X if ( sscanf( pwdfields[3], "%d", &i ) != 1 )
- X return (struct passwd*) 0;
- X pwent.pw_gid = i;
- X pwent.pw_gecos = pwdfields[4];
- X pwent.pw_dir = pwdfields[5];
- X pwent.pw_shell = pwdfields[6];
- X
- X return &pwent;
- X }
- X
- X/* fgetpwent - get a password file entry from a stream
- X**
- X** fgetpwent() reads the next line from a password file formatted stream
- X** and returns a pointer to the password structure for that line.
- X*/
- Xstruct passwd*
- Xfgetpwent( fp )
- X FILE* fp;
- X {
- X smpw_init();
- X
- X if ( fgets( pwdbuf, BUFSIZ, fp ) == (char*) 0 )
- X return (struct passwd*) 0;
- X pwdbuf[strlen( pwdbuf ) - 1] = '\0';
- X return sgetpwent();
- X }
- X
- X/* getpwent - get a password entry from the password file
- X**
- X** getpwent() opens the password file, if not already opened, and reads
- X** a single entry. NULL is returned if any errors are encountered reading
- X** the password file.
- X*/
- Xstruct passwd*
- Xgetpwent()
- X {
- X smpw_init();
- X
- X if ( pwdfp == (FILE*) 0 && setpwent() < 0 )
- X return (struct passwd*) 0;
- X return fgetpwent( pwdfp );
- X }
- X
- X/* igetpwuid - locate a password entry for a given uid using the index */
- Xstatic struct passwd*
- Xigetpwuid( uid, offP )
- X uid_t uid;
- X off_t *offP;
- X {
- X struct passwd* pwd;
- X
- X *offP = NO_OFF;
- X
- X /* Check that the uid index file was opened successfully. */
- X if ( pwufd == -1 )
- X return (struct passwd*) 0;
- X
- X /* Use the uid to index into the uid index file. */
- X if ( lseek( pwufd, (off_t) uid * sizeof(off_t), L_SET ) < 0 )
- X return (struct passwd*) 0;
- X
- X /* Read out a seek address. */
- X if ( read( pwufd, (char*) offP, sizeof(off_t) ) != sizeof(off_t) )
- X return (struct passwd*) 0;
- X
- X /* Seek to the address, making sure it's the beginning of a line. */
- X if ( *offP == 0 )
- X rewind( pwdfp );
- X else
- X {
- X if ( fseek( pwdfp, *offP - 1, 0 ) < 0 )
- X return (struct passwd*) 0;
- X if ( getc( pwdfp ) != '\n' )
- X return (struct passwd*) 0;
- X }
- X
- X /* Read the entry. */
- X pwd = fgetpwent( pwdfp );
- X if ( pwd == (struct passwd*) 0 )
- X return (struct passwd*) 0;
- X
- X /* Check that it's the right one. */
- X if ( pwd->pw_uid != uid )
- X return (struct passwd*) 0;
- X
- X /* Ok! */
- X return pwd;
- X }
- X
- X/* isetpwuid - set the index entry for a given uid
- X**
- X** isetpwuid() takes a uid and a seek address and writes the address
- X** to the uid index file.
- X*/
- Xstatic void
- Xisetpwuid( uid, off )
- X uid_t uid;
- X off_t off;
- X {
- X /* Check that the uid index file was opened successfully. */
- X if ( pwufd == -1 )
- X return;
- X
- X /* Use the uid to index into the uid index file. */
- X if ( lseek( pwufd, (off_t) uid * sizeof(off_t), L_SET ) < 0 )
- X return;
- X
- X /* Write the seek address. */
- X (void) write( pwufd, (char*) &off, sizeof(off_t) );
- X }
- X
- X/* getpwuid - locate a password entry for a given uid
- X**
- X** getpwuid() locates a password file entry for the given uid,
- X** by use of the index if possible, then by nearby search, and
- X** lastly by linear search.
- X*/
- Xstruct passwd*
- Xgetpwuid( uid )
- X uid_t uid;
- X {
- X struct passwd* pwd;
- X off_t off;
- X char buf[5000];
- X int i;
- X
- X smpw_init();
- X
- X /* Open if necessary. */
- X if ( setpwent() < 0 )
- X return (struct passwd*) 0;
- X
- X /* First try indexed access. */
- X pwd = igetpwuid( uid, &off );
- X if ( pwd != (struct passwd*) 0 )
- X return pwd;
- X
- X if ( off != NO_OFF )
- X {
- X /* Fall back on nearby search. Seek backwards a few entries. */
- X if ( off < NEARBY_ENTRIES * BYTES_PER_ENTRY / 2 )
- X off = 0;
- X else
- X off -= NEARBY_ENTRIES * BYTES_PER_ENTRY / 2;
- X if ( fseek( pwdfp, off, 0 ) >= 0 )
- X {
- X if ( off != 0 )
- X /* Start at next newline. */
- X (void) fgets( buf, sizeof(buf), pwdfp);
- X for ( i = 0; i < NEARBY_ENTRIES; ++i )
- X {
- X off = ftell( pwdfp );
- X pwd = fgetpwent( pwdfp );
- X if ( pwd == (struct passwd*) 0 )
- X break;
- X if ( pwd->pw_uid == uid )
- X {
- X isetpwuid( uid, off );
- X return pwd;
- X }
- X }
- X }
- X }
- X
- X /* Fall back on linear search. */
- X rewind( pwdfp );
- X for (;;)
- X {
- X off = ftell( pwdfp );
- X pwd = fgetpwent( pwdfp );
- X if ( pwd == (struct passwd*) 0 )
- X break;
- X if ( pwd->pw_uid == uid )
- X {
- X /* Got it. Save the seek address for next time. */
- X isetpwuid( uid, off );
- X return pwd;
- X }
- X }
- X
- X /* Couldn't find it anywhere. */
- X isetpwuid( uid, NO_OFF );
- X return (struct passwd*) 0;
- X }
- X
- X/* namehash - hash a name */
- Xstatic unsigned long
- Xnamehash( name )
- X char* name;
- X {
- X char* cp;
- X unsigned long hash;
- X
- X for ( cp = name, hash = 0; *cp != '\0'; ++cp )
- X hash = ( hash * NAMEHASHMULT + *cp ) % namehashsize;
- X
- X return hash;
- X }
- X
- X/* isetuident - set the index entry for a given name hash
- X**
- X** isetuident() takes a hash entry and a uid and writes the uid
- X** to the name index file.
- X*/
- Xstatic void
- Xisetuident( ent, uid )
- X unsigned long ent;
- X uid_t uid;
- X {
- X /* Check that the name index file was opened successfully. */
- X if ( pwnfd == -1 )
- X return;
- X
- X /* Use the hash entry to index into the name index file. */
- X if ( lseek( pwnfd, (off_t) ent * sizeof(uid_t), L_SET ) < 0 )
- X return;
- X
- X /* Write the uid. */
- X (void) write( pwnfd, (char*) &uid, sizeof(uid_t) );
- X }
- X
- X/* igetpwnam - locate a passwd entry for a given name by use of the index */
- Xstatic struct passwd*
- Xigetpwnam( name )
- X char* name;
- X {
- X uid_t uid;
- X unsigned long hash, h;
- X int first;
- X struct passwd* pwd;
- X
- X /* Check that the name index file was opened successfully. */
- X if ( pwnfd == -1 )
- X return (struct passwd*) 0;
- X
- X /* Hash the name. */
- X hash = namehash( name );
- X
- X for ( h = hash, first = 1;
- X h != hash || first;
- X h = ( h + 1 ) % namehashsize, first = 0 )
- X {
- X /* Use the hash to index into the name index file. */
- X if ( lseek( pwnfd, (off_t) h * sizeof(uid_t), L_SET ) < 0 )
- X return (struct passwd*) 0;
- X
- X /* Read out a uid. */
- X if ( read( pwnfd, (char*) &uid, sizeof(uid_t) ) != sizeof(uid_t) )
- X return (struct passwd*) 0;
- X
- X /* Has the hash chain run out? */
- X if ( uid == NO_UID )
- X return (struct passwd*) 0;
- X
- X /* Fetch the passwd entry for this uid. */
- X pwd = getpwuid( uid );
- X if ( pwd == (struct passwd*) 0 )
- X {
- X /* No uid? This must be an obsolete entry. Zero it and
- X ** continue searching.
- X */
- X isetuident( h, NO_UID );
- X continue;
- X }
- X
- X /* Check that it's the right one. */
- X if ( strcmp( pwd->pw_name, name ) == 0 )
- X return pwd;
- X }
- X
- X /* The whole name index was searched without a hit! It must be
- X ** trashed. Zero it.
- X */
- X (void) ftruncate( pwnfd, 0 );
- X (void) endpwent();
- X (void) setpwent();
- X return (struct passwd*) 0;
- X }
- X
- X/* isetuidnam - store a uid for a given name into the index */
- Xstatic void
- Xisetuidnam( name, uid )
- X char* name;
- X uid_t uid;
- X {
- X unsigned long hash, h;
- X int first;
- X uid_t juid;
- X
- X
- X /* Check that the name index file was opened successfully. */
- X if ( pwnfd == -1 )
- X return;
- X
- X /* Hash the name. */
- X hash = namehash( name );
- X
- X for ( h = hash, first = 1;
- X h != hash || first;
- X h = ( h + 1 ) % namehashsize, first = 0 )
- X {
- X /* Use the hash to index into the name index file. */
- X if ( lseek( pwnfd, (off_t) h * sizeof(uid_t), L_SET ) < 0 )
- X return;
- X
- X /* Read out a uid. */
- X if ( read( pwnfd, (char*) &juid, sizeof(uid_t) ) != sizeof(uid_t) )
- X return;
- X
- X /* Is it free? */
- X if ( juid == NO_UID )
- X {
- X /* Fill it in. Doesn't matter if someone else just filled
- X ** in this hole, whoever loses the race this time will just
- X ** try again next time. */
- X isetuident( h, uid );
- X return;
- X }
- X }
- X
- X /* The whole name index was searched without a hole! It must be
- X ** trashed. Zero it.
- X */
- X (void) ftruncate( pwnfd, 0 );
- X (void) endpwent();
- X (void) setpwent();
- X }
- X
- X/* getpwnam - locate a password entry for a given name
- X**
- X** getpwnam() locates a password file entry for the given name,
- X** by use of the index if possible and by linear search otherwise.
- X*/
- Xstruct passwd*
- Xgetpwnam( name )
- X char* name;
- X {
- X struct passwd* pwd;
- X off_t off;
- X
- X smpw_init();
- X
- X /* Open if necessary. */
- X if ( setpwent() < 0 )
- X return (struct passwd*) 0;
- X
- X /* First try indexed access. */
- X pwd = igetpwnam( name );
- X if ( pwd != (struct passwd*) 0 )
- X return pwd;
- X
- X /* Fall back on linear search. */
- X rewind( pwdfp );
- X for (;;)
- X {
- X off = ftell( pwdfp );
- X pwd = fgetpwent( pwdfp );
- X if ( pwd == (struct passwd*) 0 )
- X break;
- X if ( strcmp( pwd->pw_name, name ) == 0 )
- X {
- X /* Got it. Save the seek address and uid for next time. */
- X isetpwuid( pwd->pw_uid, off );
- X isetuidnam( name, pwd->pw_uid );
- X return pwd;
- X }
- X }
- X
- X /* Couldn't find it anywhere. */
- X return (struct passwd*) 0;
- X }
- X
- X/* checkpwu - check and adjust the uid index file
- X**
- X** Checks that the uid index file is the right size. If it's too
- X** big, truncates it, if it's too small, adds NO_OFF entries.
- X*/
- Xstatic void
- Xcheckpwu()
- X {
- X struct stat sb;
- X off_t goodsize;
- X off_t no_off_buf[1000];
- X int i;
- X
- X if ( fstat( pwufd, &sb ) < 0 )
- X { pwufd = -1; return; }
- X goodsize = ( maxuid + 1 ) * sizeof(off_t);
- X if ( sb.st_size > goodsize )
- X {
- X if ( ftruncate( pwufd, goodsize ) < 0 )
- X { pwufd = -1; return; }
- X }
- X else if ( sb.st_size < goodsize )
- X {
- X for ( i = sizeof(no_off_buf) / sizeof(off_t) - 1; i >= 0; --i )
- X no_off_buf[i] = NO_OFF;
- X if ( lseek( pwufd, sb.st_size, L_SET ) < 0 )
- X { pwufd = -1; return; }
- X while ( sb.st_size + sizeof(no_off_buf) < goodsize )
- X {
- X if ( write( pwufd, (char*) no_off_buf, sizeof(no_off_buf) ) !=
- X sizeof(no_off_buf) )
- X { pwufd = -1; return; }
- X sb.st_size += sizeof(no_off_buf);
- X }
- X if ( sb.st_size < goodsize )
- X if ( write( pwufd, (char*) no_off_buf, goodsize - sb.st_size ) !=
- X goodsize - sb.st_size )
- X { pwufd = -1; return; }
- X }
- X }
- X
- X/* checkpwn - check and adjust the name index file
- X**
- X** Checks that the name index file is the right size. If it's too
- X** big, truncates it, and if it's either too big or too small, writes
- X** it full of NO_UID entries.
- X*/
- Xstatic void
- Xcheckpwn()
- X {
- X struct stat sb;
- X off_t goodsize;
- X uid_t no_uid_buf[1000];
- X int i;
- X
- X if ( fstat( pwnfd, &sb ) < 0 )
- X { pwnfd = -1; return; }
- X goodsize = namehashsize * sizeof(uid_t);
- X if ( sb.st_size == goodsize )
- X return;
- X if ( sb.st_size > goodsize )
- X {
- X if ( ftruncate( pwnfd, goodsize ) < 0 )
- X { pwnfd = -1; return; }
- X }
- X for ( i = sizeof(no_uid_buf) / sizeof(uid_t) - 1; i >= 0; --i )
- X no_uid_buf[i] = NO_UID;
- X if ( lseek( pwnfd, (off_t) 0, L_SET ) < 0 )
- X { pwnfd = -1; return; }
- X i = 0;
- X while ( i + sizeof(no_uid_buf) < goodsize )
- X {
- X if ( write( pwnfd, (char*) no_uid_buf, sizeof(no_uid_buf) ) !=
- X sizeof(no_uid_buf) )
- X { pwnfd = -1; return; }
- X i += sizeof(no_uid_buf);
- X }
- X if ( i < goodsize )
- X if ( write( pwnfd, (char*) no_uid_buf, goodsize - i ) != goodsize - i )
- X { pwnfd = -1; return; }
- X }
- X
- X/* setpwent - open the password file
- X**
- X** setpwent() opens the system password file, or rewinds it if it was
- X** open already.
- X*/
- Xint
- Xsetpwent()
- X {
- X smpw_init();
- X
- X if ( pwdfp == (FILE*) 0 )
- X {
- X pwdfp = fopen( PWDFILE, "r" );
- X if ( pwdfp == (FILE*) 0 )
- X return -1;
- X if ( maxuid == 0 )
- X pwufd = pwnfd = -1;
- X else
- X {
- X pwufd = open( PWDUFILE, O_RDWR );
- X if ( pwufd != -1 )
- X checkpwu();
- X pwnfd = open( PWDNFILE, O_RDWR );
- X if ( pwnfd != -1 )
- X checkpwn();
- X }
- X }
- X else
- X rewind( pwdfp );
- X
- X return 0;
- X }
- X
- X/* endpwent - close a password file
- X**
- X** endpwent() closes the password file if open.
- X*/
- Xint
- Xendpwent()
- X {
- X int ret;
- X
- X smpw_init();
- X
- X ret = 0;
- X
- X if ( pwdfp != (FILE*) 0 )
- X if ( fclose( pwdfp ) != 0 )
- X ret = -1;
- X pwdfp = (FILE*) 0;
- X
- X if ( pwufd != -1 )
- X if ( close( pwufd ) < 0 )
- X ret = -1;
- X pwufd = -1;
- X
- X if ( pwnfd != -1 )
- X if ( close( pwnfd ) < 0 )
- X ret = -1;
- X pwnfd = -1;
- X
- X return ret;
- X }
- SHAR_EOF
- if test 15518 -ne "`wc -c < 'smpw.c'`"
- then
- echo shar: error transmitting "'smpw.c'" '(should have been 15518 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'Makefile'" '(3501 characters)'
- if test -f 'Makefile'
- then
- echo shar: will not over-write existing file "'Makefile'"
- else
- sed 's/^X//' << \SHAR_EOF > 'Makefile'
- X# Makefile for libsmpw
- X#
- X# Copyright (C) 1992 by Jef Poskanzer.
- X#
- X# Permission to use, copy, modify, and distribute this software and its
- X# documentation for any purpose and without fee is hereby granted, provided
- X# that the above copyright notice appear in all copies and that both that
- X# copyright notice and this permission notice appear in supporting
- X# documentation. This software is provided "as is" without express or
- X# implied warranty.
- X
- X# CONFIGURE: The maximum uid that the package should handle. Not the
- X# maximum number of uids, the maximum uid. For instance, you might
- X# have 8000 uids but the maximum uid might be 20000. In that case
- X# you might set MAXUID to 40000, to leave some room for expansion.
- X#
- X# If you want to change this number later, you only have to re-install,
- X# no recompilation is necessary. The index file size will be automatically
- X# adjusted the next time anyone runs a program linked with this library.
- X#MAXUID = 5000
- XMAXUID = 65535
- X
- X# CONFIGURE: The number of name hash entries to use. This should be
- X# a prime number somewhat larger than the number of uids you expect
- X# to handle. Not the maximum uid, the number of uids. Four times
- X# larger is probably ok.
- X#
- X# Again, if you change this number later the index file gets automatically
- X# adjusted, but in this case it also gets zeroed. You should only do this
- X# when no one is using the package, although it will clean everything up
- X# eventually no matter what you do.
- X#NAMEHASHSIZE = 10007
- XNAMEHASHSIZE = 40009
- X
- X# CONFIGURE: The directory for the uid and name index files.
- X#INDEXDIR = /etc
- XINDEXDIR = /usr/public/lib/libsmpw
- X
- X# CONFIGURE: The names of the uid and name index files, and the size file.
- XPWDUFILE = $(INDEXDIR)/passwd.u
- XPWDNFILE = $(INDEXDIR)/passwd.n
- XPWDSFILE = $(INDEXDIR)/passwd.s
- X
- X# CONFIGURE: The directory you want the library installed into.
- XLIBDIR = /usr/public/lib
- X
- X# CONFIGURE: The directory tree you want the man pages installed into.
- XMANDIR = /usr/public/man
- X
- X# CONFIGURE: The manual section.
- XMANSEC = 3
- X
- X# CONFIGURE: Your favorite C compiler.
- XCC = cc
- X#CC = gcc -ansi -pedantic -fpcc-struct-return -fcombine-regs -fstrength-reduce -finline-functions
- X#CC = gcc -ansi -pedantic -fpcc-struct-return
- X
- X# CONFIGURE: Your favorite C flags.
- X#CFLAGS = -g
- XCFLAGS = -O
- X
- X# Uncomment if you're compiling on a System V machine.
- X#DSYSV = -DSYSV
- X
- X# End of configurable definitions.
- X
- XDPWDUFILE = -DPWDUFILE=\"$(PWDUFILE)\"
- XDPWDNFILE = -DPWDNFILE=\"$(PWDNFILE)\"
- XDPWDSFILE = -DPWDSFILE=\"$(PWDSFILE)\"
- XDEFINES = $(DPWDUFILE) $(DPWDNFILE) $(DPWDSFILE) $(DSYSV)
- XLINTFLAGS = -hxz
- X
- XSRCS = smpw.c
- XOBJS = smpw.o
- XLIBS = libsmpw.a
- XMANS = libsmpw
- X
- XINCLUDES =
- XALLCFLAGS = $(CFLAGS) $(DEFINES) $(INCLUDES)
- XALLLINTFLAGS = $(LINTFLAGS) $(DEFINES) $(INCLUDES)
- X
- Xall: $(LIBS)
- X
- Xlibsmpw.a: $(OBJS)
- X rm -f libsmpw.a
- X ar rc libsmpw.a $(OBJS)
- X -ranlib libsmpw.a
- X
- Xsmpw.o: smpw.c
- X $(CC) $(ALLCFLAGS) -c smpw.c
- X
- Xlint:
- X for i in $(SRCS) ; do \
- X echo $$i ; \
- X lint $(ALLLINTFLAGS) $$i | sed -e '/but never used or defined/d' -e '/but not defined/d' -e '/but never used/d' ; \
- X done
- X
- Xinstall: install.lib install.man
- X
- Xinstall.lib: $(LIBS)
- X for i in $(LIBS) ; do \
- X install -c $$i $(LIBDIR) ; \
- X ranlib $(LIBDIR)/$$i ; \
- X done
- X -mkdir $(INDEXDIR)
- X touch $(PWDUFILE) $(PWDNFILE)
- X chmod 666 $(PWDUFILE) $(PWDNFILE)
- X echo $(MAXUID) $(NAMEHASHSIZE) > $(PWDSFILE)
- X
- Xinstall.man:
- X for i in $(MANS) ; do \
- X install -c $$i.3 $(MANDIR)/man$(MANSEC)/$$i.$(MANSEC) ; \
- X done
- X
- Xclean:
- X rm -f *.a *.o a.out core
- SHAR_EOF
- if test 3501 -ne "`wc -c < 'Makefile'`"
- then
- echo shar: error transmitting "'Makefile'" '(should have been 3501 characters)'
- fi
- fi # end of overwriting check
- # End of shell archive
- exit 0
-