home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume8 / mcp / part07 < prev    next >
Encoding:
Internet Message Format  |  1987-02-05  |  48.5 KB

  1. Subject:  v08i047:  Account creation/manipulation program, Part07/08
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: Kyle Jones <xanth!kyle>
  6. Mod.sources: Volume 8, Issue 47
  7. Archive-name: mcp/Part07
  8.  
  9. #! /bin/sh
  10. # This is a shell archive.  Remove anything before this line,
  11. # then unpack it by saving it in a file and typing "sh file".
  12. # If all goes well, you will see the message "End of archive 7 (of 8)."
  13. # Contents:  src/load.c src/main.c src/misc.c src/nitpick src/pwlock.c
  14. #   src/range.c src/range.h src/remove.c src/report.c
  15. # Wrapped by rs@mirror on Fri Feb  6 15:56:11 1987
  16. PATH=/bin:/usr/bin:/usr/ucb; export PATH
  17. echo shar: extracting "'src/load.c'" '(7238 characters)'
  18. if test -f 'src/load.c' ; then 
  19.   echo shar: will not over-write existing file "'src/load.c'"
  20. else
  21. sed 's/^X//' >src/load.c <<'@//E*O*F src/load.c//'
  22. X#include <stdio.h>
  23. X#include <sys/types.h>
  24. X#include <sys/file.h>
  25. X#include <lastlog.h>
  26. X#include <strings.h>
  27. X#include "sysdep.h"
  28. X#include "macros.h"
  29. X#include "mem.h"
  30. X#include "gpa.h"
  31. X#include "lists.h"
  32. X#include "account.h"
  33. X#include "groupmap.h"
  34. X#include "save.h"
  35. X#include "sort.h"
  36. X
  37. Xaddr    makeusername(), gethomedir();
  38. Xint    nlformat(), nfformat(), (*format)(), ModBits;
  39. Xextern    addr DEF_SHELL;
  40. Xchar    *crypt(), *sprintf();
  41. X
  42. Xint    lineno;
  43. Xaddr    *filev;
  44. X
  45. Xloadfile(c, v)
  46. Xint c;
  47. Xaddr *v;
  48. X
  49. X{
  50. X    FILE *f;
  51. X    flexaddr p;
  52. X    char line[LONG_BUF];
  53. X    addr user, password, id, dir, *vv;
  54. X    addr *realnamev;
  55. X    addr_t shell[MEDIUM_BUF];
  56. X    struct account *ac;
  57. X    struct groupmap *gm, *gm2;
  58. X    static struct list groups, classes, sigs;
  59. X    int cc, added, gid, uid, i;
  60. X    int totaladded = 0, filesloaded = 0;
  61. X
  62. X    zerolist(&groups);    tmplistadd(&groups);
  63. X    zerolist(&sigs);    tmplistadd(&sigs);
  64. X    zerolist(&classes);    tmplistadd(&classes);
  65. X    if (c == 1) {
  66. X        filev = get_gpa(8);
  67. X        GetFilenames("Files: ", 8, &cc, filev);
  68. X        if (cc == 0)
  69. X            return;
  70. X    }
  71. X    else
  72. X        filev = &v[1];
  73. X    for (; *filev; filev++) {
  74. X        added = 0;
  75. X        lineno = 1;
  76. X        if (access((char *)*filev, F_OK|R_OK) == -1) {
  77. X            perr((char *)*filev);
  78. X            err1("%s: file load aborted", (char *)*filev);
  79. X            continue;
  80. X        }
  81. X        f = fopen((char *)*filev, "r");
  82. X        if (f == NULL) {
  83. X            perr((char *)*filev);
  84. X            err1("%s: file load aborted", (char *)*filev);
  85. X            continue;
  86. X        }
  87. X        if (hascolon(f)) {
  88. X            err1("%s: file has colons in it! (load aborted)",
  89. X                (char *)*filev);
  90. X            continue;
  91. X        }
  92. X        (void) printf("%s:\n",(char *)*filev);
  93. X        /*
  94. X         * First line should identity the file format
  95. X         */
  96. X        if (fgets(line, BUFSIZ, f) == NULL) {
  97. X            gag("missing format line");
  98. X            gag("file load aborted");
  99. X            continue;
  100. X        }
  101. X        switch (*line) {
  102. X            /* name first format */
  103. X        case 'N':
  104. X        case 'n': format = nfformat;    break;
  105. X            /* Id first format */
  106. X        case 'I':
  107. X        case 'i': format = nlformat;    break;
  108. X        default:
  109. X            gag1("bad format token \"%.8s\"", line);
  110. X            gag("file load aborted");
  111. X            continue;
  112. X        }
  113. X        lineno++;
  114. X        /*
  115. X         * Second line should be a list of space separated
  116. X         * groups that the added users will be put into
  117. X         * The first group in the list will be the users base
  118. X         * gid group (the group for the gid in the passwd file).
  119. X         * It is an error for this line to be empty.
  120. X         */
  121. X        if (fgets(line, BUFSIZ, f) == NULL) {
  122. X            gag("missing groups line");
  123. X            gag("file load aborted");
  124. X            continue;
  125. X        }
  126. X        parse_line(line, &cc, &vv);
  127. X        if (cc == 0) {
  128. X            gag("groups line empty");
  129. X            gag("file load aborted");
  130. X            continue;
  131. X        }
  132. X        gm = getgmnam((char *)vv[0]);
  133. X        if (!gm) {
  134. X            gag1("%s: no such group", (char *)vv[0]);
  135. X            gag("file load aborted");
  136. X            continue;
  137. X        }
  138. X        gid = gm->gm_gid;
  139. X        for (vv++; *vv; vv++)
  140. X            if (groupexists((char *)*vv))
  141. X                strlistadd(&groups, (char *)*vv);
  142. X            else
  143. X                gag1("%s: no such group", (char *)*vv);
  144. X        lineno++;
  145. X        /*
  146. X         * Third line should be a space separated list of
  147. X         * classes for the users to put in.  This line must
  148. X         * be peresent although it is permitted to be empty.
  149. X         */
  150. X        if (fgets(line, BUFSIZ, f) == NULL) {
  151. X            gag("missing classes line");
  152. X            gag("file load aborted");
  153. X            continue;
  154. X        }
  155. X        parse_line(line, &cc, &vv);
  156. X        for (; *vv; vv++)
  157. X            if (classexists((char *)*vv))
  158. X                strlistadd(&classes, (char *)*vv);
  159. X            else
  160. X                gag1("%s: no such class", (char *)*vv);
  161. X        lineno++;
  162. X        /*
  163. X         * Fourth line should be a space separated list of
  164. X         * sigs for the users to put in.  This line must
  165. X         * be present although it is permitted to be empty.
  166. X         */
  167. X        if (fgets(line, BUFSIZ, f) == NULL) {
  168. X            gag("missing sigs line");
  169. X            gag("file load aborted");
  170. X            continue;
  171. X        }
  172. X        parse_line(line, &cc, &vv);
  173. X        for (; *vv; vv++)
  174. X            if (sigexists((char *)*vv))
  175. X                strlistadd(&sigs, (char *)*vv);
  176. X            else
  177. X                gag1("%s: no such sig", (char *)*vv);
  178. X        lineno++;
  179. X        /*
  180. X         * Fifth line should contain the name of the shell
  181. X         * the added users should have.  This line must be
  182. X         * present but it may be blank.
  183. X         */
  184. X        if (fgets(line, BUFSIZ, f) == NULL) {
  185. X            gag("missing shell line");
  186. X            gag("file load aborted");
  187. X            continue;
  188. X        }
  189. X        parse_line(line, &cc, &vv);
  190. X        if (cc && !fileexists((char *)vv[0])) {
  191. X            gag1("%s: nonexistent shell", (char *)vv[0]);
  192. X            gag("file load aborted");
  193. X        }
  194. X        else if (cc)
  195. X            (void) strcpy((char *)shell, (char *)vv[0]);
  196. X        else
  197. X            (void) strcpy((char *)shell, (char *)DEF_SHELL);
  198. X        lineno++;
  199. X        /*
  200. X         * Lines from here on should be in the format specified
  201. X         * above.
  202. X         */
  203. X        while (fgets(line, LONG_BUF, f) != NULL) {
  204. X            if ((*format)(line, &cc, &realnamev, &id) == 0) {
  205. X                gag("badly formed line");
  206. X                continue;
  207. X            }
  208. X            ac = getacid((char *)id);
  209. X            if (ac) {
  210. X                user = ac->ac_name;
  211. X                (void) orstrlist(&ac->ac_groups, &groups);
  212. X                orstrlist(&ac->ac_classes, &classes)&&
  213. X                    ModBits |= AC;
  214. X                orstrlist(&ac->ac_sigs, &sigs)&&
  215. X                    ModBits |= AC;
  216. X                for (i=0; i<groups.l_count; i++) {
  217. X                    gm2 = getgmnam((char *)groups.l_list[i]);
  218. X                    if (instrlist(&gm2->gm_mem, (char *)user))
  219. X                    continue;
  220. X                    ModBits |= (AC|GR);
  221. X                    strlistadd(&gm2->gm_mem, (char *)user);
  222. X                    sort_list(&gm2->gm_mem, pstrcmp);
  223. X                }
  224. X                (void) printf("%-12s%s\n", ac->ac_name,
  225. X                    ac->ac_realname);
  226. X                continue;
  227. X            }
  228. X            uid = findnextuid(gm->gm_name);
  229. X            if (uid == NOMORE) {
  230. X                gag("no more uids");
  231. X                gag("load terminated");
  232. X                goto nextfile;
  233. X            }
  234. X            user = makeusername(cc, realnamev);
  235. X            p.p_cp = crypt((char *)id, CRYPT_SALT);
  236. X            password = p.p_ap;
  237. X            dir = gethomedir((char *)user, gm->gm_name);
  238. X            addu(uid, gid, user, glob(realnamev), password,
  239. X                id, dir, shell);
  240. X            added++;
  241. X            ac = getacnam((char *)user);
  242. X            (void) orstrlist(&ac->ac_groups, &groups);
  243. X            orstrlist(&ac->ac_classes, &classes)&&ModBits|=AC;
  244. X            orstrlist(&ac->ac_sigs, &sigs)&&ModBits|=AC;
  245. X            for (i=0; i<groups.l_count; i++) {
  246. X                gm2 = getgmnam((char *)groups.l_list[i]);
  247. X                if (instrlist(&gm2->gm_mem, (char *)user))
  248. X                    continue;
  249. X                ModBits |= (AC|GR);
  250. X                strlistadd(&gm2->gm_mem, (char *)user);
  251. X                sort_list(&gm2->gm_mem, pstrcmp);
  252. X            }
  253. X            (void) printf("%-12s%s\n", ac->ac_name,
  254. X                    ac->ac_realname);
  255. X        }
  256. X    nextfile:
  257. X        (void) printf("%s: %d added\n", *filev, added);
  258. X        filesloaded++;
  259. X        totaladded += added;
  260. X        freelist(&groups);
  261. X        freelist(&sigs);
  262. X        freelist(&classes);
  263. X    }
  264. X    if (totaladded) {
  265. X        (void) printf("%d file%s loaded, %d user%s added\n",
  266. X                filesloaded, S(filesloaded),
  267. X                totaladded, S(totaladded));
  268. X#ifndef    DOFILES
  269. X        err("Don't forget to create directories for these users.");
  270. X#endif
  271. X    }
  272. X    return;
  273. X}
  274. X
  275. Xint
  276. Xhascolon(f)
  277. XFILE *f;
  278. X
  279. X{
  280. X    int c;
  281. X
  282. X    rewind(f);
  283. X    while ((c = getc(f)) != EOF)
  284. X        if (c == ':') {
  285. X            rewind(f);
  286. X            return 1;
  287. X        }
  288. X    rewind(f);
  289. X    return 0;
  290. X}
  291. X
  292. Xint
  293. Xnfformat(line, cc, r, id)
  294. Xchar *line;
  295. Xint *cc;
  296. Xaddr **r;
  297. Xaddr *id;
  298. X
  299. X{
  300. X    int c;
  301. X    addr *v;
  302. X
  303. X    parse_line(line, &c, &v);
  304. X    if (c < 2)
  305. X        return 0;
  306. X    *id = v[c-1];
  307. X    v[c-1] = NIL;
  308. X    *cc = c - 1;
  309. X    *r = v;
  310. X    return 1;
  311. X}
  312. X
  313. Xint
  314. Xnlformat(line, cc, r, id)
  315. Xchar *line;
  316. Xint *cc;
  317. Xaddr **r;
  318. Xaddr *id;
  319. X
  320. X{
  321. X    int c;
  322. X    addr *v;
  323. X
  324. X    parse_line(line, &c, &v);
  325. X    if (c < 2)
  326. X        return 0;
  327. X    *id = v[0];
  328. X    *cc = c - 1;
  329. X    *r = &v[1];
  330. X    return 1;
  331. X}
  332. X
  333. Xstatic
  334. Xgag(msg)
  335. Xchar *msg;
  336. X
  337. X{
  338. X    char errmsg[LONG_BUF];
  339. X
  340. X    (void) sprintf(errmsg, "%s: line %d: %s", *filev, lineno, msg);
  341. X    err(errmsg);
  342. X    return;
  343. X}
  344. X
  345. Xstatic
  346. Xgag1(msg, s1)
  347. Xchar *msg;
  348. Xchar *s1;
  349. X
  350. X{
  351. X    char errmsg[LONG_BUF];
  352. X
  353. X    (void) sprintf(errmsg, msg, s1);
  354. X    gag(errmsg);
  355. X    return;
  356. X}
  357. @//E*O*F src/load.c//
  358. if test 7238 -ne "`wc -c <'src/load.c'`"; then
  359.     echo shar: error transmitting "'src/load.c'" '(should have been 7238 characters)'
  360. fi
  361. fi # end of overwriting check
  362. echo shar: extracting "'src/main.c'" '(4050 characters)'
  363. if test -f 'src/main.c' ; then 
  364.   echo shar: will not over-write existing file "'src/main.c'"
  365. else
  366. sed 's/^X//' >src/main.c <<'@//E*O*F src/main.c//'
  367. X#include <stdio.h>
  368. X#include <sys/time.h>
  369. X#include <sys/resource.h>
  370. X#include <sys/wait.h>
  371. X#include <setjmp.h>
  372. X#include <signal.h>
  373. X#include "sysdep.h"
  374. X#include "macros.h"
  375. X#include "mem.h"
  376. X#include "command.h"
  377. X
  378. X#define        ROOT_PROMPT    "\r(mcp) "
  379. X#define        PROMPT        "\r(   ) "
  380. X#define        CARGS        32       /* # command line args allowed */
  381. X
  382. X#ifdef sun
  383. X#define    sighandler    (void (*)())
  384. X#else
  385. X#define    sighandler    (int (*)())
  386. X#endif
  387. X
  388. Xextern    int scommcmp(), kids, root, ModBits, NCommands, goodbye(), DevTty;
  389. Xextern    struct command Ctable[];
  390. Xextern    char Working_Directory[];
  391. Xextern    int ReportGoop();
  392. Xextern    Summarize();
  393. Xextern    char *sprintf();
  394. X
  395. Xjmp_buf interrupt, in_continue;            /* setjmp vectors */
  396. X
  397. Xmain(argc, argv)
  398. Xint argc;
  399. Xchar **argv;
  400. X
  401. X{
  402. X    static char *prompt;
  403. X    static addr v[CARGS+1];
  404. X    int sjval, index, c, found, goop = 0;
  405. X    int buildit, checkem, summary, listem, printversion;
  406. X    char errmsg[MEDIUM_BUF];
  407. X
  408. X    (void) umask(022);
  409. X
  410. X    /*
  411. X     * Find out if this is the superuser, what the current working 
  412. X     * directory is, seed random number generator.
  413. X     * For Sun systems, also find out about file server, etc.
  414. X     */
  415. X    init_identities();
  416. X
  417. X    buildit = checkem = summary = listem = printversion = 0;
  418. X    while (--argc && **++argv == '-')
  419. X        for (++*argv; **argv; ++*argv)
  420. X        switch (**argv) {
  421. X        case 'v':
  422. X            printversion++; break;
  423. X        case 'l':
  424. X            listem++;    break;
  425. X        case 'B':
  426. X            buildit++;    break;
  427. X        case 'c':
  428. X            checkem++;    break;
  429. X        case 's':
  430. X            summary++;    break;
  431. X        default:
  432. X            (void) sprintf(errmsg, "mcp: bad option '%c' (ignored)",
  433. X                    **argv);
  434. X            err(errmsg);
  435. X            break;
  436. X        }
  437. X    /*
  438. X     * Set up descriptor for /dev/tty or just attached to stderr
  439. X     * if not running interactively.
  440. X     */
  441. X    init_tty(buildit || (!checkem && !summary && !listem));
  442. X
  443. X    if (buildit && (checkem || summary || listem))
  444. X        fatal("mcp: can't use -B with any other option.");
  445. X    if (buildit && !root)
  446. X        fatal("mcp: must be the super-user to use -B");
  447. X    if (argc)
  448. X        err("mcp: extra arguments ignored");
  449. X    if (printversion && !buildit) {
  450. X        ShowVersion();
  451. X        if (!(checkem || summary || listem))
  452. X          goodbye(0);
  453. X    }
  454. X    /*
  455. X     * Must set up some sort of quick 'n dirty signal handling lest
  456. X     * an interrupt cause the program to exit with the password
  457. X     * file locked.  So we block all signals except SIGINT, and trap
  458. X     * SIGINT to goodbye().
  459. X     */
  460. X    (void) sigsetmask(~mask(SIGINT));
  461. X    (void) signal(SIGINT, sighandler goodbye);
  462. X
  463. X    if ( root && !(checkem || summary || listem)) {
  464. X        msg("Locking password file...");
  465. X        if (!lockpw())
  466. X            fatal("mcp: password file busy");
  467. X        prompt = ROOT_PROMPT;
  468. X    }
  469. X    else
  470. X        prompt = PROMPT;
  471. X
  472. X    if (buildit) Build();    /* Build() doesn't return */
  473. X
  474. X    /*
  475. X     * Pass a flag to init_lists() to indicate whether all or
  476. X     * or only some of the global lists need be initialized.
  477. X     */
  478. X    init_lists(!(checkem || summary || listem));
  479. X
  480. X    if (checkem) goop = ReportGoop();
  481. X    if (listem) ListThemThangs();
  482. X    if (summary) Summarize();
  483. X    if (checkem || summary || listem) goodbye(goop ? 1 : 0);
  484. X
  485. X#if CKPTIME > 0
  486. X    if (root)
  487. X        (void) alarm(CKPTIME * 60);    /* start checkpointing timer */
  488. X#endif
  489. X    /*
  490. X     * Trap interrupts back to the main command interpreter.
  491. X     */
  492. X    sjval = setjmp(interrupt);
  493. X    if (sjval)
  494. X        msg("\r\n");
  495. X
  496. X    setsignals();        /* connect signal handlers */
  497. X
  498. X    /*
  499. X     * Main command line interpreting loop
  500. X     */
  501. X    for (;;) {
  502. X        if (kids) reapchild();
  503. X        closefiles();
  504. X        freeargv(v);
  505. X        free_gpa();
  506. X        freetmplists();
  507. X        (void) chdir(Working_Directory);
  508. X        GetCommandLine(prompt, CARGS, &c, v);
  509. X        if (c == 0)
  510. X            continue;
  511. X        index = search_array((char *)Ctable, (char *)v[0], NCommands,
  512. X                sizeof (struct command), scommcmp, &found);
  513. X        if (!found) {
  514. X            err1("%s: unknown command", (char *)v[0]);
  515. X            continue;
  516. X        }
  517. X        (*Ctable[index].c_func)(c, v);
  518. X    }
  519. X}
  520. X
  521. Xreapchild()
  522. X
  523. X{
  524. X    if (wait3((union wait *)0, WNOHANG, (struct rusage *)0) > 0)
  525. X        kids--;
  526. X    return;
  527. X}
  528. X
  529. X#if CKPTIME > 0
  530. Xwakeup()
  531. X
  532. X{
  533. X    kids && reapchild();
  534. X    ModBits && ckpchanges();
  535. X    (void) alarm(CKPTIME * 60);
  536. X    return;
  537. X}
  538. X#endif
  539. X
  540. Xclosefiles()
  541. X
  542. X{
  543. X    register int i, nd = getdtablesize();
  544. X
  545. X    for (i=3; i < nd; i++)
  546. X        if (i != DevTty)
  547. X            (void) close(i);
  548. X    return;
  549. X}
  550. @//E*O*F src/main.c//
  551. if test 4050 -ne "`wc -c <'src/main.c'`"; then
  552.     echo shar: error transmitting "'src/main.c'" '(should have been 4050 characters)'
  553. fi
  554. fi # end of overwriting check
  555. echo shar: extracting "'src/misc.c'" '(8013 characters)'
  556. if test -f 'src/misc.c' ; then 
  557.   echo shar: will not over-write existing file "'src/misc.c'"
  558. else
  559. sed 's/^X//' >src/misc.c <<'@//E*O*F src/misc.c//'
  560. X/**********************************************************************\
  561. X*                                        *
  562. X*     misc.c                                   *
  563. X*                                        *
  564. X* Miscellaneous routines ranging from password generators to word      *
  565. X* capitalizers to a routine that scrubs untoward characters from user  *
  566. X* names.                                   *
  567. X*                                        *
  568. X\**********************************************************************/
  569. X
  570. X#include <stdio.h>
  571. X#include <sys/types.h>
  572. X#include <sys/stat.h>
  573. X#include <sys/time.h>
  574. X#include <sys/dir.h>
  575. X#include <strings.h>
  576. X#include <ctype.h>
  577. X#include "sysdep.h"
  578. X#include "macros.h"
  579. X#include "mem.h"
  580. X#include "lists.h"
  581. X#include "range.h"
  582. X#include "sort.h"
  583. X
  584. X#define DAY    86400    /* no. of seconds in a day */
  585. X
  586. Xextern    struct list RangeList;
  587. Xchar    *ctime(), *sprintf();
  588. Xlong    random();
  589. X
  590. Xcoloncount(s)
  591. Xregister char *s;
  592. X
  593. X{
  594. X    register int n = 0;
  595. X
  596. X    while (*s)
  597. X        if (*s++ == ':')
  598. X            n++;
  599. X    return n;
  600. X}
  601. X
  602. Xcapitalize(s)
  603. Xchar *s;
  604. X
  605. X{
  606. X    strlower(s);
  607. X    if (isalpha(*s) && islower(*s))
  608. X        *s = toupper(*s);
  609. X}
  610. X
  611. Xstrlower(s)
  612. Xchar *s;
  613. X
  614. X{
  615. X    while (*s) {
  616. X        if (isalpha(*s) && isupper(*s))
  617. X            *s = tolower(*s);
  618. X        s++;
  619. X    }
  620. X    return;
  621. X}
  622. X
  623. X
  624. Xint
  625. Xsearch_array(a, s, nelem, elemsize, compfunc, found)
  626. Xchar *a, *s;
  627. Xint nelem, elemsize, (*compfunc)(), *found;
  628. X
  629. X{
  630. X    int lo = 0, hi = nelem - 1 , middle, compval;
  631. X    int offset;
  632. X
  633. X    *found = 0;
  634. X    while (lo < hi) {
  635. X        middle = (lo + hi) / 2;
  636. X        offset = middle*elemsize;
  637. X        if ((compval = (*compfunc)(s, a+offset)) == 0) {
  638. X            *found = 1;
  639. X            return middle;
  640. X        }
  641. X        else if (compval < 0) {
  642. X            decr(middle);
  643. X            hi = middle;
  644. X        }
  645. X        else
  646. X            lo = middle + 1;
  647. X    }
  648. X    if (nelem && (*compfunc)(s, a+lo*elemsize) == 0)
  649. X        *found = 1;
  650. X    return lo;
  651. X}
  652. X
  653. Xsavestr(cpp, s)
  654. Xchar **cpp, *s;
  655. X
  656. X{
  657. X    *cpp = (char *) MEM(strlen(s)+1);
  658. X    (void) strcpy(*cpp, s);
  659. X    return;
  660. X}
  661. X
  662. Xstatic    char *suf[13] = { 
  663. X    "Jr.",        "Sr.",        "I",
  664. X    "II",        "III",        "IV",
  665. X    "V",        "VI",        "VII",
  666. X    "VIII",        "IX",        "X",
  667. X    "Esq."
  668. X};
  669. X
  670. Xstatic    char *ttl[6] = { "Prof.", "Dr.", "Mr.", "Ms.", "Mrs.", "Rev." };
  671. X
  672. Xstruct    list Suffixes = { 13, 13, (addr *)suf };
  673. Xstruct    list Titles = {    6, 6, (addr *)ttl };
  674. X
  675. Xaddr
  676. Xmakeusername(c, v)
  677. Xint c;
  678. Xaddr *v;
  679. X
  680. X{
  681. X    static addr_t user[SHORT_BUF];
  682. X    int found, tail;
  683. X    flexaddr up;
  684. X
  685. X    up.p_ap = user;
  686. X    (void) search_list(&Titles, (char *)v[0], strcmp, &found);
  687. X    if (found) {
  688. X        v++;
  689. X        c--;
  690. X    }
  691. X    (void) search_list(&Suffixes, (char *)v[c-1], strcmp, &found);
  692. X    if (found)
  693. X        c--;
  694. X    /*
  695. X     * If last name is seven characters or less and the
  696. X     * case-lowered version of this isn't taken, use it.
  697. X     */
  698. X    if (strlen((char *)v[c-1]) < 8) {
  699. X        (void) strcpy((char *)user, (char *)v[c-1]);
  700. X        strlower((char *)user);
  701. X        if (!userexists((char *)user)) {
  702. X            scrub((char *)user);
  703. X            return user;
  704. X        }
  705. X    }
  706. X    /*
  707. X     * If we have three initials and they aren't already taken, use them.
  708. X     */
  709. X    if (c == 3) {
  710. X        up.p_cp[0] = ((char *)v[0])[0];
  711. X        up.p_cp[1] = ((char *)v[1])[0];
  712. X        up.p_cp[2] = ((char *)v[2])[0];
  713. X        up.p_cp[3] = '\0';
  714. X        strlower((char *)user);
  715. X        if (!userexists((char *)user)) {
  716. X            scrub((char *)user);
  717. X            return user;
  718. X        }
  719. X    }
  720. X    /*
  721. X     * Oh, well.  Chop off last name at five characters, append '_' and
  722. X     * first initial.  If the resulting name is unused, use it.
  723. X     * If not increment the first initial through the collating
  724. X     * sequence until we find a name that isn't used.  The latter should
  725. X     * happen rarely.
  726. X     */
  727. X    (void) strcpy((char *)user, (char *)v[c-1]);
  728. X    up.p_cp[5] = '\0';
  729. X    tail = strlen((char *)user);
  730. X    up.p_cp[tail++] = '_';
  731. X    up.p_cp[tail++] = ((char *)v[0])[0];
  732. X    up.p_cp[tail--] = '\0';
  733. X    strlower((char *)user);
  734. X    while (userexists((char *)user))
  735. X        up.p_cp[tail]++;
  736. X    scrub((char *)user);
  737. X    return user;
  738. X}
  739. X
  740. X/*
  741. X * Change all unsavory characters in a username to '_'
  742. X */
  743. Xscrub(username)
  744. Xchar *username;
  745. X
  746. X{
  747. X    for (; *username; username++) {
  748. X        if (isalpha(*username) || isdigit(*username))
  749. X            continue;
  750. X        if (*username == '-')
  751. X            continue;
  752. X        *username = '_';
  753. X    }
  754. X    return;
  755. X}
  756. X
  757. X/*
  758. X * This function is used to shut lint up about long to int conversions
  759. X * that I don't CARE about when getting a tiny random number.
  760. X */
  761. Xint rnd()
  762. X{
  763. X    union a { int a_i; long a_l; } il;
  764. X
  765. X    il.a_l = random();
  766. X    return il.a_i;
  767. X}
  768. X
  769. X#define UPPER    (char)(rnd() % 26) + 'A'
  770. X#define LOWER    (char)(rnd() % 26) + 'a'
  771. X#define NUMBER    (char)(rnd() % 10) + '0'
  772. X#define ODD    (rnd() % 2 == 1)
  773. X#define EVEN    !ODD
  774. X
  775. Xchar *
  776. Xmakepass()
  777. X
  778. X{
  779. X    static char password[SHORT_BUF];
  780. X    char *cp;
  781. X
  782. X    cp = password;
  783. X    if (ODD)    *cp++ = UPPER;    else *cp++ = LOWER;
  784. X    if (EVEN)    *cp++ = NUMBER;    else *cp++ = UPPER;
  785. X    if (EVEN)    *cp++ = LOWER;    else *cp++ = NUMBER;
  786. X    if (ODD)    *cp++ = LOWER;    else *cp++ = NUMBER;
  787. X    if (ODD)    *cp++ = NUMBER;    else *cp++ = UPPER;
  788. X    if (EVEN)    *cp++ = UPPER;    else *cp++ = LOWER;
  789. X    return password;
  790. X}
  791. X
  792. Xchar *
  793. Xrsalt()
  794. X
  795. X{
  796. X    static char salt[3];
  797. X
  798. X    if (EVEN)    salt[0] = UPPER;    else salt[0] = LOWER;
  799. X    if (ODD)    salt[1] = LOWER;    else salt[1] = NUMBER;
  800. X    salt[2] = '\0';
  801. X    return salt;
  802. X}
  803. X
  804. Xchar    *re_comp();
  805. X
  806. X/* ARGSUSED1 */
  807. Xaddr
  808. Xgethomedir(user, group)
  809. Xchar *user, *group;
  810. X
  811. X#ifdef xanth
  812. X{
  813. X    static addr_t dbuf[LONG_BUF], defbuf[LONG_BUF+1];
  814. X    char expr[LONG_BUF+1];
  815. X    struct direct *dp;
  816. X    DIR *dirp;
  817. X
  818. X    (void) sprintf((char *)defbuf, "/tmp/U%s", user);
  819. X    dirp = opendir(USERDIR);
  820. X    if (dirp == NULL) {
  821. X        err1("cannot open %s (read)", USERDIR);
  822. X        return(defbuf);
  823. X    }
  824. X    for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
  825. X        if (dp->d_name[0] == '.')
  826. X            continue;
  827. X        (void) sprintf(expr, "^%s%c%c", dp->d_name, '.', '*');
  828. X        (void) re_comp(expr);
  829. X        if (re_exec(group) == 1) {
  830. X            (void) sprintf((char *)dbuf, "%s/%s/%s", USERDIR,
  831. X                    dp->d_name, user);
  832. X            closedir(dirp);
  833. X            return(dbuf);
  834. X        }
  835. X    }
  836. X    closedir(dirp);
  837. X    return(defbuf);
  838. X}
  839. X#else
  840. X{
  841. X    static addr_t dbuf[LONG_BUF];
  842. X
  843. X    (void) sprintf((char *)dbuf, "%s/%s", USERDIR, user);
  844. X    return dbuf;
  845. X}
  846. X#endif
  847. X
  848. X/*
  849. X * Figger out where the next free uid is, taking into
  850. X * consideration the range tables
  851. X */
  852. Xint findnextuid(group)
  853. Xchar *group;
  854. X
  855. X{
  856. X    struct range *rg;
  857. X    int uid, indx;
  858. X    int maxu, minu;
  859. X
  860. X    maxu = minu = 0;
  861. X    uid = NOMORE;
  862. X    for (indx=0; indx < RangeList.l_count; indx++) {
  863. X        rg = (struct range *) RangeList.l_list[indx];
  864. X        if (!eq(group, rg->rg_name))
  865. X            continue;
  866. X        if (rg->rg_from > rg->rg_to)
  867. X            uid = rnextuid(rg->rg_from, rg->rg_to);
  868. X        else
  869. X            uid = nextuid(rg->rg_from, rg->rg_to);
  870. X        if (uid != NOMORE)
  871. X            return(uid);
  872. X        maxu = max(maxu, rg->rg_from);
  873. X        maxu = max(maxu, rg->rg_to);
  874. X        minu = min(minu, rg->rg_from);
  875. X        minu = min(minu, rg->rg_to);
  876. X    }
  877. X    /*
  878. X     *  No preference or no space available so now we look for space
  879. X     *  in shared ranges.
  880. X     */
  881. X    for (indx=0; indx < RangeList.l_count; indx++) {
  882. X        rg = (struct range *) RangeList.l_list[indx];
  883. X        if (rg->rg_mode == RG_EXCLUSIVE || eq(rg->rg_name, group))
  884. X            continue;
  885. X        if (rg->rg_from > rg->rg_to)
  886. X            uid = rnextuid(rg->rg_from, rg->rg_to);
  887. X        else
  888. X            uid = nextuid(rg->rg_from, rg->rg_to);
  889. X        if (uid != NOMORE)
  890. X            break;
  891. X        maxu = max(maxu, rg->rg_from);
  892. X        maxu = max(maxu, rg->rg_to);
  893. X        minu = min(minu, rg->rg_from);
  894. X        minu = min(minu, rg->rg_to);
  895. X    }
  896. X    uid = nextuid(0, minu-1);
  897. X    if (uid == -1) uid = nextuid(maxu+1, 1000);
  898. X    return(uid);
  899. X}
  900. X
  901. Xint nextuid(lo, hi)
  902. Xint lo, hi;
  903. X
  904. X{
  905. X    int i;
  906. X
  907. X    for (i=lo; i<=hi; i++)
  908. X        if (!uidexists(i))
  909. X            return(i);
  910. X    return(NOMORE);
  911. X}
  912. X
  913. Xint rnextuid(hi, lo)
  914. Xint hi, lo;
  915. X
  916. X{
  917. X    int i;
  918. X
  919. X    for (i=hi; i>=lo; i--)
  920. X        if (!uidexists(i))
  921. X            return(i);
  922. X    return(NOMORE);
  923. X}
  924. X
  925. X/*
  926. X * Max is a function here, because it is used in places where macro side
  927. X * effects are not desired.
  928. X */
  929. Xint
  930. Xmax(a, b)
  931. Xint a, b;
  932. X
  933. X{
  934. X    return (a > b ? a : b);
  935. X}
  936. X
  937. Xint
  938. Xmin(a, b)
  939. Xint a, b;
  940. X
  941. X{
  942. X    return (a < b ? a : b);
  943. X}
  944. X
  945. Xdirscan(dir, l)
  946. Xchar *dir;
  947. Xregister struct list *l;
  948. X
  949. X{
  950. X    struct direct *dp;
  951. X    DIR *dirp;
  952. X
  953. X    zerolist(l);
  954. X    dirp = opendir(dir);
  955. X    if (dirp == NULL)
  956. X        return;
  957. X    for (dp=readdir(dirp); dp != NULL; dp=readdir(dirp)) {
  958. X        if (eq(dp->d_name, ".") || eq(dp->d_name, ".."))
  959. X            continue;
  960. X        strlistadd(l, dp->d_name);
  961. X    }
  962. X    closedir(dirp);
  963. X    sort_list(l, pstrcmp);
  964. X    return;
  965. X}
  966. X
  967. Xint
  968. Xisdir(name)
  969. Xchar *name;
  970. X
  971. X{
  972. X    struct stat sb;
  973. X
  974. X    if (stat(name, &sb) == -1)
  975. X        return 0;
  976. X    return ((sb.st_mode&S_IFMT) == S_IFDIR) ? 1 : 0;
  977. X}
  978. X
  979. Xvalidint(str)
  980. Xchar *str;
  981. X
  982. X{
  983. X    if (!str || !*str)
  984. X        return 0;
  985. X    while (*str)
  986. X        if (!isdigit(*str))
  987. X            return 0;
  988. X        else
  989. X            str++;
  990. X    return 1;
  991. X}
  992. @//E*O*F src/misc.c//
  993. if test 8013 -ne "`wc -c <'src/misc.c'`"; then
  994.     echo shar: error transmitting "'src/misc.c'" '(should have been 8013 characters)'
  995. fi
  996. fi # end of overwriting check
  997. echo shar: extracting "'src/nitpick'" '(606 characters)'
  998. if test -f 'src/nitpick' ; then 
  999.   echo shar: will not over-write existing file "'src/nitpick'"
  1000. else
  1001. sed 's/^X//' >src/nitpick <<'@//E*O*F src/nitpick//'
  1002. X#! /bin/sh
  1003. X
  1004. X#
  1005. X# Script to lint individual source modules and maintain lint
  1006. X# dependencies.
  1007. X#
  1008. X# Is invoked through 'make lintbrush'
  1009. X#
  1010. X# Works great if you have jove.  Works even better if you can use
  1011. X# jove. |-)
  1012. X#
  1013. X
  1014. Xfor file
  1015. Xdo
  1016. X    if test ! -f Lint/$file ; then
  1017. X        touch Lint/$file
  1018. X    # if the lint marker is younger than the source don't lint
  1019. X    elif test `ls -t $file Lint/$file | head -1` != $file ; then
  1020. X        continue;
  1021. X    fi
  1022. X    while test `lint -a -b -h -u $file | tee LintErrors | wc -l` != "1"
  1023. X    do
  1024. X        echo Uh, oh.  Trouble with $file...
  1025. X        jove -p LintErrors $file
  1026. X    done
  1027. X    echo $file ok.
  1028. X    touch Lint/$file
  1029. Xdone
  1030. X
  1031. Xexit 0
  1032. @//E*O*F src/nitpick//
  1033. if test 606 -ne "`wc -c <'src/nitpick'`"; then
  1034.     echo shar: error transmitting "'src/nitpick'" '(should have been 606 characters)'
  1035. fi
  1036. fi # end of overwriting check
  1037. echo shar: extracting "'src/pwlock.c'" '(712 characters)'
  1038. if test -f 'src/pwlock.c' ; then 
  1039.   echo shar: will not over-write existing file "'src/pwlock.c'"
  1040. else
  1041. sed 's/^X//' >src/pwlock.c <<'@//E*O*F src/pwlock.c//'
  1042. X#include <sys/types.h>
  1043. X#include <sys/file.h>
  1044. X#include "sysdep.h"
  1045. X
  1046. Xextern    time_t PWLockTime;
  1047. Xstatic    int pwlocked;
  1048. X
  1049. Xlockpw()
  1050. X
  1051. X{
  1052. X    int fd, i;
  1053. X    time_t time();
  1054. X
  1055. X    for (i=1; i<5; i++) {
  1056. X        if ((fd=open(PWDLOCK, O_WRONLY|O_CREAT|O_EXCL, 0644)) >= 0) {
  1057. X            (void) time(&PWLockTime);
  1058. X            (void) close(fd);
  1059. X            pwlocked++;
  1060. X            return(1);
  1061. X        }
  1062. X        else switch (i) {
  1063. X            case 2: msg("Waiting for passwd lock...");    break;
  1064. X            case 3: msg("Still waiting...");        break;
  1065. X            case 4: msg("Pacing angrily...");        break;
  1066. X            default: break;
  1067. X        }
  1068. X        sleep(2 * (unsigned)i);
  1069. X    }
  1070. X    return(0);
  1071. X}
  1072. X
  1073. Xunlockpw()
  1074. X
  1075. X{
  1076. X    if (!pwlocked) return;
  1077. X    if (unlink(PWDLOCK) == -1) {
  1078. X        perr("Warning: unable to unlock password file");
  1079. X        return;
  1080. X    }
  1081. X    pwlocked = 0;
  1082. X    return;
  1083. X}
  1084. @//E*O*F src/pwlock.c//
  1085. if test 712 -ne "`wc -c <'src/pwlock.c'`"; then
  1086.     echo shar: error transmitting "'src/pwlock.c'" '(should have been 712 characters)'
  1087. fi
  1088. fi # end of overwriting check
  1089. echo shar: extracting "'src/range.c'" '(1138 characters)'
  1090. if test -f 'src/range.c' ; then 
  1091.   echo shar: will not over-write existing file "'src/range.c'"
  1092. else
  1093. sed 's/^X//' >src/range.c <<'@//E*O*F src/range.c//'
  1094. X#include <stdio.h>
  1095. X#include "sysdep.h"
  1096. X#include "mem.h"
  1097. X#include "lists.h"
  1098. X#include "range.h"
  1099. X
  1100. Xextern    struct list RangeList;
  1101. Xextern    int srangecmp();
  1102. X
  1103. Xstatic FILE *rgf = NULL;
  1104. Xstatic char line[BUFSIZ];
  1105. Xstatic char namebuf[SHORT_BUF+1], modebuf[SHORT_BUF+1];
  1106. Xstatic struct range rg;
  1107. X
  1108. Xsetrgent()
  1109. X
  1110. X{
  1111. X    rg.rg_name = namebuf;
  1112. X    if( rgf == NULL ) {
  1113. X        rgf = fopen( RANGEFILE, "r" );
  1114. X        if (rgf == NULL) {
  1115. X            perr(RANGEFILE);
  1116. X            goodbye(1);
  1117. X        }
  1118. X        rewind(rgf);
  1119. X    }
  1120. X    else
  1121. X        rewind( rgf );
  1122. X}
  1123. X
  1124. Xendrgent()
  1125. X
  1126. X{
  1127. X    if( rgf != NULL ){
  1128. X        (void) fclose( rgf );
  1129. X        rgf = NULL;
  1130. X    }
  1131. X}
  1132. X
  1133. Xstruct range *
  1134. Xgetrgent()
  1135. X
  1136. X{
  1137. X    register char *p;
  1138. X    int n;
  1139. X
  1140. X    if (rgf == NULL)
  1141. X        setrgent();
  1142. X    p = fgets(line, BUFSIZ, rgf);
  1143. X    if (p==NULL)
  1144. X        return(0);
  1145. X    n = sscanf(line, "%s%d%d%s",rg.rg_name,
  1146. X                &rg.rg_from,
  1147. X                &rg.rg_to,
  1148. X                modebuf);
  1149. X    if (n != 4) fatal("badly formatted range file line!");
  1150. X    rg.rg_mode = (modebuf[0] == 'e' ? RG_EXCLUSIVE : RG_SHARED);
  1151. X    return(&rg);
  1152. X}
  1153. X
  1154. Xstruct range *
  1155. Xgetrgnam(name)
  1156. Xchar *name;
  1157. X
  1158. X{
  1159. X    int indx, found;
  1160. X
  1161. X    indx = search_list(&RangeList, name, srangecmp, &found);
  1162. X    if (found)
  1163. X        return (struct range *) RangeList.l_list[indx];
  1164. X    return (struct range *) 0;
  1165. X}
  1166. @//E*O*F src/range.c//
  1167. if test 1138 -ne "`wc -c <'src/range.c'`"; then
  1168.     echo shar: error transmitting "'src/range.c'" '(should have been 1138 characters)'
  1169. fi
  1170. fi # end of overwriting check
  1171. echo shar: extracting "'src/range.h'" '(158 characters)'
  1172. if test -f 'src/range.h' ; then 
  1173.   echo shar: will not over-write existing file "'src/range.h'"
  1174. else
  1175. sed 's/^X//' >src/range.h <<'@//E*O*F src/range.h//'
  1176. Xstruct range {
  1177. X    char    *rg_name;
  1178. X    int    rg_from;
  1179. X    int    rg_to;
  1180. X    int    rg_mode;
  1181. X};
  1182. X
  1183. X#define RG_EXCLUSIVE    1
  1184. X#define RG_SHARED    2
  1185. X
  1186. Xstruct range *getrgent(), *getrgnam();
  1187. @//E*O*F src/range.h//
  1188. if test 158 -ne "`wc -c <'src/range.h'`"; then
  1189.     echo shar: error transmitting "'src/range.h'" '(should have been 158 characters)'
  1190. fi
  1191. fi # end of overwriting check
  1192. echo shar: extracting "'src/remove.c'" '(14203 characters)'
  1193. if test -f 'src/remove.c' ; then 
  1194.   echo shar: will not over-write existing file "'src/remove.c'"
  1195. else
  1196. sed 's/^X//' >src/remove.c <<'@//E*O*F src/remove.c//'
  1197. X#include <stdio.h>
  1198. X#include <sys/types.h>
  1199. X#include <lastlog.h>
  1200. X#include "sysdep.h"
  1201. X#include "macros.h"
  1202. X#include "mem.h"
  1203. X#include "lists.h"
  1204. X#include "gpa.h"
  1205. X#include "sort.h"
  1206. X#include "account.h"
  1207. X#ifdef SENDMAIL
  1208. X#include "alias.h"
  1209. X#endif
  1210. X#include "groupmap.h"
  1211. X#include "class.h"
  1212. X#include "job.h"
  1213. X#include "range.h"
  1214. X#include "sig.h"
  1215. X#include "save.h"
  1216. X
  1217. X#ifdef SENDMAIL
  1218. Xextern    struct list AliasList, Aliases;
  1219. X#endif SENDMAIL
  1220. Xextern    struct list AccountList, Classes, ClassList;
  1221. Xextern    struct list GroupMapList, Groups, SigList, Sigs, RangeList, Ranges;
  1222. Xextern    struct list Users, Vigs;
  1223. Xextern    int ModBits;
  1224. Xchar    *sprintf();
  1225. X
  1226. X#ifdef SENDMAIL
  1227. Xrmalias(c, v)
  1228. Xint c;
  1229. Xaddr *v;
  1230. X
  1231. X{
  1232. X    struct alias *al;
  1233. X    struct class *cs;
  1234. X    struct sig *sg;
  1235. X    struct groupmap *gm;
  1236. X    struct account *ac;
  1237. X    char *name;
  1238. X    register int i;
  1239. X
  1240. X    if ( c > 2 ) {
  1241. X        err1("%s: too many arguments", (char *)v[0]);
  1242. X        return;
  1243. X    }
  1244. X    if ( c != 2 ) {
  1245. X        err1("usage: %s <alias>", (char *)v[0]);
  1246. X        return;
  1247. X    }
  1248. X
  1249. X    al = getalnam((char *)v[1]);
  1250. X    if (!al) {
  1251. X        err1("%s: no such alias", (char *)v[1]);
  1252. X        return;
  1253. X    }
  1254. X
  1255. X    critical();
  1256. X    name = al->al_name;
  1257. X    freelist(&al->al_addresses);
  1258. X    freelist(&al->al_groups);
  1259. X    freelist(&al->al_classes);
  1260. X    freelist(&al->al_sigs);
  1261. X    strlistdel(&Aliases, (char *)v[1]);
  1262. X    genlistdel(&AliasList, v[1], saliascmp);
  1263. X    FREEMEM(name);
  1264. X    for (i=0; i < AliasList.l_count; i++) {
  1265. X        al = (struct alias *) AliasList.l_list[i];
  1266. X        if (instrlist(&al->al_addresses, (char *)v[1]))
  1267. X        strlistdel(&al->al_addresses, (char *)v[1]);
  1268. X    }
  1269. X    for (i=0; i < GroupMapList.l_count; i++) {
  1270. X        gm = (struct groupmap *) GroupMapList.l_list[i];
  1271. X        if (instrlist(&gm->gm_aliases, (char *)v[1]))
  1272. X        strlistdel(&gm->gm_aliases, (char *)v[1]);
  1273. X    }
  1274. X    for (i=0; i < ClassList.l_count; i++) {
  1275. X        cs = (struct class *) ClassList.l_list[i];
  1276. X        if (instrlist(&cs->cs_aliases, (char *)v[1]))
  1277. X        strlistdel(&cs->cs_aliases, (char *)v[1]);
  1278. X    }
  1279. X    for (i=0; i < SigList.l_count; i++) {
  1280. X        sg = (struct sig *) SigList.l_list[i];
  1281. X        if (instrlist(&sg->sg_aliases, (char *)v[1]))
  1282. X        strlistdel(&sg->sg_aliases, (char *)v[1]);
  1283. X    }
  1284. X    for (i=0; i < AccountList.l_count; i++) {
  1285. X        ac = (struct account *) AccountList.l_list[i];
  1286. X        if (instrlist(&ac->ac_aliases, (char *)v[1])) {
  1287. X        strlistdel(&ac->ac_aliases, (char *)v[1]);
  1288. X        ModBits |= AC;
  1289. X        }
  1290. X    }
  1291. X    ModBits |= AL;
  1292. X    puts("removed");
  1293. X    non_critical();
  1294. X
  1295. X    return;
  1296. X}
  1297. X#endif
  1298. X
  1299. Xrmclass(c, v)
  1300. Xint c;
  1301. Xaddr *v;
  1302. X
  1303. X{
  1304. X    struct class *cs;
  1305. X#ifdef SENDMAIL
  1306. X    struct alias *al;
  1307. X#endif
  1308. X    struct account *ac;
  1309. X    char *name;
  1310. X    int i;
  1311. X
  1312. X    if ( c > 2 ) {
  1313. X        err1("%s: too many arguments", (char *)v[0]);
  1314. X        return;
  1315. X    }
  1316. X    if ( c != 2 ) {
  1317. X        err1("usage: %s <class>", (char *)v[0]);
  1318. X        return;
  1319. X    }
  1320. X
  1321. X    cs = getcsnam((char *)v[1]);
  1322. X    if (!cs) {
  1323. X        err1("%s: no such class", (char *)v[1]);
  1324. X        return;
  1325. X    }
  1326. X
  1327. X    critical();
  1328. X
  1329. X#ifdef SENDMAIL
  1330. X    for (i=0; i < AliasList.l_count; i++) {
  1331. X        al = (struct alias *) AliasList.l_list[i];
  1332. X        if (instrlist(&al->al_classes, (char *)v[1])) {
  1333. X        strlistdel(&al->al_classes, (char *)v[1]);
  1334. X        ModBits |= AL;
  1335. X        }
  1336. X    }
  1337. X#endif
  1338. X    for (i=0; i < AccountList.l_count; i++) {
  1339. X        ac = (struct account *) AccountList.l_list[i];
  1340. X        if (instrlist(&ac->ac_classes, (char *)v[1])) {
  1341. X            strlistdel(&ac->ac_classes, (char *)v[1]);
  1342. X#ifdef SENDMAIL
  1343. X            if (cs->cs_aliases.l_count)
  1344. X                RXBindings(ac);
  1345. X#endif
  1346. X            ModBits |= AC;
  1347. X        }
  1348. X    }
  1349. X
  1350. X    name = cs->cs_name;
  1351. X    FREEMEM(cs->cs_desc);
  1352. X    genlistdel(&ClassList, v[1], sclasscmp);
  1353. X    strlistdel(&Classes, (char *)v[1]);
  1354. X    FREEMEM(name);
  1355. X
  1356. X    ModBits |= CS;
  1357. X
  1358. X    puts("removed");
  1359. X    non_critical();
  1360. X    return;
  1361. X}
  1362. X
  1363. Xrmcryos(c, v)
  1364. Xint c;
  1365. Xchar **v;
  1366. X
  1367. X{
  1368. X    register struct account *ac;
  1369. X    register int indx;
  1370. X    int removed = 0;
  1371. X
  1372. X    if ( c > 1 ) {
  1373. X        err1("%s: too many arguments", (char *)v[0]);
  1374. X        return;
  1375. X    }
  1376. X    critical();
  1377. X    for (indx=0; indx < AccountList.l_count; indx++) {
  1378. X        ac = (struct account *) AccountList.l_list[indx];
  1379. X        if (eq(ac->ac_shell, FREEZE_SH)) {
  1380. X            rmu(ac, 1);
  1381. X            removed++;
  1382. X            /* someone else is in this spot now */
  1383. X            indx--;
  1384. X        }
  1385. X    }
  1386. X    if (removed) {
  1387. X        (void) printf("%d removed\n", removed);
  1388. X#ifndef DOFILES
  1389. X        err("Do not forget to remove the user directories.");
  1390. X#endif
  1391. X    }
  1392. X    else
  1393. X        puts("No cryos.");
  1394. X    non_critical();
  1395. X    return;
  1396. X}
  1397. X
  1398. X#ifdef SENDMAIL
  1399. Xrmfromalias(c, v)
  1400. Xint c;
  1401. Xaddr *v;
  1402. X
  1403. X{
  1404. X    struct alias *al;
  1405. X    struct account *ac;
  1406. X    addr *addressv;
  1407. X    int cc, removed = 0;
  1408. X    register int indx;
  1409. X
  1410. X    if ( c > 2 ) {
  1411. X        err1("%s: too many arguments", (char *)v[0]);
  1412. X        return;
  1413. X    }
  1414. X    if (c != 2) {
  1415. X        err1("usage: %s <alias>", (char *)v[0]);
  1416. X        return;
  1417. X    }
  1418. X    al = getalnam((char *)v[1]);
  1419. X    if (!al) {
  1420. X        err1("%s: no such alias", (char *)v[1]);
  1421. X        return;
  1422. X    }
  1423. X
  1424. X    addressv = get_gpa(65);
  1425. X    GetLine("Addresses: ", 64, &cc, addressv, &al->al_addresses);
  1426. X    if (cc == 0) {
  1427. X        err("no change");
  1428. X        return;
  1429. X    }
  1430. X
  1431. X    critical();
  1432. X    for (indx=0; indx < cc; indx++) {
  1433. X        if (!instrlist(&al->al_addresses, (char *)addressv[indx])) {
  1434. X            err1("%s: not in alias", (char *)addressv[indx]);
  1435. X            continue;
  1436. X        }
  1437. X        strlistdel(&al->al_addresses, (char *)addressv[indx]);
  1438. X        ac = getacnam((char *)addressv[indx]);
  1439. X        if (ac&&instrlist(&ac->ac_aliases, (char *)addressv[indx])) {
  1440. X            strlistdel(&ac->ac_aliases, al->al_name);
  1441. X            ModBits |= AC;
  1442. X        }
  1443. X        removed++;
  1444. X    }
  1445. X    if (removed) {
  1446. X        ModBits |= AL;
  1447. X        (void) printf("%d removed\n", removed);
  1448. X    }
  1449. X    else
  1450. X        err("no change");
  1451. X    non_critical();
  1452. X
  1453. X    return;
  1454. X}
  1455. X#endif SENDMAIL
  1456. X
  1457. Xrmfromclass(c, v)
  1458. Xint c;
  1459. Xaddr *v;
  1460. X
  1461. X{
  1462. X    struct class *cs;
  1463. X    struct account *ac;
  1464. X    addr *userv;
  1465. X    int cc;
  1466. X    register int i, removed = 0;
  1467. X
  1468. X    if ( c > 2 ) {
  1469. X        err1("%s: too many arguments", (char *)v[0]);
  1470. X        return;
  1471. X    }
  1472. X    if (c != 2) {
  1473. X        err1("usage: %s <class>", (char *)v[0]);
  1474. X        return;
  1475. X    }
  1476. X    cs = getcsnam((char *)v[1]);
  1477. X    if (!cs) {
  1478. X        err1("%s: no such class", (char *)v[1]);
  1479. X        return;
  1480. X    }
  1481. X    userv = get_gpa(65);
  1482. X    GetLine("Users: ", 64, &cc, userv, &Users);
  1483. X    if (cc == 0) {
  1484. X        err("no change");
  1485. X        return;
  1486. X    }
  1487. X
  1488. X    critical();
  1489. X
  1490. X    for (i=0; i < cc; i++) {
  1491. X        ac = getacnam((char *)userv[i]);
  1492. X        if (!ac) {
  1493. X            err1("%s: no such user", (char *)userv[i]);
  1494. X            continue;
  1495. X        }
  1496. X        if (!instrlist(&ac->ac_classes, (char *)v[1])) {
  1497. X            err1("%s: not in class", (char *)userv[i]);
  1498. X            continue;
  1499. X        }
  1500. X        strlistdel(&ac->ac_classes, (char *)v[1]);
  1501. X#ifdef SENDMAIL
  1502. X        if (cs->cs_aliases.l_count)
  1503. X            RXBindings(ac);
  1504. X#endif
  1505. X        removed++;
  1506. X    }
  1507. X    if (removed) {
  1508. X        (void) printf("%d removed\n");
  1509. X        ModBits |= AC;
  1510. X    }
  1511. X    else
  1512. X        err("no change");
  1513. X
  1514. X    non_critical();
  1515. X    return;
  1516. X}
  1517. X
  1518. Xrmfromgroup(c, v)
  1519. Xint c;
  1520. Xaddr *v;
  1521. X
  1522. X{
  1523. X    struct groupmap *gm;
  1524. X    struct account *ac;
  1525. X    addr *userv;
  1526. X    int cc;
  1527. X    register int i, removed = 0;
  1528. X
  1529. X    if ( c > 2 ) {
  1530. X        err1("%s: too many arguments", (char *)v[0]);
  1531. X        return;
  1532. X    }
  1533. X    if (c != 2) {
  1534. X        err1("usage: %s <group>", (char *)v[0]);
  1535. X        return;
  1536. X    }
  1537. X    gm = getgmnam((char *)v[1]);
  1538. X    if (!gm) {
  1539. X        err1("%s: no such group", (char *)v[1]);
  1540. X        return;
  1541. X    }
  1542. X    userv = get_gpa(65);
  1543. X    GetLine("Users: ", 64, &cc, userv, &gm->gm_mem);
  1544. X    if (cc == 0) {
  1545. X        err("no change");
  1546. X        return;
  1547. X    }
  1548. X
  1549. X    critical();
  1550. X    for (i=0; i < cc; i++) {
  1551. X        ac = getacnam((char *)userv[i]);
  1552. X        if (!ac) {
  1553. X            err1("%s: no such user", (char *)userv[i]);
  1554. X            continue;
  1555. X        }
  1556. X        if (!instrlist(&gm->gm_mem, (char *)userv[i])) {
  1557. X            err1("%s: not in group", (char *)userv[i]);
  1558. X            continue;
  1559. X        }
  1560. X        strlistdel(&ac->ac_groups, (char *)v[1]);
  1561. X        strlistdel(&gm->gm_mem, (char *)userv[i]);
  1562. X#ifdef SENDMAIL
  1563. X        if (gm->gm_aliases.l_count)
  1564. X            RXBindings(ac);
  1565. X#endif
  1566. X        removed++;
  1567. X    }
  1568. X    if (removed) {
  1569. X        (void) printf("%d removed\n");
  1570. X        ModBits |= AC|GR;
  1571. X    }
  1572. X    else
  1573. X        err("no change");
  1574. X    non_critical();
  1575. X
  1576. X    return;
  1577. X}
  1578. X
  1579. Xrmfromsig(c, v)
  1580. Xint c;
  1581. Xaddr *v;
  1582. X
  1583. X{
  1584. X    struct sig *sg;
  1585. X    struct account *ac;
  1586. X    addr *userv;
  1587. X    int cc;
  1588. X    register int i, removed = 0;
  1589. X
  1590. X    if ( c > 2 ) {
  1591. X        err1("%s: too many arguments", (char *)v[0]);
  1592. X        return;
  1593. X    }
  1594. X    if (c != 2) {
  1595. X        err1("usage: %s <sig>", (char *)v[0]);
  1596. X        return;
  1597. X    }
  1598. X    sg = getsgnam((char *)v[1]);
  1599. X    if (!sg) {
  1600. X        err1("%s: no such sig", (char *)v[1]);
  1601. X        return;
  1602. X    }
  1603. X    userv = get_gpa(65);
  1604. X    GetLine("Users: ", 64, &cc, userv, &Users);
  1605. X    if (cc == 0) {
  1606. X        err("no change");
  1607. X        return;
  1608. X    }
  1609. X
  1610. X    critical();
  1611. X    for (i=0; i < cc; i++) {
  1612. X        ac = getacnam((char *)userv[i]);
  1613. X        if (!ac) {
  1614. X            err1("%s: no such user", (char *)userv[i]);
  1615. X            continue;
  1616. X        }
  1617. X        if (!instrlist(&ac->ac_sigs, (char *)v[1])) {
  1618. X            err1("%s: not in sig", (char *)userv[i]);
  1619. X            continue;
  1620. X        }
  1621. X        strlistdel(&ac->ac_sigs, (char *)v[1]);
  1622. X#ifdef SENDMAIL
  1623. X        if (sg->sg_aliases.l_count)
  1624. X            RXBindings(ac);
  1625. X#endif
  1626. X        removed++;
  1627. X    }
  1628. X    if (removed) {
  1629. X        (void) printf("%d removed\n");
  1630. X        ModBits |= AC;
  1631. X    }
  1632. X    else
  1633. X        err("no change");
  1634. X    non_critical();
  1635. X
  1636. X    return;
  1637. X}
  1638. X
  1639. Xrmgroup(c, v)
  1640. Xint c;
  1641. Xaddr *v;
  1642. X
  1643. X{
  1644. X    struct groupmap *gm;
  1645. X    struct account *ac;
  1646. X#ifdef SENDMAIL
  1647. X    struct alias *al;
  1648. X#endif
  1649. X    char *name;
  1650. X    int i, removed = 0;
  1651. X
  1652. X    if ( c > 2 ) {
  1653. X        err1("%s: too many arguments", (char *)v[0]);
  1654. X        return;
  1655. X    }
  1656. X    if ( c != 2 ) {
  1657. X        err1("usage: %s <group>", (char *)v[0]);
  1658. X        return;
  1659. X    }
  1660. X
  1661. X    gm = getgmnam((char *)v[1]);
  1662. X    if (!gm) {
  1663. X        err1("%s: no such group", (char *)v[1]);
  1664. X        return;
  1665. X    }
  1666. X
  1667. X    critical();
  1668. X
  1669. X#ifdef SENDMAIL
  1670. X    for (i=0; i < AliasList.l_count; i++) {
  1671. X        al = (struct alias *) AliasList.l_list[i];
  1672. X        if (instrlist(&al->al_groups, (char *)v[1])) {
  1673. X        strlistdel(&al->al_groups, (char *)v[1]);
  1674. X        ModBits |= AL;
  1675. X        }
  1676. X    }
  1677. X#endif
  1678. X    for (i=0; i < gm->gm_mem.l_count; i++) {
  1679. X        ac = getacnam((char *)gm->gm_mem.l_list[i]);
  1680. X        if (!ac) continue;
  1681. X        if (instrlist(&ac->ac_groups, (char *)v[1])) {
  1682. X            strlistdel(&ac->ac_groups, (char *)v[1]);
  1683. X#ifdef SENDMAIL
  1684. X            if (gm->gm_aliases.l_count)
  1685. X                RXBindings(ac);
  1686. X#endif
  1687. X            removed++;
  1688. X        }
  1689. X    }
  1690. X
  1691. X    if (removed) ModBits |= AC;
  1692. X
  1693. X    if (rangeexists((char *)v[1])) {
  1694. X        ModBits |= RG;
  1695. X        genlistdel(&RangeList, v[1], srangecmp);
  1696. X        strlistdel(&Ranges, (char *)v[1]);
  1697. X    }
  1698. X    if (vigexists((char *)v[1])) {
  1699. X        ModBits |= VG;
  1700. X        strlistdel(&Vigs, (char *)v[1]);
  1701. X    }
  1702. X
  1703. X    ModBits |= GR;
  1704. X
  1705. X    name = gm->gm_name;
  1706. X    freelist(&gm->gm_mem);
  1707. X    genlistdel(&GroupMapList, (addr)&gm->gm_gid, igmapcmp);
  1708. X    strlistdel(&Groups, (char *)v[1]);
  1709. X    FREEMEM(name);
  1710. X    puts("removed");
  1711. X    non_critical();
  1712. X
  1713. X    return;
  1714. X}
  1715. X
  1716. Xrmrange(c, v)
  1717. Xint c;
  1718. Xaddr *v;
  1719. X
  1720. X{
  1721. X    struct range *rg;
  1722. X    char *name;
  1723. X
  1724. X    if ( c > 2 ) {
  1725. X        err1("%s: too many arguments", (char *)v[0]);
  1726. X        return;
  1727. X    }
  1728. X    if ( c != 2 ) {
  1729. X        err1("usage: %s <group>", (char *)v[0]);
  1730. X        return;
  1731. X    }
  1732. X
  1733. X    rg = getrgnam((char *)v[1]);
  1734. X    if (!rg) {
  1735. X        err1("%s: no such range", (char *)v[1]);
  1736. X        return;
  1737. X    }
  1738. X
  1739. X    critical();
  1740. X    name = rg->rg_name;
  1741. X    genlistdel(&RangeList, v[1], srangecmp);
  1742. X    strlistdel(&Ranges, (char *)v[1]);
  1743. X    FREEMEM(name);
  1744. X    ModBits |= RG;
  1745. X    puts("removed");
  1746. X    non_critical();
  1747. X
  1748. X    return;
  1749. X}
  1750. X
  1751. Xrmsig(c, v)
  1752. Xint c;
  1753. Xaddr *v;
  1754. X
  1755. X{
  1756. X    struct sig *sg;
  1757. X    struct account *ac;
  1758. X#ifdef SENDMAIL
  1759. X    struct alias *al;
  1760. X#endif
  1761. X    char *name;
  1762. X    int i;
  1763. X
  1764. X    if ( c > 2 ) {
  1765. X        err1("%s: too many arguments", (char *)v[0]);
  1766. X        return;
  1767. X    }
  1768. X    if ( c != 2 ) {
  1769. X        err1("usage: %s <sig>\n", (char *)v[0]);
  1770. X        return;
  1771. X    }
  1772. X
  1773. X    sg = getsgnam((char *)v[1]);
  1774. X    if (!sg) {
  1775. X        err1("%s: no such sig", (char *)v[1]);
  1776. X        return;
  1777. X    }
  1778. X
  1779. X    critical();
  1780. X
  1781. X#ifdef SENDMAIL
  1782. X    for (i=0; i < AliasList.l_count; i++) {
  1783. X        al = (struct alias *) AliasList.l_list[i];
  1784. X        if (instrlist(&al->al_sigs, (char *)v[1])) {
  1785. X        strlistdel(&al->al_sigs, (char *)v[1]);
  1786. X        ModBits |= AL;
  1787. X        }
  1788. X    }
  1789. X#endif
  1790. X    for (i=0; i < AccountList.l_count; i++) {
  1791. X        ac = (struct account *) AccountList.l_list[i];
  1792. X        if (instrlist(&ac->ac_sigs, (char *)v[1])) {
  1793. X            strlistdel(&ac->ac_sigs, (char *)v[1]);
  1794. X#ifdef SENDMAIL
  1795. X            if (sg->sg_aliases.l_count)
  1796. X                RXBindings(ac);
  1797. X#endif
  1798. X            ModBits |= AC;
  1799. X        }
  1800. X    }
  1801. X
  1802. X    name = sg->sg_name;
  1803. X    FREEMEM(sg->sg_desc);
  1804. X    genlistdel(&SigList, v[1], ssigcmp);
  1805. X    strlistdel(&Sigs, (char *)v[1]);
  1806. X    FREEMEM(name);
  1807. X
  1808. X    ModBits |= SG;
  1809. X
  1810. X    puts("removed");
  1811. X    non_critical();
  1812. X
  1813. X    return;
  1814. X}
  1815. X
  1816. Xrmuser(c, v)
  1817. Xint c;
  1818. Xaddr *v;
  1819. X
  1820. X{
  1821. X    struct account *ac;
  1822. X    int zapdir;
  1823. X#ifdef DOFILES
  1824. X    char prompt[LONG_BUF];
  1825. X#endif
  1826. X
  1827. X    if ( c > 2 ) {
  1828. X        err1("%s: too many arguments", (char *)v[0]);
  1829. X        return;
  1830. X    }
  1831. X    if ( c != 2 ) {
  1832. X        err1("usage: %s <user>", (char *)v[0]);
  1833. X        return;
  1834. X    }
  1835. X    ac = getacnam((char *)v[1]);
  1836. X    if (!ac) {
  1837. X        err1("%s: no such user", (char *)v[1]);
  1838. X        return;
  1839. X    }
  1840. X
  1841. X#ifdef DOFILES
  1842. X    if (fileexists((char *)ac->ac_dir)) {
  1843. X        (void) sprintf(prompt, "Home directory is %s, remove it? ",
  1844. X               ac->ac_dir);
  1845. X        zapdir = yesno(prompt);
  1846. X    }
  1847. X    else
  1848. X      err1("hmmm... home directory %s non-existent", (char *)ac->ac_dir);
  1849. X#else
  1850. X    err("Do not forget to remove the user's home directory.");
  1851. X    zapdir = 0;
  1852. X#endif
  1853. X    rmu(ac, zapdir);
  1854. X
  1855. X    (void) printf("%s removed\n", v[1]);
  1856. X    return;
  1857. X}
  1858. X
  1859. Xrmvig(c, v)
  1860. Xint c;
  1861. Xaddr *v;
  1862. X
  1863. X{
  1864. X    if ( c > 2 ) {
  1865. X        err1("%s: too many arguments", (char *)v[0]);
  1866. X        return;
  1867. X    }
  1868. X    if ( c != 2 ) {
  1869. X        err1("usage: %s <vig>", (char *)v[0]);
  1870. X        return;
  1871. X    }
  1872. X
  1873. X    if (!vigexists((char *)v[1])) {
  1874. X        err1("%s: no such vig", (char *)v[1]);
  1875. X        return;
  1876. X    }
  1877. X
  1878. X    critical();
  1879. X
  1880. X    strlistdel(&Vigs, (char *)v[1]);
  1881. X    ModBits |= VG;
  1882. X
  1883. X    puts("removed");
  1884. X    non_critical();
  1885. X    return;
  1886. X}
  1887. X
  1888. X/*
  1889. X * This is the routine that actually removes a user from the data
  1890. X * structures.  rmuser() is just a front end to this routine.
  1891. X */
  1892. X/* ARGSUSED */
  1893. Xrmu(ac, zapdir)
  1894. Xstruct account *ac;
  1895. Xint zapdir;
  1896. X
  1897. X{
  1898. X    register int i, j;
  1899. X    register struct groupmap *gm;
  1900. X#ifdef SENDMAIL
  1901. X    struct alias *al;
  1902. X#endif
  1903. X    
  1904. X    critical();
  1905. X    
  1906. X#ifdef DOFILES
  1907. X    zapdir && add_job(JB_RMDIR, ac->ac_dir, NIL, NIL);
  1908. X    add_job(JB_RMMAIL, ac->ac_name, NIL, NIL);
  1909. X#endif
  1910. X
  1911. X    for (i=0; i < GroupMapList.l_count; i++) {
  1912. X        gm = (struct groupmap *) GroupMapList.l_list[i];
  1913. X        if (instrlist(&gm->gm_mem, (char *)ac->ac_name)) {
  1914. X            strlistdel(&gm->gm_mem, (char *)ac->ac_name);
  1915. X            ModBits |= GR;
  1916. X        }
  1917. X    }
  1918. X    strlistdel(&Users, (char *)ac->ac_name);
  1919. X
  1920. X#ifdef SENDMAIL
  1921. X    for (i=0; i < AliasList.l_count; i++) {
  1922. X        al = (struct alias *) AliasList.l_list[i];
  1923. X        if (instrlist(&al->al_addresses, (char *)ac->ac_name)) {
  1924. X        strlistdel(&al->al_addresses, (char *)ac->ac_name);
  1925. X        ModBits |= AL;
  1926. X        }
  1927. X    }
  1928. X#endif
  1929. X
  1930. X    FREEMEM((char *)ac->ac_name);
  1931. X    FREEMEM((char *)ac->ac_realname);
  1932. X    FREEMEM((char *)ac->ac_gecos);
  1933. X    FREEMEM((char *)ac->ac_passwd);
  1934. X    FREEMEM((char *)ac->ac_id);
  1935. X    FREEMEM((char *)ac->ac_dir);
  1936. X    FREEMEM((char *)ac->ac_shell);
  1937. X    freelist(&ac->ac_groups);
  1938. X    freelist(&ac->ac_classes);
  1939. X    freelist(&ac->ac_sigs);
  1940. X#ifdef SENDMAIL
  1941. X    freelist(&ac->ac_aliases);
  1942. X#endif
  1943. X
  1944. X    /*
  1945. X     * Cannot use genlistdel() because AccountList is sorted by uid, and
  1946. X     * not by name.
  1947. X     */
  1948. X    for (i=0; i < AccountList.l_count; i++)
  1949. X        if (ac == (struct account *) AccountList.l_list[i])
  1950. X            break;
  1951. X    for (j=i; j < AccountList.l_count-1; j++)
  1952. X        AccountList.l_list[j] = AccountList.l_list[j+1];
  1953. X    AccountList.l_count--;
  1954. X    FREEMEM((char *)ac);
  1955. X
  1956. X    ModBits |= AC|PW;
  1957. X
  1958. X    non_critical();
  1959. X
  1960. X    return;
  1961. X}
  1962. @//E*O*F src/remove.c//
  1963. if test 14203 -ne "`wc -c <'src/remove.c'`"; then
  1964.     echo shar: error transmitting "'src/remove.c'" '(should have been 14203 characters)'
  1965. fi
  1966. fi # end of overwriting check
  1967. echo shar: extracting "'src/report.c'" '(6824 characters)'
  1968. if test -f 'src/report.c' ; then 
  1969.   echo shar: will not over-write existing file "'src/report.c'"
  1970. else
  1971. sed 's/^X//' >src/report.c <<'@//E*O*F src/report.c//'
  1972. X#include <sys/types.h>
  1973. X#include <sys/stat.h>
  1974. X#include <sys/time.h>
  1975. X#include <lastlog.h>
  1976. X#include "sysdep.h"
  1977. X#include "macros.h"
  1978. X#include "mem.h"
  1979. X#include "lists.h"
  1980. X#include "account.h"
  1981. X#ifdef SENDMAIL
  1982. X#include "alias.h"
  1983. X#endif
  1984. X#include "class.h"
  1985. X#include "groupmap.h"
  1986. X#include "range.h"
  1987. X#include "sig.h"
  1988. X#include "sort.h"
  1989. X
  1990. X#ifdef BSD4_3
  1991. Xtime_t    time();
  1992. X#endif
  1993. X
  1994. X#ifdef SENDMAIL
  1995. Xextern    struct list AliasList;
  1996. X#endif
  1997. Xextern    struct list AccountList, ClassList, GroupMapList, RangeList, SigList;
  1998. Xextern    int root;
  1999. Xextern    char *when();
  2000. X
  2001. XSummarize()
  2002. X
  2003. X{
  2004. X    (void) printf("%d user%s, %d group%s, %d class%s, %d sig%s",
  2005. X        AccountList.l_count, S(AccountList.l_count),
  2006. X        GroupMapList.l_count, S(GroupMapList.l_count),
  2007. X        ClassList.l_count, ES(ClassList.l_count),
  2008. X        SigList.l_count, S(SigList.l_count));
  2009. X#ifdef SENDMAIL
  2010. X    (void) printf(", %d alias%s\n", AliasList.l_count,
  2011. X            ES(AliasList.l_count));
  2012. X#else
  2013. X    (void) puts("");
  2014. X#endif
  2015. X    return;
  2016. X}
  2017. X
  2018. Xint
  2019. XReportGoop()
  2020. X
  2021. X{
  2022. X    struct account *ac;
  2023. X    struct groupmap *gm;
  2024. X    struct class *cs;
  2025. X    struct sig *sg;
  2026. X    struct stat sb;
  2027. X    struct list c, s;
  2028. X#ifdef SENDMAIL
  2029. X    struct alias *al;
  2030. X    char *cp;
  2031. X#endif
  2032. X    time_t now;
  2033. X    int goop = 0;
  2034. X    register int indx, i;
  2035. X
  2036. X    zerolist(&c);    zerolist(&s);
  2037. X    for (indx=0; indx < AccountList.l_count; indx++) {
  2038. X        ac = (struct account *) AccountList.l_list[indx];
  2039. X        /*
  2040. X         * For root and vig members, howl if no password.
  2041. X         */
  2042. X        if (ac->ac_passwd[0] == '\0') {
  2043. X            if (ac->ac_uid == 0) {
  2044. X            (void) printf("user \"%s\" has no password!\n", ac->ac_name);
  2045. X            continue;
  2046. X            }
  2047. X            gm = getgmgid(ac->ac_gid);
  2048. X            if (gm && vigexists((char *)gm->gm_name))
  2049. X            (void) printf("user \"%s\" has no password\n", ac->ac_name);
  2050. X        }
  2051. X        /*
  2052. X         * Report users with base gids that do not correspond
  2053. X         * to a group in /etc/group.
  2054. X         */
  2055. X        if (!gidexists(ac->ac_gid))
  2056. X            (void) printf("user \"%s\" has nonexistent gid of (%d)\n",
  2057. X                ac->ac_name, ac->ac_gid);
  2058. X        /*
  2059. X         * Report references to non-existent classes
  2060. X         */
  2061. X        for (i=0; i < ac->ac_classes.l_count; i++) {
  2062. X            if (!classexists((char *)ac->ac_classes.l_list[i])) {
  2063. X(void) printf("user \"%s\" is member of nonexistent class \"%s\"\n",
  2064. X                ac->ac_name, ac->ac_classes.l_list[i]);
  2065. X                goop++;
  2066. X                continue;
  2067. X            }
  2068. X            if (!instrlist(&c, (char *)ac->ac_classes.l_list[i]))
  2069. X                strlistadd(&c, (char *)ac->ac_classes.l_list[i]);
  2070. X        }
  2071. X        /*
  2072. X         * Report references to non-existent sigs
  2073. X         */
  2074. X        for (i=0; i < ac->ac_sigs.l_count; i++) {
  2075. X            if (!sigexists((char *)ac->ac_sigs.l_list[i])) {
  2076. X(void) printf("user \"%s\" is member of nonexistent sig \"%s\"\n",
  2077. X                ac->ac_name, ac->ac_sigs.l_list[i]);
  2078. X                goop++;
  2079. X                continue;
  2080. X            }
  2081. X            if (!instrlist(&s, (char *)ac->ac_sigs.l_list[i]))
  2082. X                strlistadd(&s, (char *)ac->ac_sigs.l_list[i]);
  2083. X        }
  2084. X        /*
  2085. X         * Skip home directory and shell check if not the super-user,
  2086. X         * since not some shells may not be accessible to non
  2087. X         * super-users.
  2088. X         */
  2089. X        if (!root)
  2090. X            continue;
  2091. X        if (!fileexists((char *)ac->ac_dir))
  2092. X(void) printf("user \"%s\"'s home directory (%s) not found\n",
  2093. X                ac->ac_name, ac->ac_dir);
  2094. X        if (stat((char *)ac->ac_dir, &sb) == 0)
  2095. X            if (sb.st_uid != ac->ac_uid)
  2096. X(void) printf("user \"%s\" does not own his home directory (%s)\n", ac->ac_name, ac->ac_dir);
  2097. X        if (!fileexists((char *)ac->ac_shell))
  2098. X(void) printf("user \"%s\" login shell (%s) not found\n",
  2099. X                ac->ac_name, ac->ac_shell);
  2100. X    }
  2101. X    sort_list(&s, pstrcmp);
  2102. X    sort_list(&c, pstrcmp);
  2103. X    for (indx=0; indx < GroupMapList.l_count; indx++) {
  2104. X        gm = (struct groupmap *) GroupMapList.l_list[indx];
  2105. X        for (i=0; i < gm->gm_mem.l_count; i++) {
  2106. X            if (!userexists((char *)gm->gm_mem.l_list[i])) {
  2107. X(void) printf("group \"%s\" contains nonexistent user \"%s\"\n",
  2108. X                gm->gm_name, gm->gm_mem.l_list[i]);
  2109. X                goop++;
  2110. X            }
  2111. X        }
  2112. X    }
  2113. X    (void) time(&now);
  2114. X    for (indx=0; indx < ClassList.l_count; indx++) {
  2115. X        cs = (struct class *) ClassList.l_list[indx];
  2116. X        if (!instrlist(&c, (char *)cs->cs_name)) {
  2117. X            (void) printf("class \"%s\" is empty\n", cs->cs_name);
  2118. X            goop++;
  2119. X        }
  2120. X        if (cs->cs_exptime && (now >= cs->cs_exptime)) {
  2121. X            (void) printf("class \"%s\" expired %s\n", cs->cs_name,
  2122. X                when(cs->cs_exptime));
  2123. X            goop++;
  2124. X        }
  2125. X    }
  2126. X    for (indx=0; indx < SigList.l_count; indx++) {
  2127. X        sg = (struct sig *) SigList.l_list[indx];
  2128. X        if (!instrlist(&s, (char *)sg->sg_name)) {
  2129. X            (void) printf("sig \"%s\" is empty\n", sg->sg_name);
  2130. X            goop++;
  2131. X        }
  2132. X        if (sg->sg_exptime && (now >= sg->sg_exptime)) {
  2133. X            (void) printf("sig \"%s\" expired %s\n", sg->sg_name,
  2134. X                when(sg->sg_exptime));
  2135. X            goop++;
  2136. X        }
  2137. X    }
  2138. X#ifdef SENDMAIL
  2139. X    for (indx=0; indx < AliasList.l_count; indx++) {
  2140. X        al = (struct alias *) AliasList.l_list[indx];
  2141. X        for (i=0; i < al->al_groups.l_count; i++) {
  2142. X            cp = (char *)al->al_groups.l_list[i];
  2143. X            if (!groupexists(cp)) {
  2144. X(void) printf("alias \"%s\" bound to nonexistent group \"%s\"\n", al->al_name, cp);
  2145. X            goop++;
  2146. X            }
  2147. X        }
  2148. X        for (i=0; i < al->al_classes.l_count; i++) {
  2149. X            cp = (char *)al->al_classes.l_list[i];
  2150. X            if (!classexists(cp)) {
  2151. X(void) printf("alias \"%s\" bound to nonexistent class \"%s\"\n", al->al_name, cp);
  2152. X            goop++;
  2153. X            }
  2154. X        }
  2155. X        for (i=0; i < al->al_sigs.l_count; i++) {
  2156. X            cp = (char *)al->al_sigs.l_list[i];
  2157. X            if (!sigexists(cp)) {
  2158. X(void) printf("alias \"%s\" bound to nonexistent sig \"%s\"\n", al->al_name, cp);
  2159. X            goop++;
  2160. X            }
  2161. X        }
  2162. X    }
  2163. X#endif
  2164. X    return goop;
  2165. X}
  2166. X
  2167. XListThemThangs()
  2168. X
  2169. X{
  2170. X  struct groupmap *gm;
  2171. X  struct class *cs;
  2172. X  struct sig *sg;
  2173. X  struct account *ac;
  2174. X  register int i, j;
  2175. X  int memcount;
  2176. X
  2177. X  if (GroupMapList.l_count) puts("== Groups ==");
  2178. X  for (i=0; i < GroupMapList.l_count; i++) {
  2179. X    gm = (struct groupmap *) GroupMapList.l_list[i];
  2180. X    memcount = gm->gm_mem.l_count;
  2181. X    for (j=0; j < AccountList.l_count; j++) {
  2182. X      ac = (struct account *) AccountList.l_list[j];
  2183. X      if (ac->ac_gid == gm->gm_gid)
  2184. X    memcount++;
  2185. X    }
  2186. X    printf("\"%s\", %d member%s, %d groupie%s\n", gm->gm_name,
  2187. X       memcount - gm->gm_mem.l_count, S(memcount - gm->gm_mem.l_count),
  2188. X       gm->gm_mem.l_count, S(gm->gm_mem.l_count));
  2189. X  }
  2190. X  if (ClassList.l_count) puts("== Classes ==");
  2191. X  for (i=0; i < ClassList.l_count; i++) {
  2192. X    memcount = 0;
  2193. X    cs = (struct class *) ClassList.l_list[i];
  2194. X    for (j=0; j < AccountList.l_count; j++) {
  2195. X      ac = (struct account *) AccountList.l_list[j];
  2196. X      if (instrlist(&ac->ac_classes, cs->cs_name))
  2197. X    memcount++;
  2198. X    }
  2199. X    printf("\"%s\", %d member%s, ends %s\n", cs->cs_name,
  2200. X       memcount, S(memcount), when(cs->cs_exptime));
  2201. X  }
  2202. X  if (SigList.l_count) puts("== Sigs ==");
  2203. X  for (i=0; i < SigList.l_count; i++) {
  2204. X    memcount = 0;
  2205. X    sg = (struct sig *) SigList.l_list[i];
  2206. X    for (j=0; j < AccountList.l_count; j++) {
  2207. X      ac = (struct account *) AccountList.l_list[j];
  2208. X      if (instrlist(&ac->ac_sigs, sg->sg_name))
  2209. X    memcount++;
  2210. X    }
  2211. X    printf("\"%s\", %d member%s, ends %s\n", sg->sg_name,
  2212. X       memcount, S(memcount), when(sg->sg_exptime));
  2213. X  }
  2214. X  return;
  2215. X}
  2216. @//E*O*F src/report.c//
  2217. if test 6824 -ne "`wc -c <'src/report.c'`"; then
  2218.     echo shar: error transmitting "'src/report.c'" '(should have been 6824 characters)'
  2219. fi
  2220. fi # end of overwriting check
  2221. echo shar: "End of archive 7 (of 8)."
  2222. cp /dev/null ark7isdone
  2223. DONE=true
  2224. for I in 1 2 3 4 5 6 7 8; do
  2225.     if test -! f ark${I}isdone; then
  2226.         echo "You still need to run archive ${I}."
  2227.         DONE=false
  2228.     fi
  2229. done
  2230. case $DONE in
  2231.     true)
  2232.         echo "You have run all 8 archives."
  2233.         echo 'See the README file'
  2234.         ;;
  2235. esac
  2236. ##  End of shell archive.
  2237. exit 0
  2238.