v08i046: Account creation/manipulation program, Part06/08

sources-request at mirror.UUCP sources-request at mirror.UUCP
Sat Feb 7 07:18:08 AEST 1987


Submitted by: Kyle Jones <xanth!kyle>
Mod.sources: Volume 8, Issue 46
Archive-name: mcp/Part06

#! /bin/sh
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
# If all goes well, you will see the message "End of archive 6 (of 8)."
# Contents:  src/gpa.c src/init.c src/job.c src/lastlog.c src/list.c
#   src/lists.c src/macros.h src/mem.c src/mem.h MANIFEST
# Wrapped by rs at mirror on Fri Feb  6 15:56:07 1987
PATH=/bin:/usr/bin:/usr/ucb; export PATH
echo shar: extracting "'src/gpa.c'" '(2500 characters)'
if test -f 'src/gpa.c' ; then 
  echo shar: will not over-write existing file "'src/gpa.c'"
else
sed 's/^X//' >src/gpa.c <<'@//E*O*F src/gpa.c//'
X/***************************************************************************\
X* 									    *
X* 	gpa.c								    *
X* 									    *
X* These are the support routines for the global_pointer_array that all	    *
X* routines that get input from the tty use, excluding main().		    *
X* 									    *
X* Routines needing an argv like array to store pointers call get_gpa()	    *
X* which returns a pointer to chunk of the global_pointer_array of the	    *
X* requested size.  Such a central array is needed to insure that all	    *
X* allocations via savestr() in get_line() are freed by a call to	    *
X* free_gpa().  This is insured even from interrupts by always calling	    *
X* free_gpa() in main() before getting the next command line.		    *
X* 									    *
X* clear_gpa() is used by routines that already have made a call to	    *
X* get_gpa() and want to reuse the space provided, but need to be sure that  *
X* any leftover pointers freed before they are overwritten.		    *
X* 									    *
X* ----------								    *
X* 									    *
X* get_gpa()	get a chunk of the global_pointer_array			    *
X* 									    *
X* clear_gpa()	free the pointers stored in a certian part		    *
X* 		of the array for reuse.					    *
X* 									    *
X* free_gpa()	free all pointers in the global_pointer_array		    *
X* 		and reset the array index to zero.			    *
X* 									    *
X* pop_gpa()	used to free last allocated part of the			    *
X* 		global_pointer_array.  Designed for use by routines	    *
X* 		in yesno.c.  No other routines should need call this.	    *
X* 									    *
X\***************************************************************************/
X
X#include "sysdep.h"
X#include "mem.h"
X#include "gpa.h"
X
Xstatic	addr global_pointer_array[G_P_A__SIZE];
Xstatic	int gpaindex;
X
Xaddr *
Xget_gpa(n)
Xint n;
X
X{
X	gpaindex += n;
X	return &global_pointer_array[gpaindex-n];
X}
X
Xfree_gpa()
X
X{
X	int i;
X
X	critical();
X	for (i=0; i<G_P_A__SIZE; i++)
X		if (global_pointer_array[i]) {
X			FREEMEM((char *)global_pointer_array[i]);
X			global_pointer_array[i] = NIL;
X		}
X	gpaindex = 0;
X	non_critical();
X	return;
X}
X
Xint clear_gpa(p, n)
Xaddr *p;
Xint n;
X
X{
X	register int i;
X
X	for (i=0; i<n; i++)
X		if (p[i]) {
X			/*
X			 * Can't let user interrupt between the FREEMEM
X			 * and zeroing the pointer.
X			 */
X			critical();
X			FREEMEM((char *)p[i]);
X			p[i] = NIL;
X			non_critical();
X		}
X	return 1;	/* used as do-while constant */
X}
X
Xpop_gpa(n)
Xint n;
X
X{
X	(void) clear_gpa(&global_pointer_array[gpaindex-n], n);
X	gpaindex -= n;
X	return;
X}
@//E*O*F src/gpa.c//
if test 2500 -ne "`wc -c <'src/gpa.c'`"; then
    echo shar: error transmitting "'src/gpa.c'" '(should have been 2500 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/init.c'" '(16005 characters)'
if test -f 'src/init.c' ; then 
  echo shar: will not over-write existing file "'src/init.c'"
else
sed 's/^X//' >src/init.c <<'@//E*O*F src/init.c//'
X#include <stdio.h>
X#include <sys/file.h>
X#include <sys/types.h>
X#include <pwd.h>
X#include <grp.h>
X#include <lastlog.h>
X#include <strings.h>
X#include <errno.h>
X#include "sysdep.h"
X#include "macros.h"
X#include "mem.h"
X#include "sort.h"
X#include "lists.h"
X#include "save.h"
X#include "sig.h"
X#include "class.h"
X#include "account.h"
X#include "command.h"
X#include "groupmap.h"
X#include "range.h"
X#ifdef SENDMAIL
X#include "alias.h"
X#endif
X
X#ifdef sun
X# ifdef DOFILES
X/*
X * Lint complains about all the unused functions declared in netdb.h
X * and mntent.h... but these functions are >>declared<< NOT
X * >>defined<< so lint should SHUT UP about this!!  Since it doesn't, 
X * we work around its ignorance.
X */
X#  ifndef lint
X#  include <mntent.h>
X#  include <netdb.h>
X#  else
Xstruct	servent {
X	char	*s_name;	/* official service name */
X	char	**s_aliases;	/* alias list */
X	int	s_port;		/* port # */
X	char	*s_proto;	/* protocol to use */
X};
Xstruct	servent *getservbyname();
X
X#  define MNTTAB	"/etc/fstab"
Xstruct	mntent{
X	char	*mnt_fsname;		/* name of mounted file system */
X	char	*mnt_dir;		/* file system path prefix */
X	char	*mnt_type;		/* MNTTYPE_* */
X	char	*mnt_opts;		/* MNTOPT* */
X	int	mnt_freq;		/* dump frequency, in days */
X	int	mnt_passno;		/* pass number on parallel fsck */
X};
Xstruct	mntent *getmntent();
XFILE 	*setmntent();
X#  endif lint
X# endif DOFILES
X#endif sun
X
Xstatic char *e1 = "password file has more lines than accounts file.";
Xstatic char *e2 = "accounts file has more lines than password file.";
Xstatic char *e3 = "line %d: login name not the same in accounts/passwd.";
X
Xextern	struct lastlog *getlluid(), *getllent();
Xextern	struct list YesNo, Titles, Suffixes, History;
Xextern	char *sprintf(), *getpass();
X
X#ifdef BSD4_3
Xuid_t	geteuid(), getuid();
Xchar	*getwd();
Xtime_t	time();
X#endif
X
X#ifdef SENDMAIL
Xextern	addalias(), addtoalias(), bindclass(), bindgroup(), bindsig();
Xextern	desalias();
Xextern	rmalias(), rmfromalias(), ubindclass(), ubindgroup(), ubindsig();
Xextern	updalias();
X#endif
X#ifdef HELPDIR
Xextern	descommand(), whatis();
X#endif
Xextern	addclass(), addgroup(), addrange(), addsig();
Xextern	addtoclass(), addtogroup();
Xextern	addtosig(), adduser(), addvig();
Xextern	ckpchanges();
Xextern	deschanges(), desclass();
Xextern	descryos(), desdeadbeats(), desgroup(), desinactives(), desrange();
Xextern	dessig(), desuser(), disableuser(), exitmcp();
Xextern	freezedeadbeats(), freezeinactives(), freezeuser();
Xextern	listgeneric(), listcryos();
Xextern	listdeadbeats(), listinactives();
Xextern	loadfile(), pausemcp(), rmclass();
Xextern	rmcryos(), rmfromclass(), rmfromgroup(), rmfromsig();
Xextern	rmgroup();
Xextern	rmrange(), rmsig(), rmuser(), rmvig(), savechanges(), saveandexit();
Xextern	shellescape();
Xextern	updclass(), updgroup(), updrange(), updsig(), upduser();
X
Xstruct command Ctable[] = {
X#ifdef SENDMAIL
X	{ "add-alias",		addalias,		1 },
X#endif
X	{ "add-class",		addclass,		1 },
X	{ "add-group",		addgroup,		1 },
X	{ "add-range",		addrange,		1 },
X	{ "add-sig",		addsig,			1 },
X#ifdef SENDMAIL
X	{ "add-to-alias",	addtoalias,		1 },
X#endif
X	{ "add-to-class",	addtoclass,		1 },
X	{ "add-to-group",	addtogroup,		1 },
X	{ "add-to-sig",		addtosig,		1 },
X	{ "add-user",		adduser,		1 },
X	{ "add-vig",		addvig,			1 },
X#ifdef SENDMAIL
X	{ "bind-group",		bindgroup,		1 },
X	{ "bind-class",		bindclass,		1 },
X	{ "bind-sig",		bindsig,		1 },
X#endif
X	{ "checkpoint-changes",	ckpchanges,		1 },
X#ifdef SENDMAIL
X	{ "describe-alias",	desalias,		0 },
X#endif
X	{ "describe-class",	desclass,		0 },
X	{ "describe-changes",	deschanges,		1 },
X#ifdef HELPDIR
X	{ "describe-command",	descommand,		0 },
X#endif
X	{ "describe-cryos",	descryos,		0 },
X	{ "describe-deadbeats",	desdeadbeats,		0 },
X	{ "describe-group",	desgroup,		0 },
X	{ "describe-inactives",	desinactives,		0 },
X	{ "describe-range",	desrange,		0 },
X	{ "describe-sig",	dessig,			0 },
X	{ "describe-user",	desuser,		0 },
X	{ "disable-user",	disableuser,		1 },
X	{ "exit-mcp",		exitmcp,		0 },
X	{ "freeze-deadbeats",	freezedeadbeats,	1 },
X	{ "freeze-inactives",	freezeinactives,	1 },
X	{ "freeze-user",	freezeuser,		1 },
X#ifdef SENDMAIL
X	{ "list-aliases",	listgeneric,		0 },
X#endif
X	{ "list-classes",	listgeneric,		0 },
X	{ "list-commands",	listgeneric,		0 },
X	{ "list-cryos",		listcryos,		0 },
X	{ "list-deadbeats",	listdeadbeats,		0 },
X	{ "list-groups",	listgeneric,		0 },
X	{ "list-inactives",	listinactives,		0 },
X	{ "list-ranges",	listgeneric,		0 },
X	{ "list-sigs",		listgeneric,		0 },
X	{ "list-users",		listgeneric,		0 },
X	{ "list-vigs",		listgeneric,		0 },
X	{ "load-file",		loadfile,		1 },
X	{ "pause-mcp",		pausemcp,		0 },
X#ifdef SENDMAIL
X	{ "remove-alias",	rmalias,		1 },
X#endif
X	{ "remove-class",	rmclass,		1 },
X	{ "remove-cryos",	rmcryos,		1 },
X#ifdef SENDMAIL
X	{ "remove-from-alias",	rmfromalias,		1 },
X#endif
X	{ "remove-from-class",	rmfromclass,		1 },
X	{ "remove-from-group",	rmfromgroup,		1 },
X	{ "remove-from-sig",	rmfromsig,		1 },
X	{ "remove-group",	rmgroup,		1 },
X	{ "remove-range",	rmrange,		1 },
X	{ "remove-sig",		rmsig,			1 },
X	{ "remove-user",	rmuser,			1 },
X	{ "remove-vig",		rmvig,			1 },
X	{ "save-and-exit",	saveandexit,		1 },
X	{ "save-changes",	savechanges,		1 },
X	{ "shell-escape",	shellescape,		0 },
X#ifdef SENDMAIL
X	{ "unbind-group",	ubindgroup,		1 },
X	{ "unbind-class",	ubindclass,		1 },
X	{ "unbind-sig",		ubindsig,		1 },
X	{ "update-alias",	updalias,		1 },
X#endif
X	{ "update-class",	updclass,		1 },
X	{ "update-group",	updgroup,		1 },
X	{ "update-range",	updrange,		1 },
X	{ "update-sig",		updsig,			1 },
X	{ "update-user",	upduser,		1 },
X#ifdef HELPDIR
X	{ "what-is",		whatis,			0 },
X#endif
X	{ (char *) 0,		(int (*)())0,		0 }
X};
X
X#ifdef HELPDIR
Xstatic	char *TermTable[] = {
X# ifdef SENDMAIL
X	"alias",
X# endif
X	"class",
X	"cryo",
X	"deadbeat",
X	"gid",
X	"inactive",
X	"range",
X	"sig",
X	"uid",
X	"vig",
X	(char *)0
X};
X#endif
X
Xstruct	list TempLists;			/* list of lists to freed */
X#ifdef SENDMAIL
Xstruct	list Aliases;			/* alias name completion list */
Xstruct	list AliasList;			/* list of alias structures */
X#endif
Xstruct	list AllCommands;		/* complete list of mcp commands */
Xstruct	list Commands;			/* commands this user is allowed */
Xstruct	list Users;			/* user name completion list */
Xstruct	list AccountList;		/* list of account structures */
Xstruct	list Classes;			/* class name completion list */
Xstruct	list ClassList;			/* list of class structures */
Xstruct	list Groups;			/* group name completion list */
Xstruct	list GroupMapList;		/* list of groupmap structures */
Xstruct	list Ranges;			/* range name completion list */
Xstruct	list RangeList;			/* list of range structures */
Xstruct	list Sigs;			/* sig name completion list */
Xstruct	list SigList;			/* list of sig structures */
Xstruct	list Jobs;			/* list of job structures */
X#ifdef HELPDIR
Xstruct	list Terms;			/* list of terms mcp can define */
X#endif
Xstruct	list Shells;			/* list of shells (from SHELLFILE) */
Xstruct	list Vigs;			/* vig completion list */
Xstruct	list Null_List;			/* empty list */
X
Xint	ModBits;			/* flags denoting modified files */
Xint	DevTty;				/* descriptor for diagnostic output
X					   and prompts. DevTty = 2 for non-
X					   interactive runs. */
Xtime_t	PWLockTime;			/* last modify time for /etc/passwd */
Xint	root;				/* is this the super-user? */
Xint	kids;				/* current # of child processes */
Xint	NCommands;			/* # of commands user can execute */
X
Xaddr	DEF_SHELL;			/* default shell */
Xchar	Working_Directory[LONG_BUF];	/* current working driectory */
X#ifdef sun
Xint	IsRemote;			/* must we use remote commands */
Xchar	HostName[MEDIUM_BUF];		/* current hostname */
X# ifdef DOFILES
Xchar	FileServer[MEDIUM_BUF];		/* hostname of file server */
Xchar	MountDirectory[MEDIUM_BUF];	/* remote mount point */
Xchar	RemotePassword[SHORT_BUF];	/* root password of fileserver */
Xu_short	ExecTcpPort;			/* port for exec/tcp service */
X# endif
X#endif
X
X
Xinit_lists(interactive)
Xint interactive;
X
X{
X	FILE *fp;
X	flexaddr p;
X#ifdef SENDMAIL
X	struct alias al, *al2;
X	struct groupmap *gm2;
X#endif
X	struct account ac, *ac2;
X	struct passwd *pw;
X	struct group *gr;
X	struct groupmap gm;
X	struct sig sg, *sg2;
X	struct class cs, *cs2;
X	struct range rg, *rg2;
X	struct lastlog *ll;
X	char buf[LONG_BUF], errmsg[LONG_BUF], sh[MEDIUM_BUF], *cp;
X	int indx, lineno = 0;
X
X	if (interactive) msg("Loading password and accounts...");
X	(void) setpwent();
X	(void) setacent();
X	(void) setllent();
X	while ((pw = getpwent()) != (struct passwd *)0) {
X		ac2 = getacent();
X		if (!ac2)
X			fatal(e1);
X		lineno++;
X		if (!eq((char *)ac2->ac_name, pw->pw_name)) {
X			(void) sprintf(errmsg, e3, lineno);
X			fatal(errmsg);
X		}
X		ac.ac_uid = pw->pw_uid;
X		ac.ac_gid = pw->pw_gid;
X		savestr((char **)&ac.ac_name, pw->pw_name);
X		savestr((char **)&ac.ac_gecos, pw->pw_gecos);
X		savestr((char **)&ac.ac_passwd, pw->pw_passwd);
X		savestr((char **)&ac.ac_dir, pw->pw_dir);
X		savestr((char **)&ac.ac_shell, pw->pw_shell);
X		savestr((char **)&ac.ac_realname, (char *)ac2->ac_realname);
X		savestr((char **)&ac.ac_id, (char *)ac2->ac_id);
X		duplist(&ac.ac_groups, &ac2->ac_groups);
X		duplist(&ac.ac_classes, &ac2->ac_classes);
X		duplist(&ac.ac_sigs, &ac2->ac_sigs);
X#ifdef SENDMAIL
X		duplist(&ac.ac_aliases, &ac2->ac_aliases);
X#endif
X		ll = getlluid(ac.ac_uid);
X		bcopy(&ac.ac_ll, ll, sizeof (struct lastlog));
X		genlistadd(&AccountList, (addr)&ac, sizeof (struct account));
X		strlistadd(&Users, pw->pw_name);
X	}
X	(void) endpwent();
X	endllent();
X	if (getacent()) fatal(e2);
X	(void) endacent();
X
X	if (interactive) msg("Loading groups...");
X	zerolist(&gm.gm_aliases);
X	(void) setgrent();
X	while ((gr = getgrent()) != (struct group *)0) {
X		zerolist(&gm.gm_mem);
X#ifdef SENDMAIL
X 		zerolist(&gm.gm_aliases);
X#endif
X		gm.gm_gid = gr->gr_gid;
X		savestr(&gm.gm_name, gr->gr_name);
X		savestr(&gm.gm_passwd, gr->gr_passwd);
X		for (indx=0; gr->gr_mem[indx]; indx++)
X			strlistadd(&gm.gm_mem, gr->gr_mem[indx]);
X		sort_list(&gm.gm_mem, pstrcmp);
X		genlistadd(&GroupMapList, (addr)&gm, sizeof(struct groupmap));
X		strlistadd(&Groups, gr->gr_name);
X	}
X	(void) endgrent();
X	if (interactive) msg("Loading classes...");
X#ifdef SENDMAIL
X	zerolist(&cs.cs_aliases);
X#endif
X	setcsent();
X	while (cs2 = getcsent()) {
X		savestr(&cs.cs_name, cs2->cs_name);
X		savestr(&cs.cs_desc, cs2->cs_desc);
X		cs.cs_dsize = cs2->cs_dsize;
X		cs.cs_exptime = cs2->cs_exptime;
X		genlistadd(&ClassList, (addr)&cs, sizeof (struct class));
X		strlistadd(&Classes, cs.cs_name);
X	}
X	endcsent();
X	if (interactive) msg("Loading sigs...");
X#ifdef SENDMAIL
X	zerolist(&sg.sg_aliases);
X#endif
X	setsgent();
X	while (sg2 = getsgent()) {
X		savestr(&sg.sg_name, sg2->sg_name);
X		savestr(&sg.sg_desc, sg2->sg_desc);
X		sg.sg_dsize = sg2->sg_dsize;
X		sg.sg_exptime = sg2->sg_exptime;
X		genlistadd(&SigList, (addr)&sg, sizeof (struct sig));
X		strlistadd(&Sigs, sg.sg_name);
X	}
X	endsgent();
X	if (interactive) msg("Loading range table...");
X	setrgent();
X	while (rg2 = getrgent()) {
X		savestr(&rg.rg_name, rg2->rg_name);
X		rg.rg_mode = rg2->rg_mode;
X		rg.rg_from = rg2->rg_from;
X		rg.rg_to = rg2->rg_to;
X		genlistadd(&RangeList, (addr)&rg, sizeof (struct range));
X		strlistadd(&Ranges, rg.rg_name);
X	}
X	endrgent();
X
X	if (interactive) msg("Loading vigs...");
X	fp = fopen(VIGFILE, "r");
X	if (fp != NULL) {
X		while (fscanf(fp, "%s", buf) != EOF)
X			strlistadd(&Vigs, buf);
X		(void) fclose(fp);
X	}
X
X#ifdef SENDMAIL
X	/*
X	 * Must sort here so that get{cs,gm,sg}nam() calls will work.
X	 */
X	if (interactive) msg("Loading and binding sendmail aliases...");
X	sort_list(&Groups, pstrcmp);
X	sort_list(&ClassList, classcmp);
X	sort_list(&SigList, sigcmp);
X	setalent();
X	while (al2 = getalent()) {
X		savestr(&al.al_name, al2->al_name);
X		duplist(&al.al_addresses, &al2->al_addresses);
X		duplist(&al.al_groups, &al2->al_groups);
X		duplist(&al.al_classes, &al2->al_classes);
X		duplist(&al.al_sigs, &al2->al_sigs);
X		genlistadd(&AliasList, (addr)&al, sizeof (struct alias));
X		strlistadd(&Aliases, al.al_name);
X		for (indx=0; indx < al.al_groups.l_count; indx++) {
X			cp = (char *)al.al_groups.l_list[indx];
X			gm2 = getgmnam(cp);
X			if (!gm2)
X				continue;
X			strlistadd(&gm2->gm_aliases, al.al_name);
X			sort_list(&gm2->gm_aliases, pstrcmp);
X		}
X		for (indx=0; indx < al.al_classes.l_count; indx++) {
X			cp = (char *)al.al_classes.l_list[indx];
X			cs2 = getcsnam(cp);
X			if (!cs2)
X				continue;
X			strlistadd(&cs2->cs_aliases, al.al_name);
X			sort_list(&cs2->cs_aliases, pstrcmp);
X		}
X		for (indx=0; indx < al.al_sigs.l_count; indx++) {
X			cp = (char *)al.al_sigs.l_list[indx];
X			sg2 = getsgnam(cp);
X			if (!sg2)
X				continue;
X			strlistadd(&sg2->sg_aliases, al.al_name);
X			sort_list(&sg2->sg_aliases, pstrcmp);
X		}
X	}
X	endalent();
X#endif
X	/*
X	 * If this is not an interactive session there is no need
X	 * to initialize the lists that are only used when mcp
X	 * is running interactively.
X	 */
X	if (!interactive) goto sort_em;
X
X	msg("Commands...");
X	for (indx=0; Ctable[indx].c_name; indx++) {
X		if (root || !Ctable[indx].c_su)
X			strlistadd(&Commands, Ctable[indx].c_name);
X		strlistadd(&AllCommands, Ctable[indx].c_name);
X	}
X	NCommands = indx;
X	qsort((char *)Ctable, NCommands, sizeof (struct command), commcmp);
X
X#ifdef HELPDIR
X	msg("Building term table...");
X	for (indx=0; TermTable[indx]; indx++)
X		strlistadd(&Terms, TermTable[indx]);
X#endif
X	msg("Loading shell table...");
X	fp = fopen(SHELLFILE, "r");
X	if (fp != NULL) {
X		while (fgets(buf, LONG_BUF, fp) != NULL) {
X			cp = index(buf, '#');
X			if (cp) *cp = '\0';
X			if (sscanf(buf, "%s", sh) != 1)
X				continue;
X			strlistadd(&Shells, sh);
X		}
X		(void) fclose(fp);
X	}
X	p.p_cp = (Shells.l_count ? (char *) Shells.l_list[0] : "/bin/sh");
X	DEF_SHELL = p.p_ap;
X
Xsort_em:
X	if (interactive) msg("Sorting lists...");
X	sort_list(&AccountList, acctcmp);
X	sort_list(&GroupMapList, gmapcmp);
X	sort_list(&Users, pstrcmp);
X	sort_list(&Classes, pstrcmp);
X	sort_list(&Sigs, pstrcmp);
X	sort_list(&Ranges, pstrcmp);
X	sort_list(&RangeList, rangecmp);
X	sort_list(&Vigs, pstrcmp);
X#ifdef SENDMAIL
X	sort_list(&AliasList, aliascmp);
X	sort_list(&Aliases, pstrcmp);
X#else
X	sort_list(&Groups, pstrcmp);
X	sort_list(&ClassList, classcmp);
X	sort_list(&SigList, sigcmp);
X#endif
X	if (interactive) {
X		sort_list(&Titles, pstrcmp);
X		sort_list(&Suffixes, pstrcmp);
X		sort_list(&YesNo, pstrcmp);
X		sort_list(&Shells, pstrcmp);
X		sort_list(&Commands, pstrcmp);
X		sort_list(&AllCommands, pstrcmp);
X#ifdef HELPDIR
X		sort_list(&Terms, pstrcmp);
X#endif
X		msg("and...");
X		zerolist(&History);
X		zerolist(&TempLists);
X		msg("");
X	}
X	return;
X}
X
Xinit_tty(interactive)
Xint interactive;
X
X{
X	extern int errno;
X	long lseek();
X
X	if (!interactive) {
X		DevTty = 2;
X		return;
X	}
X	if ((DevTty = open("/dev/tty", O_RDWR)) < 0) {
X		perror("/dev/tty");
X		goodbye(1);
X	}
X	if (lseek(0, 0L, L_INCR) == -1) {
X	    if (errno == ESPIPE)
X		err("mcp reading from a pipe...");
X	}
X	else if (!isatty(0))
X	    err("mcp reading from a file...");
X	return;
X}
X
Xinit_identities()
X
X{
X#ifdef sun
X# ifdef DOFILES
X	FILE *mnf;
X	struct mntent *mn;
X	struct servent *sv;
X	char *cp, prompt[MEDIUM_BUF];
X# endif
X#endif
X	root = !(getuid() && geteuid());
X	if (!getwd(Working_Directory))
X		fatal1("getwd() failed!?: %s", Working_Directory);
X	srandom(getpid() + getppid() + time((time_t *)0));
X#ifdef sun
X	if (gethostname(HostName, MEDIUM_BUF) == -1) {
X		perr("gethostname");
X		fatal("mcp: Sorry, but I must have a hostname.");
X	}
X# ifdef DOFILES
X	if (!root) return;
X	mnf = setmntent(MNTTAB, "r");
X	if (mnf == NULL) {
X		fatal1("can't open %s", MNTTAB);
X		goodbye(1);
X	}
X	while (mn = getmntent(mnf))
X		if (eq(mn->mnt_dir, USERDIR))
X			break;
X	if (mn && eq(mn->mnt_type, "nfs")) {
X		cp = index(mn->mnt_fsname, ':');
X		*cp++ = '\0';
X		(void) strcpy(FileServer, mn->mnt_fsname);
X		(void) strcpy(MountDirectory, cp);
X		sv = getservbyname("exec", "tcp");
X		if (!sv)
X			fatal("mcp: can't find service exec/tcp");
X		ExecTcpPort = sv->s_port;
X	/* root is not trusted over the network */
X		(void) sprintf(prompt, "Root password on %s:", FileServer);
X		cp = getpass(prompt);
X		(void) strcpy(RemotePassword, cp);
X		if (DoRemote("/bin/true") == 0)
X			fatal("Sorry");
X		IsRemote = 1;
X	}
X	(void) endmntent(mnf);
X# endif
X#endif
X	return;
X}
@//E*O*F src/init.c//
if test 16005 -ne "`wc -c <'src/init.c'`"; then
    echo shar: error transmitting "'src/init.c'" '(should have been 16005 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/job.c'" '(8459 characters)'
if test -f 'src/job.c' ; then 
  echo shar: will not over-write existing file "'src/job.c'"
else
sed 's/^X//' >src/job.c <<'@//E*O*F src/job.c//'
X/****************************************************************************\
X* 									     *
X* 	job.c								     *
X* 									     *
X* add_job()	add a job to the job list for later execution.		     *
X* do_jobs()	do the jobs in the job list.				     *
X* rmmail()	remove a user's mail					     *
X* rmsmail()	remove a user's secretmail				     *
X* omni_chown()	change the ownership of all a user's files to another uid    *
X* 									     *
X* Also lastlog entries are updated here, although the actual routine that    *
X* writes the file is in lastlog.c .  Directories are made and moved around   *
X* here, but there are system calls that do these things.		     *
X* 									     *
X\****************************************************************************/
X
X#include <stdio.h>
X#include <strings.h>
X#include <sys/wait.h>
X#include <sys/types.h>
X#include <sys/time.h>
X#include <sys/resource.h
X#include <sys/dir.h>
X#include <lastlog.h>
X#include "sysdep.h"
X#include "mem.h"
X#include "lists.h"
X#include "job.h"
X
X#ifdef sun
X# ifdef DOFILES
Xextern	u_short ExecTcpPort;
Xextern	char FileServer[], MountDirectory[], RemotePassword[];
Xextern	int IsRemote;
Xextern	char HostName[];
X# endif
X#endif
Xextern	struct list Jobs;
Xchar	*re_comp(), *sprintf();
Xextern	int kids;
X
X/* ARGSUSED */
Xadd_job(todo, arg1, arg2, arg3)
Xint todo;
Xaddr arg1, arg2, arg3;
X
X{
X	struct job jb;
X
X	jb.jb_todo = todo;
X	switch (jb.jb_todo) {
X	case JB_LASTLOG:
X		jb.jb_uid = (int) *arg1;
X		jb.jb_addr = MEM(sizeof (struct lastlog));
X		bcopy(jb.jb_addr, arg2, sizeof (struct lastlog));
X		break;
X
X#ifdef DOFILES
X	case JB_MKDIR:
X		savestr(&jb.jb_name, (char *) arg1);
X		jb.jb_uid = (int) *arg2;
X		jb.jb_gid = (int) *arg3;
X		break;
X
X	case JB_MV:
X		savestr(&jb.jb_oldname, (char *) arg1);
X		savestr(&jb.jb_name, (char *) arg2);
X		break;
X	case JB_RMDIR:
X	case JB_RMMAIL:
X		savestr(&jb.jb_name, (char *) arg1);
X		break;
X
X	case JB_OMNICHOWN:
X		jb.jb_olduid = (int) *arg1; 
X		jb.jb_uid = (int) *arg2;
X		break;
X#endif
X
X	default:
X		return;
X	}
X	genlistadd(&Jobs, (addr) &jb, sizeof (struct job));
X	return;
X}
X
Xdo_jobs()
X
X{
X	struct job *jb;
X	struct lastlog ll;
X	int currjobs, success;
X	char errmsg[LONG_BUF];
X
X	currjobs = Jobs.l_count;
X	while (currjobs--) {
X		jb = (struct job *) listpop(&Jobs);
X		success = 0;
X		switch (jb->jb_todo) {
X		case JB_LASTLOG:
X			bcopy(&ll, jb->jb_addr, sizeof (struct lastlog));
X			addllent(&ll, jb->jb_uid);
X			FREEMEM((char *)jb->jb_addr);
X			success++;
X			break;
X
X#ifdef DOFILES
X		case JB_MKDIR:
X# ifdef sun
X			if (IsRemote) {
X				success = makedir(jb->jb_name, 0755,
X						jb->jb_uid, jb->jb_gid);
X				if (success) FREEMEM(jb->jb_name);
X				break;
X			}
X			else
X# endif
X			/*
X			 * Here we assume if the mkdir() fails the  directory
X			 * must already be there.
X			 */
X			if (mkdir(jb->jb_name, 0755) == 0) {
X				(void) chown(jb->jb_name,
X						jb->jb_uid, jb->jb_gid);
X			}
X			FREEMEM(jb->jb_name);
X			success++;
X			break;
X
X		case JB_MV:
X# ifdef sun
X			if (IsRemote) {
X				success=rrename(jb->jb_oldname, jb->jb_name);
X				if (success) {
X					FREEMEM(jb->jb_name);
X					FREEMEM(jb->jb_oldname);
X				}
X			}
X			else
X# endif
X			if (rename(jb->jb_oldname, jb->jb_name) == -1) {
X				perr("rename");
X				err2("rename %s -> %s failed.",
X					jb->jb_oldname,
X					jb->jb_name);
X				break;
X			}
X			success++;
X			FREEMEM(jb->jb_name);
X			FREEMEM(jb->jb_oldname);
X			break;
X
X		case JB_RMDIR:
X			success = purge(jb->jb_name);
X			if (!success) break;
X			FREEMEM(jb->jb_name);
X			break;
X
X		case JB_RMMAIL:
X			success = rmmail(jb->jb_name) && rmsmail(jb->jb_name);
X			if (!success) break;
X			FREEMEM(jb->jb_name);
X			break;
X
X		case JB_OMNICHOWN:
X			success = omni_chown(jb->jb_olduid, jb->jb_uid);
X			break;
X#endif
X		default:
X			(void) sprintf(errmsg,
X				"internal error: bad todo in job list (%d)",
X				jb->jb_todo);
X			err(errmsg);
X			success++;	/* to get it out of the list */
X			break;
X		}
X		if (success)
X			FREEMEM((char *)jb);
X		else
X			genlistadd(&Jobs, (addr)jb, sizeof (struct job));
X	}
X	return;
X}
X
X#ifdef DOFILES
Xchar	**environ;
X
Xint
Xpurge(path)
Xchar *path;
X
X{
X	char command[LONG_BUF];
X	addr *v;
X	int c, pid;
X#ifdef sun
X	int n;
X
X	n = strlen(USERDIR)-1;
X	if (IsRemote && strncmp(path, USERDIR, n) == 0 && path[n] == '/') {
X		(void) strcpy(command, RM);
X		(void) strcat(command, " -rf ");
X		(void) strcat(command, MountDirectory);
X		(void) strcat(command, &path[n]);
X		return (DoRemote(command) && !fileexists(path));
X	}
X#endif
X	(void) strcpy(command, RM);
X	(void) strcat(command, " -rf ");
X	(void) strcat(command, path);
X	c = cut(command);
X	v = mkargv(command, c);
X	pid = vfork();
X	if (pid == -1) {
X		err1("can't vfork to remove %s", path);
X		return 0;
X	}
X	if (pid == 0) {
X		execve((char *)v[0], (char **)v, environ);
X		perr((char *)v[0]);
X		_exit(1);
X	}
X	while (wait((union wait *)0) != pid)
X		kids--;
X	return !fileexists(path);
X}
X
Xint
Xrmmail(user)
Xchar *user;
X
X{
X	if (chdir(MAILSPOOL) == -1) {
X		perr(SMAILSPOOL);
X		return 0;
X	}
X	(void) unlink(user);
X	return 1;
X}
X
Xint
Xrmsmail(user)
Xchar *user;
X
X{
X	DIR *dirp;
X	char buf[MEDIUM_BUF];
X	struct direct *dp;
X
X	if (chdir(SMAILSPOOL) == -1) {
X		perr(SMAILSPOOL);
X		return 0;
X	}
X	dirp = opendir(".");
X	if (dirp == NULL) {
X		err1("can't open %s (read)", SMAILSPOOL);
X		return 0;
X	}
X	(void) sprintf(buf, "%s\\..*", user);
X	(void) re_comp(buf);
X	for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp))
X		if (re_exec(dp->d_name) == 1)
X			(void) unlink(dp->d_name);
X	closedir(dirp);
X	return 1;
X}
X
X#define OMNIFMT "%s -15 %s %s -user %d -exec %s %d {} ;"
X
X/*
X * When changing file ownerships on Sun's distributed filesystem, we
X * must be careful not to disturb files belonging to a user with the same
X * uid but on another machine!
X */
Xint
Xomni_chown(ouid, nuid)
Xint ouid, nuid;
X
X{
X	char command[LONG_BUF];
X# ifdef sun
X	char dirbuf[MEDIUM_BUF];
X
X	if (IsRemote) {
X(void)sprintf(command, OMNIFMT, NICE, FIND, MountDirectory, ouid, CHOWN,nuid);
X		(void) strcat(command, " &");
X		if (DoRemote(command) == 0) return 0;
X	}
X	else {
X		(void) sprintf(dirbuf, "%s/%s", USERDIR, HostName);
X(void) sprintf(command, OMNIFMT, NICE, FIND, dirbuf, ouid, CHOWN, nuid);
X		if (BackGround(command) == 0) return 0;
X	}
X(void) sprintf(command, OMNIFMT, NICE, FIND, SMAILSPOOL, ouid, CHOWN, nuid);
X	if (BackGround(command) == 0) return 0;
X(void) sprintf(command, OMNIFMT, NICE, FIND, MAILSPOOL, ouid, CHOWN, nuid);
X	if (BackGround(command) == 0) return 0;
X# else
X	(void) sprintf(command, OMNIFMT, NICE, FIND, "/", ouid, CHOWN, nuid);
X	if (BackGround(command) == 0) return 0;
X# endif
X	return 1;
X}
X
XBackGround(command)
Xchar *command;
X
X{
X	int c, pid;
X	addr *v;
X
X	c = cut(command);
X	v = mkargv(command, c);
X
X	pid = vfork();
X	if (pid == -1) {
X		perr("can't vfork");
X		return 0;
X	}
X	kids++;
X	if (pid == 0) {
X		(void) setpgrp(0, getpid());
X		execve((char *)*v, (char **)v, environ);
X		perr((char *)*v);
X		_exit(1);
X	}
X	(void) setpriority(PRIO_PROCESS, pid, 15);
X	return 1;
X}
X
X# ifdef sun
X
Xrrename(from, to)
Xchar *from, *to;
X
X{
X	int n;
X	char command[LONG_BUF];
X
X	n = strlen(USERDIR)-1;
X	if (strncmp(from, USERDIR, n) || from[n] != '/') {
X		err2("rrename: %s not in %s", from, USERDIR);
X		return 0;
X	}
X	if (strncmp(to, USERDIR, n) || from[n] != '/') {
X		err2("rrename: %s not in %s", from, USERDIR);
X		return 0;
X	}
X	(void) sprintf(command, "%s %s%s %s%s", MV, MountDirectory,
X			&from[n], MountDirectory, &to[n]);
X	return ((!DoRemote(command)) || fileexists(from) || !fileexists(to))
X		? 0 : 1;
X}
X
Xmakedir(path, mode, uid, gid)
Xchar *path;
Xint mode, uid, gid;
X
X{
X	int n;
X	char command[LONG_BUF];
X
X	n = strlen(USERDIR);
X	if (strncmp(path, USERDIR, n) || path[n] != '/') {
X		err2("makedir: %s not in %s", path, USERDIR);
X		return 0;
X	}
X(void)	sprintf(command, "%s %s%s", MKDIR, MountDirectory, &path[n]);
X	(void) DoRemote(command);
X(void)	sprintf(command, "%s %d %s%s", CHOWN, uid, MountDirectory, &path[n]);
X	(void) DoRemote(command);
X(void)	sprintf(command, "%s %d %s%s", CHGRP, gid, MountDirectory, &path[n]);
X	(void) DoRemote(command);
X(void)	sprintf(command, "%s %o %s%s", CHMOD, mode, MountDirectory, &path[n]);
X	(void) DoRemote(command);
X	return 1;
X}
X
Xstatic
XTweedle(d)
Xint d;
X
X{
X	char c;
X
X	(void) shutdown(d, 1);
X	while (read(d, &c, 1) == 1)
X		(void) write(1, &c, 1);
X	(void) fsync(1);
X	return;
X}
X
Xint
XDoRemote(command)
Xchar *command;
X
X{
X	char f[MEDIUM_BUF], *h[1];
X	int d;
X
X	(void) strcpy(f, FileServer);
X	*h = f;
X	d = rexec(h, ExecTcpPort, "root", RemotePassword, command, (int *)0);
X	if (d == -1) return 0;
X	Tweedle(d);
X	(void) close(d);
X	return 1;
X}
X
X# endif
X#endif
@//E*O*F src/job.c//
if test 8459 -ne "`wc -c <'src/job.c'`"; then
    echo shar: error transmitting "'src/job.c'" '(should have been 8459 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/lastlog.c'" '(1294 characters)'
if test -f 'src/lastlog.c' ; then 
  echo shar: will not over-write existing file "'src/lastlog.c'"
else
sed 's/^X//' >src/lastlog.c <<'@//E*O*F src/lastlog.c//'
X#include <sys/file.h>
X#include <stdio.h>
X#include <sys/types.h>
X#include <lastlog.h>
X#include "sysdep.h"
X#include "mem.h"
X#include "save.h"
X
Xstatic	struct lastlog zero;
Xstruct	lastlog ll;
Xlong	lseek();
X
Xint LL_FileDes = UNDEFINED;
X
Xsetllent()
X
X{
X	if (LL_FileDes == UNDEFINED) {
X		LL_FileDes = open(LASTLOG, O_RDONLY);
X		if (LL_FileDes < 0) {
X			perr(LASTLOG);
X			goodbye(1);
X		}
X	}
X	lseek(LL_FileDes, (long)0, L_SET)<0&&perr("setllent: lseek failed?!");
X	return;
X}
X
Xendllent()
X
X{
X	if (LL_FileDes == UNDEFINED)
X		return;
X	(void) close(LL_FileDes);
X	LL_FileDes = UNDEFINED;
X	return;
X}
X
Xstruct lastlog *
Xgetllent()
X
X{
X	if (LL_FileDes == UNDEFINED)
X		setllent();
X	if (read(LL_FileDes, (char *)&ll, sizeof ll) != sizeof ll)
X		return(&zero);
X	else
X		return(&ll);
X}
X
Xstruct lastlog *
Xgetlluid(uid)
Xint uid;
X
X{
X	if (LL_FileDes == UNDEFINED)
X		setllent();
X	lseek(LL_FileDes, (long)(uid * sizeof(struct lastlog)), L_SET)<0
X		&& perr("getlluid: lseek failed!?");
X	return(getllent());
X}
X
Xaddllent(lp, uid)
Xstruct lastlog *lp;
Xint uid;
X
X{
X	int fd;
X
X	fd = open(LASTLOG, O_WRONLY);
X	if (fd < 0) {
X		perr(LASTLOG);
X		return;
X	}
X	lseek(fd, (long)(uid * sizeof(struct lastlog)), L_SET)<0&&
X		panic("addllent: lseek failed!?");
X	(void) write(fd, (char *)lp, sizeof(struct lastlog));
X	(void) close(fd);
X	return;
X}
@//E*O*F src/lastlog.c//
if test 1294 -ne "`wc -c <'src/lastlog.c'`"; then
    echo shar: error transmitting "'src/lastlog.c'" '(should have been 1294 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/list.c'" '(3995 characters)'
if test -f 'src/list.c' ; then 
  echo shar: will not over-write existing file "'src/list.c'"
else
sed 's/^X//' >src/list.c <<'@//E*O*F src/list.c//'
X/****************************************************************************\
X* 									     *
X* 	list.c								     *
X* 									     *
X* Code for the list- commands.  listgeneric() just chooses and prints the    *
X* appropriate completion list.  The other routines handle special cases for  *
X* which there are no completion lists kept.				     *
X* 									     *
X\****************************************************************************/
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <lastlog.h>
X#include "sysdep.h"
X#include "macros.h"
X#include "mem.h"
X#include "lists.h"
X#include "account.h"
X#ifdef SENDMAIL
X#include "alias.h"
X#endif
X#include "groupmap.h"
X#include "job.h"
X
X#ifdef BSD4_3
Xtime_t	time();
X#endif
X
X#ifdef SENDMAIL
Xextern	struct list Aliases;
X#endif
Xextern	struct list Users, Groups, Vigs, Ranges, Classes, Sigs;
Xextern	struct list AccountList, AllCommands;
Xchar	*sprintf();
Xstruct 	list *picklist();
Xstatic	char *allv[2] = { ".*", 0 };
X
Xlistgeneric(c, v)
Xint c;
Xaddr *v;
X
X{
X	int count;
X	struct list *List;
X
X	List = picklist((char *)v[0]);
X	c--; v++;
X	if (c == 0) {
X	    (void) showlist(List, (addr *)allv);
X	    count = List->l_count;
X	}
X	else
X	    count = showlist(List, v);
X	if (count)
X	    (void) printf("%d listed\n", count);
X	return;
X}
X
Xlistcryos(c, v)
Xint c;
Xaddr *v;
X
X{
X	static struct list cryos;
X	struct account *ac;
X	int indx, count;
X
X	zerolist(&cryos);
X	tmplistadd(&cryos);
X	for (indx=0; indx < AccountList.l_count; indx++) {
X		ac = (struct account *) AccountList.l_list[indx];
X		if (eq((char *)ac->ac_shell, FREEZE_SH))
X			strlistadd(&cryos, (char *)ac->ac_name);
X	}
X	c--; v++;
X	if (c == 0) {
X		(void) showlist(&cryos, (addr *)allv);
X		count = cryos.l_count;
X	}
X	else
X		count = showlist(&cryos, v);
X	if (count)
X	    (void) printf("%d listed\n", count);
X	return;
X}
X
Xlistdeadbeats(c, v)
Xint c;
Xaddr *v;
X
X{
X	static struct list deadbeats;
X	struct account *ac;
X	struct groupmap *gm;
X	int indx, count;
X	char errmsg[LONG_BUF];
X
X	zerolist(&deadbeats);
X	tmplistadd(&deadbeats);
X	for (indx=0; indx < AccountList.l_count; indx++) {
X		ac = (struct account *) AccountList.l_list[indx];
X		if (ac->ac_classes.l_count)
X			continue;
X		if (ac->ac_sigs.l_count)
X			continue;
X		/*
X		 * Cryos are not deadbeats.
X		 */
X		if (eq(ac->ac_shell, FREEZE_SH))
X			continue;
X		gm = getgmgid(ac->ac_gid);
X		if (!gm) {
X			(void) sprintf(errmsg,
X					"no group for gid %d!",
X					ac->ac_gid);
X			err(errmsg);
X			return;
X		}
X		if (vigexists(gm->gm_name))
X			continue;
X		strlistadd(&deadbeats, (char *)ac->ac_name);
X	}
X	c--; v++;
X	if (c == 0) {
X		(void) showlist(&deadbeats, (addr *)allv);
X		count = deadbeats.l_count;
X	}
X	else
X		count = showlist(&deadbeats, v);
X	if (count)
X	    (void) printf("%d listed\n", count);
X	return;
X}
X
Xlistinactives(c, v)
Xint c;
Xaddr *v;
X
X{
X	static struct list inactives;
X	struct account *ac;
X	struct groupmap *gm;
X	int indx, count;
X	time_t now;
X	long toolong;
X	char errmsg[LONG_BUF];
X
X	if ( c < 2 ) {
X		err1("usage: %s <days> [expr ...]", (char *)v[0]);
X		return;
X	}
X	if (!validint((char *)v[1])) {
X		err2("%s: %s doesn't make sense as a number", (char *)v[0],
X			(char *)v[1]);
X		return;
X	}
X	toolong = atoi((char *)v[1]) * 86400;
X
X	zerolist(&inactives);
X	tmplistadd(&inactives);
X	now = time((time_t *)0);
X	for (indx=0; indx < AccountList.l_count; indx++) {
X		ac = (struct account *) AccountList.l_list[indx];
X		if ((long)(now - ac->ac_ll.ll_time) < toolong)
X			continue;
X		/*
X		 * Cryos are not inactive.
X		 */
X		if (eq(ac->ac_shell, FREEZE_SH))
X			continue;
X		/*
X		 * Vig members are not inactive.
X		 */
X		gm = getgmgid(ac->ac_gid);
X		if (!gm) {
X			(void) sprintf(errmsg,
X					"no group for gid %d!",
X					ac->ac_gid);
X			err(errmsg);
X			return;
X		}
X		if (vigexists(gm->gm_name))
X			continue;
X		strlistadd(&inactives, (char *)ac->ac_name);
X	}
X	c -= 2;
X	v += 2;
X	if (c == 0) {
X		(void) showlist(&inactives, (addr *)allv);
X		count = inactives.l_count;
X	}
X	else
X		count = showlist(&inactives, v);
X	if (count)
X	    (void) printf("%d listed\n", count);
X	return;
X}
@//E*O*F src/list.c//
if test 3995 -ne "`wc -c <'src/list.c'`"; then
    echo shar: error transmitting "'src/list.c'" '(should have been 3995 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/lists.c'" '(9337 characters)'
if test -f 'src/lists.c' ; then 
  echo shar: will not over-write existing file "'src/lists.c'"
else
sed 's/^X//' >src/lists.c <<'@//E*O*F src/lists.c//'
X/************************************************************************\
X* 									 *
X* 	lists.c								 *
X* 									 *
X* Routines to maintain, scan and manipulate the generic list structures	 *
X* that permeate the program.  Some of the most oft used routines:	 *
X* 									 *
X* strlistadd()	add to a list of strings				 *
X* genlistadd()	add an abitrary object to a list			 *
X* strlistdel()	delete a string from a list				 *
X* genlistdel()	delete an abitrary object from a list			 *
X* search_list()	search a list for a particular item			 *
X* tmplistadd()	add a list pointer to the queue of string lists		 *
X* 		that is freed just before mcp prompt for another	 *
X* 		command							 *
X* freelist()	free all memory associated with a list structure	 *
X* listpop()	pop the first pointer from a list			 *
X* orstrlist()	make the union of two string lists			 *
X* 									 *
X\************************************************************************/
X
X#include <stdio.h>
X#include <strings.h>
X#include <ctype.h>
X#include "sysdep.h"
X#include "macros.h"
X#include "mem.h"
X#include "gpa.h"
X#include "lists.h"
X#include "sort.h"
X
Xextern	struct list TempLists;
X
Xchar *
Xskipspace(s)
Xchar *s;
X
X{
X	while (*s && isspace(*s))
X		s++;
X	return(s);
X}
X
X/*
X *	Cuts a string of space separated words into a series of null separated
X *	words.  Spaces may be imbedded in words only when the word is surround
X *	ed by double quotes [""]. Returns the number of words in the string.
X */
Xint cut(line)
Xchar *line;
X
X{
X	int wc = 0;
X	register char *cp;
X
X	cp = line;
X	if (*line == '\0')
X		return(0);
X	while ( *line != '\0' ) {
X		if ( isspace(*line) ) {
X			*cp++ = '\0';
X			line++;
X			line = skipspace(line);
X		}
X		else {
X			wc++;
X			while ( *line ) {
X				if (*line == '"') {
X					*cp++ = *line++;
X					while (*line && *line != '"')
X						*cp++ = *line++;
X					if (*line == '\0')
X						break;
X				}
X				else if (isspace(*line))
X					break;
X				*cp++ = *line++;
X			}
X		}
X	}
X	return(wc);
X}
X
X/*
X *	Makes a vector of pointers to the null separated strings pointed
X *	to by line.  The number count is needed to keep the thing from 
X *	going on forever.  Note the arg vector is in a static area, and
X *	is overwritten by subsequent calls.
X */
Xaddr *
Xmkargv(line, n)
Xchar *line;
Xint n;
X
X{
X	static addr argv[G_P_A__SIZE];
X	int i;
X	flexaddr p;
X
X	i = 0;
X	p.p_cp = line;
X	while ( i < n && i < 128) {
X		argv[i] = p.p_ap;
X		p.p_cp += strlen(p.p_cp) + 1;
X		i++;
X	}
X	argv[i] = NIL;
X	return(argv);
X}
X
X/*
X * Globs the arguments of an argv-like vector into a single string.
X */
Xaddr
Xglob(v)
Xaddr *v;
X
X{
X	static addr_t gob[LONG_BUF];
X	flexaddr p;
X
X	p.p_ap = gob;
X	p.p_cp[0] = '\0';
X	while ( *v ) {
X		(void) strcat(p.p_cp, (char *)*v++);
X		(void) strcat(p.p_cp, " ");
X	}
X	p.p_cp[strlen(p.p_cp)-1] = '\0';	/* remove trailing blank */
X	return(gob);
X}
X
Xparse_line(line, cc, vv)
Xchar *line;
Xint *cc;
Xaddr **vv;
X
X{
X	*cc = cut(line);
X	*vv = mkargv(line, *cc);
X	return;
X}
X
Xfreeargv(v)
Xaddr *v;
X
X{
X	critical();
X	while (*v) {
X		FREEMEM((char *)*v);
X		*v++ = NIL;
X	}
X	non_critical();
X}
X
Xint
Xsearch_list(l, s, compfunc, found)
Xstruct list *l;
Xchar *s;
Xint (*compfunc)(), *found;
X
X{
X	int lo = 0, hi = l->l_count - 1, middle, compval;
X
X	*found = 0;
X	while (lo < hi) {
X		middle = (lo + hi) / 2;
X		if ((compval = (*compfunc)(s, l->l_list[middle])) == 0) {
X			*found = 1;
X			return middle;
X		}
X		else if (compval < 0) {
X			decr(middle);
X			hi = middle;
X		}
X		else
X			lo = middle + 1;
X	}
X	if (l->l_count && ((*compfunc)(s, l->l_list[lo])) == 0)
X		*found = 1;
X	return lo;
X}
X
Xfreelist(l)
Xstruct list *l;
X
X{
X	register int i;
X
X	critical();
X	for (i=0; i<l->l_count; i++)
X		FREEMEM((char *)l->l_list[i]);
X	if (l->l_spacefor > 0)
X		FREEMEM((char *)l->l_list);
X	l->l_count = l->l_spacefor = 0;
X	non_critical();
X	return;
X}
X
Xstrlistadd(l, s)
Xstruct list *l;
Xchar *s;
X
X{
X	critical();
X	if (l->l_spacefor == 0) {
X		l->l_list = (addr *) MEM(STARTSIZE * sizeof (addr));
X		l->l_spacefor = STARTSIZE;
X	}
X	else if (l->l_count == l->l_spacefor) {
X		l->l_list = (addr *) DELTAMEM((addr)l->l_list,
X					2 * l->l_spacefor * sizeof(addr));
X		l->l_spacefor *= 2;
X	}
X	savestr((char **)&l->l_list[l->l_count], s);
X	l->l_count++;
X	non_critical();
X	return;
X}
X
Xgenlistadd(l, p, n)
Xregister struct list *l;
Xregister addr p;
Xint n;
X
X{
X	critical();
X	if (l->l_spacefor == 0) {
X		l->l_list = (addr *) MEM(STARTSIZE * sizeof (addr));
X		l->l_spacefor = STARTSIZE;
X	}
X	else if (l->l_count == l->l_spacefor) {
X		l->l_list = (addr *) DELTAMEM((addr)l->l_list,
X					2 * l->l_spacefor * sizeof (addr));
X		l->l_spacefor *= 2;
X	}
X	l->l_list[l->l_count] = MEM(n);
X	bcopy(l->l_list[l->l_count], p, n);
X	l->l_count++;
X	non_critical();
X	return;
X}
X
Xlistadd(l, p)
Xstruct list *l;
Xaddr p;
X
X{
X	critical();
X	if (l->l_spacefor == 0) {
X		l->l_list = (addr *) MEM(STARTSIZE * sizeof (addr));
X		l->l_spacefor = STARTSIZE;
X	}
X	else if (l->l_count == l->l_spacefor) {
X		l->l_list = (addr *) DELTAMEM((addr)l->l_list,
X					2 * l->l_spacefor * sizeof (addr));
X		l->l_spacefor *= 2;
X	}
X	l->l_list[l->l_count] = p;
X	l->l_count++;
X	non_critical();
X	return;
X}
X
Xstrlistdel(l, s)
Xstruct list *l;
Xchar *s;
X
X{
X	register int i;
X	int found, indx, halfavail;
X
X	critical();
X	indx = search_list(l, s, strcmp, &found);
X	if (found) {
X		FREEMEM((char *)l->l_list[indx]);
X		for (i=indx; i<l->l_count-1; i++)
X			l->l_list[i] = l->l_list[i+1];
X		l->l_count--;
X		halfavail = l->l_spacefor / 2;
X		if (l->l_count < halfavail && l->l_spacefor > STARTSIZE) {
X			l->l_list = (addr *) DELTAMEM((addr)l->l_list,
X						halfavail * sizeof (addr));
X			l->l_spacefor = halfavail;
X		}
X	}
X	non_critical();
X	return;
X}
X
Xgenlistdel(l, p, compfunc)
Xstruct list *l;
Xaddr p;
Xint (*compfunc)();
X
X{
X	register int i;
X	int found, indx, halfavail;
X
X	critical();
X	indx = search_list(l, (char *)p, compfunc, &found);
X	if (found) {
X		FREEMEM((char *)l->l_list[indx]);
X		for (i=indx; i<l->l_count-1; i++)
X			l->l_list[i] = l->l_list[i+1];
X		l->l_count--;
X		halfavail = l->l_spacefor / 2;
X		if (l->l_count < halfavail && l->l_spacefor > STARTSIZE) {
X			l->l_list = (addr *) DELTAMEM((addr)l->l_list,
X						halfavail * sizeof (addr));
X			l->l_spacefor = halfavail;
X		}
X	}
X	non_critical();
X	return;
X}
X
Xint
Xstrlistchg(l, old, new)
Xstruct list *l;
Xchar *old, *new;
X
X{
X	int found, indx;
X
X	indx = search_list(l, old, strcmp, &found);
X	if (!found)
X	    return 0;
X	FREEMEM((char *)l->l_list[indx]);
X	savestr((char **)&l->l_list[indx], new);
X	sort_list(l, pstrcmp);
X	return 1;
X}
X
Xaddr
Xlistpop(l)
Xstruct list *l;
X
X{
X	register int i;
X	addr first;
X	int halfavail;
X
X	critical();
X	first = l->l_list[0];
X	for (i=0; i<l->l_count-1; i++)
X		l->l_list[i] = l->l_list[i+1];
X	l->l_count--;
X	halfavail = l->l_spacefor / 2;
X	if (l->l_count < halfavail && l->l_spacefor > STARTSIZE) {
X		l->l_list = (addr *) DELTAMEM((addr)l->l_list,
X						halfavail * sizeof (addr));
X		l->l_spacefor = halfavail;
X	}
X	non_critical();
X	return first;
X}
X
Xint
Xinstrlist(l, s)
Xstruct list *l;
Xchar *s;
X
X{
X	int found;
X
X	(void) search_list(l, s, strcmp, &found);
X	return found;
X}
X
Xzerolist(l)
Xstruct list *l;
X
X{
X	l->l_count = 0;
X	l->l_spacefor = 0;
X}
X
Xduplist(new, old)
Xstruct list *new, *old;
X
X{
X	critical();
X	new->l_count = old->l_count;
X	new->l_spacefor = old->l_spacefor;
X	new->l_list = old->l_list;
X	non_critical();
X	return;
X}
X
X/*
X**copylist(dest, src, objsize)
X**struct list *dest, *src;
X**int objsize;
X**
X**{
X**	register int i;
X**
X**	zerolist(dest);
X**	for (i=0; i<src->l_count; i++)
X**		genlistadd(dest, src->l_list[i], objsize);
X**	return;
X**}
X */
X
Xint
Xorstrlist(l, ll)
Xstruct list *l, *ll;
X
X{
X	register int indx;
X	int changed = 0;
X
X	for (indx=0; indx<ll->l_count; indx++) {
X		if (instrlist(l, (char *)ll->l_list[indx]))
X			continue;
X		changed++;
X		strlistadd(l, (char *)ll->l_list[indx]);
X		sort_list(l, pstrcmp);
X	}
X	return changed;
X}
X
Xtmplistadd(l)
Xstruct list *l;
X
X{
X	critical();
X	listadd(&TempLists, (addr)l);
X	non_critical();
X	return;
X}
X
Xfreetmplists()
X
X{
X	while (TempLists.l_count)
X		freelist((struct list *) listpop(&TempLists));
X	return;
X}
X
X#define COLUMNS		80
X#define SEPDIST		3
X
Xchar	*re_comp();
X
Xshowlist(l, regexv)
Xstruct list *l;
Xaddr *regexv;
X
X{
X	register int i, k;
X	int tabs, h, j, longest, n;
X	static struct list matches;
X	char *errmsg;
X	register char *cp;
X
X	if (l->l_count == 0)
X		return 0;
X	longest = 0;
X	zerolist(&matches);
X	tmplistadd(&matches);
X	for (h=0; regexv[h]; h++) {
X	    errmsg = re_comp((char *)regexv[h]);
X	    if (errmsg) {
X		err(errmsg);
X		continue;
X	    }
X	    for (i=0; i < l->l_count; i++) {
X		cp = (char *)l->l_list[i];
X		if (re_exec(cp) == 0)
X		    continue;
X		if (instrlist(&matches, cp))
X		    continue;
X		longest = max(longest, strlen(cp));
X		strlistadd(&matches, cp);
X	    }
X	}
X	n = matches.l_count;
X	if (n == 0)
X	    return n;
X        sort_list(&matches, pstrcmp);
X	tabs = n / ((COLUMNS-1) / (longest + SEPDIST));
X	tabs += ( n % ((COLUMNS-1) / (longest + SEPDIST)) ? 1 : 0 );
X	for (j = 1; j <= tabs; j++) {
X	    for (k = j - 1; k < n; k += tabs) {
X		(void) fputs((char *)matches.l_list[k], stdout);
X		space(longest - strlen((char *)matches.l_list[k])
X			+ SEPDIST);
X	    }
X	    puts("");
X	}
X	return n;
X}
X
Xlistlist(l)
Xstruct list *l;
X
X{
X	int indx;
X
X	for (indx=0; indx < l->l_count; indx++)
X		(void) printf("%s ", l->l_list[indx]);
X	puts("");
X}
X
Xlistout(l, fp)
Xstruct list *l;
XFILE *fp;
X
X{
X	int i;
X
X	for (i=0; i < l->l_count; i++) {
X		if (i > 0)
X			fputs(",", fp);
X		fputs((char *)l->l_list[i], fp);
X	}
X	return;
X}
@//E*O*F src/lists.c//
if test 9337 -ne "`wc -c <'src/lists.c'`"; then
    echo shar: error transmitting "'src/lists.c'" '(should have been 9337 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/macros.h'" '(345 characters)'
if test -f 'src/macros.h' ; then 
  echo shar: will not over-write existing file "'src/macros.h'"
else
sed 's/^X//' >src/macros.h <<'@//E*O*F src/macros.h//'
X#define	eq(a, b)	!strcmp(((char *)a), ((char *)b))
X#define	space(n)	{ int ii; for(ii=0;ii<n;ii++) fputs(" ", stdout); }
X#define	decr(a)		(a) = ((a)>0 ? (a)-1 : (a))
X#define	mask(i)		(1 << (i - 1))
X#define S(n)		((n)!=1 ? "s" : "")
X#define ES(n)		((n)!=1 ? "es" : "")
X
X#define INRANGE(n, f, t) ((f)<(t) ? (f)<=(n)&&(n)<=(t) : (t)<=(n)&&(n)<=(f))
@//E*O*F src/macros.h//
if test 345 -ne "`wc -c <'src/macros.h'`"; then
    echo shar: error transmitting "'src/macros.h'" '(should have been 345 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/mem.c'" '(522 characters)'
if test -f 'src/mem.c' ; then 
  echo shar: will not over-write existing file "'src/mem.c'"
else
sed 's/^X//' >src/mem.c <<'@//E*O*F src/mem.c//'
X#include "mem.h"
X
Xchar	*realloc(), *malloc();
X
Xaddr
XMEM(n)
Xint n;
X
X{
X	flexaddr m;
X
X	critical();
X	m.p_cp = malloc( (unsigned) n );
X	if (!m.p_cp)
X		panic("MEM internal error: out of memory");
X	non_critical();
X	return m.p_ap;
X}
X
Xaddr
XDELTAMEM(p, n)
Xaddr p;
Xint n;
X
X{
X	flexaddr m;
X
X	critical();
X	m.p_cp = realloc((char *)p, (unsigned) n);
X	if (!m.p_cp)
X		panic("DELTAMEM internal error: out of memory");
X	non_critical();
X	return m.p_ap;
X}
X
XFREEMEM(cp)
Xchar *cp;
X
X{
X	critical();
X	free((char *) cp);
X	non_critical();
X	return;
X}
@//E*O*F src/mem.c//
if test 522 -ne "`wc -c <'src/mem.c'`"; then
    echo shar: error transmitting "'src/mem.c'" '(should have been 522 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/mem.h'" '(544 characters)'
if test -f 'src/mem.h' ; then 
  echo shar: will not over-write existing file "'src/mem.h'"
else
sed 's/^X//' >src/mem.h <<'@//E*O*F src/mem.h//'
X#define SHORT_BUF	16
X#define MEDIUM_BUF	48
X#define	LONG_BUF	256
X#define NIL		((addr)0)
X#define NOMORE		-1
X#define	UNDEFINED	-1
X
X#define	bcopy(dest, source, n)				\
X	{						\
X		register char *from = (char *)source;	\
X		register char *to = (char *) dest;	\
X		register int ii;			\
X		int nn = n;				\
X		for (ii=0; ii<nn; ii++)			\
X			*to++ = *from++;		\
X	}
X
Xtypedef	int 		addr_t;
Xtypedef	addr_t *	addr;	/* general purpose pointer type */
Xtypedef union {
X		addr	p_ap;
X		char	*p_cp;
X	} flexaddr;		/* to make lint shut UP! */
X
Xaddr	MEM(), DELTAMEM();
@//E*O*F src/mem.h//
if test 544 -ne "`wc -c <'src/mem.h'`"; then
    echo shar: error transmitting "'src/mem.h'" '(should have been 544 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'MANIFEST'" '(4939 characters)'
if test -f 'MANIFEST' ; then 
  echo shar: will not over-write existing file "'MANIFEST'"
else
sed 's/^X//' >MANIFEST <<'@//E*O*F MANIFEST//'
X  File Name             Kit #   Description
X-----------------------------------------------------------
X Copyright                 1
X Futuribles                1
X Installation              1
X MANIFEST                  6   This shipping list
X Makefile                  1
X PATCHED                   1
X README                    1
X help                      1
X help/Copyright            1
X help/Makefile             1
X help/add-alias.n          1
X help/add-class.n          1
X help/add-group.n          1
X help/add-range.n          1
X help/add-sig.n            1
X help/add-to-alias.n       1
X help/add-to-class.n       1
X help/add-to-group.n       1
X help/add-to-sig.n         1
X help/add-user.n           1
X help/add-vig.n            1
X help/alias.n              1
X help/bind-class.n         1
X help/bind-group.n         1
X help/bind-sig.n           1
X help/checkpoint-changes.n 1
X help/class.n              1
X help/cryo.n               1
X help/deadbeat.n           1
X help/describe-alias.n     1
X help/describe-changes.n   1
X help/describe-class.n     1
X help/describe-command.n   1
X help/describe-cryos.n     1
X help/describe-deadbeats.n 1
X help/describe-group.n     1
X help/describe-inactives.n 1
X help/describe-range.n     1
X help/describe-sig.n       1
X help/describe-user.n      1
X help/disable-user.n       1
X help/exit-mcp.n           1
X help/freeze-deadbeats.n   1
X help/freeze-inactives.n   1
X help/freeze-user.n        1
X help/gid.n                1
X help/inactive.n           1
X help/list-aliases.n       1
X help/list-classes.n       1
X help/list-commands.n      1
X help/list-cryos.n         1
X help/list-deadbeats.n     1
X help/list-groups.n        1
X help/list-inactives.n     1
X help/list-ranges.n        1
X help/list-sigs.n          1
X help/list-users.n         1
X help/list-vigs.n          1
X help/load-file.n          2
X help/pause-mcp.n          1
X help/range.n              2
X help/remove-alias.n       2
X help/remove-class.n       2
X help/remove-cryos.n       2
X help/remove-from-alias.n  2
X help/remove-from-class.n  2
X help/remove-from-group.n  2
X help/remove-from-sig.n    2
X help/remove-group.n       2
X help/remove-range.n       2
X help/remove-sig.n         2
X help/remove-user.n        2
X help/remove-vig.n         2
X help/save-and-exit.n      2
X help/save-changes.n       2
X help/shell-escape.n       2
X help/sig.n                2
X help/uid.n                2
X help/unbind-class.n       2
X help/unbind-group.n       2
X help/unbind-sig.n         2
X help/update-alias.n       2
X help/update-class.n       2
X help/update-group.n       2
X help/update-range.n       2
X help/update-sig.n         2
X help/update-user.n        2
X help/vig.n                2
X help/what-is.n            2
X man                       1
X man/Copyright             2
X man/Makefile              2
X man/accounts.n            2
X man/classes.n             2
X man/mcp.n                 2
X man/ranges.n              2
X man/shells.n              2
X man/sigs.n                3
X man/vigs.n                3
X misc                      1
X misc/freeze               3
X misc/sorry                3
X src                       1
X src/Copyright             3
X src/Makefile              3
X src/account.c             3
X src/account.h             3
X src/add.c                 3
X src/alias.c               3
X src/alias.h               2
X src/backup.c              3
X src/bind.c                4
X src/build.c               4
X src/ckp.c                 4
X src/class.c               3
X src/class.h               3
X src/command.h             3
X src/complete.c            5
X src/date.c                4
X src/describe.c            5
X src/disable.c             4
X src/edit.c                4
X src/errmsg.c              4
X src/exists.c              4
X src/exit.c                4
X src/exits.c               4
X src/freeze.c              4
X src/gpa.c                 6
X src/gpa.h                 3
X src/groupmap.c            4
X src/groupmap.h            4
X src/history.h             4
X src/init.c                6
X src/job.c                 6
X src/job.h                 4
X src/lastlog.c             6
X src/lastlog.h             5
X src/list.c                6
X src/lists.c               6
X src/lists.h               5
X src/load.c                7
X src/macros.h              6
X src/main.c                7
X src/mem.c                 6
X src/mem.h                 6
X src/misc.c                7
X src/nitpick               7
X src/pause.c               5
X src/pwlock.c              7
X src/range.c               7
X src/range.h               7
X src/remove.c              7
X src/report.c              7
X src/save.c                8
X src/save.h                8
X src/shell.c               8
X src/sig.c                 8
X src/sig.h                 8
X src/signals.c             8
X src/sort.c                8
X src/sort.h                8
X src/sysdep.h              8
X src/tty.c                 8
X src/update.c              9
X src/version.c             8
X src/yesno.c               8
@//E*O*F MANIFEST//
if test 4939 -ne "`wc -c <'MANIFEST'`"; then
    echo shar: error transmitting "'MANIFEST'" '(should have been 4939 characters)'
fi
fi # end of overwriting check
echo shar: "End of archive 6 (of 8)."
cp /dev/null ark6isdone
DONE=true
for I in 1 2 3 4 5 6 7 8; do
    if test -! f ark${I}isdone; then
        echo "You still need to run archive ${I}."
        DONE=false
    fi
done
case $DONE in
    true)
        echo "You have run all 8 archives."
        echo 'See the README file'
        ;;
esac
##  End of shell archive.
exit 0



More information about the Mod.sources mailing list