sources-request@mirror.UUCP (02/07/87)
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@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