Password file routines with DBM support [ repost ]
John F. Haugh II
jfh at rpp386.cactus.org
Sun Jul 22 23:53:24 AEST 1990
[ This is the second time I'm posting this. The first post included a very
nasty bug which I hadn't caught. So, if you have managed to get a copy of
that version, trash it ... ]
I keep seeing password file routines get posted which have no support
for DBM files. I decided to collect a few sources I had hanging around
and send them out to the world. To use this stuff, compile with
cc -c -O getpwent.c pwpack.c
or whatever other magical incantations you use, and then link whatever
you want these to be a part of with these two files. The routines which
get defined here are getpwent, getpwuid, getpwnam, setpwent, endpwent,
fgetpwent, and sgetpwent. Two additional routines, pw_pack and pw_unpack
are defined to pack and unpack DBM records containing password file
entries.
If anyone manages to put NDBM stuff in here, please send back the
patches.
DISCLAIMER: Also, this is alt.sources stuff, don't expect it to actually
work. I wouldn't use it in the ICBM controller you've been working on
without first making sure it works correctly in your environment.
Unshar and enjoy!
------ cut here ------
#! /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:
# getpwent.c
# pwpack.c
# This archive created: Sat Jul 21 17:42:05 1990
# By: John F. Haugh II (River Parishes Programming, Austin TX)
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'getpwent.c'" '(6614 characters)'
if test -f 'getpwent.c'
then
echo shar: "will not over-write existing file 'getpwent.c'"
else
sed 's/^X//' << \SHAR_EOF > 'getpwent.c'
X/*
X * Copyright 1990, John F. Haugh II
X * All rights reserved.
X *
X * Use, duplication, and disclosure prohibited without
X * the express written permission of the author.
X *
X * Duplication is permitted for non-commercial [ non-profit making ]
X * purposes provided this and other copyright notices remain
X * intact.
X */
X
X#include <stdio.h>
X#include <pwd.h>
X#include <string.h>
X#include <dbm.h>
X
X#define SBUFSIZ 64
X#define NFIELDS 7
X
Xstatic FILE *pwdfp;
Xstatic char pwdbuf[BUFSIZ];
Xstatic char *pwdfile = "/etc/passwd";
Xstatic int dbmopened;
Xstatic int dbmerror;
Xstatic char *pwdfields[NFIELDS];
Xstatic struct passwd pwent;
X
X/*
X * sgetpwent - convert a string to a (struct passwd)
X *
X * sgetpwent() parses a string 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 */
X
Xstruct passwd *sgetpwent (buf)
Xchar *buf;
X{
X int i;
X char *cp;
X
X /*
X * Copy the string to a static buffer so the pointers into
X * the password structure remain valid.
X */
X
X strncpy (pwdbuf, buf, BUFSIZ);
X pwdbuf[BUFSIZ-1] = '\0';
X
X /*
X * Save a pointer to the start of each colon separated
X * field. The fields are converted into NUL terminated strings.
X */
X
X for (cp = pwdbuf, i = 0;i < NFIELDS && cp;i++) {
X pwdfields[i] = cp;
X if (cp = strchr (cp, ':'))
X *cp++ = 0;
X }
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
X if (i != NFIELDS || *pwdfields[2] == '\0' || *pwdfields[3] == '\0')
X return 0;
X
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
X pwent.pw_name = pwdfields[0];
X pwent.pw_passwd = pwdfields[1];
X if ((pwent.pw_uid = strtol (pwdfields[2], &cp, 10)) == 0 && *cp)
X return 0;
X
X if ((pwent.pw_gid = strtol (pwdfields[3], &cp, 10)) == 0 && *cp)
X return 0;
X
X if (cp = strchr (pwent.pw_passwd, ',')) {
X pwent.pw_age = cp + 1;
X *cp = '\0';
X }
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/*
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 */
X
Xstruct passwd *fgetpwent (fp)
XFILE *fp;
X{
X char buf[BUFSIZ];
X char *cp;
X
X if (! fgets (buf, BUFSIZ, fp))
X return 0;
X
X if (cp = strrchr (buf, '\n'))
X *cp = '\0';
X
X return sgetpwent (buf);
X}
X
X/*
X * endpwent - close a password file
X *
X * endpwent() closes the password file if open.
X */
X
Xint endpwent ()
X{
X if (pwdfp)
X if (fclose (pwdfp))
X return -1;
X
X return 0;
X}
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 */
X
Xstruct passwd *getpwent ()
X{
X if (! pwdfp && setpwent ())
X return 0;
X
X return fgetpwent (pwdfp);
X}
X
X/*
X * getpwuid - locate the password entry for a given UID
X *
X * getpwuid() locates the first password file entry for the given UID.
X * If there is a valid DBM file, the DBM files are queried first for
X * the entry. Otherwise, a linear search is begun of the password file
X * searching for an entry which matches the provided UID.
X */
X
Xstruct passwd *getpwuid (uid)
Xint uid;
X{
X struct passwd *pwd;
X datum key;
X datum content;
X
X /*
X * Attempt to open the DBM files if they have never been opened
X * and an error has never been returned.
X */
X
X if (! dbmerror && ! dbmopened)
X if (dbminit (pwdfile) == 0)
X dbmopened = 1;
X else
X dbmerror = 1;
X
X /*
X * If the DBM file are now open, create a key for this UID and
X * try to fetch the entry from the database. A matching record
X * will be unpacked into a static structure and returned to
X * the user.
X */
X
X if (dbmopened) {
X pwent.pw_uid = uid;
X key.dsize = sizeof pwent.pw_uid;
X key.dptr = (char *) &pwent.pw_uid;
X content = fetch (key);
X if (content.dptr != 0) {
X memcpy (pwdbuf, content.dptr, content.dsize);
X pw_unpack (pwdbuf, content.dsize, &pwent);
X return &pwent;
X }
X }
X
X /*
X * Rewind the database and begin searching for an entry which
X * matches the UID. Return the entry when a match is found.
X */
X
X if (setpwent ())
X return 0;
X
X while (pwd = getpwent ())
X if (pwd->pw_uid == uid)
X return pwd;
X
X return 0;
X}
X
X/*
X * getpwuid - locate the password entry for a given name
X *
X * getpwuid() locates the first password file entry for the given name.
X * If there is a valid DBM file, the DBM files are queried first for
X * the entry. Otherwise, a linear search is begun of the password file
X * searching for an entry which matches the provided name.
X */
X
Xstruct passwd *getpwnam (name)
Xchar *name;
X{
X struct passwd *pwd;
X datum key;
X datum content;
X
X /*
X * Attempt to open the DBM files if they have never been opened
X * and an error has never been returned.
X */
X
X if (! dbmerror && ! dbmopened)
X if (dbminit (pwdfile) == 0)
X dbmopened = 1;
X else
X dbmerror = 1;
X
X /*
X * If the DBM file are now open, create a key for this name and
X * try to fetch the entry from the database. A matching record
X * will be unpacked into a static structure and returned to
X * the user.
X */
X
X if (dbmopened) {
X key.dsize = strlen (name);
X key.dptr = name;
X content = fetch (key);
X if (content.dptr != 0) {
X memcpy (pwdbuf, content.dptr, content.dsize);
X pw_unpack (pwdbuf, content.dsize, &pwent);
X return &pwent;
X }
X }
X
X /*
X * Rewind the database and begin searching for an entry which
X * matches the name. Return the entry when a match is found.
X */
X
X if (setpwent ())
X return 0;
X
X while (pwd = getpwent ())
X if (strcmp (pwd->pw_name, name) == 0)
X return pwd;
X
X return 0;
X}
X
X/*
X * setpwent - open the password file
X *
X * setpwent() opens the system password file, and the DBM password files
X * if they are present. The system password file is rewound if it was
X * open already.
X */
X
Xint setpwent ()
X{
X if (! pwdfp) {
X if (! (pwdfp = fopen (pwdfile, "r")))
X return -1;
X } else {
X if (fseek (pwdfp, 0L, 0) != 0)
X return -1;
X }
X
X /*
X * Attempt to open the DBM files if they have never been opened
X * and an error has never been returned.
X */
X
X if (! dbmerror && ! dbmopened)
X if (dbminit (pwdfile) == 0)
X dbmopened = 1;
X else
X dbmerror = 1;
X return 0;
X}
SHAR_EOF
if test 6614 -ne "`wc -c < 'getpwent.c'`"
then
echo shar: "error transmitting 'getpwent.c'" '(should have been 6614 characters)'
fi
fi
echo shar: "extracting 'pwpack.c'" '(1791 characters)'
if test -f 'pwpack.c'
then
echo shar: "will not over-write existing file 'pwpack.c'"
else
sed 's/^X//' << \SHAR_EOF > 'pwpack.c'
X/*
X * Copyright 1990, John F. Haugh II
X * All rights reserved.
X *
X * Use, duplication, and disclosure prohibited without
X * the express written permission of the author.
X *
X * Duplication is permitted for non-commercial [ profit making ]
X * purposes provided this and other copyright notices remain
X * intact.
X */
X
X#include <pwd.h>
X
Xint pw_pack (passwd, buf)
Xstruct passwd *passwd;
Xchar *buf;
X{
X char *cp;
X
X cp = buf;
X strcpy (cp, passwd->pw_name);
X cp += strlen (cp) + 1;
X
X strcpy (cp, passwd->pw_passwd);
X cp += strlen (cp) + 1;
X
X memcpy (cp, (void *) &passwd->pw_uid, sizeof passwd->pw_uid);
X cp += sizeof passwd->pw_uid;
X
X memcpy (cp, (void *) &passwd->pw_gid, sizeof passwd->pw_gid);
X cp += sizeof passwd->pw_gid;
X
X strcpy (cp, passwd->pw_gecos);
X cp += strlen (cp) + 1;
X
X strcpy (cp, passwd->pw_dir);
X cp += strlen (cp) + 1;
X
X strcpy (cp, passwd->pw_shell);
X cp += strlen (cp) + 1;
X
X return cp - buf;
X}
X
Xint pw_unpack (buf, len, passwd)
Xchar *buf;
Xint len;
Xstruct passwd *passwd;
X{
X char *org = buf;
X
X passwd->pw_name = buf;
X buf += strlen (buf) + 1;
X if (buf - org > len)
X return -1;
X
X passwd->pw_passwd = buf;
X buf += strlen (buf) + 1;
X if (buf - org > len)
X return -1;
X
X memcpy ((void *) &passwd->pw_uid, (void *) buf, sizeof passwd->pw_uid);
X buf += sizeof passwd->pw_uid;
X if (buf - org > len)
X return -1;
X
X memcpy ((void *) &passwd->pw_gid, (void *) buf, sizeof passwd->pw_gid);
X buf += sizeof passwd->pw_gid;
X if (buf - org > len)
X return -1;
X
X passwd->pw_gecos = buf;
X buf += strlen (buf) + 1;
X if (buf - org > len)
X return -1;
X
X passwd->pw_dir = buf;
X buf += strlen (buf) + 1;
X if (buf - org > len)
X return -1;
X
X passwd->pw_shell = buf;
X buf += strlen (buf) + 1;
X if (buf - org > len)
X return -1;
X
X return 0;
X}
SHAR_EOF
if test 1791 -ne "`wc -c < 'pwpack.c'`"
then
echo shar: "error transmitting 'pwpack.c'" '(should have been 1791 characters)'
fi
fi
exit 0
# End of shell archive
--
John F. Haugh II UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 832-8832 Domain: jfh at rpp386.cactus.org
More information about the Alt.sources
mailing list