Shadow Login Suite, version 3 (part 6 of 8)

John F Haugh II jfh at rpp386.cactus.org
Fri May 17 02:32:11 AEST 1991


#! /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:
#	gspack.c
#	spdbm.c
#	lastlog.h
#	shell.c
#	login.c
#	sub.c
#	dpmain.c
#	mail.c
#	env.c
#	pwd.h
#	grpack.c
#	shadow.h
#	log.c
#	grent.c
#	motd.c
#	dialup.h
#	fields.c
#	gsdbm.c
# This archive created: Sun Mar  3 13:27:34 1991
# By:	John F Haugh II (River Parishes Programming, Austin TX)
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'gspack.c'" '(2890 characters)'
if test -f 'gspack.c'
then
	echo shar: "will not over-write existing file 'gspack.c'"
else
sed 's/^X//' << \SHAR_EOF > 'gspack.c'
X/*
X * Copyright 1990, 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 "shadow.h"
X#ifdef	BSD
X#include <strings.h>
X#else
X#include <string.h>
X#endif
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)gspack.c	3.1	09:13:50	12/13/90";
X#endif
X
X/*
X * sgr_pack - convert a shadow group structure to a packed
X *	      shadow group record
X *
X *	sgr_pack takes the shadow group structure and packs
X *	the components in a record.  this record will be
X *	unpacked later by sgr_unpack.
X */
X
Xint
Xsgr_pack (sgrp, buf)
Xstruct	sgrp	*sgrp;
Xchar	*buf;
X{
X	char	*cp;
X	int	i;
X
X	/*
X	 * The name and password are both easy - append each string
X	 * to the buffer.  These are always the first two strings
X	 * in a record.
X	 */
X
X	cp = buf;
X	strcpy (cp, sgrp->sg_name);
X	cp += strlen (cp) + 1;
X
X	strcpy (cp, sgrp->sg_passwd);
X	cp += strlen (cp) + 1;
X
X	/*
X	 * The arrays of administrators and members are slightly
X	 * harder.  Each element is appended as a string, with a
X	 * final '\0' appended to serve as a blank string.  The
X	 * number of elements is not known in advance, so the
X	 * entire collection of administrators must be scanned to
X	 * find the start of the members.
X	 */
X
X	for (i = 0;sgrp->sg_adm[i];i++) {
X		strcpy (cp, sgrp->sg_adm[i]);
X		cp += strlen (cp) + 1;
X	}
X	*cp++ = '\0';
X
X	for (i = 0;sgrp->sg_mem[i];i++) {
X		strcpy (cp, sgrp->sg_mem[i]);
X		cp += strlen (cp) + 1;
X	}
X	*cp++ = '\0';
X
X	return cp - buf;
X}
X
X/*
X * sgr_unpack - convert a packed shadow group record to an
X *	        unpacked record
X *
X *	sgr_unpack converts a record which was packed by sgr_pack
X *	into the normal shadow group structure format.
X */
X
Xint
Xsgr_unpack (buf, len, sgrp)
Xchar	*buf;
Xint	len;
Xstruct	sgrp	*sgrp;
X{
X	char	*org = buf;
X	int	i;
X
X	/*
X	 * The name and password are both easy - they are the first
X	 * two strings in the record.
X	 */
X
X	sgrp->sg_name = buf;
X	buf += strlen (buf) + 1;
X	if (buf - org > len)
X		return -1;
X
X	sgrp->sg_passwd = buf;
X	buf += strlen (buf) + 1;
X	if (buf - org > len)
X		return -1;
X
X	/*
X	 * The administrators and members are slightly more difficult.
X	 * The arrays are lists of strings.  Each list is terminated
X	 * by a string of length zero.  This string is detected by
X	 * looking for an initial character of '\0'.
X	 */
X
X	for (i = 0;*buf && i < 1024;i++) {
X		sgrp->sg_adm[i] = buf;
X		buf += strlen (buf) + 1;
X
X		if (buf - org > len)
X			return -1;
X	}
X	sgrp->sg_adm[i] = (char *) 0;
X	if (! *buf)
X		buf++;
X
X	for (i = 0;*buf && i < 1024;i++) {
X		sgrp->sg_mem[i] = buf;
X		buf += strlen (buf) + 1;
X
X		if (buf - org > len)
X			return -1;
X	}
X	sgrp->sg_mem[i] = (char *) 0;
X
X	return 0;
X}
SHAR_EOF
if test 2890 -ne "`wc -c < 'gspack.c'`"
then
	echo shar: "error transmitting 'gspack.c'" '(should have been 2890 characters)'
fi
fi
echo shar: "extracting 'spdbm.c'" '(933 characters)'
if test -f 'spdbm.c'
then
	echo shar: "will not over-write existing file 'spdbm.c'"
else
sed 's/^X//' << \SHAR_EOF > 'spdbm.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
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)spdbm.c	3.1	08:16:16	11/21/90";
X#endif
X
X#include <string.h>
X#include <stdio.h>
X#include "config.h"
X#include "shadow.h"
X
X#ifdef	NDBM
X#include <ndbm.h>
XDBM	*sp_dbm;
X
X/*
X * sp_dbm_update
X *
X * Updates the DBM password files, if they exist.
X */
X
Xint
Xsp_dbm_update (sp)
Xstruct	spwd	*sp;
X{
X	datum	key;
X	datum	content;
X	char	data[BUFSIZ];
X	char	spwdkey[60];
X	char	*cp;
X	int	len;
X	int	i;
X	int	cnt;
X	static	int	once;
X
X	if (! once) {
X		if (! sp_dbm)
X			setspent ();
X
X		once++;
X	}
X	if (! sp_dbm)
X		return 0;
X
X	len = spw_pack (sp, data);
X
X	content.dsize = len;
X	content.dptr = data;
X
X	key.dsize = strlen (sp->sp_namp);
X	key.dptr = sp->sp_namp;
X	if (dbm_store (sp_dbm, key, content, DBM_REPLACE))
X		return 0;
X
X	return 1;
X}
X#endif
SHAR_EOF
if test 933 -ne "`wc -c < 'spdbm.c'`"
then
	echo shar: "error transmitting 'spdbm.c'" '(should have been 933 characters)'
fi
fi
echo shar: "extracting 'lastlog.h'" '(511 characters)'
if test -f 'lastlog.h'
then
	echo shar: "will not over-write existing file 'lastlog.h'"
else
sed 's/^X//' << \SHAR_EOF > 'lastlog.h'
X/*
X * Copyright 1989, 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
X/*
X * lastlog.h - structure of lastlog file
X *
X *	@(#)lastlog.h	2.3	19:23:49	7/29/90
X *
X *	This file defines a lastlog file structure which should be sufficient
X *	to hold the information required by login.  It should only be used if
X *	there is no real lastlog.h file.
X */
X
Xstruct	lastlog	{
X	time_t	ll_time;
X	char	ll_line[8];
X};
SHAR_EOF
if test 511 -ne "`wc -c < 'lastlog.h'`"
then
	echo shar: "error transmitting 'lastlog.h'" '(should have been 511 characters)'
fi
fi
echo shar: "extracting 'shell.c'" '(2527 characters)'
if test -f 'shell.c'
then
	echo shar: "will not over-write existing file 'shell.c'"
else
sed 's/^X//' << \SHAR_EOF > 'shell.c'
X/*
X * Copyright 1989, 1990, 1991, 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
X#include <stdio.h>
X#include <errno.h>
X#ifndef	BSD
X#include <string.h>
X#include <memory.h>
X#else
X#include <strings.h>
X#define	strchr	index
X#define	strrchr	rindex
X#endif
X#include "config.h"
X
X#ifndef	lint
Xstatic	char	_sccsid[] = "@(#)shell.c	3.2	07:55:08	2/6/91";
X#endif
X
Xextern	char	*newenvp[];
X
X/*
X * shell - execute the named program
X *
X *	shell begins by trying to figure out what argv[0] is going to
X *	be for the named process.  The user may pass in that argument,
X *	or it will be the last pathname component of the file with a
X *	'-' prepended.  The first attempt is to just execute the named
X *	file.  If the errno comes back "ENOEXEC", the file is assumed
X *	at first glance to be a shell script.  The first two characters
X *	must be "#!", in which case "/bin/sh" is executed to process
X *	the file.  If all that fails, give up in disgust ...
X */
X
Xvoid	shell (file, arg)
Xchar	*file;
Xchar	*arg;
X{
X	char	arg0[BUFSIZ];
X	FILE	*fp;
X	char	*path;
X	int	err;
X
X	if (file == (char *) 0)
X		exit (1);
X
X	/*
X	 * The argv[0]'th entry is usually the path name, but
X	 * for various reasons the invoker may want to override
X	 * that.  So, we determine the 0'th entry only if they
X	 * don't want to tell us what it is themselves.
X	 */
X
X	if (arg == (char *) 0) {
X		if (path = strrchr (file, '/'))
X			path++;
X		else
X			path = file;
X
X		(void) strcpy (arg0 + 1, path);
X		arg0[0] = '-';
X		arg = arg0;
X	}
X#ifndef	NDEBUG
X	printf ("Executing shell %s\n", file);
X#endif
X
X	/*
X	 * First we try the direct approach.  The system should be
X	 * able to figure out what we are up to without too much
X	 * grief.
X	 */
X
X	execle (file, arg, (char *) 0, newenvp);
X	err = errno;
X
X	/*
X	 * It is perfectly OK to have a shell script for a login
X	 * shell, and this code attempts to support that.  It
X	 * relies on the standard shell being able to make sense
X	 * of the "#!" magic number.
X	 */
X
X	if (err == ENOEXEC) {
X		if (fp = fopen (file, "r")) {
X			if (getc (fp) == '#' && getc (fp) == '!') {
X				fclose (fp);
X				execle ("/bin/sh", "sh",
X					file, (char *) 0, newenvp);
X				err = errno;
X			} else {
X				fclose (fp);
X			}
X		}
X	}
X
X	/*
X	 * Obviously something is really wrong - I can't figure out
X	 * how to execute this stupid shell, so I might as well give
X	 * up in disgust ...
X	 */
X
X	sprintf (arg0, "Cannot execute %s", file);
X	errno = err;
X	perror (arg0);
X	exit (err);
X}
SHAR_EOF
if test 2527 -ne "`wc -c < 'shell.c'`"
then
	echo shar: "error transmitting 'shell.c'" '(should have been 2527 characters)'
fi
fi
echo shar: "extracting 'login.c'" '(1164 characters)'
if test -f 'login.c'
then
	echo shar: "will not over-write existing file 'login.c'"
else
sed 's/^X//' << \SHAR_EOF > 'login.c'
X/*
X * Copyright 1989, 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
X#include <stdio.h>
X#include <ctype.h>
X#ifndef	BSD
X#include <string.h>
X#include <memory.h>
X#else
X#include <strings.h>
X#define	strchr	index
X#define	strrchr	rindex
X#endif
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)login.c	2.3	19:23:55	7/29/90";
X#endif
X
Xvoid	setenv ();
X
Xvoid	login (name)
Xchar	*name;
X{
X	char	buf[BUFSIZ];
X	char	*envp[32];
X	int	envc;
X	char	*cp;
X	int	i;
X
X#ifndef	BSD
X	(void) memset (buf, '\0', sizeof buf);
X#else
X	bzero (buf, sizeof buf);
X#endif
X	fputs ("login: ", stdout);
X
X	if (fgets (buf, BUFSIZ, stdin) != buf)
X		exit (1);
X
X	buf[strlen (buf) - 1] = '\0';	/* remove \n [ must be there ] */
X
X	for (cp = buf;*cp == ' ' || *cp == '\t';cp++)
X		;
X
X	for (i = 0;i < BUFSIZ - 1 && isgraph (*cp);name[i++] = *cp++)
X		;
X
X	if (*cp)
X		cp++;
X
X	name[i] = '\0';
X
X	if (*cp != '\0') {		/* process new variables */
X		for (envc = 0;envc < 32;envc++) {
X			envp[envc] = strtok (envc == 0 ? cp:(char *) 0, " \t,");
X
X			if (envp[envc] == (char *) 0)
X				break;
X		}
X		setenv (envc, envp);
X	}
X}
SHAR_EOF
if test 1164 -ne "`wc -c < 'login.c'`"
then
	echo shar: "error transmitting 'login.c'" '(should have been 1164 characters)'
fi
fi
echo shar: "extracting 'sub.c'" '(1538 characters)'
if test -f 'sub.c'
then
	echo shar: "will not over-write existing file 'sub.c'"
else
sed 's/^X//' << \SHAR_EOF > 'sub.c'
X/*
X * Copyright 1989, 1990, 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 <sys/types.h>
X#include <syslog.h>
X
X#include "pwd.h"
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)sub.c	3.2	08:22:12	1/30/91";
X#endif
X
X#define	BAD_SUBROOT	"Invalid root directory \"%s\"\n"
X#define	BAD_SUBROOT2	"invalid root `%s' for user `%s'\n"
X#define	NO_SUBROOT	"Can't change root directory to \"%s\"\n"
X#define	NO_SUBROOT2	"no subsystem root `%s' for user `%s'\n"
X
X/*
X * subsystem - change to subsystem root
X *
X *	A subsystem login is indicated by the presense of a "*" as
X *	the first character of the login shell.  The given home
X *	directory will be used as the root of a new filesystem which
X *	the user is actually logged into.
X */
X
Xvoid	subsystem (pw)
Xstruct	passwd	*pw;
X{
X	/*
X	 * The new root directory must begin with a "/" character.
X	 */
X
X	if (pw->pw_dir[0] != '/') {
X		printf (BAD_SUBROOT, pw->pw_dir);
X		syslog (LOG_WARN, BAD_SUBROOT2, pw->pw_dir, pw->pw_name);
X		exit (1);
X	}
X
X	/*
X	 * The directory must be accessible and the current process
X	 * must be able to change into it.
X	 */
X
X	if (chdir (pw->pw_dir) || chroot (pw->pw_dir)) {
X		printf (NO_SUBROOT, pw->pw_dir);
X		syslog (LOG_WARN, NO_SUBROOT2, pw->pw_dir, pw->pw_name);
X		exit (1);
X	}
X}
SHAR_EOF
if test 1538 -ne "`wc -c < 'sub.c'`"
then
	echo shar: "error transmitting 'sub.c'" '(should have been 1538 characters)'
fi
fi
echo shar: "extracting 'dpmain.c'" '(2895 characters)'
if test -f 'dpmain.c'
then
	echo shar: "will not over-write existing file 'dpmain.c'"
else
sed 's/^X//' << \SHAR_EOF > 'dpmain.c'
X/*
X * Copyright 1990, 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 <sys/types.h>
X#include <sys/stat.h>
X#include <stdio.h>
X#include <fcntl.h>
X#ifdef	BSD
X#include <strings.h>
X#else
X#include <string.h>
X#endif
X#include "dialup.h"
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)dpmain.c	3.2	12:30:37	12/12/90";
X#endif
X
X#define	DTMP	"/etc/d_passwd.tmp"
X
X/*
X * Prompts and messages go here.
X */
X
X#define	PASS1	"Shell password:"
X#define	PASS2	"re-enter Shell password:"
X#define	NOMATCH	"%s: Passwords do not match, try again.\n"
X#define	NOFOUND	"%s: Shell %s not found.\n"
X
Xint	aflg;
Xint	dflg;
Xchar	*Prog;
X
Xextern	char	*pw_encrypt();
Xextern	char	*getpass();
X
Xusage ()
X{
X	fprintf (stderr, "Usage: %s -a|c|d shell\n", Prog);
X	exit (1);
X}
X
Xmain (argc, argv)
Xint	argc;
Xchar	**argv;
X{
X	struct	dialup	*dial;
X	struct	dialup	dent;
X	struct	stat	sb;
X	FILE	*fp;
X	char	*shell;
X	char	*cp;
X	char	pass[BUFSIZ];
X	int	fd;
X	int	found = 0;
X	int	opt;
X	extern	int	optind;
X	extern	char	*optarg;
X
X	if (Prog = strrchr (argv[0], '/'))
X		Prog++;
X	else
X		Prog = argv[0];
X
X	while ((opt = getopt (argc, argv, "a:d:")) != EOF) {
X		switch (opt) {
X			case 'a':
X				aflg++;
X				shell = optarg;
X				break;
X			case 'd':
X				dflg++;
X				shell = optarg;
X				break;
X			default:
X				usage ();
X		}
X	}
X	if (aflg + dflg != 1)
X		usage ();
X
X	if (aflg) {
X		dent.du_shell = shell;
X		dent.du_passwd = "";
X
X		if (! (cp = getpass (PASS1))) {
X			unlink (DTMP);
X			exit (1);
X		}
X		strcpy (pass, cp);
X		if (! (cp = getpass (PASS2))) {
X			unlink (DTMP);
X			exit (1);
X		}
X		if (strcmp (pass, cp)) {
X			fprintf (stderr, NOMATCH, Prog);
X			unlink (DTMP);
X			exit (1);
X		}
X		dent.du_passwd = pw_encrypt (pass, (char *) 0);
X	}
X	if ((fd = open (DTMP, O_CREAT|O_EXCL|O_RDWR, 0600)) < 0) {
X		sprintf (pass, "%s: can't create %s", Prog, DTMP);
X		perror (pass);
X		exit (1);
X	}
X	if (! (fp = fdopen (fd, "r+"))) {
X		sprintf (pass, "%s: can't open %s", Prog, DTMP);
X		perror (pass);
X		exit (1);
X	}
X	while (dial = getduent ()) {
X		if (strcmp (dial->du_shell, shell) == 0) {
X			found = 1;
X			break;
X		}
X		if (putduent (dial, fp))
X			goto failure;
X	}
X	if (dflg && ! found) {
X		fprintf (stderr, NOMATCH, Prog, shell);
X		exit (1);
X	}
X	if (aflg)
X		if (putduent (&dent, fp))
X			goto failure;
X
X	while (dial = getduent ())
X		if (putduent (dial, fp))
X			goto failure;
X
X	if (fflush (fp))
X		goto failure;
X
X	if (! stat (DIALPWD, &sb)) {
X		chown (DTMP, sb.st_uid, sb.st_gid);
X		chmod (DTMP, sb.st_mode);
X		unlink (DIALPWD);
X	} else {
X		chown (DTMP, 0, 0);
X		chmod (DTMP, 0400);
X	}
X	link (DTMP, DIALPWD);
X	unlink (DTMP);
X
X	sync ();
X	exit (0);
X
Xfailure:
X	unlink (DTMP);
X	exit (1);
X}
SHAR_EOF
if test 2895 -ne "`wc -c < 'dpmain.c'`"
then
	echo shar: "error transmitting 'dpmain.c'" '(should have been 2895 characters)'
fi
fi
echo shar: "extracting 'mail.c'" '(998 characters)'
if test -f 'mail.c'
then
	echo shar: "will not over-write existing file 'mail.c'"
else
sed 's/^X//' << \SHAR_EOF > 'mail.c'
X/*
X * Copyright 1989, 1990, 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 <sys/types.h>
X#include <sys/stat.h>
X
X#ifndef	BSD
X#include <string.h>
X#include <memory.h>
X#else
X#include <strings.h>
X#define	strchr	index
X#define	strrchr	rindex
X#endif
X
X#include "config.h"
X#ifdef	MAILCHECK
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)mail.c	3.2	13:28:27	12/19/90";
X#endif
X
Xextern	char	*getenv();
X
Xvoid	mailcheck ()
X{
X	struct	stat	statbuf;
X	char	*mailbox;
X
X	if (! (mailbox = getenv ("MAIL")))
X		return;
X
X	if (stat (mailbox, &statbuf) == -1 || statbuf.st_size == 0)
X		puts ("No mail.");
X	else if (statbuf.st_atime > statbuf.st_mtime)
X		puts ("You have mail.");
X	else
X		puts ("You have new mail.");
X}
X#endif
SHAR_EOF
if test 998 -ne "`wc -c < 'mail.c'`"
then
	echo shar: "error transmitting 'mail.c'" '(should have been 998 characters)'
fi
fi
echo shar: "extracting 'env.c'" '(1788 characters)'
if test -f 'env.c'
then
	echo shar: "will not over-write existing file 'env.c'"
else
sed 's/^X//' << \SHAR_EOF > 'env.c'
X/*
X * Copyright 1989, 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
X#include <stdio.h>
X#ifndef	BSD
X#include <string.h>
X#else
X#define	strchr	index
X#define	strrchr	rindex
X#include <strings.h>
X#endif
X
X#ifndef	lint
Xstatic	char	_sccsid[] = "@(#)env.c	2.2	19:23:43	7/29/90";
X#endif
X
Xextern	char	**environ;
Xextern	char	*newenvp[];
Xextern	int	newenvc;
Xextern	int	maxenv;
X
Xchar	*strdup ();
Xvoid	free ();
X
Xstatic	char	*forbid[] = {
X	"HOME",
X	"IFS",
X	"PATH",
X	"SHELL",
X	(char *) 0
X};
X
Xvoid	addenv (entry)
Xchar	*entry;
X{
X	char	*cp;
X	int	i;
X	int	len;
X
X	if (cp = strchr (entry, '='))
X		len = cp - entry;
X	else
X		return;
X
X	for (i = 0;i < newenvc;i++)
X		if (strncmp (entry, newenvp[i], len) == 0 &&
X			(newenvp[i][len] == '=' || newenvp[i][len] == '\0'))
X			break;
X
X	if (i == maxenv) {
X		puts ("Environment overflow");
X		return;
X	}
X	if (i == newenvc) {
X		newenvp[newenvc++] = strdup (entry);
X	} else {
X		free (newenvp[i]);
X		newenvp[i] = strdup (entry);
X	}
X}
X
Xvoid	setenv (argc, argv)
Xint	argc;
Xchar	**argv;
X{
X	int	i;
X	int	n;
X	int	noname = 1;
X	char	variable[BUFSIZ];
X	char	*cp;
X
X	for (i = 0;i < argc;i++) {
X		if ((n = strlen (argv[i])) >= BUFSIZ)
X			continue;	/* ignore long entries */
X
X		if (! (cp = strchr (argv[i], '='))) {
X			(void) strcpy (variable, argv[i]);
X		} else {
X			(void) strncpy (variable, argv[i], cp - argv[i]);
X			variable[cp - argv[i]] = '\0';
X		}
X		for (n = 0;forbid[n] != (char *) 0;n++)
X			if (strcmp (variable, forbid[n]) == 0)
X				break;
X
X		if (forbid[n] != (char *) 0) {
X			printf ("You may not change $%s\n", forbid[n]);
X			continue;
X		}
X		if (cp) {
X			addenv (argv[i]);
X		} else {
X			sprintf (variable, "L%d=%s", noname++, argv[i]);
X			addenv (variable);
X		}
X	}
X}
SHAR_EOF
if test 1788 -ne "`wc -c < 'env.c'`"
then
	echo shar: "error transmitting 'env.c'" '(should have been 1788 characters)'
fi
fi
echo shar: "extracting 'pwd.h'" '(2383 characters)'
if test -f 'pwd.h'
then
	echo shar: "will not over-write existing file 'pwd.h'"
else
sed 's/^X//' << \SHAR_EOF > 'pwd.h'
X/*
X * Copyright 1990, John F. Haugh II and Steve Simmons
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/*
X * Standard definitions for password files.  This is an independant
X * reimplementation of the definitions used by AT&T, BSD, and POSIX.
X * It is not derived from any of those sources.  Note that it can be
X * site-defined to have non-POSIX features as well.
X *
X * $RCSfile$	$Revision$
X *
X * $Author$	$Date$
X *
X * $State$	$Locker$
X *
X * $Log$
X */
X
X#ifndef	PWD_H
X#define	PWD_H
X
X#include	<sys/types.h>
X
X/*
X * For now these are defined here.  Later they should be moved to
X * the configuration file or this file should be generated by
X * a configurator.
X */
X
X#undef	BSD_QUOTAS
X#define	ATT_AGE
X#define	ATT_COMMENT
X
X/*
X * This is the data structure returned by the getpw* functions.  The
X * names of the elements and the structure are taken from traditional
X * usage.
X */
X
Xstruct passwd	{
X	char	*pw_name ;	/* User login name */
X	char	*pw_passwd ;	/* Encrypted passwd or dummy field */
X	uid_t	pw_uid ;	/* User uid number */
X	gid_t	pw_gid ;	/* User group id number */
X#ifdef	BSD_QUOTAS
X	/* Most BSD systems have quotas, most USG ones don't	*/
X	int	pw_quota ;	/* The BSD magic doodah */
X#endif
X#ifdef	ATT_AGE
X	/* Use ATT-style password aging	*/
X	char	*pw_age ;	/* ATT radix-64 encoded data */
X#endif
X#ifdef	ATT_COMMENT
X	/* Provide the unused comment field */
X	char	*pw_comment;	/* Unused comment field */
X#endif
X	char	*pw_gecos ;	/* ASCII user name, other data */
X	char	*pw_dir ;	/* User home directory */
X	char	*pw_shell ;	/* User startup shell */
X} ;
X
X#ifdef	ATT_COMMENT
X/* Provide the unused comment structure */
Xstruct comment {
X	char	*c_dept;
X	char	*c_name;
X	char	*c_acct;
X	char	*c_bin;
X};
X#endif
X
X#ifdef	__STDC__
X
Xextern	struct	passwd	*getpwent( void ) ;
Xextern	struct	passwd	*getpwuid( uid_t user_uid ) ;
Xextern	struct	passwd	*getpwnam( char *name ) ;
Xint	setpwent( void );
Xint	endpwent( void );
X
X#else
X
Xextern	struct	passwd	*getpwent();
Xextern	struct	passwd	*getpwuid();
Xextern	struct	passwd	*getpwnam();
Xint	setpwent();
Xint	endpwent();
X
X#endif	/* of ifdef __STDC__ */
X
X#endif	/* of ifdef PWD_H */
SHAR_EOF
if test 2383 -ne "`wc -c < 'pwd.h'`"
then
	echo shar: "error transmitting 'pwd.h'" '(should have been 2383 characters)'
fi
fi
echo shar: "extracting 'grpack.c'" '(1512 characters)'
if test -f 'grpack.c'
then
	echo shar: "will not over-write existing file 'grpack.c'"
else
sed 's/^X//' << \SHAR_EOF > 'grpack.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 <stdio.h>
X#include <grp.h>
X#ifdef	BSD
X#include <strings.h>
X#else
X#include <string.h>
X#endif
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)grpack.c	3.2	08:11:20	11/21/90";
X#endif
X
Xint	gr_pack (group, buf)
Xstruct	group	*group;
Xchar	*buf;
X{
X	char	*cp;
X	int	i;
X
X	cp = buf;
X	strcpy (cp, group->gr_name);
X	cp += strlen (cp) + 1;
X
X	strcpy (cp, group->gr_passwd);
X	cp += strlen (cp) + 1;
X
X	memcpy (cp, (void *) &group->gr_gid, sizeof group->gr_gid);
X	cp += sizeof group->gr_gid;
X
X	for (i = 0;group->gr_mem[i];i++) {
X		strcpy (cp, group->gr_mem[i]);
X		cp += strlen (cp) + 1;
X	}
X	*cp++ = '\0';
X
X	return cp - buf;
X}
X
Xint	gr_unpack (buf, len, group)
Xchar	*buf;
Xint	len;
Xstruct	group	*group;
X{
X	char	*org = buf;
X	int	i;
X
X	group->gr_name = buf;
X	buf += strlen (buf) + 1;
X	if (buf - org > len)
X		return -1;
X
X	group->gr_passwd = buf;
X	buf += strlen (buf) + 1;
X	if (buf - org > len)
X		return -1;
X
X	memcpy ((void *) &group->gr_gid, (void *) buf, sizeof group->gr_gid);
X	buf += sizeof group->gr_gid;
X	if (buf - org > len)
X		return -1;
X
X	for (i = 0;*buf && i < 1024;i++) {
X		group->gr_mem[i] = buf;
X		buf += strlen (buf) + 1;
X
X		if (buf - org > len)
X			return -1;
X	}
X	group->gr_mem[i] = (char *) 0;
X	return 0;
X}
SHAR_EOF
if test 1512 -ne "`wc -c < 'grpack.c'`"
then
	echo shar: "error transmitting 'grpack.c'" '(should have been 1512 characters)'
fi
fi
echo shar: "extracting 'shadow.h'" '(1823 characters)'
if test -f 'shadow.h'
then
	echo shar: "will not over-write existing file 'shadow.h'"
else
sed 's/^X//' << \SHAR_EOF > 'shadow.h'
X/*
X * Copyright 1988, 1989, 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
X#ifndef	_H_SHADOW
X#define	_H_SHADOW
X
X/*
X * This information is not derived from AT&T licensed sources.  Posted
X * to the USENET 11/88, and updated 11/90 with information from SVR4.
X *
X *	@(#)shadow.h	3.3	09:06:50	12/7/90
X */
X
X#ifdef	ITI_AGING
Xtypedef	time_t	sptime;
X#else
Xtypedef	long	sptime;
X#endif
X
X/*
X * Shadow password security file structure.
X */
X
Xstruct	spwd {
X	char	*sp_namp;	/* login name */
X	char	*sp_pwdp;	/* encrypted password */
X	sptime	sp_lstchg;	/* date of last change */
X	sptime	sp_min;		/* minimum number of days between changes */
X	sptime	sp_max;		/* maximum number of days between changes */
X	sptime	sp_warn;	/* number of days of warning before password
X				   expires */
X	sptime	sp_inact;	/* number of days after password expires
X				   until the account becomes unusable. */
X	sptime	sp_expire;	/* days since 1/1/70 until account expires */
X	unsigned long	sp_flag; /* reserved for future use */
X};
X
X/*
X * Shadow password security file functions.
X */
X
Xstruct	spwd	*getspent ();
Xstruct	spwd	*getspnam ();
Xstruct	spwd	*sgetspent ();
Xstruct	spwd	*fgetspent ();
Xvoid	setspent ();
Xvoid	endspent ();
Xint	putspent ();
X
X#define  SHADOW "/etc/shadow"
X
X/*
X * Shadow group security file structure
X */
X
Xstruct	sgrp {
X	char	*sg_name;	/* group name */
X	char	*sg_passwd;	/* group password */
X	char	**sg_adm;	/* group administator list */
X	char	**sg_mem;	/* group membership list */
X};
X
X/*
X * Shadow group security file functions.
X */
X
Xstruct	sgrp	*getsgent ();
Xstruct	sgrp	*getsgnam ();
Xstruct	sgrp	*sgetsgent ();
Xstruct	sgrp	*fgetsgent ();
Xvoid	setsgent ();
Xvoid	endsgent ();
Xint	putsgent ();
X
X#define	GSHADOW	"/etc/gshadow"
X#endif
SHAR_EOF
if test 1823 -ne "`wc -c < 'shadow.h'`"
then
	echo shar: "error transmitting 'shadow.h'" '(should have been 1823 characters)'
fi
fi
echo shar: "extracting 'log.c'" '(1543 characters)'
if test -f 'log.c'
then
	echo shar: "will not over-write existing file 'log.c'"
else
sed 's/^X//' << \SHAR_EOF > 'log.c'
X/*
X * Copyright 1989, 1990, 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 <sys/types.h>
X#include <utmp.h>
X#include "pwd.h"
X#include <fcntl.h>
X#include <time.h>
X#ifndef	BSD
X#include <string.h>
X#include <memory.h>
X#else
X#include <strings.h>
X#define	strchr	index
X#define	strrchr	rindex
X#endif
X#include "config.h"
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)log.c	3.1	12:30:53	12/12/90";
X#endif
X
X#ifdef	LASTLOG
X
X#include "lastlog.h"
X
Xextern	struct	utmp	utent;
Xextern	struct	passwd	pwent;
Xextern	struct	lastlog	lastlog;
Xextern	char	**environ;
X
Xlong	lseek ();
Xtime_t	time ();
X
Xvoid	log ()
X{
X	int	fd;
X	off_t	offset;
X	struct	lastlog	newlog;
X
X	if ((fd = open ("/usr/adm/lastlog", O_RDWR)) == -1)
X		return;
X
X	offset = pwent.pw_uid * sizeof lastlog;
X
X	if (lseek (fd, offset, 0) != offset) {
X		(void) close (fd);
X		return;
X	}
X	if (read (fd, (char *) &lastlog, sizeof lastlog) != sizeof lastlog)
X#ifndef	BSD
X		memset ((char *) &lastlog, sizeof lastlog, 0);
X#else
X		bzero ((char *) &lastlog, sizeof lastlog);
X#endif
X	newlog = lastlog;
X
X	(void) time (&newlog.ll_time);
X	(void) strncpy (newlog.ll_line, utent.ut_line, sizeof newlog.ll_line);
X	(void) lseek (fd, offset, 0);
X	(void) write (fd, (char *) &newlog, sizeof newlog);
X	(void) close (fd);
X}
X#endif
SHAR_EOF
if test 1543 -ne "`wc -c < 'log.c'`"
then
	echo shar: "error transmitting 'log.c'" '(should have been 1543 characters)'
fi
fi
echo shar: "extracting 'grent.c'" '(9437 characters)'
if test -f 'grent.c'
then
	echo shar: "will not over-write existing file 'grent.c'"
else
sed 's/^X//' << \SHAR_EOF > 'grent.c'
X/*
X * Copyright 1990, John F. Haugh II
X * All rights reserved.
X *
X * 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 <grp.h>
X#ifdef	BSD
X#include <strings.h>
X#define	strchr	index
X#define	strrchr	rindex
X#else	/* !BSD */
X#include <string.h>
X#endif	/* BSD */
X#include "config.h"
X
X#ifdef	AUTOSHADOW
X#include "shadow.h"
X#endif	/* AUTOSHADOW */
X
X#ifdef	NDBM
X#include <ndbm.h>
X#include <fcntl.h>
XDBM	*gr_dbm;
Xint	gr_dbm_mode = -1;
X#endif	/* NDBM */
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)grent.c	3.7	08:03:08	12/20/90";
X#endif	/* !lint */
X
X#define	NFIELDS	4
X#define	MAXMEM	1024
X
Xstatic	char	grpbuf[4*BUFSIZ];
Xstatic	char	*grpfields[NFIELDS];
Xstatic	char	*members[MAXMEM+1];
Xstatic	struct	group	grent;
X
Xstatic	FILE	*grpfp;
Xstatic	char	*grpfile = GRPFILE;
X#ifdef	NDBM
Xstatic	int	dbmopened;
Xstatic	int	dbmerror;
X#endif	/* NDBM */
X
Xchar *
Xfgetsx (buf, cnt, f)
Xchar	*buf;
Xint	cnt;
XFILE	*f;
X{
X	int	c;
X	char	*cp = buf;
X	char	*ep;
X
X	while (cnt > 0) {
X		if (fgets (cp, cnt, f) == 0)
X			if (cp == buf)
X				return 0;
X			else
X				break;
X
X		if ((ep = strrchr (cp, '\\')) && *(ep + 1) == '\n') {
X			if ((cnt -= ep - cp) > 0)
X				*(cp = ep) = '\0';
X		} else
X			break;
X	}
X	return buf;
X}
X
Xint
Xfputsx (s, stream)
Xchar	*s;
XFILE	*stream;
X{
X	int	i;
X
X	for (i = 0;*s;i++, s++) {
X		if (putc (*s, stream) == EOF)
X			return EOF;
X
X		if (i > (BUFSIZ/2)) {
X			if (putc ('\\', stream) == EOF ||
X			    putc ('\n', stream) == EOF)
X				return EOF;
X
X			i = 0;
X		}
X	}
X	return 0;
X}
X
Xstatic char **
Xlist (s)
Xchar	*s;
X{
X	int	nmembers = 0;
X
X	while (*s) {
X		members[nmembers++] = s;
X		if (s = strchr (s, ','))
X			*s++ = '\0';
X	}
X	members[nmembers] = (char *) 0;
X	return members;
X}
X
Xstruct	group	*sgetgrent (buf)
Xchar	*buf;
X{
X	int	i;
X	char	*cp;
X
X	strncpy (grpbuf, buf, sizeof grpbuf);
X	grpbuf[sizeof grpbuf - 1] = '\0';
X	if (cp = strrchr (grpbuf, '\n'))
X		*cp = '\0';
X
X	for (cp = grpbuf, i = 0;i < NFIELDS && cp;i++) {
X		grpfields[i] = cp;
X		if (cp = strchr (cp, ':'))
X			*cp++ = 0;
X	}
X	if (i < (NFIELDS-1) || *grpfields[2] == '\0')
X		return ((struct group *) 0);
X
X	grent.gr_name = grpfields[0];
X	grent.gr_passwd = grpfields[1];
X	grent.gr_gid = atoi (grpfields[2]);
X	grent.gr_mem = list (grpfields[3]);
X
X	return (&grent);
X}
X
Xint
Xputgrent (g, f)
Xstruct	group	*g;
XFILE	*f;
X{
X	int	i;
X	char	*cp;
X	char	buf[BUFSIZ*4];
X
X	if (! g || ! f)
X		return -1;
X
X	sprintf (buf, "%s:%s:%d:", g->gr_name, g->gr_passwd, g->gr_gid);
X	if (g->gr_mem) {
X		cp = strchr (buf, '\0');
X		for (i = 0;g->gr_mem[i];i++) {
X			if ((cp - buf) + strlen (g->gr_mem[i]) + 2
X					>= sizeof buf)
X				return -1;
X
X			if (i > 0) {
X				strcpy (cp, ",");
X				cp++;
X			}
X			strcpy (cp, g->gr_mem[i]);
X			cp = strchr (cp, '\0');
X		}
X		strcat (cp, "\n");
X	} else
X		strcat (buf, "\n");
X
X	if (fputsx (buf, f) == EOF || ferror (f))
X		return -1;
X
X	return 0;
X}
X
X/*
X * fgetgrent - get a group file entry from a stream
X *
X * fgetgrent() reads the next line from a group file formatted stream
X * and returns a pointer to the group structure for that line.
X */
X
Xstruct	group	*fgetgrent (fp)
XFILE	*fp;
X{
X	char	buf[BUFSIZ*4];
X	char	*cp;
X
X	if (fgetsx (buf, sizeof buf, fp) != (char *) 0) {
X		if (cp = strchr (buf, '\n'))
X			*cp = '\0';
X
X		return (sgetgrent (buf));
X	}
X	return 0;
X}
X
X/*
X * endgrent - close a group file
X *
X * endgrent() closes the group file if open.
X */
X
Xint	endgrent ()
X{
X	if (grpfp)
X		if (fclose (grpfp))
X			return -1;
X
X	grpfp = 0;
X#ifdef	NDBM
X	if (dbmopened && gr_dbm) {
X		dbm_close (gr_dbm);
X		gr_dbm = 0;
X	}
X	dbmopened = 0;
X	dbmerror = 0;
X#endif	/* NDBM */
X	return 0;
X}
X
X/*
X * getgrent - get a group entry from the group file
X *
X * getgrent() opens the group file, if not already opened, and reads
X * a single entry.  NULL is returned if any errors are encountered reading
X * the group file.
X */
X
Xstruct	group	*getgrent ()
X{
X	if (! grpfp && setgrent ())
X		return 0;
X
X	return fgetgrent (grpfp);
X}
X
X/*
X * getgrgid - locate the group entry for a given GID
X *
X * getgrgid() locates the first group file entry for the given GID.
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 group file
X * searching for an entry which matches the provided GID.
X */
X
Xstruct	group	*getgrgid (gid)
Xint	gid;
X{
X	struct	group	*grp;
X#ifdef NDBM
X	datum	key;
X	datum	content;
X	int	cnt;
X	int	i;
X	char	*cp;
X	char	grpkey[64];
X#endif	/* NDBM */
X#ifdef	AUTOSHADOW
X	struct	sgrp	*sgrp;
X#endif	/* AUTOSHADOW */
X
X	if (setgrent ())
X		return 0;
X
X#ifdef NDBM
X
X	/*
X	 * If the DBM file are now open, create a key for this GID 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		grent.gr_gid = gid;
X		key.dsize = sizeof grent.gr_gid;
X		key.dptr = (char *) &grent.gr_gid;
X		content = dbm_fetch (gr_dbm, key);
X		if (content.dptr == 0)
X			return 0;
X
X		if (content.dsize == sizeof (int)) {
X			memcpy (&cnt, content.dptr, content.dsize);
X			for (cp = grpbuf, i = 0;i < cnt;i++) {
X				memcpy (grpkey, &i, sizeof i);
X				memcpy (grpkey + sizeof i, &grent.gr_gid,
X					sizeof grent.gr_gid);
X
X				key.dsize = sizeof i + sizeof grent.gr_gid;
X				key.dptr = grpkey;
X
X				content = dbm_fetch (gr_dbm, key);
X				if (content.dptr == 0)
X					return 0;
X
X				memcpy (cp, content.dptr, content.dsize);
X				cp += content.dsize;
X			}
X			grent.gr_mem = members;
X			gr_unpack (grpbuf, cp - grpbuf, &grent);
X#ifdef	AUTOSHADOW
X			if (sgrp = getsgnam (grent.gr_name)) {
X				grent.gr_passwd = sgrp->sg_passwd;
X				grent.gr_mem = sgrp->sg_mem;
X			}
X#endif	/* AUTOSHADOW */
X			return &grent;
X		} else {
X			grent.gr_mem = members;
X			memcpy (grpbuf, content.dptr, content.dsize);
X			gr_unpack (grpbuf, content.dsize, &grent);
X#ifdef	AUTOSHADOW
X			if (sgrp = getsgnam (grent.gr_name)) {
X				grent.gr_passwd = sgrp->sg_passwd;
X				grent.gr_mem = sgrp->sg_mem;
X			}
X#endif	/* AUTOSHADOW */
X			return &grent;
X		}
X	}
X#endif	/* NDBM */
X	/*
X	 * Search for an entry which matches the GID.  Return the
X	 * entry when a match is found.
X	 */
X
X	while (grp = getgrent ())
X		if (grp->gr_gid == gid)
X			break;
X
X#ifdef	AUTOSHADOW
X	if (grp) {
X		if (sgrp = getsgnam (grent.gr_name)) {
X			grp->gr_passwd = sgrp->sg_passwd;
X			grp->gr_mem = sgrp->sg_mem;
X		}
X	}
X#endif	/* AUTOSHADOW */
X	return grp;
X}
X
Xstruct	group	*getgrnam (name)
Xchar	*name;
X{
X	struct	group	*grp;
X#ifdef NDBM
X	datum	key;
X	datum	content;
X	int	cnt;
X	int	i;
X	char	*cp;
X	char	grpkey[64];
X#endif	/* NDBM */
X#ifdef	AUTOSHADOW
X	struct	sgrp	*sgrp;
X#endif	/* AUTOSHADOW */
X
X	if (setgrent ())
X		return 0;
X
X#ifdef NDBM
X
X	/*
X	 * If the DBM file are now open, create a key for this GID 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 = dbm_fetch (gr_dbm, key);
X		if (content.dptr == 0)
X			return 0;
X
X		if (content.dsize == sizeof (int)) {
X			memcpy (&cnt, content.dptr, content.dsize);
X			for (cp = grpbuf, i = 0;i < cnt;i++) {
X				memcpy (grpkey, &i, sizeof i);
X				strcpy (grpkey + sizeof i, name);
X
X				key.dsize = sizeof i + strlen (name);
X				key.dptr = grpkey;
X
X				content = dbm_fetch (gr_dbm, key);
X				if (content.dptr == 0)
X					return 0;
X
X				memcpy (cp, content.dptr, content.dsize);
X				cp += content.dsize;
X			}
X			grent.gr_mem = members;
X			gr_unpack (grpbuf, cp - grpbuf, &grent);
X#ifdef	AUTOSHADOW
X			if (sgrp = getsgnam (grent.gr_name)) {
X				grent.gr_passwd = sgrp->sg_passwd;
X				grent.gr_mem = sgrp->sg_mem;
X			}
X#endif	/* AUTOSHADOW */
X			return &grent;
X		} else {
X			grent.gr_mem = members;
X			memcpy (grpbuf, content.dptr, content.dsize);
X			gr_unpack (grpbuf, content.dsize, &grent);
X#ifdef	AUTOSHADOW
X			if (sgrp = getsgnam (grent.gr_name)) {
X				grent.gr_passwd = sgrp->sg_passwd;
X				grent.gr_mem = sgrp->sg_mem;
X			}
X#endif	/* AUTOSHADOW */
X			return &grent;
X		}
X	}
X#endif	/* NDBM */
X	/*
X	 * Search for an entry which matches the name.  Return the
X	 * entry when a match is found.
X	 */
X
X	while (grp = getgrent ())
X		if (strcmp (grp->gr_name, name) == 0)
X			break;
X
X#ifdef	AUTOSHADOW
X	if (grp) {
X		if (sgrp = getsgnam (grent.gr_name)) {
X			grp->gr_passwd = sgrp->sg_passwd;
X			grp->gr_mem = sgrp->sg_mem;
X		}
X	}
X#endif	/* AUTOSHADOW */
X	return 0;
X}
X
X/*
X * setgrent - open the group file
X *
X * setgrent() opens the system group file, and the DBM group files
X * if they are present.  The system group file is rewound if it was
X * open already.
X */
X
Xint
Xsetgrent ()
X{
X#ifdef	NDBM
X	int	mode;
X#endif	/* NDBM */
X
X	if (! grpfp) {
X		if (! (grpfp = fopen (grpfile, "r")))
X			return -1;
X	} else {
X		if (fseek (grpfp, 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#ifdef NDBM
X	if (! dbmerror && ! dbmopened) {
X		char	dbmfiles[BUFSIZ];
X
X		strcpy (dbmfiles, grpfile);
X		strcat (dbmfiles, ".pag");
X		if (gr_dbm_mode == -1)
X			mode = O_RDONLY;
X		else
X			mode = (gr_dbm_mode == O_RDONLY ||
X				gr_dbm_mode == O_RDWR) ? gr_dbm_mode:O_RDONLY;
X
X		if (access (dbmfiles, 0) ||
X			(! (gr_dbm = dbm_open (grpfile, mode, 0))))
X			dbmerror = 1;
X		else
X			dbmopened = 1;
X	}
X#endif	/* NDBM */
X	return 0;
X}
SHAR_EOF
if test 9437 -ne "`wc -c < 'grent.c'`"
then
	echo shar: "error transmitting 'grent.c'" '(should have been 9437 characters)'
fi
fi
echo shar: "extracting 'motd.c'" '(750 characters)'
if test -f 'motd.c'
then
	echo shar: "will not over-write existing file 'motd.c'"
else
sed 's/^X//' << \SHAR_EOF > 'motd.c'
X/*
X * Copyright 1989, 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
X#include <stdio.h>
X#ifndef	BSD
X#include <string.h>
X#include <memory.h>
X#else
X#include <strings.h>
X#define	strchr	index
X#define	strrchr	rindex
X#endif
X#include "config.h"
X
X#ifndef	lint
Xstatic	char	_sccsid[] = "@(#)motd.c	2.2	19:23:58	7/29/90";
X#endif
X
Xextern	char	home[];
X#ifdef	HUSHLOGIN
Xextern	int	hushed;
X#endif
X
X#ifdef	MOTD
Xvoid	motd ()
X{
X	FILE	*fp;
X	register int	c;
X
X#ifdef	HUSHLOGIN
X	if (hushed)
X		return;
X#endif
X	if ((fp = fopen ("/etc/motd", "r")) == (FILE *) 0)
X		return;
X
X	while ((c = getc (fp)) != EOF)
X		putchar (c);
X
X	fclose (fp);
X	fflush (stdout);
X}
X#endif
SHAR_EOF
if test 750 -ne "`wc -c < 'motd.c'`"
then
	echo shar: "error transmitting 'motd.c'" '(should have been 750 characters)'
fi
fi
echo shar: "extracting 'dialup.h'" '(1598 characters)'
if test -f 'dialup.h'
then
	echo shar: "will not over-write existing file 'dialup.h'"
else
sed 's/^X//' << \SHAR_EOF > 'dialup.h'
X/*
X * Copyright 1989, 1990, 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/*
X * Structure of the /etc/d_passwd file
X *
X *	The d_passwd file contains the names of login shells which require
X *	dialup passwords.  Each line contains the fully qualified path name
X *	for the shell, followed by an optional password.  Each field is
X *	separated by a ':'.
X *
X * Structure of the /etc/dialups file
X *
X *	The dialups file contains the names of ports which may be dialup
X *	lines.  Each line consists of the last component of the path
X *	name.  The leading "/dev/" string is removed.
X *
X *	@(#)dialup.h	3.1	19:44:22	12/10/90
X */
X
X#ifndef	_DIALUP_H
X#define	_DIALUP_H
X
X#include <stdio.h>
X
Xstruct	dialup {
X	char	*du_shell;
X	char	*du_passwd;
X};
X
X#ifdef	__STDC__
Xextern	void	setduent ();
Xextern	void	endduent ();
Xextern	struct	dialup	*fgetduent ();
Xextern	struct	dialup	*getduent ();
Xextern	struct	dialup	*getdushell ();
Xextern	int	putduent ();
Xextern	int	isadialup ();
X#else
Xextern	void	setduent (void);
Xextern	void	endduent (void);
Xextern	struct	dialup	*fgetduent (FILE *);
Xextern	struct	dialup	*getduent (void);
Xextern	struct	dialup	*getdushell (char *);
Xextern	int	putduent (struct dialup *, FILE *);
Xextern	int	isadialup (char *);
X#endif
X
X#define	DIALPWD	"/etc/d_passwd"
X#define	DIALUPS	"/etc/dialups"
X
X#endif
SHAR_EOF
if test 1598 -ne "`wc -c < 'dialup.h'`"
then
	echo shar: "error transmitting 'dialup.h'" '(should have been 1598 characters)'
fi
fi
echo shar: "extracting 'fields.c'" '(1230 characters)'
if test -f 'fields.c'
then
	echo shar: "will not over-write existing file 'fields.c'"
else
sed 's/^X//' << \SHAR_EOF > 'fields.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
X#include <ctype.h>
X#include <string.h>
X#include <stdio.h>
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)fields.c	3.2	08:26:23	11/26/90";
X#endif
X
Xextern	char	*Progname;
X
X/*
X * valid_field - insure that a field contains all legal characters
X *
X * The supplied field is scanned for non-printing and other illegal
X * characters.  If any illegal characters are found, valid_field
X * returns -1.  Zero is returned for success.
X */
X
Xint
Xvalid_field (field, illegal)
Xchar	*field;
Xchar	*illegal;
X{
X	char	*cp;
X
X	for (cp = field;*cp && isprint (*cp) && ! strchr (illegal, *cp);cp++)
X		;
X
X	if (*cp)
X		return -1;
X	else
X		return 0;
X}
X
X/*
X * change_field - change a single field if a new value is given.
X *
X * prompt the user with the name of the field being changed and the
X * current value.
X */
X
Xvoid
Xchange_field (buf, prompt)
Xchar	*buf;
Xchar	*prompt;
X{
X	char	new[BUFSIZ];
X	char	*cp;
X
X	printf ("\t%s [%s]: ", prompt, buf);
X	if (fgets (new, BUFSIZ, stdin) != new)
X		return;
X
X	if (cp = strchr (new, '\n'))
X		*cp = '\0';
X	else
X		return;
X
X	if (new[0])
X		strcpy (buf, new);
X}
SHAR_EOF
if test 1230 -ne "`wc -c < 'fields.c'`"
then
	echo shar: "error transmitting 'fields.c'" '(should have been 1230 characters)'
fi
fi
echo shar: "extracting 'gsdbm.c'" '(1823 characters)'
if test -f 'gsdbm.c'
then
	echo shar: "will not over-write existing file 'gsdbm.c'"
else
sed 's/^X//' << \SHAR_EOF > 'gsdbm.c'
X/*
X * Copyright 1990, 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#ifndef	lint
Xstatic	char	sccsid[] = "@(#)gsdbm.c	3.3	11:25:29	12/19/90";
X#endif
X
X#include <string.h>
X#include <stdio.h>
X#include "shadow.h"
X#include "config.h"
X
X#ifdef	NDBM
X#include <ndbm.h>
XDBM	*sgr_dbm;
X
X#define	GRP_FRAG	256
X
X/*
X * sgr_dbm_update
X *
X * Updates the DBM password files, if they exist.
X */
X
Xint
Xsgr_dbm_update (sgr)
Xstruct	sgrp	*sgr;
X{
X	datum	key;
X	datum	content;
X	char	data[BUFSIZ*8];
X	char	sgrpkey[60];
X	char	*cp;
X	int	len;
X	int	i;
X	int	cnt;
X	static	int	once;
X
X	if (! once) {
X		if (! sgr_dbm)
X			setsgent ();
X
X		once++;
X	}
X	if (! sgr_dbm)
X		return 0;
X
X	len = sgr_pack (sgr, data);
X
X	if (len <= GRP_FRAG) {
X		content.dsize = len;
X		content.dptr = data;
X
X		key.dsize = strlen (sgr->sg_name);
X		key.dptr = sgr->sg_name;
X		if (dbm_store (sgr_dbm, key, content, DBM_REPLACE))
X			return 0;
X	} else {
X		content.dsize = sizeof cnt;
X		content.dptr = (char *) &cnt;
X		cnt = (len + (GRP_FRAG-1)) / GRP_FRAG;
X
X		key.dsize = strlen (sgr->sg_name);
X		key.dptr = sgr->sg_name;
X		if (dbm_store (sgr_dbm, key, content, DBM_REPLACE))
X			return 0;
X
X		for (cp = data, i = 0;i < cnt;i++) {
X			content.dsize = len > GRP_FRAG ? GRP_FRAG:len;
X			len -= content.dsize;
X			content.dptr = cp;
X			cp += content.dsize;
X
X			key.dsize = sizeof i + strlen (sgr->sg_name);
X			key.dptr = sgrpkey;
X			memcpy (sgrpkey, &i, sizeof i);
X			strcpy (sgrpkey + sizeof i, sgr->sg_name);
X			if (dbm_store (sgr_dbm, key, content, DBM_REPLACE))
X				return 0;
X		}
X	}
X	return 1;
X}
X#endif
SHAR_EOF
if test 1823 -ne "`wc -c < 'gsdbm.c'`"
then
	echo shar: "error transmitting 'gsdbm.c'" '(should have been 1823 characters)'
fi
fi
exit 0
#	End of shell archive
-- 
John F. Haugh II        | Distribution to  | UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 255-8251 | GEnie PROHIBITED :-) |  Domain: jfh at rpp386.cactus.org
"If liberals interpreted the 2nd Amendment the same way they interpret the
 rest of the Constitution, gun ownership would be mandatory."



More information about the Alt.sources mailing list