v08i044: Account creation/manipulation program, Part04/08

sources-request at mirror.UUCP sources-request at mirror.UUCP
Sat Feb 7 07:13:28 AEST 1987


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

#! /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 4 (of 8)."
# Contents:  src/bind.c src/build.c src/ckp.c src/date.c src/disable.c
#   src/edit.c src/errmsg.c src/exists.c src/exit.c src/exits.c
#   src/freeze.c src/groupmap.c src/groupmap.h src/history.h src/job.h
# Wrapped by rs at mirror on Fri Feb  6 15:55:57 1987
PATH=/bin:/usr/bin:/usr/ucb; export PATH
echo shar: extracting "'src/bind.c'" '(12012 characters)'
if test -f 'src/bind.c' ; then 
  echo shar: will not over-write existing file "'src/bind.c'"
else
sed 's/^X//' >src/bind.c <<'@//E*O*F src/bind.c//'
X/***************************************************************************\
X* 									    *
X* 	bind.c								    *
X* 									    *
X* Herein lie most of the user interface routines to bind classes, sigs and  *
X* groups to sendmail aliases.  The idea behind the bindings is that	    *
X* accurate e-mail mailing lists can be maintained most easily be	    *
X* integrating their maintenance into the same software that creates and	    *
X* deletes accounts.							    *
X* 									    *
X\***************************************************************************/
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <lastlog.h>
X#include "sysdep.h"
X
X#ifdef SENDMAIL
X#include "macros.h"
X#include "mem.h"
X#include "gpa.h"
X#include "lists.h"
X#include "account.h"
X#include "alias.h"
X#include "class.h"
X#include "groupmap.h"
X#include "sig.h"
X#include "sort.h"
X#include "save.h"
X
Xextern	struct list AccountList, Aliases, AliasList;
Xextern	int ModBits;
X
Xbindgroup(c, v)
Xint c;
Xaddr *v;
X
X{
X	struct alias *al;
X	struct account *ac;
X	struct groupmap *gm;
X	addr *aliasv;
X	int cc, bound = 0;
X	register int i, j;
X
X	if (c > 2) {
X	    err1("%s: too many arguments", (char *)v[0]);
X	    return;
X	}
X	if (c != 2) {
X	    err1("usage: %s <group>", (char *)v[0]);
X	    return;
X	}
X	gm = getgmnam((char *)v[1]);
X	if (!gm) {
X	    err1("%s: no such group", (char *)v[1]);
X	    return;
X	}
X
X	aliasv = get_gpa(17);
X	GetLine("To-Aliases: ", 16, &cc, aliasv, &Aliases);
X	if (cc == 0) {
X	    err("no change");
X	    return;
X	}
X
X	for (i=0; i < cc; i++) {
X	    al = getalnam((char *)aliasv[i]);
X	    if (!al) {
X		err1("%s: no such alias", (char *)aliasv[i]);
X		continue;
X	    }
X	    if (instrlist(&al->al_groups, (char *)v[1])) {
X		err2("%s: already bound to %s", (char *)v[1], al->al_name);
X		continue;
X	    }
X	    strlistadd(&al->al_groups, (char *)v[1]);
X	    strlistadd(&gm->gm_aliases, al->al_name);
X	    sort_list(&al->al_groups, pstrcmp);
X	    sort_list(&gm->gm_aliases, pstrcmp);
X	    for (j=0; j < AccountList.l_count; j++) {
X		ac = (struct account *) AccountList.l_list[j];
X		if (ac->ac_gid != gm->gm_gid &&
X			!instrlist(&ac->ac_groups, (char *)v[1]))
X		    continue;
X		if (instrlist(&al->al_addresses, (char *)ac->ac_name))
X		    continue;
X		strlistadd(&al->al_addresses, (char *)ac->ac_name);
X		sort_list(&al->al_addresses, pstrcmp);
X	    }
X	    bound++;
X	}
X	if (bound) {
X	    ModBits |= AL;
X	    (void) printf("%d bound\n", bound);
X	}
X	non_critical();
X
X	return;
X}
X
Xbindclass(c, v)
Xint c;
Xaddr *v;
X
X{
X	struct alias *al;
X	struct account *ac;
X	struct class *cs;
X	addr *aliasv;
X	int cc, bound = 0;
X	register int i, j;
X
X	if (c > 2) {
X	    err1("%s: too many arguments", (char *)v[0]);
X	    return;
X	}
X	if (c != 2) {
X	    err1("usage: %s <class>", (char *)v[0]);
X	    return;
X	}
X	cs = getcsnam((char *)v[1]);
X	if (!cs) {
X	    err1("%s: no such class", (char *)v[1]);
X	    return;
X	}
X
X	aliasv = get_gpa(17);
X	GetLine("To-Aliases: ", 16, &cc, aliasv, &Aliases);
X	if (cc == 0) {
X	    err("no change");
X	    return;
X	}
X
X	for (i=0; i < cc; i++) {
X	    al = getalnam((char *)aliasv[i]);
X	    if (!al) {
X		err1("%s: no such alias", (char *)aliasv[i]);
X		continue;
X	    }
X	    if (instrlist(&al->al_classes, (char *)v[1])) {
X		err2("%s: already bound to %s", (char *)v[1], al->al_name);
X		continue;
X	    }
X	    strlistadd(&al->al_classes, (char *)v[1]);
X	    strlistadd(&cs->cs_aliases, al->al_name);
X	    sort_list(&al->al_classes, pstrcmp);
X	    sort_list(&cs->cs_aliases, pstrcmp);
X	    for (j=0; j < AccountList.l_count; j++) {
X		ac = (struct account *) AccountList.l_list[j];
X		if (!instrlist(&ac->ac_classes, (char *)v[1]))
X		    continue;
X		if (instrlist(&al->al_addresses, (char *)ac->ac_name))
X		    continue;
X		strlistadd(&al->al_addresses, (char *)ac->ac_name);
X		sort_list(&al->al_addresses, pstrcmp);
X	    }
X	    bound++;
X	}
X	if (bound) {
X	    ModBits |= AL;
X	    (void) printf("%d bound\n", bound);
X	}
X	non_critical();
X
X	return;
X}
X
Xbindsig(c, v)
Xint c;
Xaddr *v;
X
X{
X	struct alias *al;
X	struct account *ac;
X	struct sig *sg;
X	addr *aliasv;
X	int cc, bound = 0;
X	register int i, j;
X
X	if (c > 2) {
X	    err1("%s: too many arguments", (char *)v[0]);
X	    return;
X	}
X	if (c != 2) {
X	    err1("usage: %s <sig>", (char *)v[0]);
X	    return;
X	}
X	sg = getsgnam((char *)v[1]);
X	if (!sg) {
X	    err1("%s: no such sig", (char *)v[1]);
X	    return;
X	}
X
X	aliasv = get_gpa(17);
X	GetLine("To-Aliases: ", 16, &cc, aliasv, &Aliases);
X	if (cc == 0) {
X	    err("no change");
X	    return;
X	}
X
X	for (i=0; i < cc; i++) {
X	    al = getalnam((char *)aliasv[i]);
X	    if (!al) {
X		err1("%s: no such alias", (char *)aliasv[i]);
X		continue;
X	    }
X	    if (instrlist(&al->al_sigs, (char *)v[1])) {
X		err2("%s: already bound to %s", (char *)v[1], al->al_name);
X		continue;
X	    }
X	    strlistadd(&al->al_sigs, (char *)v[1]);
X	    strlistadd(&sg->sg_aliases, al->al_name);
X	    sort_list(&al->al_sigs, pstrcmp);
X	    sort_list(&sg->sg_aliases, pstrcmp);
X	    for (j=0; j < AccountList.l_count; j++) {
X		ac = (struct account *) AccountList.l_list[j];
X		if (!instrlist(&ac->ac_sigs, (char *)v[1]))
X		    continue;
X		if (instrlist(&al->al_addresses, (char *)ac->ac_name))
X		    continue;
X		strlistadd(&al->al_addresses, (char *)ac->ac_name);
X		sort_list(&al->al_addresses, pstrcmp);
X	    }
X	    bound++;
X	}
X	if (bound) {
X	    ModBits |= AL;
X	    (void) printf("%d bound\n", bound);
X	}
X	non_critical();
X
X	return;
X}
X
Xubindgroup(c, v)
Xint c;
Xaddr *v;
X
X{
X	struct account *ac;
X	struct alias *al;
X	struct groupmap *gm;
X	addr *aliasv;
X	register int i, j;
X	int unbound = 0, cc;
X
X	if (c > 2) {
X	    err1("%s: too many arguements", (char *)v[0]);
X	    return;
X	}
X	if (c < 2) {
X	    err1("usage: %s <group>", (char *)v[0]);
X	    return;
X	}
X	gm = getgmnam((char *)v[1]);
X	if (!gm) {
X	    err1("%s: no such group", (char *)v[1]);
X	    return;
X	}
X	if (gm->gm_aliases.l_count) {
X	    err1("%s: not bound to any aliases", gm->gm_name);
X	    return;
X	}
X
X	aliasv = get_gpa(17);
X	GetLine("From-Aliases: ", 16, &cc, aliasv, &Aliases);
X	if (cc == 0) {
X	    err("no change");
X	    return;
X	}
X
X	critical();
X	for (i=0; i < cc; i++) {
X	    al = getalnam((char *)aliasv[i]);
X	    if (!al) {
X		err1("%s: no such alias", (char *)aliasv[i]);
X		continue;
X	    }
X	    if (!instrlist(&al->al_groups, (char *)v[1])) {
X		err2("%s: not bound to %s", (char *)v[1], al->al_name);
X		continue;
X	    }
X	    strlistdel(&al->al_groups, (char *)v[1]);
X	    strlistdel(&gm->gm_aliases, al->al_name);
X	    for (j=0; j < AccountList.l_count; j++) {
X		ac = (struct account *) AccountList.l_list[j];
X		if (!instrlist(&al->al_addresses, (char *)ac->ac_name))
X		    continue;
X		if (LegalAKA(ac, al))
X		    continue;
X		strlistdel(&al->al_addresses, (char *)ac->ac_name);
X	    }
X	    unbound++;
X	}
X	if (unbound) {
X	    (void) printf("%d unbound\n", unbound);
X	    ModBits |= AL;
X	}
X	non_critical();
X
X	return;
X}
X
Xubindclass(c, v)
Xint c;
Xaddr *v;
X
X{
X	struct account *ac;
X	struct alias *al;
X	struct class *cs;
X	addr *aliasv;
X	register int i, j;
X	int unbound = 0, cc;
X
X	if (c > 2) {
X	    err1("%s: too many arguements", (char *)v[0]);
X	    return;
X	}
X	if (c < 2) {
X	    err1("usage: %s <class>", (char *)v[0]);
X	    return;
X	}
X	cs = getcsnam((char *)v[1]);
X	if (!cs) {
X	    err1("%s: no such class", (char *)v[1]);
X	    return;
X	}
X	if (cs->cs_aliases.l_count) {
X	    err1("%s: not bound to any aliases", cs->cs_name);
X	    return;
X	}
X
X	aliasv = get_gpa(17);
X	GetLine("From-Aliases: ", 16, &cc, aliasv, &Aliases);
X	if (cc == 0) {
X	    err("no change");
X	    return;
X	}
X
X	critical();
X	for (i=0; i < cc; i++) {
X	    al = getalnam((char *)aliasv[i]);
X	    if (!al) {
X		err1("%s: no such alias", (char *)aliasv[i]);
X		continue;
X	    }
X	    if (!instrlist(&al->al_classes, (char *)v[1])) {
X		err2("%s: not bound to %s", (char *)v[1], al->al_name);
X		continue;
X	    }
X	    strlistdel(&al->al_classes, (char *)v[1]);
X	    strlistdel(&cs->cs_aliases, al->al_name);
X	    for (j=0; j < AccountList.l_count; j++) {
X		ac = (struct account *) AccountList.l_list[j];
X		if (!instrlist(&ac->ac_classes, (char *)v[1]))
X		    continue;
X		if (!instrlist(&al->al_addresses, (char *)ac->ac_name))
X		    continue;
X		if (LegalAKA(ac, al))
X		    continue;
X		strlistdel(&al->al_addresses, (char *)ac->ac_name);
X	    }
X	    unbound++;
X	}
X	if (unbound) {
X	    (void) printf("%d unbound\n", unbound);
X	    ModBits |= AL;
X	}
X	non_critical();
X
X	return;
X}
X
Xubindsig(c, v)
Xint c;
Xaddr *v;
X
X{
X	struct account *ac;
X	struct alias *al;
X	struct sig *sg;
X	addr *aliasv;
X	register int i, j;
X	int unbound = 0, cc;
X
X	if (c > 2) {
X	    err1("%s: too many arguements", (char *)v[0]);
X	    return;
X	}
X	if (c < 2) {
X	    err1("usage: %s <sig>", (char *)v[0]);
X	    return;
X	}
X	sg = getsgnam((char *)v[1]);
X	if (!sg) {
X	    err1("%s: no such sig", (char *)v[1]);
X	    return;
X	}
X	if (sg->sg_aliases.l_count) {
X	    err1("%s: not bound to any aliases", sg->sg_name);
X	    return;
X	}
X
X	aliasv = get_gpa(17);
X	GetLine("From-Aliases: ", 16, &cc, aliasv, &Aliases);
X	if (cc == 0) {
X	    err("no change");
X	    return;
X	}
X
X	critical();
X	for (i=0; i < cc; i++) {
X	    al = getalnam((char *)aliasv[i]);
X	    if (!al) {
X		err1("%s: no such alias", (char *)aliasv[i]);
X		continue;
X	    }
X	    if (!instrlist(&al->al_sigs, (char *)v[1])) {
X		err2("%s: not bound to %s", (char *)v[1], al->al_name);
X		continue;
X	    }
X	    strlistdel(&al->al_sigs, (char *)v[1]);
X	    strlistdel(&sg->sg_aliases, al->al_name);
X	    for (j=0; j < AccountList.l_count; j++) {
X		ac = (struct account *) AccountList.l_list[j];
X		if (!instrlist(&ac->ac_sigs, (char *)v[1]))
X		    continue;
X		if (!instrlist(&al->al_addresses, (char *)ac->ac_name))
X		    continue;
X		if (LegalAKA(ac, al))
X		    continue;
X		strlistdel(&al->al_addresses, (char *)ac->ac_name);
X	    }
X	    unbound++;
X	}
X	if (unbound) {
X	    (void) printf("%d unbound\n", unbound);
X	    ModBits |= AL;
X	}
X	non_critical();
X
X	return;
X}
X
X/*
X * Routine to determine if a user should be left in an alias after
X * his class, sig, or group memberships have changed.  If the user is still
X * a member of another class, sig or group that is bound to the given aliasm
X * then the user should remain in the alias.  Also if the user a member of
X * the alias above and beyond any class, sig or group bindings he should be
X * allowed to remain.
X */
Xint
XLegalAKA(ac, al)
Xstruct account *ac;
Xstruct alias *al;
X
X{
X	char *name;
X	struct groupmap *gm;
X	register int i;
X
X	/*
X	 * REMEMBER:
X	 * ac_aliases always contains the list of aliasses that the user is
X	 * in, even if he were not member of classes, sig, etc. that
X	 * are bound to aliases.  Thus class, sig, or group membership
X	 * changes have no bearing on this so we return 1 immediately.
X	 */
X	if (instrlist(&ac->ac_aliases, al->al_name))
X	    return 1;
X	/*
X	 * Check for membership via group being bound.
X	 */
X	gm = getgmgid(ac->ac_gid);
X	if (gm && instrlist(&al->al_groups, (char *)gm->gm_name))
X	    return 1;
X	for (i=0; i < ac->ac_groups.l_count; i++) {
X	    name = (char *) ac->ac_groups.l_list[i];
X	    if (instrlist(&al->al_groups, name))
X		return 1;
X	}
X	/*
X	 * Are any of this user's classes bound to this alias?
X	 */
X	for (i=0; i < ac->ac_classes.l_count; i++) {
X	    name = (char *) ac->ac_classes.l_list[i];
X	    if (instrlist(&al->al_classes, name))
X		return 1;
X	}
X	/*
X	 * Are any of this user's sigs bound to this alias?
X	 */
X	for (i=0; i < ac->ac_sigs.l_count; i++) {
X	    name = (char *) ac->ac_sigs.l_list[i];
X	    if (instrlist(&al->al_sigs, name))
X		return 1;
X	}
X	return 0;
X}
X
X/*
X * Patch up aliases.
X * Should be used right after removing users from classes,
X * sigs, or groups, to be sure that if these are bound the changes are
X * reflected in the aliases.
X */
XRXBindings(ac)
Xstruct account *ac;
X
X{
X    register struct alias *al;
X    register int i;
X
X    critical();
X    for (i=0; i < AliasList.l_count; i++) {
X	al = (struct alias *) AliasList.l_list[i];
X	if (instrlist(&al->al_addresses, (char *)ac->ac_name)) {
X	    if (LegalAKA(ac, al) == 0) {
X		strlistdel(&al->al_addresses, (char *)ac->ac_name);
X		ModBits |= AL;
X	    }
X	}
X    }
X    non_critical();
X    return;
X}
X
X#endif SENDMAIL
@//E*O*F src/bind.c//
if test 12012 -ne "`wc -c <'src/bind.c'`"; then
    echo shar: error transmitting "'src/bind.c'" '(should have been 12012 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/build.c'" '(5892 characters)'
if test -f 'src/build.c' ; then 
  echo shar: will not over-write existing file "'src/build.c'"
else
sed 's/^X//' >src/build.c <<'@//E*O*F src/build.c//'
X/***************************************************************************\
X* 									    *
X* 	build.c								    *
X* 									    *
X* Routines to build the accounts file from the existing passwd and group    *
X* files, i.e. the -I option to mcp.  All information about who is in what   *
X* class and what sig is destroyed by this process.  If the class, sig, vig  *
X* or range files do not exist, mcp will attempt to create them, otherwise   *
X* these are untouched.							    *
X* 									    *
X\***************************************************************************/
X
X#include <stdio.h>
X#include <sys/file.h>
X#include <sys/types.h>
X#include <strings.h>
X#include <pwd.h>
X#include <grp.h>
X#include <lastlog.h>
X#include "sysdep.h"
X#include "macros.h"
X#include "mem.h"
X#include "lists.h"
X#ifdef SENDMAIL
X#include "alias.h"
X#endif
X#include "account.h"
X#include "groupmap.h"
X#include "sort.h"
X#include "save.h"
X#ifdef SENDMAIL
X#include <ctype.h>
X#endif
X
Xextern	struct list AccountList, GroupMapList, Groups, Users;
Xextern	int ModBits, root, acck();
X
XBuild()
X
X{
X#ifdef SENDMAIL
X	struct alias *al;
X	char line[BUFSIZ];
X#endif
X	struct account a, *ac, *ac2;
X	struct passwd *pw;
X	struct group *gr;
X	struct groupmap gm;
X	register int indx;
X	char *cp;
X
X	ShowVersion();
X	msg("Building accounting files...");
X#ifdef SENDMAIL
X	zerolist(&a.ac_aliases);
X#endif
X	zerolist(&a.ac_groups);
X	zerolist(&a.ac_classes);   zerolist(&a.ac_sigs);
X	(void) setpwent();
X	while (pw = getpwent()) {
X		a.ac_uid = pw->pw_uid;
X		a.ac_gid = pw->pw_gid;
X		savestr((char **)&a.ac_name, pw->pw_name);
X		savestr((char **)&a.ac_gecos, pw->pw_gecos);
X		cp = index(pw->pw_gecos, ',');	if (cp) *cp = '\0';
X		savestr((char **)&a.ac_realname, pw->pw_gecos);
X		savestr((char **)&a.ac_passwd, pw->pw_passwd);
X		savestr((char **)&a.ac_dir, pw->pw_dir);
X		savestr((char **)&a.ac_shell, pw->pw_shell);
X		savestr((char **)&a.ac_id, "exception");
X		genlistadd(&AccountList, (addr)&a, sizeof (struct account));
X		strlistadd(&Users, pw->pw_name);
X	}
X	sort_list(&AccountList, acctcmp);
X	sort_list(&Users, pstrcmp);
X	(void) endpwent();
X	(void) setgrent();
X	while (gr = getgrent()) {
X		zerolist(&gm.gm_mem);
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			ac = getacnam(gr->gr_mem[indx]);
X			if (ac) {
X				strlistadd(&ac->ac_groups, gr->gr_name);
X				sort_list(&ac->ac_groups, pstrcmp);
X			}
X			else
X				continue;
X			strlistadd(&gm.gm_mem, gr->gr_mem[indx]);
X		}
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	/*
X	 * If an accounts file already exists get the unchanged
X	 * information from it before overwriting it.
X	 */
X	if (!fileexists(ACFILE)) goto finish;
X	if (acck() == 0) {
X		err("I can't get the class and sig membership info");
X		err("nor the ID's or real names of current users");
X		err("nor the non-binding alias memberships");
X		err1("from the old %s because the file format is bad.",
X			ACFILE);
X		err("");
X		if (yesno("Overwrite it anyway? ") == 0)
X			fatal("aborted");
X	}
X	(void) setacent();
X	while (ac2 = getacent()) {
X		ac = getacnam((char *)ac2->ac_name);
X		if (!ac) {
X(void) printf("accounts line for nonexistent user \"%s\" removed\n",
X			ac2->ac_name);
X			continue;
X		}
X		FREEMEM((char *)ac->ac_realname);
X		savestr((char **)&ac->ac_realname, (char *)ac2->ac_realname);
X		FREEMEM((char *)ac->ac_id);
X		savestr((char **)&ac->ac_id, (char *)ac2->ac_id);
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	}
Xfinish:
X	!fileexists(CSFILE) && createfile(CSFILE);
X	!fileexists(RANGEFILE) && createfile(RANGEFILE);
X	!fileexists(SIGFILE) && createfile(SIGFILE);
X	!fileexists(VIGFILE) && createfile(VIGFILE);
X	!fileexists(SHELLFILE) && createfile(SHELLFILE);
X	!fileexists(ACFILE) && createfile(ACFILE);
X#ifdef SENDMAIL
X	!fileexists(ALIASFILE) && createfile(ALIASFILE);
X#endif
X
X	critical();
X#ifdef SENDMAIL
X	/*
X	 * Check to see if an alias bindings file needs to be created
X	 * to represent the current aliases file.  Also if no alias bindings
X	 * file exists we must assume that all users that are currently in
X	 * aliases are not there because of bindings, hence updating
X	 * ac_aliases for each user where appropriate.
X	 */
X	if (!fileexists(ALBIND)) {
X		FILE *bindf = fopen(ALBIND, "w");
X		FILE *alf = fopen(ALIASFILE, "r");
X
X		if (alf == NULL) {
X			err1("can't open %s (read)", ALIASFILE);
X			fatal("mcp: -B aborted");
X		}
X		if (bindf == NULL) {
X			(void) fclose(alf);
X			err1("can't open %s (write)", ALBIND);
X			fatal("mcp: -B aborted");
X		}
X		while (fgets(line, BUFSIZ, alf) != NULL) {
X			if (isspace(line[0]) || line[0] == '#')
X				continue;
X			cp = index(line, '#');
X			if (cp) *cp = '\0';
X			cp = index(line, ':');
X			if (cp) *cp = '\0';
X			if (line[0] == '\n')
X				continue;
X			cp = index(line, '\n');
X			if (cp) *cp = '\0';
X			(void) fprintf(bindf, "%s:::\n", line);
X		}
X		(void) fchmod(fileno(bindf), 0644);
X		(void) fclose(bindf);
X		(void) fclose(alf);
X		setalent();
X		while (al = getalent()) {
X		    for (indx=0; indx < al->al_addresses.l_count; indx++) {
X			cp = (char *) al->al_addresses.l_list[indx];
X			ac = getacnam(cp);
X			if (ac && !instrlist(&ac->ac_aliases, cp)) {
X			    strlistadd(&ac->ac_aliases, al->al_name);
X			    sort_list(&ac->ac_aliases, pstrcmp);
X			}
X		    }
X		}
X		endalent();
X	}
X#endif
X	if (backup(PW) == 0 || backup(AC) == 0)
X		fatal("mcp: -B aborted");
X	msg("");
X	save_pw();
X	save_ac();
X	non_critical();
X
X	goodbye(0);
X}
X
Xstatic
Xcreatefile(file)
Xchar *file;
X
X{
X	int d;
X
X	d = open(file, O_WRONLY|O_CREAT);
X	if (d == -1) {
X		perr(file);
X		return;
X	}
X	(void) write(d, "Toto IV", 7);
X	(void) ftruncate(d, (off_t)0);
X	(void) fchmod(d, 0644);
X	(void) fsync(d);
X	(void) close(d);
X}
@//E*O*F src/build.c//
if test 5892 -ne "`wc -c <'src/build.c'`"; then
    echo shar: error transmitting "'src/build.c'" '(should have been 5892 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/ckp.c'" '(6255 characters)'
if test -f 'src/ckp.c' ; then 
  echo shar: will not over-write existing file "'src/ckp.c'"
else
sed 's/^X//' >src/ckp.c <<'@//E*O*F src/ckp.c//'
X/****************************************************************************\
X* 									     *
X* 	ckp.c								     *
X* 									     *
X* These are the routines that put changes that have not been saved, into     *
X* the .mcp checkpoint files.  An important thing to remember here is that    *
X* checkpointing should not be interupted by anything, particularly not by    *
X* another checkpoint, or chaos will ensue.  There are only one set ot temp   *
X* files shared by save and the checkpoint routines.  This was done for the   *
X* sake of simplicity and also since the tempfiles are in the same	     *
X* filesystem as their accounting counterparts, these can be rename()'d into  *
X* place without the possibility of being caught by a system crash with a     *
X* file copy partially completed.					     *
X* 									     *
X\****************************************************************************/
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <signal.h>
X#include <lastlog.h>
X#include "sysdep.h"
X#include "macros.h"
X#include "mem.h"
X#include "lists.h"
X#ifdef SENDMAIL
X#include "alias.h"
X#endif
X#include "account.h"
X#include "class.h"
X#include "sig.h"
X#include "range.h"
X#include "groupmap.h"
X#include "save.h"
X
Xextern	int ModBits;
X
X#ifdef SENDMAIL
Xextern	struct list AliasList;
X#endif
Xextern	struct list AccountList, GroupMapList, SigList, ClassList, RangeList;
Xextern	struct list Vigs, Jobs;
X
Xckp_pw()
X
X{
X	FILE *pwf;
X	register int i;
X	struct account *ac;
X
X	pwf = fopen(PWDTMP, "w");
X	if (pwf == NULL) {
X		perr(PWDTMP);
X		return;
X	}
X	for (i=0; i < AccountList.l_count; i++) {
X		ac = (struct account *) AccountList.l_list[i];
X		(void) fprintf(pwf, "%s:%s:%d:%d:%s:%s:%s\n",
X			ac->ac_name,
X			ac->ac_passwd,
X			ac->ac_uid,
X			ac->ac_gid,
X			ac->ac_gecos,
X			ac->ac_dir,
X			ac->ac_shell);
X	}
X	(void) fclose(pwf);
X	if (rename(PWDTMP, PWDCKP) == -1) {
X		perr(PWDTMP);
X		return;
X	}
X	return;
X}
X
X#ifdef SENDMAIL
Xckp_al()
X
X{
X	FILE *alf, *bindf;
X	struct alias *al;
X	register int i;
X
X	alf = fopen(ALIASTMP, "w");
X	if (alf == NULL) {
X		perr(ALIASTMP);
X		return;
X	}
X	bindf = fopen(ALBINDTMP, "w");
X	if (bindf == NULL) {
X		perr(ALBINDTMP);
X		(void) fclose(alf);
X		return;
X	}
X	for (i=0; i < AliasList.l_count; i++) {
X		al = (struct alias *) AliasList.l_list[i];
X		(void) fprintf(alf, "%s:", al->al_name);
X		listout(&al->al_addresses, alf);
X		fputs("\n", alf);
X		(void) fprintf(bindf, "%s:", al->al_name);
X		listout(&al->al_groups, bindf);
X		fputs(":", bindf);
X		listout(&al->al_classes, bindf);
X		fputs(":", bindf);
X		listout(&al->al_sigs, bindf);
X		fputs("\n", bindf);
X	}
X	(void) fclose(alf);
X	(void) fclose(bindf);
X	if (rename(ALIASTMP, ALIASCKP) == -1) {
X		perr(ALIASTMP);
X		return;
X	}
X	if (rename(ALBINDTMP, ALBINDCKP) == -1) {
X		perr(ALBINDTMP);
X		return;
X	}
X	return;
X}
X#endif
X
Xckp_ac()
X
X{
X	FILE *acf;
X	register int i;
X	struct account *ac;
X
X	acf = fopen(ACTMP, "w");
X	if (acf == NULL) {
X		perr(ACTMP);
X		return;
X	}
X	for (i=0; i < AccountList.l_count; i++) {
X		ac = (struct account *) AccountList.l_list[i];
X		(void) fprintf(acf, "%s:%s:%s:%d:%d:",
X			ac->ac_name,
X			ac->ac_realname,
X			ac->ac_id,
X			ac->ac_uid,
X			ac->ac_gid);
X		listout(&ac->ac_groups, acf);
X		fputs(":", acf);
X		listout(&ac->ac_classes, acf);
X		fputs(":", acf);
X		listout(&ac->ac_sigs, acf);
X		fputs(":", acf);
X#ifdef SENDMAIL
X		listout(&ac->ac_aliases, acf);
X#endif
X		fputs("\n", acf);
X	}
X	(void) fclose(acf);
X	if (rename(ACTMP, ACCKP) == -1) {
X		perr(ACTMP);
X		return;
X	}
X	return;
X}
X
Xckp_gr()
X
X{
X	FILE *grf;
X	register int i;
X	struct groupmap *gm;
X
X	grf = fopen(GRPTMP, "w");
X	if (grf == NULL) {
X		perr(GRPTMP);
X		return;
X	}
X	for (i=0; i < GroupMapList.l_count; i++) {
X		gm = (struct groupmap *) GroupMapList.l_list[i];
X		(void) fprintf(grf, "%s:%s:%d:",
X			gm->gm_name,
X			gm->gm_passwd,
X			gm->gm_gid);
X		listout(&gm->gm_mem, grf);
X		fputs("\n", grf);
X	}
X	(void) fclose(grf);
X	if (rename(GRPTMP, GRPCKP) == -1) {
X		perr(GRPTMP);
X		return;
X	}
X	return;
X}
X
Xckp_cs()
X
X{
X	struct class *cs;
X	register int i;
X	FILE *csf;
X
X	csf = fopen(CSTMP, "w");
X	if (csf == NULL) {
X		perr(CSTMP);
X		return;
X	}
X	for (i=0; i < ClassList.l_count; i++) {
X		cs = (struct class *) ClassList.l_list[i];
X		(void) fprintf(csf, "%s %d %d\n", cs->cs_name, cs->cs_dsize,
X					   cs->cs_exptime);
X		(void) fprintf(csf, "%s", cs->cs_desc);
X	}
X	(void) fclose(csf);
X	if (rename(CSTMP, CSCKP) == -1) {
X		perr(CSTMP);
X		return;
X	}
X	return;
X}
X
Xckp_sg()
X
X{
X	struct sig *sg;
X	register int i;
X	FILE *sgf;
X
X	sgf = fopen(SIGTMP, "w");
X	if (sgf == NULL) {
X		perr(SIGTMP);
X		return;
X	}
X	for (i=0; i < SigList.l_count; i++) {
X		sg = (struct sig *) SigList.l_list[i];
X		(void) fprintf(sgf, "%s %d %d\n", sg->sg_name, sg->sg_dsize,
X					   sg->sg_exptime);
X		(void) fprintf(sgf, "%s", sg->sg_desc);
X	}
X	(void) fclose(sgf);
X	if (rename(SIGTMP, SIGCKP) == -1) {
X		perr(SIGTMP);
X		return;
X	}
X	return;
X}
X
Xckp_rg()
X
X{
X	struct range *rg;
X	register int i;
X	FILE *rgf;
X
X	rgf = fopen(RANGETMP, "w");
X	if (rgf == NULL) {
X		perr(RANGETMP);
X		return;
X	}
X	for (i=0; i < RangeList.l_count; i++) {
X		rg = (struct range *) RangeList.l_list[i];
X		(void) fprintf(rgf, "%s\t%d\t%d\t%s\n",
X			rg->rg_name,
X			rg->rg_from,
X			rg->rg_to,
X			(rg->rg_mode == RG_SHARED ? "shared" : "exclusive"));
X	}
X	(void) fclose(rgf);
X	if (rename(RANGETMP, RANGECKP) == -1) {
X		perr(RANGETMP);
X		return;
X	}
X	return;
X}
X
Xckp_vg()
X
X{
X	register int i;
X	FILE *vgf;
X
X	vgf = fopen(VIGTMP, "w");
X	if (vgf == NULL) {
X		perr(VIGTMP);
X		return;
X	}
X	for (i=0; i < Vigs.l_count; i++)
X		(void) fprintf(vgf, "%s\n", Vigs.l_list[i]);
X	(void) fclose(vgf);
X	if (rename(VIGTMP, VIGCKP) == -1) {
X		perr(VIGTMP);
X		return;
X	}
X	return;
X}
X
Xpanic(reason)
Xchar *reason;
X
X{
X	err("");
X	err(reason);
X	if (ModBits) {
X		msg("Checkpointing...");
X		ckpchanges();
X		err("All changes made to the accounting files");
X		err("have been checkpointed.");
X	}
X	goodbye(1);
X}
X
Xckpchanges()
X
X{
X	/*
X	 * All signals that could cause an unwanted checkpoint are blocked
X	 * here lest file collisions and choas ensue.
X	 */
X	critical();
X
X	(ModBits&PW) && ckp_pw();
X	(ModBits&AC) && ckp_ac();
X#ifdef SENDMAIL
X	(ModBits&AL) && ckp_al();
X#endif
X	(ModBits&CS) && ckp_cs();
X	(ModBits&GR) && ckp_gr();
X	(ModBits&RG) && ckp_rg();
X	(ModBits&SG) && ckp_sg();
X	(ModBits&VG) && ckp_vg();
X	sync();
X
X	non_critical();
X	return;
X}
@//E*O*F src/ckp.c//
if test 6255 -ne "`wc -c <'src/ckp.c'`"; then
    echo shar: error transmitting "'src/ckp.c'" '(should have been 6255 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/date.c'" '(8068 characters)'
if test -f 'src/date.c' ; then 
  echo shar: will not over-write existing file "'src/date.c'"
else
sed 's/^X//' >src/date.c <<'@//E*O*F src/date.c//'
X#include <sys/types.h>
X#include <sys/time.h>
X#include <setjmp.h>
X#include <signal.h>
X#include <strings.h>
X#include "macros.h"
X#include "mem.h"
X
X#define DOOMYEAR	2010
X#define STONEAGES	1975
X#define DAY		(4*21600)
X#define ISLEAPYEAR(y)	(((y)%4==0) && (((y)%100!=0) || ((y)%400==0)))
X
Xchar	*sprintf(), GET();
X
X#ifdef sun
X#define	sighandler	(void (*)())
X#else
X#define	sighandler	(int (*)())
X#endif
X
Xextern	jmp_buf in_continue;
X#ifdef sun
Xvoid	tstp_cleanup(), input_continue();
X#else
Xint	tstp_cleanup(), input_continue();
X#endif
X
Xstatic 	char *days[] = {
X	"Sunday",	"Monday",	"Tuesday",	"Wednesday",
X	"Thursday", 	"Friday", 	"Saturday"
X};
X
Xstatic	char *how_many[] = {
X	"zero",		"one",		"two",		"three",
X	"four",		"five",		"six",		"seven",
X	"eigth",	"nine",		"ten", 		"eleven",
X	"twelve"
X};
X
Xstatic	char *Months[12] = {
X	"January", "February", "March", "April",
X	"May", "June", "July", "August",
X	"September", "October", "November", "December"
X};
X
Xstatic	int DaysInMonths[12] = {
X	31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
X};
X
Xtime_t	tmtotime_t();
X
Xtime_t
Xchoosedate(starttime)
Xtime_t starttime;
X
X{
X	struct tm *t, newt;
X	time_t time();
X	char prompt[MEDIUM_BUF], line[MEDIUM_BUF];
X	register int indx;
X	int leapday;
X	char c;
X
X	err("Use SPACE to go forward, ^H or DELETE to go backwards.");
X	err("Hit RETURN to select.");
X	err("");
X
X	if (starttime == (time_t) 0)
X	  starttime = time((time_t *)0);
X	t = localtime(&starttime);
X	bcopy(&newt, t, sizeof (struct tm));
X	prompt[0] = '\0';
X	/*
X	 * Choose month
X	 */
X	indx = t->tm_mon;
X	(void) strcpy(line, Months[indx]);
X	cbreak();
X	(void) signal(SIGTSTP, tstp_cleanup);
X	(void) signal(SIGCONT, input_continue);
X	(void) setjmp(in_continue);
X	redraw(prompt, line);
X	while ((c = GET()) != '\r') {
X		if (setjmp(in_continue) == SIGCONT) {
X			redraw(prompt, line);
X			continue;
X		}
X		switch (c) {
X		case ' ':
X			indx = (indx+1) % 12;
X			(void) sprintf(line, "%-9s", Months[indx]);
X			redraw(prompt, line);
X			break;
X		case '\b':
X		case '\177':
X			if (--indx < 0)
X				indx = 11;
X			(void) sprintf(line, "%-9s", Months[indx]);
X			redraw(prompt, line);
X			break;
X		default:
X			break;
X		}
X	}
X	(void) strcpy(prompt, Months[indx]);
X	(void) strcat(prompt, " ");
X	newt.tm_mon = indx;
X	indx = t->tm_mday;
X	if (indx > DaysInMonths[newt.tm_mon])
X		indx = DaysInMonths[newt.tm_mon];
X	(void) sprintf(line, "%2d", indx);
X	(void) setjmp(in_continue);
X	redraw(prompt, line);
X	/*
X	 * Choose day of the month.
X	 */
X	while ((c = GET()) != '\r') {
X		if (setjmp(in_continue) == SIGCONT) {
X			redraw(prompt, line);
X			continue;
X		}
X		switch (c) {
X		case ' ':
X			if (++indx > DaysInMonths[newt.tm_mon])
X				indx = 1;
X			(void) sprintf(line, "%2d", indx);
X			redraw(prompt, line);
X			break;
X		case '\b':
X		case '\177':
X			if (--indx < 1)
X				indx = DaysInMonths[newt.tm_mon];
X			(void) sprintf(line, "%2d", indx);
X			redraw(prompt, line);
X			break;
X		default:
X			break;
X		}
X	}
X	(void) strcat(prompt, line);
X	(void) strcat(prompt, ", ");
X	newt.tm_mday = indx;
X	leapday = (newt.tm_mon == 1 && newt.tm_mday == 29);
X	indx = t->tm_year + 1900;
X	if (leapday)
X		indx = nextleapyear(indx);
X	(void) sprintf(line, "%4d", indx);
X	/*
X	 * Choose year
X	 */
X	(void) setjmp(in_continue);
X	redraw(prompt, line);
X	while ((c = GET()) != '\r') {
X		if (setjmp(in_continue) == SIGCONT) {
X			redraw(prompt, line);
X			continue;
X		}
X		switch (c) {
X		case ' ':
X			if (leapday)
X				indx = nextleapyear(indx);
X			else if (++indx > DOOMYEAR)
X				indx = DOOMYEAR;
X			(void) sprintf(line, "%4d", indx);
X			redraw(prompt, line);
X			break;
X		case '\b':
X		case '\177':
X			if (leapday)
X				indx = lastleapyear(indx);
X			else if (--indx < STONEAGES)
X				indx = STONEAGES;
X			(void) sprintf(line, "%4d", indx);
X			redraw(prompt, line);
X			break;
X		default:
X			break;
X		}
X	}
X	newt.tm_year = indx - 1900;
X	newt.tm_hour = 0;
X	newt.tm_min = 0;
X	newt.tm_sec = 0;
X	(void) signal(SIGCONT, sighandler SIG_DFL);
X	(void) signal(SIGTSTP, sighandler SIG_DFL);
X	nocbreak();
X	err("");
X	return tmtotime_t(&newt);
X}
X
Xtime_t
Xtmtotime_t(t)
Xregister struct tm *t;
X
X{
X	time_t newtime;
X	struct timezone tz;
X	struct timeval tv;
X	int year, newyear, i;
X
X	newtime = (t->tm_year - 70) * 365 * DAY;
X	for (i=0; i<t->tm_mon; i++)
X		newtime += (DaysInMonths[i] * DAY);
X	newtime += (t->tm_mday * DAY);
X	newyear = t->tm_year + 1900;
X	year = 1970;
X	for (; year < newyear; year++)
X		if (ISLEAPYEAR(year))
X			newtime += DAY;
X	if (!ISLEAPYEAR(newyear) && t->tm_mon > 1)
X		newtime -= DAY;
X	/* set for midnight in this timezone and correct for dst shifts */
X	(void) gettimeofday(&tv, &tz);
X	newtime += tz.tz_minuteswest * 60 - DAY;
X	t = localtime(&newtime);
X	switch (t->tm_hour) {
X	case 23: newtime += 3600;	break;
X	case  1: newtime -= 3600;	break;
X	default: break;
X	}
X	return newtime;
X}
X
Xint
Xnextleapyear(startyear)
Xint startyear;
X
X{
X	register int year;
X
X	year = startyear;
X	while (++year <= DOOMYEAR) {
X		if (ISLEAPYEAR(year))
X			return year;
X	}
X	return startyear;
X}
X
Xint
Xlastleapyear(startyear)
Xint startyear;
X
X{
X	register int year;
X
X	year = startyear;
X	while (--year >= STONEAGES)
X		if (ISLEAPYEAR(year))
X			return year;
X	return startyear;
X}
X
Xchar *
Xwhen(then)
Xtime_t then;
X
X{
X	static char tstr[LONG_BUF], descbuf[MEDIUM_BUF];
X	char *cp, *description, *ampm;
X	struct tm *tt, tn, *localtime();
X	time_t time(), now, tilthen, indx, remainder;
X
X	now = time((time_t *)0);
X	tt = localtime(&now);
X	bcopy(&tn, tt, sizeof (struct tm));
X	tt = localtime(&then);
X	tilthen = then - now;
X	if (then == 0)
X		return "never";
X	if (tilthen >= 365 * DAY)
X		description = "sometime in the distant future";
X	else if (tilthen >= 30 * DAY) {
X		indx = tilthen / (30*DAY);
X		remainder = (tilthen - indx * 30 * DAY) / DAY;
X		description = sprintf(descbuf,
X				"%smore than %s month%s hence",
X				(remainder < 5) ? "a little " : "",
X				how_many[indx], S(indx));
X	}
X	else if (tilthen >= 7 * DAY) {
X		indx = tilthen / (7*DAY);
X		remainder = (tilthen - indx * 7 * DAY) / DAY;
X		description = sprintf(descbuf,
X				"%smore than %s week%s hence",
X				(remainder < 3) ? "a little " : "",
X				how_many[indx], S(indx));
X	}
X	else if (tilthen > DAY)
X		description = sprintf(descbuf, "this %s",
X					days[tt->tm_wday]);
X	else if (tilthen > -DAY) {
X		if (tn.tm_wday == tt->tm_wday)
X			if (tt->tm_hour < 7)
X				description = "early this morning";
X			else if (tt->tm_hour < 12)
X				description = "this morning";
X			else if (tt->tm_hour < 17)
X				description = "this afternoon";
X			else if (tt->tm_hour < 22)
X				description = "tonight";
X			else
X				description = "late tonight";
X		else if (tilthen > 0)
X			if (tt->tm_hour < 7)
X				description = "early tomorrow morning";
X			else if (tt->tm_hour < 12)
X				description = "tomorrow morning";
X			else if (tt->tm_hour < 17)
X				description = "tomorrow afternoon";
X			else if (tt->tm_hour < 22)
X				description = "tomorrow night";
X			else
X				description = "late tomorrow night";
X		else
X			if (tt->tm_hour < 7)
X				description = "early yesterday morning";
X			else if (tt->tm_hour < 12)
X				description = "yesterday morning";
X			else if (tt->tm_hour < 17)
X				description = "yesterday afternoon";
X			else if (tt->tm_hour < 22)
X				description = "last night";
X			else
X				description = "late last night";
X	}
X	else if (tilthen > -7 * DAY) {
X		description = sprintf(descbuf, "last %s",
X					days[tt->tm_wday]);
X	}
X	else if (tilthen > -30 * DAY) {
X		indx = -tilthen / (7*DAY);
X		remainder = (-tilthen % (7*DAY)) / DAY;
X		description = sprintf(descbuf,
X				"%sover %s week%s ago",
X				remainder < 3 ? "a little " : "",
X				how_many[indx],
X				S(indx));
X	}
X	else if (tilthen > -365 * DAY) {
X		indx = -tilthen / (30*DAY);
X		description = sprintf(descbuf,
X				"over %s month%s ago", how_many[indx],
X				S(indx));
X	}
X	else
X		description = "sometime during the Triassic...";
X#ifdef sun
X	cp = ctime((long *)&then);
X#else
X	cp = ctime(&then);
X#endif
X
X	ampm = (tt->tm_hour < 12) ? "am" : "pm";
X	if (tt->tm_hour > 12)
X		tt->tm_hour -= 12;
X	else if (tt->tm_hour == 0)
X		tt->tm_hour = 12;
X
X	(void) sprintf(tstr, "%d:%02d%s  %.3s. %d, %.4s (%s)",
X				tt->tm_hour, tt->tm_min, ampm,
X				cp+4, tt->tm_mday, 
X				cp+20, description);
X	return tstr;
X}
@//E*O*F src/date.c//
if test 8068 -ne "`wc -c <'src/date.c'`"; then
    echo shar: error transmitting "'src/date.c'" '(should have been 8068 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/disable.c'" '(621 characters)'
if test -f 'src/disable.c' ; then 
  echo shar: will not over-write existing file "'src/disable.c'"
else
sed 's/^X//' >src/disable.c <<'@//E*O*F src/disable.c//'
X#include <sys/types.h>
X#include <lastlog.h>
X#include "sysdep.h"
X#include "mem.h"
X#include "lists.h"
X#include "account.h"
X#include "save.h"
X
Xextern	int ModBits;
X
Xdisableuser(c, v)
Xint c;
Xaddr *v;
X
X{
X	struct account *ac;
X
X	if ( c > 2 ) {
X		err1("%s: too many arguments", (char *)v[0]);
X		return;
X	}
X	if (c != 2) {
X		err1("usage: %s <user>", (char *)v[0]);
X		return;
X	}
X	ac = getacnam((char *)v[1]);
X	if (!ac) {
X		err1("%s: no such user", (char *)v[1]);
X		return;
X	}
X
X	critical();
X	FREEMEM((char *)ac->ac_shell);
X	savestr((char **)&ac->ac_shell, DISABLED_SH);
X	ModBits |= PW;
X	puts("disabled");
X	non_critical();
X
X	return;
X}
@//E*O*F src/disable.c//
if test 621 -ne "`wc -c <'src/disable.c'`"; then
    echo shar: error transmitting "'src/disable.c'" '(should have been 621 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/edit.c'" '(613 characters)'
if test -f 'src/edit.c' ; then 
  echo shar: will not over-write existing file "'src/edit.c'"
else
sed 's/^X//' >src/edit.c <<'@//E*O*F src/edit.c//'
X#include <strings.h>
X#include "sysdep.h"
X#include "macros.h"
X#include "mem.h"
X
Xchar	*getenv();
X
Xedit(file)
Xchar *file;
X
X{
X	char *av[4];
X	char *term = getenv("TERM");
X	char *visual = getenv("VISUAL");
X	char *editor = getenv("EDITOR");
X	char *which;
X
X	if (!visual)
X		visual = DEF_VISUAL;
X	if (!editor)
X		editor = DEF_EDITOR;
X	if (!term)
X		term = "dumb";
X
X	if (eq(term, "dialup") || eq(term, "dumb"))
X		which = editor;
X	else if (eq(term, "network"))
X		which = editor;
X	else
X		which = visual;
X
X	av[0] = "shell-escape";
X	av[1] = which;
X	av[2] = file;
X	av[3] = (char *)0;
X	(void) shellescape(3, (addr *)av);
X	return;
X}
@//E*O*F src/edit.c//
if test 613 -ne "`wc -c <'src/edit.c'`"; then
    echo shar: error transmitting "'src/edit.c'" '(should have been 613 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/errmsg.c'" '(1741 characters)'
if test -f 'src/errmsg.c' ; then 
  echo shar: will not over-write existing file "'src/errmsg.c'"
else
sed 's/^X//' >src/errmsg.c <<'@//E*O*F src/errmsg.c//'
X/**********************************************************************\
X* 								       *
X* 	errmsg.c						       *
X* 								       *
X* Mcp eschews stderr and instead dumps things not wanted on stdout to  *
X* /dev/tty.  These routines should not be used while in cbreak mode    *
X* because they change the mode without regard to its previous state.   *
X* 								       *
X\**********************************************************************/
X
X#include <stdio.h>
X#include <strings.h>
X#include "mem.h"
X
Xextern	int errno, DevTty;
Xextern	char *sys_errlist[];
Xchar	*sprintf();
X
Xchar_scr(c)
Xchar c;
X
X{
X	(void) write(DevTty, &c, 1);
X	return;
X}
X
Xstr_scr(s)
Xregister char *s;
X
X{
X	(void) write(DevTty, s, strlen(s));
X}
X
Xmsg(ss)
Xchar *ss;
X
X{
X	static int old_length;
X	int i, new_length, hadnewline = 0;
X	char s[LONG_BUF];
X
X	(void) strcpy(s, ss);
X	new_length = strlen(s);
X	cbreak();
X	char_scr('\r');
X	if (s[new_length-1] == '\n') {
X		s[new_length-1] = '\0';
X		hadnewline++;
X		new_length--;
X	}
X	str_scr(s);
X	if (new_length < old_length) {
X		for (i=new_length; i<old_length; i++)
X			char_scr(' ');
X		for (i=new_length; i<old_length; i++)
X			char_scr('\b');
X	}
X	if (hadnewline) str_scr("\r\n");
X	nocbreak();
X	old_length = (hadnewline ? 0 : new_length);
X	return;
X}
X
Xerr(s)
Xchar *s;
X
X{
X	char errmsg[LONG_BUF];
X
X	(void) sprintf(errmsg, "%s\n", s);
X	msg(errmsg);
X	return;
X}
X
Xerr1(fmt, s1)
Xchar *fmt, *s1;
X
X{
X	char errmsg[LONG_BUF];
X
X	(void) sprintf(errmsg, fmt, s1);
X	(void) strcat(errmsg, "\n");
X	msg(errmsg);
X	return;
X}
X
Xerr2(fmt, s1, s2)
Xchar *fmt, *s1, *s2;
X
X{
X	char errmsg[LONG_BUF];
X
X	(void) sprintf(errmsg, fmt, s1, s2);
X	(void) strcat(errmsg, "\n");
X	msg(errmsg);
X	return;
X}
X
Xperr(s)
Xchar *s;
X
X{
X	err2("%s: %s", s, sys_errlist[errno]);
X	return;
X}
@//E*O*F src/errmsg.c//
if test 1741 -ne "`wc -c <'src/errmsg.c'`"; then
    echo shar: error transmitting "'src/errmsg.c'" '(should have been 1741 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/exists.c'" '(1531 characters)'
if test -f 'src/exists.c' ; then 
  echo shar: will not over-write existing file "'src/exists.c'"
else
sed 's/^X//' >src/exists.c <<'@//E*O*F src/exists.c//'
X#include <sys/file.h>
X#include <sys/types.h>
X#include <strings.h>
X#include <lastlog.h>
X#include "sysdep.h"
X#include "mem.h"
X#include "lists.h"
X#include "sort.h"
X#include "account.h"
X#include "groupmap.h"
X#include "class.h"
X#include "sig.h"
X
X#ifdef SENDMAIL
Xextern	struct list Aliases;
X#endif
Xextern	struct list AccountList, GroupMapList, Groups, Users;
Xextern	struct list Classes, Sigs, Ranges, Vigs;
X
Xint userexists(s)
Xchar *s;
X
X{
X	int found;
X
X	(void) search_list(&Users, s, strcmp, &found);
X	return found;
X}
X
Xint groupexists(s)
Xchar *s;
X
X{
X	int found;
X
X	(void) search_list(&Groups, s, strcmp, &found);
X	return found;
X}
X
Xint classexists(s)
Xchar *s;
X
X{
X	int found;
X
X	(void) search_list(&Classes, s, strcmp, &found);
X	return found;
X}
X
Xint rangeexists(s)
Xchar *s;
X
X{
X	int found;
X
X	(void) search_list(&Ranges, s, strcmp, &found);
X	return found;
X}
X
Xint vigexists(s)
Xchar *s;
X
X{
X	int found;
X
X	(void) search_list(&Vigs, s, strcmp, &found);
X	return found;
X}
X
Xint uidexists(n)
Xint n;
X
X{
X	int found;
X
X	(void) search_list(&AccountList, (char *)&n, iacctcmp, &found);
X	return found;
X}
X
Xint gidexists(n)
Xint n;
X
X{
X	int found;
X
X	(void) search_list(&GroupMapList, (char *)&n, igmapcmp, &found);
X	return found;
X}
X
Xsigexists(s)
Xchar *s;
X
X{
X	int found;
X
X	(void) search_list(&Sigs, s, strcmp, &found);
X	return found;
X}
X
X#ifdef SENDMAIL
Xaliasexists(name)
Xchar *name;
X
X{
X	int found;
X
X	(void) search_list(&Aliases, name, strcmp, &found);
X	return found;
X}
X#endif SENDMAIL
X
Xint
Xfileexists(file)
Xchar *file;
X
X{
X	return access(file, F_OK) == -1 ? 0 : 1;
X}
@//E*O*F src/exists.c//
if test 1531 -ne "`wc -c <'src/exists.c'`"; then
    echo shar: error transmitting "'src/exists.c'" '(should have been 1531 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/exit.c'" '(211 characters)'
if test -f 'src/exit.c' ; then 
  echo shar: will not over-write existing file "'src/exit.c'"
else
sed 's/^X//' >src/exit.c <<'@//E*O*F src/exit.c//'
X#include "mem.h"
X#include "lists.h"
X
Xextern	struct list Jobs;
Xextern	int ModBits;
X
Xexitmcp()
X
X{
X	if (ModBits || Jobs.l_count)
X		if (no("There are unsaved changes, exit anyway? [no] "))
X			return;
X	goodbye(0);
X}
@//E*O*F src/exit.c//
if test 211 -ne "`wc -c <'src/exit.c'`"; then
    echo shar: error transmitting "'src/exit.c'" '(should have been 211 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/exits.c'" '(483 characters)'
if test -f 'src/exits.c' ; then 
  echo shar: will not over-write existing file "'src/exits.c'"
else
sed 's/^X//' >src/exits.c <<'@//E*O*F src/exits.c//'
X#include <stdio.h>
X#include <strings.h>
X#include "sysdep.h"
X#include "mem.h"
X
Xextern	int root;
Xchar	*sprintf();
X
Xgoodbye(n)
Xint n;
X
X{
X	if (root)
X		unlockpw();
X	msg("");
X	nocbreak();
X	exit(n);
X}
X
Xfatal(s)
Xchar *s;
X
X{
X	char fatalmsg[LONG_BUF];
X
X	(void) sprintf(fatalmsg, "%s\n", s);
X	msg(fatalmsg);
X	goodbye(1);
X}
X
Xfatal1(fmt, s1)
Xchar *fmt, *s1;
X
X{
X	char fatalmsg[LONG_BUF];
X
X	(void) sprintf(fatalmsg, fmt, s1);
X	(void) strcat(fatalmsg, "\n");
X	msg(fatalmsg);
X	goodbye(1);
X	return;
X}
@//E*O*F src/exits.c//
if test 483 -ne "`wc -c <'src/exits.c'`"; then
    echo shar: error transmitting "'src/exits.c'" '(should have been 483 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/freeze.c'" '(3001 characters)'
if test -f 'src/freeze.c' ; then 
  echo shar: will not over-write existing file "'src/freeze.c'"
else
sed 's/^X//' >src/freeze.c <<'@//E*O*F src/freeze.c//'
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#include "groupmap.h"
X#include "save.h"
X#include "sort.h"
X
X#ifdef BSD4_3
Xtime_t	time();
X#endif
X
X#define DAY	(4*21600)
X
Xextern	struct list AccountList;
Xextern	int ModBits;
Xchar	*sprintf(), *when();
X
Xfreezeuser(c, v)
Xint c;
Xchar **v;
X
X{
X	struct account *ac;
X	struct groupmap *gm;
X	char errmsg[LONG_BUF];
X
X	if (c != 2) {
X		err1("usage: %s <user>", (char *)v[0]);
X		return;
X	}
X	ac = getacnam((char *)v[1]);
X	if (!ac) {
X		err1("%s: no such user", (char *)v[1]);
X		return;
X	}
X	if (eq(ac->ac_shell, FREEZE_SH)) {
X		err1("%s: already frozen", (char *)ac->ac_name);
X		return;
X	}
X	gm = getgmgid(ac->ac_gid);
X	if (!gm) {
X		(void) sprintf(errmsg,
X			"no group for gid %d!", ac->ac_gid);
X		err(errmsg);
X		return;
X	}
X	if (vigexists(gm->gm_name)) {
X		(void) sprintf(errmsg,
X			"%s is in vig %s, freeze anyway? [yes] ",
X			ac->ac_name, gm->gm_name);
X		if (yes(errmsg) == 0)
X			return;
X	}
X
X	critical();
X	FREEMEM((char *)ac->ac_shell);
X	savestr((char **)&ac->ac_shell, FREEZE_SH);
X	ModBits |= PW;
X	puts("frozen");
X	non_critical();
X
X	return;
X}
X
Xfreezeinactives(c, v)
Xint c;
Xchar **v;
X
X{
X	struct account *ac;
X	struct groupmap *gm;
X	time_t now, toolong, doomsday;
X	register int indx;
X	int frozen = 0;
X
X	if (c != 2) {
X		err1("usage: %s <user>", (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	now = time((time_t *)0);
X	toolong = atoi((char *)v[1]) * DAY;
X	if (toolong <= 0) {
X		err1("%s: Not bloody likely.", (char *)v[0]);;
X		return;
X	}
X	doomsday = now - toolong;
X	(void) printf("The axe falls %s\n", when(doomsday));
X
X	critical();
X	for (indx=0; indx < AccountList.l_count; indx++) {
X		ac = (struct account *) AccountList.l_list[indx];
X		if (ac->ac_ll.ll_time > doomsday)
X			continue;
X		/*
X		 * Don't freeze cryos again.
X		 */
X		if (eq(ac->ac_shell, FREEZE_SH))
X			continue;
X		gm = getgmgid(ac->ac_gid);
X		if (gm && vigexists(gm->gm_name))
X				continue;
X		FREEMEM((char *)ac->ac_shell);
X		savestr((char **)&ac->ac_shell, FREEZE_SH);
X		frozen++;
X	}
X	if (frozen) {
X		(void) printf("%d frozen\n", frozen);
X		ModBits |= PW;
X	}
X	else
X		err("no change");
X	non_critical();
X
X	return;
X}
X
Xfreezedeadbeats()
X
X{
X	struct account *ac;
X	struct groupmap *gm;
X	register int indx;
X	int frozen = 0;
X
X	critical();
X	for (indx=0; indx < AccountList.l_count; indx++) {
X		ac = (struct account *) AccountList.l_list[indx];
X		if (ac->ac_classes.l_count || ac->ac_sigs.l_count)
X			continue;
X		/*
X		 * Don't freeze cryos again.
X		 */
X		if (eq(ac->ac_shell, FREEZE_SH))
X			continue;
X		gm = getgmgid(ac->ac_gid);
X		if (gm && vigexists(gm->gm_name))
X			continue;
X		FREEMEM((char *)ac->ac_shell);
X		savestr((char **)&ac->ac_shell, FREEZE_SH);
X		frozen++;
X	}
X	if (frozen) {
X		(void) printf("%d frozen\n", frozen);
X		ModBits |= PW;
X	}
X	else
X		err("no change");
X	non_critical();
X
X	return;
X}
@//E*O*F src/freeze.c//
if test 3001 -ne "`wc -c <'src/freeze.c'`"; then
    echo shar: error transmitting "'src/freeze.c'" '(should have been 3001 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/groupmap.c'" '(727 characters)'
if test -f 'src/groupmap.c' ; then 
  echo shar: will not over-write existing file "'src/groupmap.c'"
else
sed 's/^X//' >src/groupmap.c <<'@//E*O*F src/groupmap.c//'
X#include "sysdep.h"
X#include "macros.h"
X#include "mem.h"
X#include "lists.h"
X#include "groupmap.h"
X
Xextern	struct list GroupMapList;
Xextern	int igmapcmp();
X
Xstruct groupmap *
Xgetgmnam(name)
Xchar *name;
X
X{
X	register int index;
X	struct groupmap *g;
X
X	if (!groupexists(name))
X		return (struct groupmap *) 0;
X	for (index=0; index < GroupMapList.l_count; index++) {
X		g = (struct groupmap *) GroupMapList.l_list[index];
X		if (eq(g->gm_name, name))
X			return g;
X	}
X	return (struct groupmap *) 0;
X}
X
Xstruct groupmap *
Xgetgmgid(gid)
Xint gid;
X
X{
X	int index, found;
X
X	index = search_list(&GroupMapList, (char *)&gid, igmapcmp, &found);
X	if (found)
X		return (struct groupmap *) GroupMapList.l_list[index];
X	return (struct groupmap *) 0;
X}
@//E*O*F src/groupmap.c//
if test 727 -ne "`wc -c <'src/groupmap.c'`"; then
    echo shar: error transmitting "'src/groupmap.c'" '(should have been 727 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/groupmap.h'" '(161 characters)'
if test -f 'src/groupmap.h' ; then 
  echo shar: will not over-write existing file "'src/groupmap.h'"
else
sed 's/^X//' >src/groupmap.h <<'@//E*O*F src/groupmap.h//'
Xstruct groupmap {
X	int		gm_gid;
X	char		*gm_name;
X	char		*gm_passwd;
X	struct list	gm_mem;
X	struct list 	gm_aliases;
X};
X
Xstruct groupmap *getgmnam(), *getgmgid();
@//E*O*F src/groupmap.h//
if test 161 -ne "`wc -c <'src/groupmap.h'`"; then
    echo shar: error transmitting "'src/groupmap.h'" '(should have been 161 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/history.h'" '(278 characters)'
if test -f 'src/history.h' ; then 
  echo shar: will not over-write existing file "'src/history.h'"
else
sed 's/^X//' >src/history.h <<'@//E*O*F src/history.h//'
X#define MAXHIST		40
X
Xstruct	hist {
X	char		*h_line;	/* contents of line */
X	char		*h_prompt;	/* prompt */
X	int		h_argc;		/* arg count */
X	int		h_index;	/* cursor */
X	int		h_windex;	/* word index */
X	int		h_qopen;	/* quote open? */
X	struct list	*h_list;	/* completion list */
X};
X
@//E*O*F src/history.h//
if test 278 -ne "`wc -c <'src/history.h'`"; then
    echo shar: error transmitting "'src/history.h'" '(should have been 278 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/job.h'" '(242 characters)'
if test -f 'src/job.h' ; then 
  echo shar: will not over-write existing file "'src/job.h'"
else
sed 's/^X//' >src/job.h <<'@//E*O*F src/job.h//'
Xstruct	job {
X	int	jb_todo;
X	char	*jb_name;
X	char	*jb_oldname;
X	int	jb_uid;
X	int	jb_olduid;
X	int	jb_gid;
X	addr	jb_addr;
X};
X
X#define JB_LASTLOG	1
X#define JB_MKDIR	2
X#define JB_MV		3
X#define JB_OMNICHOWN	4
X#define JB_RMDIR	5
X#define JB_RMMAIL	6
@//E*O*F src/job.h//
if test 242 -ne "`wc -c <'src/job.h'`"; then
    echo shar: error transmitting "'src/job.h'" '(should have been 242 characters)'
fi
fi # end of overwriting check
echo shar: "End of archive 4 (of 8)."
cp /dev/null ark4isdone
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