DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T i

⟦0e5fc1a3d⟧ TextFile

    Length: 16005 (0x3e85)
    Types: TextFile
    Names: »init.c«

Derivation

└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
    └─ ⟦this⟧ »EUUGD11/euug-87hel/sec8/mcp/src/init.c« 

TextFile

#include <stdio.h>
#include <sys/file.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#include <lastlog.h>
#include <strings.h>
#include <errno.h>
#include "sysdep.h"
#include "macros.h"
#include "mem.h"
#include "sort.h"
#include "lists.h"
#include "save.h"
#include "sig.h"
#include "class.h"
#include "account.h"
#include "command.h"
#include "groupmap.h"
#include "range.h"
#ifdef SENDMAIL
#include "alias.h"
#endif

#ifdef sun
# ifdef DOFILES
/*
 * Lint complains about all the unused functions declared in netdb.h
 * and mntent.h... but these functions are >>declared<< NOT
 * >>defined<< so lint should SHUT UP about this!!  Since it doesn't, 
 * we work around its ignorance.
 */
#  ifndef lint
#  include <mntent.h>
#  include <netdb.h>
#  else
struct	servent {
	char	*s_name;	/* official service name */
	char	**s_aliases;	/* alias list */
	int	s_port;		/* port # */
	char	*s_proto;	/* protocol to use */
};
struct	servent *getservbyname();

#  define MNTTAB	"/etc/fstab"
struct	mntent{
	char	*mnt_fsname;		/* name of mounted file system */
	char	*mnt_dir;		/* file system path prefix */
	char	*mnt_type;		/* MNTTYPE_* */
	char	*mnt_opts;		/* MNTOPT* */
	int	mnt_freq;		/* dump frequency, in days */
	int	mnt_passno;		/* pass number on parallel fsck */
};
struct	mntent *getmntent();
FILE 	*setmntent();
#  endif lint
# endif DOFILES
#endif sun

static char *e1 = "password file has more lines than accounts file.";
static char *e2 = "accounts file has more lines than password file.";
static char *e3 = "line %d: login name not the same in accounts/passwd.";

extern	struct lastlog *getlluid(), *getllent();
extern	struct list YesNo, Titles, Suffixes, History;
extern	char *sprintf(), *getpass();

#ifdef BSD4_3
uid_t	geteuid(), getuid();
char	*getwd();
time_t	time();
#endif

#ifdef SENDMAIL
extern	addalias(), addtoalias(), bindclass(), bindgroup(), bindsig();
extern	desalias();
extern	rmalias(), rmfromalias(), ubindclass(), ubindgroup(), ubindsig();
extern	updalias();
#endif
#ifdef HELPDIR
extern	descommand(), whatis();
#endif
extern	addclass(), addgroup(), addrange(), addsig();
extern	addtoclass(), addtogroup();
extern	addtosig(), adduser(), addvig();
extern	ckpchanges();
extern	deschanges(), desclass();
extern	descryos(), desdeadbeats(), desgroup(), desinactives(), desrange();
extern	dessig(), desuser(), disableuser(), exitmcp();
extern	freezedeadbeats(), freezeinactives(), freezeuser();
extern	listgeneric(), listcryos();
extern	listdeadbeats(), listinactives();
extern	loadfile(), pausemcp(), rmclass();
extern	rmcryos(), rmfromclass(), rmfromgroup(), rmfromsig();
extern	rmgroup();
extern	rmrange(), rmsig(), rmuser(), rmvig(), savechanges(), saveandexit();
extern	shellescape();
extern	updclass(), updgroup(), updrange(), updsig(), upduser();

struct command Ctable[] = {
#ifdef SENDMAIL
	{ "add-alias",		addalias,		1 },
#endif
	{ "add-class",		addclass,		1 },
	{ "add-group",		addgroup,		1 },
	{ "add-range",		addrange,		1 },
	{ "add-sig",		addsig,			1 },
#ifdef SENDMAIL
	{ "add-to-alias",	addtoalias,		1 },
#endif
	{ "add-to-class",	addtoclass,		1 },
	{ "add-to-group",	addtogroup,		1 },
	{ "add-to-sig",		addtosig,		1 },
	{ "add-user",		adduser,		1 },
	{ "add-vig",		addvig,			1 },
#ifdef SENDMAIL
	{ "bind-group",		bindgroup,		1 },
	{ "bind-class",		bindclass,		1 },
	{ "bind-sig",		bindsig,		1 },
#endif
	{ "checkpoint-changes",	ckpchanges,		1 },
#ifdef SENDMAIL
	{ "describe-alias",	desalias,		0 },
#endif
	{ "describe-class",	desclass,		0 },
	{ "describe-changes",	deschanges,		1 },
#ifdef HELPDIR
	{ "describe-command",	descommand,		0 },
#endif
	{ "describe-cryos",	descryos,		0 },
	{ "describe-deadbeats",	desdeadbeats,		0 },
	{ "describe-group",	desgroup,		0 },
	{ "describe-inactives",	desinactives,		0 },
	{ "describe-range",	desrange,		0 },
	{ "describe-sig",	dessig,			0 },
	{ "describe-user",	desuser,		0 },
	{ "disable-user",	disableuser,		1 },
	{ "exit-mcp",		exitmcp,		0 },
	{ "freeze-deadbeats",	freezedeadbeats,	1 },
	{ "freeze-inactives",	freezeinactives,	1 },
	{ "freeze-user",	freezeuser,		1 },
#ifdef SENDMAIL
	{ "list-aliases",	listgeneric,		0 },
#endif
	{ "list-classes",	listgeneric,		0 },
	{ "list-commands",	listgeneric,		0 },
	{ "list-cryos",		listcryos,		0 },
	{ "list-deadbeats",	listdeadbeats,		0 },
	{ "list-groups",	listgeneric,		0 },
	{ "list-inactives",	listinactives,		0 },
	{ "list-ranges",	listgeneric,		0 },
	{ "list-sigs",		listgeneric,		0 },
	{ "list-users",		listgeneric,		0 },
	{ "list-vigs",		listgeneric,		0 },
	{ "load-file",		loadfile,		1 },
	{ "pause-mcp",		pausemcp,		0 },
#ifdef SENDMAIL
	{ "remove-alias",	rmalias,		1 },
#endif
	{ "remove-class",	rmclass,		1 },
	{ "remove-cryos",	rmcryos,		1 },
#ifdef SENDMAIL
	{ "remove-from-alias",	rmfromalias,		1 },
#endif
	{ "remove-from-class",	rmfromclass,		1 },
	{ "remove-from-group",	rmfromgroup,		1 },
	{ "remove-from-sig",	rmfromsig,		1 },
	{ "remove-group",	rmgroup,		1 },
	{ "remove-range",	rmrange,		1 },
	{ "remove-sig",		rmsig,			1 },
	{ "remove-user",	rmuser,			1 },
	{ "remove-vig",		rmvig,			1 },
	{ "save-and-exit",	saveandexit,		1 },
	{ "save-changes",	savechanges,		1 },
	{ "shell-escape",	shellescape,		0 },
#ifdef SENDMAIL
	{ "unbind-group",	ubindgroup,		1 },
	{ "unbind-class",	ubindclass,		1 },
	{ "unbind-sig",		ubindsig,		1 },
	{ "update-alias",	updalias,		1 },
#endif
	{ "update-class",	updclass,		1 },
	{ "update-group",	updgroup,		1 },
	{ "update-range",	updrange,		1 },
	{ "update-sig",		updsig,			1 },
	{ "update-user",	upduser,		1 },
#ifdef HELPDIR
	{ "what-is",		whatis,			0 },
#endif
	{ (char *) 0,		(int (*)())0,		0 }
};

#ifdef HELPDIR
static	char *TermTable[] = {
# ifdef SENDMAIL
	"alias",
# endif
	"class",
	"cryo",
	"deadbeat",
	"gid",
	"inactive",
	"range",
	"sig",
	"uid",
	"vig",
	(char *)0
};
#endif

struct	list TempLists;			/* list of lists to freed */
#ifdef SENDMAIL
struct	list Aliases;			/* alias name completion list */
struct	list AliasList;			/* list of alias structures */
#endif
struct	list AllCommands;		/* complete list of mcp commands */
struct	list Commands;			/* commands this user is allowed */
struct	list Users;			/* user name completion list */
struct	list AccountList;		/* list of account structures */
struct	list Classes;			/* class name completion list */
struct	list ClassList;			/* list of class structures */
struct	list Groups;			/* group name completion list */
struct	list GroupMapList;		/* list of groupmap structures */
struct	list Ranges;			/* range name completion list */
struct	list RangeList;			/* list of range structures */
struct	list Sigs;			/* sig name completion list */
struct	list SigList;			/* list of sig structures */
struct	list Jobs;			/* list of job structures */
#ifdef HELPDIR
struct	list Terms;			/* list of terms mcp can define */
#endif
struct	list Shells;			/* list of shells (from SHELLFILE) */
struct	list Vigs;			/* vig completion list */
struct	list Null_List;			/* empty list */

int	ModBits;			/* flags denoting modified files */
int	DevTty;				/* descriptor for diagnostic output
					   and prompts. DevTty = 2 for non-
					   interactive runs. */
time_t	PWLockTime;			/* last modify time for /etc/passwd */
int	root;				/* is this the super-user? */
int	kids;				/* current # of child processes */
int	NCommands;			/* # of commands user can execute */

addr	DEF_SHELL;			/* default shell */
char	Working_Directory[LONG_BUF];	/* current working driectory */
#ifdef sun
int	IsRemote;			/* must we use remote commands */
char	HostName[MEDIUM_BUF];		/* current hostname */
# ifdef DOFILES
char	FileServer[MEDIUM_BUF];		/* hostname of file server */
char	MountDirectory[MEDIUM_BUF];	/* remote mount point */
char	RemotePassword[SHORT_BUF];	/* root password of fileserver */
u_short	ExecTcpPort;			/* port for exec/tcp service */
# endif
#endif


init_lists(interactive)
int interactive;

{
	FILE *fp;
	flexaddr p;
#ifdef SENDMAIL
	struct alias al, *al2;
	struct groupmap *gm2;
#endif
	struct account ac, *ac2;
	struct passwd *pw;
	struct group *gr;
	struct groupmap gm;
	struct sig sg, *sg2;
	struct class cs, *cs2;
	struct range rg, *rg2;
	struct lastlog *ll;
	char buf[LONG_BUF], errmsg[LONG_BUF], sh[MEDIUM_BUF], *cp;
	int indx, lineno = 0;

	if (interactive) msg("Loading password and accounts...");
	(void) setpwent();
	(void) setacent();
	(void) setllent();
	while ((pw = getpwent()) != (struct passwd *)0) {
		ac2 = getacent();
		if (!ac2)
			fatal(e1);
		lineno++;
		if (!eq((char *)ac2->ac_name, pw->pw_name)) {
			(void) sprintf(errmsg, e3, lineno);
			fatal(errmsg);
		}
		ac.ac_uid = pw->pw_uid;
		ac.ac_gid = pw->pw_gid;
		savestr((char **)&ac.ac_name, pw->pw_name);
		savestr((char **)&ac.ac_gecos, pw->pw_gecos);
		savestr((char **)&ac.ac_passwd, pw->pw_passwd);
		savestr((char **)&ac.ac_dir, pw->pw_dir);
		savestr((char **)&ac.ac_shell, pw->pw_shell);
		savestr((char **)&ac.ac_realname, (char *)ac2->ac_realname);
		savestr((char **)&ac.ac_id, (char *)ac2->ac_id);
		duplist(&ac.ac_groups, &ac2->ac_groups);
		duplist(&ac.ac_classes, &ac2->ac_classes);
		duplist(&ac.ac_sigs, &ac2->ac_sigs);
#ifdef SENDMAIL
		duplist(&ac.ac_aliases, &ac2->ac_aliases);
#endif
		ll = getlluid(ac.ac_uid);
		bcopy(&ac.ac_ll, ll, sizeof (struct lastlog));
		genlistadd(&AccountList, (addr)&ac, sizeof (struct account));
		strlistadd(&Users, pw->pw_name);
	}
	(void) endpwent();
	endllent();
	if (getacent()) fatal(e2);
	(void) endacent();

	if (interactive) msg("Loading groups...");
	zerolist(&gm.gm_aliases);
	(void) setgrent();
	while ((gr = getgrent()) != (struct group *)0) {
		zerolist(&gm.gm_mem);
#ifdef SENDMAIL
 		zerolist(&gm.gm_aliases);
#endif
		gm.gm_gid = gr->gr_gid;
		savestr(&gm.gm_name, gr->gr_name);
		savestr(&gm.gm_passwd, gr->gr_passwd);
		for (indx=0; gr->gr_mem[indx]; indx++)
			strlistadd(&gm.gm_mem, gr->gr_mem[indx]);
		sort_list(&gm.gm_mem, pstrcmp);
		genlistadd(&GroupMapList, (addr)&gm, sizeof(struct groupmap));
		strlistadd(&Groups, gr->gr_name);
	}
	(void) endgrent();
	if (interactive) msg("Loading classes...");
#ifdef SENDMAIL
	zerolist(&cs.cs_aliases);
#endif
	setcsent();
	while (cs2 = getcsent()) {
		savestr(&cs.cs_name, cs2->cs_name);
		savestr(&cs.cs_desc, cs2->cs_desc);
		cs.cs_dsize = cs2->cs_dsize;
		cs.cs_exptime = cs2->cs_exptime;
		genlistadd(&ClassList, (addr)&cs, sizeof (struct class));
		strlistadd(&Classes, cs.cs_name);
	}
	endcsent();
	if (interactive) msg("Loading sigs...");
#ifdef SENDMAIL
	zerolist(&sg.sg_aliases);
#endif
	setsgent();
	while (sg2 = getsgent()) {
		savestr(&sg.sg_name, sg2->sg_name);
		savestr(&sg.sg_desc, sg2->sg_desc);
		sg.sg_dsize = sg2->sg_dsize;
		sg.sg_exptime = sg2->sg_exptime;
		genlistadd(&SigList, (addr)&sg, sizeof (struct sig));
		strlistadd(&Sigs, sg.sg_name);
	}
	endsgent();
	if (interactive) msg("Loading range table...");
	setrgent();
	while (rg2 = getrgent()) {
		savestr(&rg.rg_name, rg2->rg_name);
		rg.rg_mode = rg2->rg_mode;
		rg.rg_from = rg2->rg_from;
		rg.rg_to = rg2->rg_to;
		genlistadd(&RangeList, (addr)&rg, sizeof (struct range));
		strlistadd(&Ranges, rg.rg_name);
	}
	endrgent();

	if (interactive) msg("Loading vigs...");
	fp = fopen(VIGFILE, "r");
	if (fp != NULL) {
		while (fscanf(fp, "%s", buf) != EOF)
			strlistadd(&Vigs, buf);
		(void) fclose(fp);
	}

#ifdef SENDMAIL
	/*
	 * Must sort here so that get{cs,gm,sg}nam() calls will work.
	 */
	if (interactive) msg("Loading and binding sendmail aliases...");
	sort_list(&Groups, pstrcmp);
	sort_list(&ClassList, classcmp);
	sort_list(&SigList, sigcmp);
	setalent();
	while (al2 = getalent()) {
		savestr(&al.al_name, al2->al_name);
		duplist(&al.al_addresses, &al2->al_addresses);
		duplist(&al.al_groups, &al2->al_groups);
		duplist(&al.al_classes, &al2->al_classes);
		duplist(&al.al_sigs, &al2->al_sigs);
		genlistadd(&AliasList, (addr)&al, sizeof (struct alias));
		strlistadd(&Aliases, al.al_name);
		for (indx=0; indx < al.al_groups.l_count; indx++) {
			cp = (char *)al.al_groups.l_list[indx];
			gm2 = getgmnam(cp);
			if (!gm2)
				continue;
			strlistadd(&gm2->gm_aliases, al.al_name);
			sort_list(&gm2->gm_aliases, pstrcmp);
		}
		for (indx=0; indx < al.al_classes.l_count; indx++) {
			cp = (char *)al.al_classes.l_list[indx];
			cs2 = getcsnam(cp);
			if (!cs2)
				continue;
			strlistadd(&cs2->cs_aliases, al.al_name);
			sort_list(&cs2->cs_aliases, pstrcmp);
		}
		for (indx=0; indx < al.al_sigs.l_count; indx++) {
			cp = (char *)al.al_sigs.l_list[indx];
			sg2 = getsgnam(cp);
			if (!sg2)
				continue;
			strlistadd(&sg2->sg_aliases, al.al_name);
			sort_list(&sg2->sg_aliases, pstrcmp);
		}
	}
	endalent();
#endif
	/*
	 * If this is not an interactive session there is no need
	 * to initialize the lists that are only used when mcp
	 * is running interactively.
	 */
	if (!interactive) goto sort_em;

	msg("Commands...");
	for (indx=0; Ctable[indx].c_name; indx++) {
		if (root || !Ctable[indx].c_su)
			strlistadd(&Commands, Ctable[indx].c_name);
		strlistadd(&AllCommands, Ctable[indx].c_name);
	}
	NCommands = indx;
	qsort((char *)Ctable, NCommands, sizeof (struct command), commcmp);

#ifdef HELPDIR
	msg("Building term table...");
	for (indx=0; TermTable[indx]; indx++)
		strlistadd(&Terms, TermTable[indx]);
#endif
	msg("Loading shell table...");
	fp = fopen(SHELLFILE, "r");
	if (fp != NULL) {
		while (fgets(buf, LONG_BUF, fp) != NULL) {
			cp = index(buf, '#');
			if (cp) *cp = '\0';
			if (sscanf(buf, "%s", sh) != 1)
				continue;
			strlistadd(&Shells, sh);
		}
		(void) fclose(fp);
	}
	p.p_cp = (Shells.l_count ? (char *) Shells.l_list[0] : "/bin/sh");
	DEF_SHELL = p.p_ap;

sort_em:
	if (interactive) msg("Sorting lists...");
	sort_list(&AccountList, acctcmp);
	sort_list(&GroupMapList, gmapcmp);
	sort_list(&Users, pstrcmp);
	sort_list(&Classes, pstrcmp);
	sort_list(&Sigs, pstrcmp);
	sort_list(&Ranges, pstrcmp);
	sort_list(&RangeList, rangecmp);
	sort_list(&Vigs, pstrcmp);
#ifdef SENDMAIL
	sort_list(&AliasList, aliascmp);
	sort_list(&Aliases, pstrcmp);
#else
	sort_list(&Groups, pstrcmp);
	sort_list(&ClassList, classcmp);
	sort_list(&SigList, sigcmp);
#endif
	if (interactive) {
		sort_list(&Titles, pstrcmp);
		sort_list(&Suffixes, pstrcmp);
		sort_list(&YesNo, pstrcmp);
		sort_list(&Shells, pstrcmp);
		sort_list(&Commands, pstrcmp);
		sort_list(&AllCommands, pstrcmp);
#ifdef HELPDIR
		sort_list(&Terms, pstrcmp);
#endif
		msg("and...");
		zerolist(&History);
		zerolist(&TempLists);
		msg("");
	}
	return;
}

init_tty(interactive)
int interactive;

{
	extern int errno;
	long lseek();

	if (!interactive) {
		DevTty = 2;
		return;
	}
	if ((DevTty = open("/dev/tty", O_RDWR)) < 0) {
		perror("/dev/tty");
		goodbye(1);
	}
	if (lseek(0, 0L, L_INCR) == -1) {
	    if (errno == ESPIPE)
		err("mcp reading from a pipe...");
	}
	else if (!isatty(0))
	    err("mcp reading from a file...");
	return;
}

init_identities()

{
#ifdef sun
# ifdef DOFILES
	FILE *mnf;
	struct mntent *mn;
	struct servent *sv;
	char *cp, prompt[MEDIUM_BUF];
# endif
#endif
	root = !(getuid() && geteuid());
	if (!getwd(Working_Directory))
		fatal1("getwd() failed!?: %s", Working_Directory);
	srandom(getpid() + getppid() + time((time_t *)0));
#ifdef sun
	if (gethostname(HostName, MEDIUM_BUF) == -1) {
		perr("gethostname");
		fatal("mcp: Sorry, but I must have a hostname.");
	}
# ifdef DOFILES
	if (!root) return;
	mnf = setmntent(MNTTAB, "r");
	if (mnf == NULL) {
		fatal1("can't open %s", MNTTAB);
		goodbye(1);
	}
	while (mn = getmntent(mnf))
		if (eq(mn->mnt_dir, USERDIR))
			break;
	if (mn && eq(mn->mnt_type, "nfs")) {
		cp = index(mn->mnt_fsname, ':');
		*cp++ = '\0';
		(void) strcpy(FileServer, mn->mnt_fsname);
		(void) strcpy(MountDirectory, cp);
		sv = getservbyname("exec", "tcp");
		if (!sv)
			fatal("mcp: can't find service exec/tcp");
		ExecTcpPort = sv->s_port;
	/* root is not trusted over the network */
		(void) sprintf(prompt, "Root password on %s:", FileServer);
		cp = getpass(prompt);
		(void) strcpy(RemotePassword, cp);
		if (DoRemote("/bin/true") == 0)
			fatal("Sorry");
		IsRemote = 1;
	}
	(void) endmntent(mnf);
# endif
#endif
	return;
}