Subject: v08i047: Account creation/manipulation program, Part07/08 Newsgroups: mod.sources Approved: mirror!rs Submitted by: Kyle Jones 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@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 X#include X#include X#include X#include 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; igm_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; igm_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 X#include X#include X#include X#include X#include 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 X#include X#include X#include X#include X#include X#include 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 X#include 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 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 X#include X#include 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 ", (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 ", (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 ", (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 ", (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 ", (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 ", (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 ", (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 ", (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 \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 ", (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 ", (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 X#include X#include X#include 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