v08i047: Account creation/manipulation program, Part07/08
sources-request at mirror.UUCP
sources-request at mirror.UUCP
Sat Feb 7 07:19:57 AEST 1987
Submitted by: Kyle Jones <xanth!kyle>
Mod.sources: Volume 8, Issue 47
Archive-name: mcp/Part07
#! /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 7 (of 8)."
# Contents: src/load.c src/main.c src/misc.c src/nitpick src/pwlock.c
# src/range.c src/range.h src/remove.c src/report.c
# Wrapped by rs at mirror on Fri Feb 6 15:56:11 1987
PATH=/bin:/usr/bin:/usr/ucb; export PATH
echo shar: extracting "'src/load.c'" '(7238 characters)'
if test -f 'src/load.c' ; then
echo shar: will not over-write existing file "'src/load.c'"
else
sed 's/^X//' >src/load.c <<'@//E*O*F src/load.c//'
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/file.h>
X#include <lastlog.h>
X#include <strings.h>
X#include "sysdep.h"
X#include "macros.h"
X#include "mem.h"
X#include "gpa.h"
X#include "lists.h"
X#include "account.h"
X#include "groupmap.h"
X#include "save.h"
X#include "sort.h"
X
Xaddr makeusername(), gethomedir();
Xint nlformat(), nfformat(), (*format)(), ModBits;
Xextern addr DEF_SHELL;
Xchar *crypt(), *sprintf();
X
Xint lineno;
Xaddr *filev;
X
Xloadfile(c, v)
Xint c;
Xaddr *v;
X
X{
X FILE *f;
X flexaddr p;
X char line[LONG_BUF];
X addr user, password, id, dir, *vv;
X addr *realnamev;
X addr_t shell[MEDIUM_BUF];
X struct account *ac;
X struct groupmap *gm, *gm2;
X static struct list groups, classes, sigs;
X int cc, added, gid, uid, i;
X int totaladded = 0, filesloaded = 0;
X
X zerolist(&groups); tmplistadd(&groups);
X zerolist(&sigs); tmplistadd(&sigs);
X zerolist(&classes); tmplistadd(&classes);
X if (c == 1) {
X filev = get_gpa(8);
X GetFilenames("Files: ", 8, &cc, filev);
X if (cc == 0)
X return;
X }
X else
X filev = &v[1];
X for (; *filev; filev++) {
X added = 0;
X lineno = 1;
X if (access((char *)*filev, F_OK|R_OK) == -1) {
X perr((char *)*filev);
X err1("%s: file load aborted", (char *)*filev);
X continue;
X }
X f = fopen((char *)*filev, "r");
X if (f == NULL) {
X perr((char *)*filev);
X err1("%s: file load aborted", (char *)*filev);
X continue;
X }
X if (hascolon(f)) {
X err1("%s: file has colons in it! (load aborted)",
X (char *)*filev);
X continue;
X }
X (void) printf("%s:\n",(char *)*filev);
X /*
X * First line should identity the file format
X */
X if (fgets(line, BUFSIZ, f) == NULL) {
X gag("missing format line");
X gag("file load aborted");
X continue;
X }
X switch (*line) {
X /* name first format */
X case 'N':
X case 'n': format = nfformat; break;
X /* Id first format */
X case 'I':
X case 'i': format = nlformat; break;
X default:
X gag1("bad format token \"%.8s\"", line);
X gag("file load aborted");
X continue;
X }
X lineno++;
X /*
X * Second line should be a list of space separated
X * groups that the added users will be put into
X * The first group in the list will be the users base
X * gid group (the group for the gid in the passwd file).
X * It is an error for this line to be empty.
X */
X if (fgets(line, BUFSIZ, f) == NULL) {
X gag("missing groups line");
X gag("file load aborted");
X continue;
X }
X parse_line(line, &cc, &vv);
X if (cc == 0) {
X gag("groups line empty");
X gag("file load aborted");
X continue;
X }
X gm = getgmnam((char *)vv[0]);
X if (!gm) {
X gag1("%s: no such group", (char *)vv[0]);
X gag("file load aborted");
X continue;
X }
X gid = gm->gm_gid;
X for (vv++; *vv; vv++)
X if (groupexists((char *)*vv))
X strlistadd(&groups, (char *)*vv);
X else
X gag1("%s: no such group", (char *)*vv);
X lineno++;
X /*
X * Third line should be a space separated list of
X * classes for the users to put in. This line must
X * be peresent although it is permitted to be empty.
X */
X if (fgets(line, BUFSIZ, f) == NULL) {
X gag("missing classes line");
X gag("file load aborted");
X continue;
X }
X parse_line(line, &cc, &vv);
X for (; *vv; vv++)
X if (classexists((char *)*vv))
X strlistadd(&classes, (char *)*vv);
X else
X gag1("%s: no such class", (char *)*vv);
X lineno++;
X /*
X * Fourth line should be a space separated list of
X * sigs for the users to put in. This line must
X * be present although it is permitted to be empty.
X */
X if (fgets(line, BUFSIZ, f) == NULL) {
X gag("missing sigs line");
X gag("file load aborted");
X continue;
X }
X parse_line(line, &cc, &vv);
X for (; *vv; vv++)
X if (sigexists((char *)*vv))
X strlistadd(&sigs, (char *)*vv);
X else
X gag1("%s: no such sig", (char *)*vv);
X lineno++;
X /*
X * Fifth line should contain the name of the shell
X * the added users should have. This line must be
X * present but it may be blank.
X */
X if (fgets(line, BUFSIZ, f) == NULL) {
X gag("missing shell line");
X gag("file load aborted");
X continue;
X }
X parse_line(line, &cc, &vv);
X if (cc && !fileexists((char *)vv[0])) {
X gag1("%s: nonexistent shell", (char *)vv[0]);
X gag("file load aborted");
X }
X else if (cc)
X (void) strcpy((char *)shell, (char *)vv[0]);
X else
X (void) strcpy((char *)shell, (char *)DEF_SHELL);
X lineno++;
X /*
X * Lines from here on should be in the format specified
X * above.
X */
X while (fgets(line, LONG_BUF, f) != NULL) {
X if ((*format)(line, &cc, &realnamev, &id) == 0) {
X gag("badly formed line");
X continue;
X }
X ac = getacid((char *)id);
X if (ac) {
X user = ac->ac_name;
X (void) orstrlist(&ac->ac_groups, &groups);
X orstrlist(&ac->ac_classes, &classes)&&
X ModBits |= AC;
X orstrlist(&ac->ac_sigs, &sigs)&&
X ModBits |= AC;
X for (i=0; i<groups.l_count; i++) {
X gm2 = getgmnam((char *)groups.l_list[i]);
X if (instrlist(&gm2->gm_mem, (char *)user))
X continue;
X ModBits |= (AC|GR);
X strlistadd(&gm2->gm_mem, (char *)user);
X sort_list(&gm2->gm_mem, pstrcmp);
X }
X (void) printf("%-12s%s\n", ac->ac_name,
X ac->ac_realname);
X continue;
X }
X uid = findnextuid(gm->gm_name);
X if (uid == NOMORE) {
X gag("no more uids");
X gag("load terminated");
X goto nextfile;
X }
X user = makeusername(cc, realnamev);
X p.p_cp = crypt((char *)id, CRYPT_SALT);
X password = p.p_ap;
X dir = gethomedir((char *)user, gm->gm_name);
X addu(uid, gid, user, glob(realnamev), password,
X id, dir, shell);
X added++;
X ac = getacnam((char *)user);
X (void) orstrlist(&ac->ac_groups, &groups);
X orstrlist(&ac->ac_classes, &classes)&&ModBits|=AC;
X orstrlist(&ac->ac_sigs, &sigs)&&ModBits|=AC;
X for (i=0; i<groups.l_count; i++) {
X gm2 = getgmnam((char *)groups.l_list[i]);
X if (instrlist(&gm2->gm_mem, (char *)user))
X continue;
X ModBits |= (AC|GR);
X strlistadd(&gm2->gm_mem, (char *)user);
X sort_list(&gm2->gm_mem, pstrcmp);
X }
X (void) printf("%-12s%s\n", ac->ac_name,
X ac->ac_realname);
X }
X nextfile:
X (void) printf("%s: %d added\n", *filev, added);
X filesloaded++;
X totaladded += added;
X freelist(&groups);
X freelist(&sigs);
X freelist(&classes);
X }
X if (totaladded) {
X (void) printf("%d file%s loaded, %d user%s added\n",
X filesloaded, S(filesloaded),
X totaladded, S(totaladded));
X#ifndef DOFILES
X err("Don't forget to create directories for these users.");
X#endif
X }
X return;
X}
X
Xint
Xhascolon(f)
XFILE *f;
X
X{
X int c;
X
X rewind(f);
X while ((c = getc(f)) != EOF)
X if (c == ':') {
X rewind(f);
X return 1;
X }
X rewind(f);
X return 0;
X}
X
Xint
Xnfformat(line, cc, r, id)
Xchar *line;
Xint *cc;
Xaddr **r;
Xaddr *id;
X
X{
X int c;
X addr *v;
X
X parse_line(line, &c, &v);
X if (c < 2)
X return 0;
X *id = v[c-1];
X v[c-1] = NIL;
X *cc = c - 1;
X *r = v;
X return 1;
X}
X
Xint
Xnlformat(line, cc, r, id)
Xchar *line;
Xint *cc;
Xaddr **r;
Xaddr *id;
X
X{
X int c;
X addr *v;
X
X parse_line(line, &c, &v);
X if (c < 2)
X return 0;
X *id = v[0];
X *cc = c - 1;
X *r = &v[1];
X return 1;
X}
X
Xstatic
Xgag(msg)
Xchar *msg;
X
X{
X char errmsg[LONG_BUF];
X
X (void) sprintf(errmsg, "%s: line %d: %s", *filev, lineno, msg);
X err(errmsg);
X return;
X}
X
Xstatic
Xgag1(msg, s1)
Xchar *msg;
Xchar *s1;
X
X{
X char errmsg[LONG_BUF];
X
X (void) sprintf(errmsg, msg, s1);
X gag(errmsg);
X return;
X}
@//E*O*F src/load.c//
if test 7238 -ne "`wc -c <'src/load.c'`"; then
echo shar: error transmitting "'src/load.c'" '(should have been 7238 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/main.c'" '(4050 characters)'
if test -f 'src/main.c' ; then
echo shar: will not over-write existing file "'src/main.c'"
else
sed 's/^X//' >src/main.c <<'@//E*O*F src/main.c//'
X#include <stdio.h>
X#include <sys/time.h>
X#include <sys/resource.h>
X#include <sys/wait.h>
X#include <setjmp.h>
X#include <signal.h>
X#include "sysdep.h"
X#include "macros.h"
X#include "mem.h"
X#include "command.h"
X
X#define ROOT_PROMPT "\r(mcp) "
X#define PROMPT "\r( ) "
X#define CARGS 32 /* # command line args allowed */
X
X#ifdef sun
X#define sighandler (void (*)())
X#else
X#define sighandler (int (*)())
X#endif
X
Xextern int scommcmp(), kids, root, ModBits, NCommands, goodbye(), DevTty;
Xextern struct command Ctable[];
Xextern char Working_Directory[];
Xextern int ReportGoop();
Xextern Summarize();
Xextern char *sprintf();
X
Xjmp_buf interrupt, in_continue; /* setjmp vectors */
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X
X{
X static char *prompt;
X static addr v[CARGS+1];
X int sjval, index, c, found, goop = 0;
X int buildit, checkem, summary, listem, printversion;
X char errmsg[MEDIUM_BUF];
X
X (void) umask(022);
X
X /*
X * Find out if this is the superuser, what the current working
X * directory is, seed random number generator.
X * For Sun systems, also find out about file server, etc.
X */
X init_identities();
X
X buildit = checkem = summary = listem = printversion = 0;
X while (--argc && **++argv == '-')
X for (++*argv; **argv; ++*argv)
X switch (**argv) {
X case 'v':
X printversion++; break;
X case 'l':
X listem++; break;
X case 'B':
X buildit++; break;
X case 'c':
X checkem++; break;
X case 's':
X summary++; break;
X default:
X (void) sprintf(errmsg, "mcp: bad option '%c' (ignored)",
X **argv);
X err(errmsg);
X break;
X }
X /*
X * Set up descriptor for /dev/tty or just attached to stderr
X * if not running interactively.
X */
X init_tty(buildit || (!checkem && !summary && !listem));
X
X if (buildit && (checkem || summary || listem))
X fatal("mcp: can't use -B with any other option.");
X if (buildit && !root)
X fatal("mcp: must be the super-user to use -B");
X if (argc)
X err("mcp: extra arguments ignored");
X if (printversion && !buildit) {
X ShowVersion();
X if (!(checkem || summary || listem))
X goodbye(0);
X }
X /*
X * Must set up some sort of quick 'n dirty signal handling lest
X * an interrupt cause the program to exit with the password
X * file locked. So we block all signals except SIGINT, and trap
X * SIGINT to goodbye().
X */
X (void) sigsetmask(~mask(SIGINT));
X (void) signal(SIGINT, sighandler goodbye);
X
X if ( root && !(checkem || summary || listem)) {
X msg("Locking password file...");
X if (!lockpw())
X fatal("mcp: password file busy");
X prompt = ROOT_PROMPT;
X }
X else
X prompt = PROMPT;
X
X if (buildit) Build(); /* Build() doesn't return */
X
X /*
X * Pass a flag to init_lists() to indicate whether all or
X * or only some of the global lists need be initialized.
X */
X init_lists(!(checkem || summary || listem));
X
X if (checkem) goop = ReportGoop();
X if (listem) ListThemThangs();
X if (summary) Summarize();
X if (checkem || summary || listem) goodbye(goop ? 1 : 0);
X
X#if CKPTIME > 0
X if (root)
X (void) alarm(CKPTIME * 60); /* start checkpointing timer */
X#endif
X /*
X * Trap interrupts back to the main command interpreter.
X */
X sjval = setjmp(interrupt);
X if (sjval)
X msg("\r\n");
X
X setsignals(); /* connect signal handlers */
X
X /*
X * Main command line interpreting loop
X */
X for (;;) {
X if (kids) reapchild();
X closefiles();
X freeargv(v);
X free_gpa();
X freetmplists();
X (void) chdir(Working_Directory);
X GetCommandLine(prompt, CARGS, &c, v);
X if (c == 0)
X continue;
X index = search_array((char *)Ctable, (char *)v[0], NCommands,
X sizeof (struct command), scommcmp, &found);
X if (!found) {
X err1("%s: unknown command", (char *)v[0]);
X continue;
X }
X (*Ctable[index].c_func)(c, v);
X }
X}
X
Xreapchild()
X
X{
X if (wait3((union wait *)0, WNOHANG, (struct rusage *)0) > 0)
X kids--;
X return;
X}
X
X#if CKPTIME > 0
Xwakeup()
X
X{
X kids && reapchild();
X ModBits && ckpchanges();
X (void) alarm(CKPTIME * 60);
X return;
X}
X#endif
X
Xclosefiles()
X
X{
X register int i, nd = getdtablesize();
X
X for (i=3; i < nd; i++)
X if (i != DevTty)
X (void) close(i);
X return;
X}
@//E*O*F src/main.c//
if test 4050 -ne "`wc -c <'src/main.c'`"; then
echo shar: error transmitting "'src/main.c'" '(should have been 4050 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/misc.c'" '(8013 characters)'
if test -f 'src/misc.c' ; then
echo shar: will not over-write existing file "'src/misc.c'"
else
sed 's/^X//' >src/misc.c <<'@//E*O*F src/misc.c//'
X/**********************************************************************\
X* *
X* misc.c *
X* *
X* Miscellaneous routines ranging from password generators to word *
X* capitalizers to a routine that scrubs untoward characters from user *
X* names. *
X* *
X\**********************************************************************/
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/time.h>
X#include <sys/dir.h>
X#include <strings.h>
X#include <ctype.h>
X#include "sysdep.h"
X#include "macros.h"
X#include "mem.h"
X#include "lists.h"
X#include "range.h"
X#include "sort.h"
X
X#define DAY 86400 /* no. of seconds in a day */
X
Xextern struct list RangeList;
Xchar *ctime(), *sprintf();
Xlong random();
X
Xcoloncount(s)
Xregister char *s;
X
X{
X register int n = 0;
X
X while (*s)
X if (*s++ == ':')
X n++;
X return n;
X}
X
Xcapitalize(s)
Xchar *s;
X
X{
X strlower(s);
X if (isalpha(*s) && islower(*s))
X *s = toupper(*s);
X}
X
Xstrlower(s)
Xchar *s;
X
X{
X while (*s) {
X if (isalpha(*s) && isupper(*s))
X *s = tolower(*s);
X s++;
X }
X return;
X}
X
X
Xint
Xsearch_array(a, s, nelem, elemsize, compfunc, found)
Xchar *a, *s;
Xint nelem, elemsize, (*compfunc)(), *found;
X
X{
X int lo = 0, hi = nelem - 1 , middle, compval;
X int offset;
X
X *found = 0;
X while (lo < hi) {
X middle = (lo + hi) / 2;
X offset = middle*elemsize;
X if ((compval = (*compfunc)(s, a+offset)) == 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 (nelem && (*compfunc)(s, a+lo*elemsize) == 0)
X *found = 1;
X return lo;
X}
X
Xsavestr(cpp, s)
Xchar **cpp, *s;
X
X{
X *cpp = (char *) MEM(strlen(s)+1);
X (void) strcpy(*cpp, s);
X return;
X}
X
Xstatic char *suf[13] = {
X "Jr.", "Sr.", "I",
X "II", "III", "IV",
X "V", "VI", "VII",
X "VIII", "IX", "X",
X "Esq."
X};
X
Xstatic char *ttl[6] = { "Prof.", "Dr.", "Mr.", "Ms.", "Mrs.", "Rev." };
X
Xstruct list Suffixes = { 13, 13, (addr *)suf };
Xstruct list Titles = { 6, 6, (addr *)ttl };
X
Xaddr
Xmakeusername(c, v)
Xint c;
Xaddr *v;
X
X{
X static addr_t user[SHORT_BUF];
X int found, tail;
X flexaddr up;
X
X up.p_ap = user;
X (void) search_list(&Titles, (char *)v[0], strcmp, &found);
X if (found) {
X v++;
X c--;
X }
X (void) search_list(&Suffixes, (char *)v[c-1], strcmp, &found);
X if (found)
X c--;
X /*
X * If last name is seven characters or less and the
X * case-lowered version of this isn't taken, use it.
X */
X if (strlen((char *)v[c-1]) < 8) {
X (void) strcpy((char *)user, (char *)v[c-1]);
X strlower((char *)user);
X if (!userexists((char *)user)) {
X scrub((char *)user);
X return user;
X }
X }
X /*
X * If we have three initials and they aren't already taken, use them.
X */
X if (c == 3) {
X up.p_cp[0] = ((char *)v[0])[0];
X up.p_cp[1] = ((char *)v[1])[0];
X up.p_cp[2] = ((char *)v[2])[0];
X up.p_cp[3] = '\0';
X strlower((char *)user);
X if (!userexists((char *)user)) {
X scrub((char *)user);
X return user;
X }
X }
X /*
X * Oh, well. Chop off last name at five characters, append '_' and
X * first initial. If the resulting name is unused, use it.
X * If not increment the first initial through the collating
X * sequence until we find a name that isn't used. The latter should
X * happen rarely.
X */
X (void) strcpy((char *)user, (char *)v[c-1]);
X up.p_cp[5] = '\0';
X tail = strlen((char *)user);
X up.p_cp[tail++] = '_';
X up.p_cp[tail++] = ((char *)v[0])[0];
X up.p_cp[tail--] = '\0';
X strlower((char *)user);
X while (userexists((char *)user))
X up.p_cp[tail]++;
X scrub((char *)user);
X return user;
X}
X
X/*
X * Change all unsavory characters in a username to '_'
X */
Xscrub(username)
Xchar *username;
X
X{
X for (; *username; username++) {
X if (isalpha(*username) || isdigit(*username))
X continue;
X if (*username == '-')
X continue;
X *username = '_';
X }
X return;
X}
X
X/*
X * This function is used to shut lint up about long to int conversions
X * that I don't CARE about when getting a tiny random number.
X */
Xint rnd()
X{
X union a { int a_i; long a_l; } il;
X
X il.a_l = random();
X return il.a_i;
X}
X
X#define UPPER (char)(rnd() % 26) + 'A'
X#define LOWER (char)(rnd() % 26) + 'a'
X#define NUMBER (char)(rnd() % 10) + '0'
X#define ODD (rnd() % 2 == 1)
X#define EVEN !ODD
X
Xchar *
Xmakepass()
X
X{
X static char password[SHORT_BUF];
X char *cp;
X
X cp = password;
X if (ODD) *cp++ = UPPER; else *cp++ = LOWER;
X if (EVEN) *cp++ = NUMBER; else *cp++ = UPPER;
X if (EVEN) *cp++ = LOWER; else *cp++ = NUMBER;
X if (ODD) *cp++ = LOWER; else *cp++ = NUMBER;
X if (ODD) *cp++ = NUMBER; else *cp++ = UPPER;
X if (EVEN) *cp++ = UPPER; else *cp++ = LOWER;
X return password;
X}
X
Xchar *
Xrsalt()
X
X{
X static char salt[3];
X
X if (EVEN) salt[0] = UPPER; else salt[0] = LOWER;
X if (ODD) salt[1] = LOWER; else salt[1] = NUMBER;
X salt[2] = '\0';
X return salt;
X}
X
Xchar *re_comp();
X
X/* ARGSUSED1 */
Xaddr
Xgethomedir(user, group)
Xchar *user, *group;
X
X#ifdef xanth
X{
X static addr_t dbuf[LONG_BUF], defbuf[LONG_BUF+1];
X char expr[LONG_BUF+1];
X struct direct *dp;
X DIR *dirp;
X
X (void) sprintf((char *)defbuf, "/tmp/U%s", user);
X dirp = opendir(USERDIR);
X if (dirp == NULL) {
X err1("cannot open %s (read)", USERDIR);
X return(defbuf);
X }
X for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
X if (dp->d_name[0] == '.')
X continue;
X (void) sprintf(expr, "^%s%c%c", dp->d_name, '.', '*');
X (void) re_comp(expr);
X if (re_exec(group) == 1) {
X (void) sprintf((char *)dbuf, "%s/%s/%s", USERDIR,
X dp->d_name, user);
X closedir(dirp);
X return(dbuf);
X }
X }
X closedir(dirp);
X return(defbuf);
X}
X#else
X{
X static addr_t dbuf[LONG_BUF];
X
X (void) sprintf((char *)dbuf, "%s/%s", USERDIR, user);
X return dbuf;
X}
X#endif
X
X/*
X * Figger out where the next free uid is, taking into
X * consideration the range tables
X */
Xint findnextuid(group)
Xchar *group;
X
X{
X struct range *rg;
X int uid, indx;
X int maxu, minu;
X
X maxu = minu = 0;
X uid = NOMORE;
X for (indx=0; indx < RangeList.l_count; indx++) {
X rg = (struct range *) RangeList.l_list[indx];
X if (!eq(group, rg->rg_name))
X continue;
X if (rg->rg_from > rg->rg_to)
X uid = rnextuid(rg->rg_from, rg->rg_to);
X else
X uid = nextuid(rg->rg_from, rg->rg_to);
X if (uid != NOMORE)
X return(uid);
X maxu = max(maxu, rg->rg_from);
X maxu = max(maxu, rg->rg_to);
X minu = min(minu, rg->rg_from);
X minu = min(minu, rg->rg_to);
X }
X /*
X * No preference or no space available so now we look for space
X * in shared ranges.
X */
X for (indx=0; indx < RangeList.l_count; indx++) {
X rg = (struct range *) RangeList.l_list[indx];
X if (rg->rg_mode == RG_EXCLUSIVE || eq(rg->rg_name, group))
X continue;
X if (rg->rg_from > rg->rg_to)
X uid = rnextuid(rg->rg_from, rg->rg_to);
X else
X uid = nextuid(rg->rg_from, rg->rg_to);
X if (uid != NOMORE)
X break;
X maxu = max(maxu, rg->rg_from);
X maxu = max(maxu, rg->rg_to);
X minu = min(minu, rg->rg_from);
X minu = min(minu, rg->rg_to);
X }
X uid = nextuid(0, minu-1);
X if (uid == -1) uid = nextuid(maxu+1, 1000);
X return(uid);
X}
X
Xint nextuid(lo, hi)
Xint lo, hi;
X
X{
X int i;
X
X for (i=lo; i<=hi; i++)
X if (!uidexists(i))
X return(i);
X return(NOMORE);
X}
X
Xint rnextuid(hi, lo)
Xint hi, lo;
X
X{
X int i;
X
X for (i=hi; i>=lo; i--)
X if (!uidexists(i))
X return(i);
X return(NOMORE);
X}
X
X/*
X * Max is a function here, because it is used in places where macro side
X * effects are not desired.
X */
Xint
Xmax(a, b)
Xint a, b;
X
X{
X return (a > b ? a : b);
X}
X
Xint
Xmin(a, b)
Xint a, b;
X
X{
X return (a < b ? a : b);
X}
X
Xdirscan(dir, l)
Xchar *dir;
Xregister struct list *l;
X
X{
X struct direct *dp;
X DIR *dirp;
X
X zerolist(l);
X dirp = opendir(dir);
X if (dirp == NULL)
X return;
X for (dp=readdir(dirp); dp != NULL; dp=readdir(dirp)) {
X if (eq(dp->d_name, ".") || eq(dp->d_name, ".."))
X continue;
X strlistadd(l, dp->d_name);
X }
X closedir(dirp);
X sort_list(l, pstrcmp);
X return;
X}
X
Xint
Xisdir(name)
Xchar *name;
X
X{
X struct stat sb;
X
X if (stat(name, &sb) == -1)
X return 0;
X return ((sb.st_mode&S_IFMT) == S_IFDIR) ? 1 : 0;
X}
X
Xvalidint(str)
Xchar *str;
X
X{
X if (!str || !*str)
X return 0;
X while (*str)
X if (!isdigit(*str))
X return 0;
X else
X str++;
X return 1;
X}
@//E*O*F src/misc.c//
if test 8013 -ne "`wc -c <'src/misc.c'`"; then
echo shar: error transmitting "'src/misc.c'" '(should have been 8013 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/nitpick'" '(606 characters)'
if test -f 'src/nitpick' ; then
echo shar: will not over-write existing file "'src/nitpick'"
else
sed 's/^X//' >src/nitpick <<'@//E*O*F src/nitpick//'
X#! /bin/sh
X
X#
X# Script to lint individual source modules and maintain lint
X# dependencies.
X#
X# Is invoked through 'make lintbrush'
X#
X# Works great if you have jove. Works even better if you can use
X# jove. |-)
X#
X
Xfor file
Xdo
X if test ! -f Lint/$file ; then
X touch Lint/$file
X # if the lint marker is younger than the source don't lint
X elif test `ls -t $file Lint/$file | head -1` != $file ; then
X continue;
X fi
X while test `lint -a -b -h -u $file | tee LintErrors | wc -l` != "1"
X do
X echo Uh, oh. Trouble with $file...
X jove -p LintErrors $file
X done
X echo $file ok.
X touch Lint/$file
Xdone
X
Xexit 0
@//E*O*F src/nitpick//
if test 606 -ne "`wc -c <'src/nitpick'`"; then
echo shar: error transmitting "'src/nitpick'" '(should have been 606 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/pwlock.c'" '(712 characters)'
if test -f 'src/pwlock.c' ; then
echo shar: will not over-write existing file "'src/pwlock.c'"
else
sed 's/^X//' >src/pwlock.c <<'@//E*O*F src/pwlock.c//'
X#include <sys/types.h>
X#include <sys/file.h>
X#include "sysdep.h"
X
Xextern time_t PWLockTime;
Xstatic int pwlocked;
X
Xlockpw()
X
X{
X int fd, i;
X time_t time();
X
X for (i=1; i<5; i++) {
X if ((fd=open(PWDLOCK, O_WRONLY|O_CREAT|O_EXCL, 0644)) >= 0) {
X (void) time(&PWLockTime);
X (void) close(fd);
X pwlocked++;
X return(1);
X }
X else switch (i) {
X case 2: msg("Waiting for passwd lock..."); break;
X case 3: msg("Still waiting..."); break;
X case 4: msg("Pacing angrily..."); break;
X default: break;
X }
X sleep(2 * (unsigned)i);
X }
X return(0);
X}
X
Xunlockpw()
X
X{
X if (!pwlocked) return;
X if (unlink(PWDLOCK) == -1) {
X perr("Warning: unable to unlock password file");
X return;
X }
X pwlocked = 0;
X return;
X}
@//E*O*F src/pwlock.c//
if test 712 -ne "`wc -c <'src/pwlock.c'`"; then
echo shar: error transmitting "'src/pwlock.c'" '(should have been 712 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/range.c'" '(1138 characters)'
if test -f 'src/range.c' ; then
echo shar: will not over-write existing file "'src/range.c'"
else
sed 's/^X//' >src/range.c <<'@//E*O*F src/range.c//'
X#include <stdio.h>
X#include "sysdep.h"
X#include "mem.h"
X#include "lists.h"
X#include "range.h"
X
Xextern struct list RangeList;
Xextern int srangecmp();
X
Xstatic FILE *rgf = NULL;
Xstatic char line[BUFSIZ];
Xstatic char namebuf[SHORT_BUF+1], modebuf[SHORT_BUF+1];
Xstatic struct range rg;
X
Xsetrgent()
X
X{
X rg.rg_name = namebuf;
X if( rgf == NULL ) {
X rgf = fopen( RANGEFILE, "r" );
X if (rgf == NULL) {
X perr(RANGEFILE);
X goodbye(1);
X }
X rewind(rgf);
X }
X else
X rewind( rgf );
X}
X
Xendrgent()
X
X{
X if( rgf != NULL ){
X (void) fclose( rgf );
X rgf = NULL;
X }
X}
X
Xstruct range *
Xgetrgent()
X
X{
X register char *p;
X int n;
X
X if (rgf == NULL)
X setrgent();
X p = fgets(line, BUFSIZ, rgf);
X if (p==NULL)
X return(0);
X n = sscanf(line, "%s%d%d%s",rg.rg_name,
X &rg.rg_from,
X &rg.rg_to,
X modebuf);
X if (n != 4) fatal("badly formatted range file line!");
X rg.rg_mode = (modebuf[0] == 'e' ? RG_EXCLUSIVE : RG_SHARED);
X return(&rg);
X}
X
Xstruct range *
Xgetrgnam(name)
Xchar *name;
X
X{
X int indx, found;
X
X indx = search_list(&RangeList, name, srangecmp, &found);
X if (found)
X return (struct range *) RangeList.l_list[indx];
X return (struct range *) 0;
X}
@//E*O*F src/range.c//
if test 1138 -ne "`wc -c <'src/range.c'`"; then
echo shar: error transmitting "'src/range.c'" '(should have been 1138 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/range.h'" '(158 characters)'
if test -f 'src/range.h' ; then
echo shar: will not over-write existing file "'src/range.h'"
else
sed 's/^X//' >src/range.h <<'@//E*O*F src/range.h//'
Xstruct range {
X char *rg_name;
X int rg_from;
X int rg_to;
X int rg_mode;
X};
X
X#define RG_EXCLUSIVE 1
X#define RG_SHARED 2
X
Xstruct range *getrgent(), *getrgnam();
@//E*O*F src/range.h//
if test 158 -ne "`wc -c <'src/range.h'`"; then
echo shar: error transmitting "'src/range.h'" '(should have been 158 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/remove.c'" '(14203 characters)'
if test -f 'src/remove.c' ; then
echo shar: will not over-write existing file "'src/remove.c'"
else
sed 's/^X//' >src/remove.c <<'@//E*O*F src/remove.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 "gpa.h"
X#include "sort.h"
X#include "account.h"
X#ifdef SENDMAIL
X#include "alias.h"
X#endif
X#include "groupmap.h"
X#include "class.h"
X#include "job.h"
X#include "range.h"
X#include "sig.h"
X#include "save.h"
X
X#ifdef SENDMAIL
Xextern struct list AliasList, Aliases;
X#endif SENDMAIL
Xextern struct list AccountList, Classes, ClassList;
Xextern struct list GroupMapList, Groups, SigList, Sigs, RangeList, Ranges;
Xextern struct list Users, Vigs;
Xextern int ModBits;
Xchar *sprintf();
X
X#ifdef SENDMAIL
Xrmalias(c, v)
Xint c;
Xaddr *v;
X
X{
X struct alias *al;
X struct class *cs;
X struct sig *sg;
X struct groupmap *gm;
X struct account *ac;
X char *name;
X register int i;
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 <alias>", (char *)v[0]);
X return;
X }
X
X al = getalnam((char *)v[1]);
X if (!al) {
X err1("%s: no such alias", (char *)v[1]);
X return;
X }
X
X critical();
X name = al->al_name;
X freelist(&al->al_addresses);
X freelist(&al->al_groups);
X freelist(&al->al_classes);
X freelist(&al->al_sigs);
X strlistdel(&Aliases, (char *)v[1]);
X genlistdel(&AliasList, v[1], saliascmp);
X FREEMEM(name);
X for (i=0; i < AliasList.l_count; i++) {
X al = (struct alias *) AliasList.l_list[i];
X if (instrlist(&al->al_addresses, (char *)v[1]))
X strlistdel(&al->al_addresses, (char *)v[1]);
X }
X for (i=0; i < GroupMapList.l_count; i++) {
X gm = (struct groupmap *) GroupMapList.l_list[i];
X if (instrlist(&gm->gm_aliases, (char *)v[1]))
X strlistdel(&gm->gm_aliases, (char *)v[1]);
X }
X for (i=0; i < ClassList.l_count; i++) {
X cs = (struct class *) ClassList.l_list[i];
X if (instrlist(&cs->cs_aliases, (char *)v[1]))
X strlistdel(&cs->cs_aliases, (char *)v[1]);
X }
X for (i=0; i < SigList.l_count; i++) {
X sg = (struct sig *) SigList.l_list[i];
X if (instrlist(&sg->sg_aliases, (char *)v[1]))
X strlistdel(&sg->sg_aliases, (char *)v[1]);
X }
X for (i=0; i < AccountList.l_count; i++) {
X ac = (struct account *) AccountList.l_list[i];
X if (instrlist(&ac->ac_aliases, (char *)v[1])) {
X strlistdel(&ac->ac_aliases, (char *)v[1]);
X ModBits |= AC;
X }
X }
X ModBits |= AL;
X puts("removed");
X non_critical();
X
X return;
X}
X#endif
X
Xrmclass(c, v)
Xint c;
Xaddr *v;
X
X{
X struct class *cs;
X#ifdef SENDMAIL
X struct alias *al;
X#endif
X struct account *ac;
X char *name;
X int i;
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
X cs = getcsnam((char *)v[1]);
X if (!cs) {
X err1("%s: no such class", (char *)v[1]);
X return;
X }
X
X critical();
X
X#ifdef SENDMAIL
X for (i=0; i < AliasList.l_count; i++) {
X al = (struct alias *) AliasList.l_list[i];
X if (instrlist(&al->al_classes, (char *)v[1])) {
X strlistdel(&al->al_classes, (char *)v[1]);
X ModBits |= AL;
X }
X }
X#endif
X for (i=0; i < AccountList.l_count; i++) {
X ac = (struct account *) AccountList.l_list[i];
X if (instrlist(&ac->ac_classes, (char *)v[1])) {
X strlistdel(&ac->ac_classes, (char *)v[1]);
X#ifdef SENDMAIL
X if (cs->cs_aliases.l_count)
X RXBindings(ac);
X#endif
X ModBits |= AC;
X }
X }
X
X name = cs->cs_name;
X FREEMEM(cs->cs_desc);
X genlistdel(&ClassList, v[1], sclasscmp);
X strlistdel(&Classes, (char *)v[1]);
X FREEMEM(name);
X
X ModBits |= CS;
X
X puts("removed");
X non_critical();
X return;
X}
X
Xrmcryos(c, v)
Xint c;
Xchar **v;
X
X{
X register struct account *ac;
X register int indx;
X int removed = 0;
X
X if ( c > 1 ) {
X err1("%s: too many arguments", (char *)v[0]);
X return;
X }
X critical();
X for (indx=0; indx < AccountList.l_count; indx++) {
X ac = (struct account *) AccountList.l_list[indx];
X if (eq(ac->ac_shell, FREEZE_SH)) {
X rmu(ac, 1);
X removed++;
X /* someone else is in this spot now */
X indx--;
X }
X }
X if (removed) {
X (void) printf("%d removed\n", removed);
X#ifndef DOFILES
X err("Do not forget to remove the user directories.");
X#endif
X }
X else
X puts("No cryos.");
X non_critical();
X return;
X}
X
X#ifdef SENDMAIL
Xrmfromalias(c, v)
Xint c;
Xaddr *v;
X
X{
X struct alias *al;
X struct account *ac;
X addr *addressv;
X int cc, removed = 0;
X register int indx;
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 <alias>", (char *)v[0]);
X return;
X }
X al = getalnam((char *)v[1]);
X if (!al) {
X err1("%s: no such alias", (char *)v[1]);
X return;
X }
X
X addressv = get_gpa(65);
X GetLine("Addresses: ", 64, &cc, addressv, &al->al_addresses);
X if (cc == 0) {
X err("no change");
X return;
X }
X
X critical();
X for (indx=0; indx < cc; indx++) {
X if (!instrlist(&al->al_addresses, (char *)addressv[indx])) {
X err1("%s: not in alias", (char *)addressv[indx]);
X continue;
X }
X strlistdel(&al->al_addresses, (char *)addressv[indx]);
X ac = getacnam((char *)addressv[indx]);
X if (ac&&instrlist(&ac->ac_aliases, (char *)addressv[indx])) {
X strlistdel(&ac->ac_aliases, al->al_name);
X ModBits |= AC;
X }
X removed++;
X }
X if (removed) {
X ModBits |= AL;
X (void) printf("%d removed\n", removed);
X }
X else
X err("no change");
X non_critical();
X
X return;
X}
X#endif SENDMAIL
X
Xrmfromclass(c, v)
Xint c;
Xaddr *v;
X
X{
X struct class *cs;
X struct account *ac;
X addr *userv;
X int cc;
X register int i, removed = 0;
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 userv = get_gpa(65);
X GetLine("Users: ", 64, &cc, userv, &Users);
X if (cc == 0) {
X err("no change");
X return;
X }
X
X critical();
X
X for (i=0; i < cc; i++) {
X ac = getacnam((char *)userv[i]);
X if (!ac) {
X err1("%s: no such user", (char *)userv[i]);
X continue;
X }
X if (!instrlist(&ac->ac_classes, (char *)v[1])) {
X err1("%s: not in class", (char *)userv[i]);
X continue;
X }
X strlistdel(&ac->ac_classes, (char *)v[1]);
X#ifdef SENDMAIL
X if (cs->cs_aliases.l_count)
X RXBindings(ac);
X#endif
X removed++;
X }
X if (removed) {
X (void) printf("%d removed\n");
X ModBits |= AC;
X }
X else
X err("no change");
X
X non_critical();
X return;
X}
X
Xrmfromgroup(c, v)
Xint c;
Xaddr *v;
X
X{
X struct groupmap *gm;
X struct account *ac;
X addr *userv;
X int cc;
X register int i, removed = 0;
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 userv = get_gpa(65);
X GetLine("Users: ", 64, &cc, userv, &gm->gm_mem);
X if (cc == 0) {
X err("no change");
X return;
X }
X
X critical();
X for (i=0; i < cc; i++) {
X ac = getacnam((char *)userv[i]);
X if (!ac) {
X err1("%s: no such user", (char *)userv[i]);
X continue;
X }
X if (!instrlist(&gm->gm_mem, (char *)userv[i])) {
X err1("%s: not in group", (char *)userv[i]);
X continue;
X }
X strlistdel(&ac->ac_groups, (char *)v[1]);
X strlistdel(&gm->gm_mem, (char *)userv[i]);
X#ifdef SENDMAIL
X if (gm->gm_aliases.l_count)
X RXBindings(ac);
X#endif
X removed++;
X }
X if (removed) {
X (void) printf("%d removed\n");
X ModBits |= AC|GR;
X }
X else
X err("no change");
X non_critical();
X
X return;
X}
X
Xrmfromsig(c, v)
Xint c;
Xaddr *v;
X
X{
X struct sig *sg;
X struct account *ac;
X addr *userv;
X int cc;
X register int i, removed = 0;
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 userv = get_gpa(65);
X GetLine("Users: ", 64, &cc, userv, &Users);
X if (cc == 0) {
X err("no change");
X return;
X }
X
X critical();
X for (i=0; i < cc; i++) {
X ac = getacnam((char *)userv[i]);
X if (!ac) {
X err1("%s: no such user", (char *)userv[i]);
X continue;
X }
X if (!instrlist(&ac->ac_sigs, (char *)v[1])) {
X err1("%s: not in sig", (char *)userv[i]);
X continue;
X }
X strlistdel(&ac->ac_sigs, (char *)v[1]);
X#ifdef SENDMAIL
X if (sg->sg_aliases.l_count)
X RXBindings(ac);
X#endif
X removed++;
X }
X if (removed) {
X (void) printf("%d removed\n");
X ModBits |= AC;
X }
X else
X err("no change");
X non_critical();
X
X return;
X}
X
Xrmgroup(c, v)
Xint c;
Xaddr *v;
X
X{
X struct groupmap *gm;
X struct account *ac;
X#ifdef SENDMAIL
X struct alias *al;
X#endif
X char *name;
X int i, removed = 0;
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
X gm = getgmnam((char *)v[1]);
X if (!gm) {
X err1("%s: no such group", (char *)v[1]);
X return;
X }
X
X critical();
X
X#ifdef SENDMAIL
X for (i=0; i < AliasList.l_count; i++) {
X al = (struct alias *) AliasList.l_list[i];
X if (instrlist(&al->al_groups, (char *)v[1])) {
X strlistdel(&al->al_groups, (char *)v[1]);
X ModBits |= AL;
X }
X }
X#endif
X for (i=0; i < gm->gm_mem.l_count; i++) {
X ac = getacnam((char *)gm->gm_mem.l_list[i]);
X if (!ac) continue;
X if (instrlist(&ac->ac_groups, (char *)v[1])) {
X strlistdel(&ac->ac_groups, (char *)v[1]);
X#ifdef SENDMAIL
X if (gm->gm_aliases.l_count)
X RXBindings(ac);
X#endif
X removed++;
X }
X }
X
X if (removed) ModBits |= AC;
X
X if (rangeexists((char *)v[1])) {
X ModBits |= RG;
X genlistdel(&RangeList, v[1], srangecmp);
X strlistdel(&Ranges, (char *)v[1]);
X }
X if (vigexists((char *)v[1])) {
X ModBits |= VG;
X strlistdel(&Vigs, (char *)v[1]);
X }
X
X ModBits |= GR;
X
X name = gm->gm_name;
X freelist(&gm->gm_mem);
X genlistdel(&GroupMapList, (addr)&gm->gm_gid, igmapcmp);
X strlistdel(&Groups, (char *)v[1]);
X FREEMEM(name);
X puts("removed");
X non_critical();
X
X return;
X}
X
Xrmrange(c, v)
Xint c;
Xaddr *v;
X
X{
X struct range *rg;
X char *name;
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
X rg = getrgnam((char *)v[1]);
X if (!rg) {
X err1("%s: no such range", (char *)v[1]);
X return;
X }
X
X critical();
X name = rg->rg_name;
X genlistdel(&RangeList, v[1], srangecmp);
X strlistdel(&Ranges, (char *)v[1]);
X FREEMEM(name);
X ModBits |= RG;
X puts("removed");
X non_critical();
X
X return;
X}
X
Xrmsig(c, v)
Xint c;
Xaddr *v;
X
X{
X struct sig *sg;
X struct account *ac;
X#ifdef SENDMAIL
X struct alias *al;
X#endif
X char *name;
X int i;
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>\n", (char *)v[0]);
X return;
X }
X
X sg = getsgnam((char *)v[1]);
X if (!sg) {
X err1("%s: no such sig", (char *)v[1]);
X return;
X }
X
X critical();
X
X#ifdef SENDMAIL
X for (i=0; i < AliasList.l_count; i++) {
X al = (struct alias *) AliasList.l_list[i];
X if (instrlist(&al->al_sigs, (char *)v[1])) {
X strlistdel(&al->al_sigs, (char *)v[1]);
X ModBits |= AL;
X }
X }
X#endif
X for (i=0; i < AccountList.l_count; i++) {
X ac = (struct account *) AccountList.l_list[i];
X if (instrlist(&ac->ac_sigs, (char *)v[1])) {
X strlistdel(&ac->ac_sigs, (char *)v[1]);
X#ifdef SENDMAIL
X if (sg->sg_aliases.l_count)
X RXBindings(ac);
X#endif
X ModBits |= AC;
X }
X }
X
X name = sg->sg_name;
X FREEMEM(sg->sg_desc);
X genlistdel(&SigList, v[1], ssigcmp);
X strlistdel(&Sigs, (char *)v[1]);
X FREEMEM(name);
X
X ModBits |= SG;
X
X puts("removed");
X non_critical();
X
X return;
X}
X
Xrmuser(c, v)
Xint c;
Xaddr *v;
X
X{
X struct account *ac;
X int zapdir;
X#ifdef DOFILES
X char prompt[LONG_BUF];
X#endif
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#ifdef DOFILES
X if (fileexists((char *)ac->ac_dir)) {
X (void) sprintf(prompt, "Home directory is %s, remove it? ",
X ac->ac_dir);
X zapdir = yesno(prompt);
X }
X else
X err1("hmmm... home directory %s non-existent", (char *)ac->ac_dir);
X#else
X err("Do not forget to remove the user's home directory.");
X zapdir = 0;
X#endif
X rmu(ac, zapdir);
X
X (void) printf("%s removed\n", v[1]);
X return;
X}
X
Xrmvig(c, v)
Xint c;
Xaddr *v;
X
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 <vig>", (char *)v[0]);
X return;
X }
X
X if (!vigexists((char *)v[1])) {
X err1("%s: no such vig", (char *)v[1]);
X return;
X }
X
X critical();
X
X strlistdel(&Vigs, (char *)v[1]);
X ModBits |= VG;
X
X puts("removed");
X non_critical();
X return;
X}
X
X/*
X * This is the routine that actually removes a user from the data
X * structures. rmuser() is just a front end to this routine.
X */
X/* ARGSUSED */
Xrmu(ac, zapdir)
Xstruct account *ac;
Xint zapdir;
X
X{
X register int i, j;
X register struct groupmap *gm;
X#ifdef SENDMAIL
X struct alias *al;
X#endif
X
X critical();
X
X#ifdef DOFILES
X zapdir && add_job(JB_RMDIR, ac->ac_dir, NIL, NIL);
X add_job(JB_RMMAIL, ac->ac_name, NIL, NIL);
X#endif
X
X for (i=0; i < GroupMapList.l_count; i++) {
X gm = (struct groupmap *) GroupMapList.l_list[i];
X if (instrlist(&gm->gm_mem, (char *)ac->ac_name)) {
X strlistdel(&gm->gm_mem, (char *)ac->ac_name);
X ModBits |= GR;
X }
X }
X strlistdel(&Users, (char *)ac->ac_name);
X
X#ifdef SENDMAIL
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 strlistdel(&al->al_addresses, (char *)ac->ac_name);
X ModBits |= AL;
X }
X }
X#endif
X
X FREEMEM((char *)ac->ac_name);
X FREEMEM((char *)ac->ac_realname);
X FREEMEM((char *)ac->ac_gecos);
X FREEMEM((char *)ac->ac_passwd);
X FREEMEM((char *)ac->ac_id);
X FREEMEM((char *)ac->ac_dir);
X FREEMEM((char *)ac->ac_shell);
X freelist(&ac->ac_groups);
X freelist(&ac->ac_classes);
X freelist(&ac->ac_sigs);
X#ifdef SENDMAIL
X freelist(&ac->ac_aliases);
X#endif
X
X /*
X * Cannot use genlistdel() because AccountList is sorted by uid, and
X * not by name.
X */
X for (i=0; i < AccountList.l_count; i++)
X if (ac == (struct account *) AccountList.l_list[i])
X break;
X for (j=i; j < AccountList.l_count-1; j++)
X AccountList.l_list[j] = AccountList.l_list[j+1];
X AccountList.l_count--;
X FREEMEM((char *)ac);
X
X ModBits |= AC|PW;
X
X non_critical();
X
X return;
X}
@//E*O*F src/remove.c//
if test 14203 -ne "`wc -c <'src/remove.c'`"; then
echo shar: error transmitting "'src/remove.c'" '(should have been 14203 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'src/report.c'" '(6824 characters)'
if test -f 'src/report.c' ; then
echo shar: will not over-write existing file "'src/report.c'"
else
sed 's/^X//' >src/report.c <<'@//E*O*F src/report.c//'
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/time.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 "class.h"
X#include "groupmap.h"
X#include "range.h"
X#include "sig.h"
X#include "sort.h"
X
X#ifdef BSD4_3
Xtime_t time();
X#endif
X
X#ifdef SENDMAIL
Xextern struct list AliasList;
X#endif
Xextern struct list AccountList, ClassList, GroupMapList, RangeList, SigList;
Xextern int root;
Xextern char *when();
X
XSummarize()
X
X{
X (void) printf("%d user%s, %d group%s, %d class%s, %d sig%s",
X AccountList.l_count, S(AccountList.l_count),
X GroupMapList.l_count, S(GroupMapList.l_count),
X ClassList.l_count, ES(ClassList.l_count),
X SigList.l_count, S(SigList.l_count));
X#ifdef SENDMAIL
X (void) printf(", %d alias%s\n", AliasList.l_count,
X ES(AliasList.l_count));
X#else
X (void) puts("");
X#endif
X return;
X}
X
Xint
XReportGoop()
X
X{
X struct account *ac;
X struct groupmap *gm;
X struct class *cs;
X struct sig *sg;
X struct stat sb;
X struct list c, s;
X#ifdef SENDMAIL
X struct alias *al;
X char *cp;
X#endif
X time_t now;
X int goop = 0;
X register int indx, i;
X
X zerolist(&c); zerolist(&s);
X for (indx=0; indx < AccountList.l_count; indx++) {
X ac = (struct account *) AccountList.l_list[indx];
X /*
X * For root and vig members, howl if no password.
X */
X if (ac->ac_passwd[0] == '\0') {
X if (ac->ac_uid == 0) {
X (void) printf("user \"%s\" has no password!\n", ac->ac_name);
X continue;
X }
X gm = getgmgid(ac->ac_gid);
X if (gm && vigexists((char *)gm->gm_name))
X (void) printf("user \"%s\" has no password\n", ac->ac_name);
X }
X /*
X * Report users with base gids that do not correspond
X * to a group in /etc/group.
X */
X if (!gidexists(ac->ac_gid))
X (void) printf("user \"%s\" has nonexistent gid of (%d)\n",
X ac->ac_name, ac->ac_gid);
X /*
X * Report references to non-existent classes
X */
X for (i=0; i < ac->ac_classes.l_count; i++) {
X if (!classexists((char *)ac->ac_classes.l_list[i])) {
X(void) printf("user \"%s\" is member of nonexistent class \"%s\"\n",
X ac->ac_name, ac->ac_classes.l_list[i]);
X goop++;
X continue;
X }
X if (!instrlist(&c, (char *)ac->ac_classes.l_list[i]))
X strlistadd(&c, (char *)ac->ac_classes.l_list[i]);
X }
X /*
X * Report references to non-existent sigs
X */
X for (i=0; i < ac->ac_sigs.l_count; i++) {
X if (!sigexists((char *)ac->ac_sigs.l_list[i])) {
X(void) printf("user \"%s\" is member of nonexistent sig \"%s\"\n",
X ac->ac_name, ac->ac_sigs.l_list[i]);
X goop++;
X continue;
X }
X if (!instrlist(&s, (char *)ac->ac_sigs.l_list[i]))
X strlistadd(&s, (char *)ac->ac_sigs.l_list[i]);
X }
X /*
X * Skip home directory and shell check if not the super-user,
X * since not some shells may not be accessible to non
X * super-users.
X */
X if (!root)
X continue;
X if (!fileexists((char *)ac->ac_dir))
X(void) printf("user \"%s\"'s home directory (%s) not found\n",
X ac->ac_name, ac->ac_dir);
X if (stat((char *)ac->ac_dir, &sb) == 0)
X if (sb.st_uid != ac->ac_uid)
X(void) printf("user \"%s\" does not own his home directory (%s)\n", ac->ac_name, ac->ac_dir);
X if (!fileexists((char *)ac->ac_shell))
X(void) printf("user \"%s\" login shell (%s) not found\n",
X ac->ac_name, ac->ac_shell);
X }
X sort_list(&s, pstrcmp);
X sort_list(&c, pstrcmp);
X for (indx=0; indx < GroupMapList.l_count; indx++) {
X gm = (struct groupmap *) GroupMapList.l_list[indx];
X for (i=0; i < gm->gm_mem.l_count; i++) {
X if (!userexists((char *)gm->gm_mem.l_list[i])) {
X(void) printf("group \"%s\" contains nonexistent user \"%s\"\n",
X gm->gm_name, gm->gm_mem.l_list[i]);
X goop++;
X }
X }
X }
X (void) time(&now);
X for (indx=0; indx < ClassList.l_count; indx++) {
X cs = (struct class *) ClassList.l_list[indx];
X if (!instrlist(&c, (char *)cs->cs_name)) {
X (void) printf("class \"%s\" is empty\n", cs->cs_name);
X goop++;
X }
X if (cs->cs_exptime && (now >= cs->cs_exptime)) {
X (void) printf("class \"%s\" expired %s\n", cs->cs_name,
X when(cs->cs_exptime));
X goop++;
X }
X }
X for (indx=0; indx < SigList.l_count; indx++) {
X sg = (struct sig *) SigList.l_list[indx];
X if (!instrlist(&s, (char *)sg->sg_name)) {
X (void) printf("sig \"%s\" is empty\n", sg->sg_name);
X goop++;
X }
X if (sg->sg_exptime && (now >= sg->sg_exptime)) {
X (void) printf("sig \"%s\" expired %s\n", sg->sg_name,
X when(sg->sg_exptime));
X goop++;
X }
X }
X#ifdef SENDMAIL
X for (indx=0; indx < AliasList.l_count; indx++) {
X al = (struct alias *) AliasList.l_list[indx];
X for (i=0; i < al->al_groups.l_count; i++) {
X cp = (char *)al->al_groups.l_list[i];
X if (!groupexists(cp)) {
X(void) printf("alias \"%s\" bound to nonexistent group \"%s\"\n", al->al_name, cp);
X goop++;
X }
X }
X for (i=0; i < al->al_classes.l_count; i++) {
X cp = (char *)al->al_classes.l_list[i];
X if (!classexists(cp)) {
X(void) printf("alias \"%s\" bound to nonexistent class \"%s\"\n", al->al_name, cp);
X goop++;
X }
X }
X for (i=0; i < al->al_sigs.l_count; i++) {
X cp = (char *)al->al_sigs.l_list[i];
X if (!sigexists(cp)) {
X(void) printf("alias \"%s\" bound to nonexistent sig \"%s\"\n", al->al_name, cp);
X goop++;
X }
X }
X }
X#endif
X return goop;
X}
X
XListThemThangs()
X
X{
X struct groupmap *gm;
X struct class *cs;
X struct sig *sg;
X struct account *ac;
X register int i, j;
X int memcount;
X
X if (GroupMapList.l_count) puts("== Groups ==");
X for (i=0; i < GroupMapList.l_count; i++) {
X gm = (struct groupmap *) GroupMapList.l_list[i];
X memcount = gm->gm_mem.l_count;
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 memcount++;
X }
X printf("\"%s\", %d member%s, %d groupie%s\n", gm->gm_name,
X memcount - gm->gm_mem.l_count, S(memcount - gm->gm_mem.l_count),
X gm->gm_mem.l_count, S(gm->gm_mem.l_count));
X }
X if (ClassList.l_count) puts("== Classes ==");
X for (i=0; i < ClassList.l_count; i++) {
X memcount = 0;
X cs = (struct class *) ClassList.l_list[i];
X for (j=0; j < AccountList.l_count; j++) {
X ac = (struct account *) AccountList.l_list[j];
X if (instrlist(&ac->ac_classes, cs->cs_name))
X memcount++;
X }
X printf("\"%s\", %d member%s, ends %s\n", cs->cs_name,
X memcount, S(memcount), when(cs->cs_exptime));
X }
X if (SigList.l_count) puts("== Sigs ==");
X for (i=0; i < SigList.l_count; i++) {
X memcount = 0;
X sg = (struct sig *) SigList.l_list[i];
X for (j=0; j < AccountList.l_count; j++) {
X ac = (struct account *) AccountList.l_list[j];
X if (instrlist(&ac->ac_sigs, sg->sg_name))
X memcount++;
X }
X printf("\"%s\", %d member%s, ends %s\n", sg->sg_name,
X memcount, S(memcount), when(sg->sg_exptime));
X }
X return;
X}
@//E*O*F src/report.c//
if test 6824 -ne "`wc -c <'src/report.c'`"; then
echo shar: error transmitting "'src/report.c'" '(should have been 6824 characters)'
fi
fi # end of overwriting check
echo shar: "End of archive 7 (of 8)."
cp /dev/null ark7isdone
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