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

  1. Subject:  v08i048:  Account creation/manipulation program, Part08/08
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: Kyle Jones <xanth!kyle>
  6. Mod.sources: Volume 8, Issue 48
  7. Archive-name: mcp/Part08
  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 8 (of 8)."
  13. # Contents:  src/save.c src/save.h src/shell.c src/sig.c src/sig.h
  14. #   src/signals.c src/sort.c src/sort.h src/sysdep.h src/tty.c
  15. #   src/version.c src/yesno.c src/update.c
  16. # Wrapped by rs@mirror on Fri Feb  6 15:56:15 1987
  17. PATH=/bin:/usr/bin:/usr/ucb; export PATH
  18. echo shar: extracting "'src/save.c'" '(8666 characters)'
  19. if test -f 'src/save.c' ; then 
  20.   echo shar: will not over-write existing file "'src/save.c'"
  21. else
  22. sed 's/^X//' >src/save.c <<'@//E*O*F src/save.c//'
  23. X/**************************************************************************\
  24. X*                                        *
  25. X*     save.c                                   *
  26. X*                                        *
  27. X* These are the routines that save the information into the respective       *
  28. X* accounting files.  An important thing to remember here is that the save  *
  29. X* and checkpointing routines USE THE SAME TEMPORARY FILES.  So no       *
  30. X* checkpointing must be done while saving is being done, and vice versa.   *
  31. X* Conflicts are avoided by blocking the all signals that would trigger       *
  32. X* either periodic or crash checkpointing, until saving is complete.       *
  33. X*                                        *
  34. X* Also the tempfiles must be in the same filesystem as their associated       *
  35. X* accounting files or the rename() system call will fail attempting to       *
  36. X* link the tempfile to the accounting file with errno == EXDEV.           *
  37. X*                                        *
  38. X\**************************************************************************/
  39. X
  40. X#include <stdio.h>
  41. X#include <sys/types.h>
  42. X#include <sys/stat.h>
  43. X#include <signal.h>
  44. X#include <lastlog.h>
  45. X#include <strings.h>
  46. X#include "sysdep.h"
  47. X#include "macros.h"
  48. X#include "mem.h"
  49. X#include "lists.h"
  50. X#include "account.h"
  51. X#ifdef SENDMAIL
  52. X#include "alias.h"
  53. X#endif
  54. X#include "class.h"
  55. X#include "sig.h"
  56. X#include "range.h"
  57. X#include "groupmap.h"
  58. X#include "save.h"
  59. X
  60. Xextern    int ModBits;
  61. Xextern    time_t PWLockTime, time();
  62. X
  63. X#ifdef SENDMAIL
  64. Xextern    struct list AliasList;
  65. X#endif
  66. Xextern    struct list AccountList, GroupMapList, SigList, ClassList, RangeList;
  67. Xextern    struct list Vigs;
  68. X
  69. Xsave_pw()
  70. X
  71. X{
  72. X    FILE *pwf;
  73. X    int i;
  74. X    struct account *ac;
  75. X#ifdef BSD4_3
  76. X    char *av[4];
  77. X    char tmpdotdir[MEDIUM_BUF], tmpdotpag[MEDIUM_BUF];
  78. X    char dotdir[MEDIUM_BUF], dotpag[MEDIUM_BUF];
  79. X#endif
  80. X
  81. X    pwf = fopen(PWDTMP, "w");
  82. X    if (pwf == NULL) {
  83. X        perr(PWDTMP);
  84. X        return;
  85. X    }
  86. X    for (i=0; i < AccountList.l_count; i++) {
  87. X        ac = (struct account *) AccountList.l_list[i];
  88. X        (void) fprintf(pwf, "%s:%s:%d:%d:%s:%s:%s\n",
  89. X            ac->ac_name,
  90. X            ac->ac_passwd,
  91. X            ac->ac_uid,
  92. X            ac->ac_gid,
  93. X            ac->ac_gecos,
  94. X            ac->ac_dir,
  95. X            ac->ac_shell);
  96. X    }
  97. X    (void) fclose(pwf);
  98. X#ifdef BSD4_3
  99. X    (void) strcpy(tmpdotdir, PWDTMP);
  100. X    (void) strcpy(tmpdotpag, PWDTMP);
  101. X    (void) strcpy(dotdir, PWDFILE);
  102. X    (void) strcpy(dotpag, PWDFILE);
  103. X    (void) strcat(tmpdotdir, ".dir");
  104. X    (void) strcat(tmpdotpag, ".pag");
  105. X    (void) strcat(dotdir, ".dir");
  106. X    (void) strcat(dotpag, ".pag");
  107. X    (void) unlink(tmpdotdir);
  108. X    (void) unlink(tmpdotpag);
  109. X    av[0] = "shell-escape";
  110. X    av[1] = DBMPASSWORD;
  111. X    av[2] = PWDTMP;
  112. X    av[3] = (char *) 0;
  113. X    if (shellescape(3, (addr *)av) != 0) {
  114. X        err1("%s failed", DBMPASSWORD);
  115. X        return;
  116. X    }
  117. X    if (rename(tmpdotdir, dotdir) == -1) {
  118. X        perr("rename");
  119. X        err2("%s -> %s rename failed", tmpdotdir, dotdir);
  120. X        return;
  121. X    }
  122. X    if (rename(tmpdotpag, dotpag) == -1) {
  123. X        perr("rename");
  124. X        err2("%s -> %s rename failed", tmpdotdir, dotdir);
  125. X        return;
  126. X    }
  127. X#endif
  128. X    if (rename(PWDTMP, PWDFILE) == -1) {
  129. X        perr(PWDTMP);
  130. X        return;
  131. X    }
  132. X    ModBits &= ~PW;
  133. X    (void) unlink(PWDCKP);
  134. X    return;
  135. X}
  136. X
  137. X#ifdef SENDMAIL
  138. Xsave_al()
  139. X
  140. X{
  141. X    FILE *alf, *bindf;
  142. X    struct alias *al;
  143. X    char *av[3];
  144. X    register int i;
  145. X
  146. X    alf = fopen(ALIASTMP, "w");
  147. X    if (alf == NULL) {
  148. X        perr(ALIASTMP);
  149. X        return;
  150. X    }
  151. X    bindf = fopen(ALBINDTMP, "w");
  152. X    if (bindf == NULL) {
  153. X        perr(ALBINDTMP);
  154. X        (void) fclose(alf);
  155. X        return;
  156. X    }
  157. X    for (i=0; i < AliasList.l_count; i++) {
  158. X        al = (struct alias *) AliasList.l_list[i];
  159. X        (void) fprintf(alf, "%s:", al->al_name);
  160. X        listout(&al->al_addresses, alf);
  161. X        fputs("\n", alf);
  162. X        (void) fprintf(bindf, "%s:", al->al_name);
  163. X        listout(&al->al_groups, bindf);
  164. X        fputs(":", bindf);
  165. X        listout(&al->al_classes, bindf);
  166. X        fputs(":", bindf);
  167. X        listout(&al->al_sigs, bindf);
  168. X        fputs("\n", bindf);
  169. X    }
  170. X    (void) fclose(alf);
  171. X    (void) fclose(bindf);
  172. X    av[0] = "shell-escape";
  173. X    av[1] = NEWALIASES;
  174. X    av[2] = (char *)0;
  175. X    if (rename(ALIASTMP, ALIASFILE) == -1) {
  176. X        perr(ALIASTMP);
  177. X        return;
  178. X    }
  179. X    if (rename(ALBINDTMP, ALBIND) == -1) {
  180. X        perr(ALBINDTMP);
  181. X        return;
  182. X    }
  183. X    if (shellescape(2, (addr *) av) != 0) {
  184. X        err1("newaliases seemed unhappy with %s", ALIASFILE);
  185. X        return;
  186. X    }
  187. X    ModBits &= ~AL;
  188. X    (void) unlink(ALIASCKP);
  189. X    (void) unlink(ALBINDCKP);
  190. X}
  191. X#endif
  192. X
  193. Xsave_ac()
  194. X
  195. X{
  196. X    FILE *acf;
  197. X    register int i;
  198. X    struct account *ac;
  199. X
  200. X    acf = fopen(ACTMP, "w");
  201. X    if (acf == NULL) {
  202. X        perr(ACTMP);
  203. X        return;
  204. X    }
  205. X    for (i=0; i < AccountList.l_count; i++) {
  206. X        ac = (struct account *) AccountList.l_list[i];
  207. X        (void) fprintf(acf, "%s:%s:%s:%d:%d:",
  208. X            ac->ac_name,
  209. X            ac->ac_realname,
  210. X            ac->ac_id,
  211. X            ac->ac_uid,
  212. X            ac->ac_gid);
  213. X        listout(&ac->ac_groups, acf);
  214. X        fputs(":", acf);
  215. X        listout(&ac->ac_classes, acf);
  216. X        fputs(":", acf);
  217. X        listout(&ac->ac_sigs, acf);
  218. X        fputs(":", acf);
  219. X#ifdef SENDMAIL
  220. X        listout(&ac->ac_aliases, acf);
  221. X#endif
  222. X        fputs("\n", acf);
  223. X    }
  224. X    (void) fclose(acf);
  225. X    if (rename(ACTMP, ACFILE) == -1) {
  226. X        perr(ACTMP);
  227. X        return;
  228. X    }
  229. X    ModBits &= ~AC;
  230. X    (void) unlink(ACCKP);
  231. X    return;
  232. X}
  233. X
  234. Xsave_gr()
  235. X
  236. X{
  237. X    FILE *grf;
  238. X    register int i;
  239. X    struct groupmap *gm;
  240. X
  241. X    grf = fopen(GRPTMP, "w");
  242. X    if (grf == NULL) {
  243. X        perr(GRPTMP);
  244. X        return;
  245. X    }
  246. X    for (i=0; i < GroupMapList.l_count; i++) {
  247. X        gm = (struct groupmap *) GroupMapList.l_list[i];
  248. X        (void) fprintf(grf, "%s:%s:%d:",
  249. X            gm->gm_name,
  250. X            gm->gm_passwd,
  251. X            gm->gm_gid);
  252. X        listout(&gm->gm_mem, grf);
  253. X        fputs("\n", grf);
  254. X    }
  255. X    (void) fclose(grf);
  256. X    if (rename(GRPTMP, GRPFILE) == -1) {
  257. X        perr(GRPTMP);
  258. X        return;
  259. X    }
  260. X    ModBits &= ~GR;
  261. X    (void) unlink(GRPCKP);
  262. X    return;
  263. X}
  264. X
  265. Xsave_cs()
  266. X
  267. X{
  268. X    struct class *cs;
  269. X    register int i;
  270. X    FILE *csf;
  271. X
  272. X    csf = fopen(CSTMP, "w");
  273. X    if (csf == NULL) {
  274. X        perr(CSTMP);
  275. X        return;
  276. X    }
  277. X    for (i=0; i < ClassList.l_count; i++) {
  278. X        cs = (struct class *) ClassList.l_list[i];
  279. X        (void) fprintf(csf, "%s %d %d\n", cs->cs_name, cs->cs_dsize,
  280. X                       cs->cs_exptime);
  281. X        (void) fprintf(csf, "%s", cs->cs_desc);
  282. X    }
  283. X    (void) fclose(csf);
  284. X    if (rename(CSTMP, CSFILE) == -1) {
  285. X        perr(CSTMP);
  286. X        return;
  287. X    }
  288. X    ModBits &= ~CS;
  289. X    (void) unlink(CSCKP);
  290. X    return;
  291. X}
  292. X
  293. Xsave_sg()
  294. X
  295. X{
  296. X    struct sig *sg;
  297. X    register int i;
  298. X    FILE *sgf;
  299. X
  300. X    sgf = fopen(SIGTMP, "w");
  301. X    if (sgf == NULL) {
  302. X        perr(SIGTMP);
  303. X        return;
  304. X    }
  305. X    for (i=0; i < SigList.l_count; i++) {
  306. X        sg = (struct sig *) SigList.l_list[i];
  307. X        (void) fprintf(sgf, "%s %d %d\n", sg->sg_name, sg->sg_dsize,
  308. X                       sg->sg_exptime);
  309. X        (void) fprintf(sgf, "%s", sg->sg_desc);
  310. X    }
  311. X    (void) fclose(sgf);
  312. X    if (rename(SIGTMP, SIGFILE) == -1) {
  313. X        perr(SIGTMP);
  314. X        return;
  315. X    }
  316. X    ModBits &= ~SG;
  317. X    (void) unlink(SIGCKP);
  318. X    return;
  319. X}
  320. X
  321. Xsave_rg()
  322. X
  323. X{
  324. X    struct range *rg;
  325. X    register int i;
  326. X    FILE *rgf;
  327. X
  328. X    rgf = fopen(RANGETMP, "w");
  329. X    if (rgf == NULL) {
  330. X        perr(RANGETMP);
  331. X        return;
  332. X    }
  333. X    for (i=0; i < RangeList.l_count; i++) {
  334. X        rg = (struct range *) RangeList.l_list[i];
  335. X        (void) fprintf(rgf, "%s\t%d\t%d\t%s\n",
  336. X            rg->rg_name,
  337. X            rg->rg_from,
  338. X            rg->rg_to,
  339. X            (rg->rg_mode == RG_SHARED ? "shared" : "exclusive"));
  340. X    }
  341. X    (void) fclose(rgf);
  342. X    if (rename(RANGETMP, RANGEFILE) == -1) {
  343. X        perr(RANGETMP);
  344. X        return;
  345. X    }
  346. X    ModBits &= ~RG;
  347. X    (void) unlink(RANGECKP);
  348. X    return;
  349. X}
  350. X
  351. Xsave_vg()
  352. X
  353. X{
  354. X    register int i;
  355. X    FILE *vgf;
  356. X
  357. X    vgf = fopen(VIGTMP, "w");
  358. X    if (vgf == NULL) {
  359. X        perr(VIGTMP);
  360. X        return;
  361. X    }
  362. X    for (i=0; i < Vigs.l_count; i++)
  363. X        (void) fprintf(vgf, "%s\n", Vigs.l_list[i]);
  364. X    (void) fclose(vgf);
  365. X    if (rename(VIGTMP, VIGFILE) == -1) {
  366. X        perr(VIGTMP);
  367. X        return;
  368. X    }
  369. X    ModBits &= ~VG;
  370. X    (void) unlink(VIGCKP);
  371. X    return;
  372. X}
  373. X
  374. Xsaveandexit()
  375. X
  376. X{
  377. X    savechanges();
  378. X    exitmcp();
  379. X}
  380. X
  381. Xsavechanges()
  382. X
  383. X{
  384. X    if (ModBits == 0 || lock_check() == 0)
  385. X        return;
  386. X    /*
  387. X     * Interrupts are disabled for obvious reasons.
  388. X     * SIGTERM, SIGALRM, SIGHUP, and SIGQUIT must be blocked because 
  389. X     * the save and checkpoint routines use the same tempfiles.
  390. X     * If a checkpoint were to occur while files where being saved,
  391. X     * chaos would ensue.
  392. X     */
  393. X    critical();
  394. X
  395. X    do_jobs();
  396. X
  397. X    (ModBits&PW) && backup(PW) && save_pw();
  398. X    (ModBits&AC) && backup(AC) && save_ac();
  399. X#ifdef SENDMAIL
  400. X    (ModBits&AL) && backup(AL) && save_al();
  401. X#endif
  402. X    (ModBits&CS) && backup(CS) && save_cs();
  403. X    (ModBits&GR) && backup(GR) && save_gr();
  404. X    (ModBits&RG) && backup(RG) && save_rg();
  405. X    (ModBits&SG) && backup(SG) && save_sg();
  406. X    (ModBits&VG) && backup(VG) && save_vg();
  407. X    sync();
  408. X    (void) time(&PWLockTime);
  409. X
  410. X    non_critical();
  411. X    return;
  412. X}
  413. X
  414. Xstatic    char *acctfile[] = {
  415. X    PWDFILE,
  416. X    ACFILE,
  417. X#ifdef SENDMAIL
  418. X    ALIASFILE,
  419. X    ALBIND,
  420. X#endif
  421. X    CSFILE,
  422. X    GRPFILE,
  423. X    RANGEFILE,
  424. X    SIGFILE,
  425. X    VIGFILE,
  426. X    (char *) 0
  427. X};
  428. X
  429. Xint
  430. Xlock_check()
  431. X
  432. X{
  433. X    register int i;
  434. X    struct stat s;
  435. X    int uhoh = 0;
  436. X
  437. X    if (!fileexists(PWDLOCK)) {
  438. X        err1("My %s lockfile has been been removed!", PWDLOCK);
  439. X        if (yesno("Do the save anyway? ") == 0)
  440. X        return 0;
  441. X    }
  442. X    for (i=0; acctfile[i]; i++) {
  443. X        if (stat(acctfile[i], &s) == -1)
  444. X        continue;
  445. X        if (s.st_mtime > PWLockTime) {
  446. X        err1("%s has been modified", acctfile[i]);
  447. X        uhoh = 1;
  448. X        }
  449. X    }
  450. X    if (uhoh) {
  451. X        err1("My %s lock has been violated.", PWDLOCK);
  452. X        err("");
  453. X        return yesno("Do the save anyway? ");
  454. X    }
  455. X    return 1;
  456. X}
  457. @//E*O*F src/save.c//
  458. if test 8666 -ne "`wc -c <'src/save.c'`"; then
  459.     echo shar: error transmitting "'src/save.c'" '(should have been 8666 characters)'
  460. fi
  461. fi # end of overwriting check
  462. echo shar: extracting "'src/save.h'" '(601 characters)'
  463. if test -f 'src/save.h' ; then 
  464.   echo shar: will not over-write existing file "'src/save.h'"
  465. else
  466. sed 's/^X//' >src/save.h <<'@//E*O*F src/save.h//'
  467. X/**********************************************************************\
  468. X*                                        *
  469. X*     save.h                                   *
  470. X*                                        *
  471. X* Definitions for ModBits flags which determine which files have been  *
  472. X* modified.                                   *
  473. X*                                        *
  474. X\**********************************************************************/
  475. X
  476. X#define AC    0x01    /* accounts */
  477. X#ifdef SENDMAIL
  478. X#define AL    0x02    /* aliases or alias bindings */
  479. X#endif
  480. X#define CS    0x04    /* classes */
  481. X#define GR    0x08    /* group */
  482. X#define PW    0x10    /* passwd */
  483. X#define RG    0x20    /* ranges */
  484. X#define SG    0x40    /* sigs */
  485. X#define VG    0x80    /* vigs */
  486. @//E*O*F src/save.h//
  487. if test 601 -ne "`wc -c <'src/save.h'`"; then
  488.     echo shar: error transmitting "'src/save.h'" '(should have been 601 characters)'
  489. fi
  490. fi # end of overwriting check
  491. echo shar: extracting "'src/shell.c'" '(3616 characters)'
  492. if test -f 'src/shell.c' ; then 
  493.   echo shar: will not over-write existing file "'src/shell.c'"
  494. else
  495. sed 's/^X//' >src/shell.c <<'@//E*O*F src/shell.c//'
  496. X#include <stdio.h>
  497. X#include <sys/types.h>
  498. X#include <sys/time.h>
  499. X#include <sys/resource.h>
  500. X#include <sys/ioctl.h>
  501. X#include <sys/wait.h>
  502. X#include <signal.h>
  503. X#include <strings.h>
  504. X#include "sysdep.h"
  505. X#include "macros.h"
  506. X#include "mem.h"
  507. X
  508. X#ifdef BSD4_3
  509. Xuid_t    getuid();
  510. Xgid_t    getgid();
  511. X#endif
  512. X
  513. X#define NILRUSAGE    (struct rusage *) 0
  514. X
  515. Xchar    *getenv();
  516. X
  517. Xextern     addr DEF_SHELL;
  518. Xextern    int DevTty, kids;
  519. X
  520. Xint
  521. Xshellescape(c, v)
  522. Xint c;
  523. Xaddr *v;
  524. X
  525. X{
  526. X    int kidpid, mypgrp, newpgrp, pid, omask, exitcode = 0;
  527. X    union wait status;
  528. X
  529. X    mypgrp = getpgrp(0);
  530. X
  531. X    c--; v++;
  532. X    /*
  533. X     * Don't want to be interrupted while forking and leave zombies
  534. X     * and things floating around.  WHo knows what happens when the
  535. X     * parent is interrupted in the midst of a vfork() ?
  536. X     */
  537. X    critical();
  538. X    kidpid = vfork();
  539. X    if (kidpid == -1) {
  540. X        perr("vfork failed!");
  541. X        return -1;
  542. X    }
  543. X    non_critical();
  544. X
  545. X    if (kidpid) {
  546. X        /*
  547. X         * Do nothing here, because we are the parent; we should go
  548. X         * directly to the wait loop.
  549. X         */
  550. X    }
  551. X    else if (c == 0) {
  552. X        char *shell = getenv("SHELL");
  553. X        char *sname;
  554. X
  555. X        if (!shell)
  556. X            shell = (char *)DEF_SHELL;
  557. X        if (!kidpid) {
  558. X            sname = rindex(shell, '/');
  559. X            sname = (sname ? sname+1 : shell);
  560. X            pid = getpid();
  561. X            (void) ioctl(DevTty, TIOCSPGRP, (char *)&pid);
  562. X            (void) setpgrp(0, pid);
  563. X            (void) setuid(getuid());  /* better safe than... */
  564. X            (void) setgid(getgid());  /* ... */
  565. X            execl(shell, sname, 0);
  566. X            perr(shell);
  567. X            _exit(1);
  568. X        }
  569. X    }
  570. X    else {
  571. X        if (!kidpid) {
  572. X            pid = getpid();
  573. X            (void) ioctl(DevTty, TIOCSPGRP, (char *)&pid);
  574. X            (void) setpgrp(0, pid);
  575. X            (void) setuid(getuid());
  576. X            (void) setgid(getgid());
  577. X            execvp((char *)*v, (char **)v);
  578. X            perr((char *)*v);
  579. X            _exit(1);
  580. X        }
  581. X    }
  582. X    for (;;) {
  583. X        /*
  584. X         *    KLUDGE ALERT! BATTLE STATIONS...
  585. X         *
  586. X         * Here we temporarily block possible SIGALRM's that
  587. X         * might be generated when mcp wants to checkpoint itself.
  588. X         * This is due to a bug in wait3() (4.2 BSD).  If the signal
  589. X         * were processed while in wait3(), the wait3() would be
  590. X         * restarted >>without<< the WUNTRACED option, which would
  591. X         * cause a deadlock here if the child were to stop.
  592. X         *
  593. X         * SIGALRM will be released once the child
  594. X         * has terminated.
  595. X         */
  596. X        omask = sigblock(mask(SIGALRM));
  597. X
  598. X        pid = wait3(&status, WUNTRACED, NILRUSAGE);
  599. X        if (pid == 0)
  600. X            continue;
  601. X        else if (pid > 0 && pid != kidpid) {
  602. X            /*
  603. X             * Apparently this isn't the child we just spawned
  604. X             * (could be an omnichown that terminated), so
  605. X             * we note its passing.
  606. X             */
  607. X            kids--;
  608. X            continue;
  609. X        }
  610. X        if (WIFSTOPPED(status)) {
  611. X            /*
  612. X             * The child has stopped due to some signal,
  613. X             * so mcp stops itself with the same signal
  614. X             * to achieve transparency.
  615. X             */
  616. X            (void) kill(getpid(), (int)status.w_stopsig);
  617. X            /*
  618. X             * We've been continued, but the our parent
  619. X             * (the shell) has given us back the tty, so
  620. X             * we must pass it back to the child before
  621. X             * continuing it.
  622. X             */
  623. X            (void) setpgrp(kidpid, kidpid);
  624. X            (void) ioctl(DevTty, TIOCSPGRP, (char *)&kidpid);
  625. X            /*
  626. X             * Now set the child in motion...
  627. X             */
  628. X            (void) killpg(kidpid, SIGCONT);
  629. X            /*
  630. X             * And keep waiting...
  631. X             */
  632. X            continue;
  633. X        }
  634. X        break;
  635. X    }
  636. X
  637. X    /*
  638. X     * Note if anything went amiss.
  639. X     */
  640. X    if (status.w_termsig != 0)
  641. X        exitcode = status.w_termsig;
  642. X    if (status.w_retcode != 0)
  643. X        exitcode = status.w_retcode;
  644. X    /*
  645. X     * Child has exited, so now we can release any pending
  646. X     * SIGALRM.
  647. X     */
  648. X    (void) sigsetmask(omask);
  649. X
  650. X    /*
  651. X     * Take command of the tty again.
  652. X     */
  653. X    (void) ioctl(DevTty, TIOCGPGRP, (char *)&newpgrp);
  654. X    (void) setpgrp(0, newpgrp);
  655. X    (void) ioctl(DevTty, TIOCSPGRP, (char *)&mypgrp);
  656. X    (void) setpgrp(0, mypgrp);
  657. X
  658. X    return exitcode;
  659. X}
  660. @//E*O*F src/shell.c//
  661. if test 3616 -ne "`wc -c <'src/shell.c'`"; then
  662.     echo shar: error transmitting "'src/shell.c'" '(should have been 3616 characters)'
  663. fi
  664. fi # end of overwriting check
  665. echo shar: extracting "'src/sig.c'" '(1855 characters)'
  666. if test -f 'src/sig.c' ; then 
  667.   echo shar: will not over-write existing file "'src/sig.c'"
  668. else
  669. sed 's/^X//' >src/sig.c <<'@//E*O*F src/sig.c//'
  670. X#include <sys/types.h>
  671. X#include <sys/file.h>
  672. X#include <stdio.h>
  673. X#include "sysdep.h"
  674. X#include "mem.h"
  675. X#include "lists.h"
  676. X#include "sig.h"
  677. X
  678. Xextern    struct list SigList;
  679. Xextern    int ssigcmp();
  680. Xlong    lseek();
  681. X
  682. Xstatic char sdesc[DESCSIZE+1], sname[SHORT_BUF], ssize[SHORT_BUF];
  683. Xstatic char sexp[SHORT_BUF];
  684. Xstruct sig sg = { sname, 0, (time_t)0, sdesc };
  685. X
  686. Xint SG_FileDes = UNDEFINED;
  687. X
  688. Xsetsgent()
  689. X
  690. X{
  691. X    if (SG_FileDes == UNDEFINED) {
  692. X        SG_FileDes = open(SIGFILE, O_RDONLY);
  693. X        if (SG_FileDes < 0) {
  694. X            perr(SIGFILE);
  695. X            goodbye(1);
  696. X        }
  697. X    }
  698. X    lseek(SG_FileDes, (long) 0, L_SET)<0 &&
  699. X        perr("setsgent: lseek failed?!");
  700. X    return;
  701. X}
  702. X
  703. Xendsgent()
  704. X
  705. X{
  706. X    if (SG_FileDes == UNDEFINED)
  707. X        return;
  708. X    (void) close(SG_FileDes);
  709. X    SG_FileDes = UNDEFINED;
  710. X    return;
  711. X}
  712. X
  713. Xstruct sig *
  714. Xgetsgent()
  715. X
  716. X{
  717. X    register int i;
  718. X    char c;
  719. X
  720. X    if (SG_FileDes == UNDEFINED)
  721. X        setsgent();
  722. X#ifdef SENDMAIL
  723. X    zerolist(&sg.sg_aliases);
  724. X#endif
  725. X    i = 0;
  726. X    while (read(SG_FileDes, &c, 1) != 0) {
  727. X        c &= 0177;
  728. X        if (c == ' ')
  729. X            break;
  730. X        sname[i++] = c;
  731. X    }
  732. X    sname[i] = '\0';
  733. X    if (i == 0)
  734. X        return (struct sig *)0;
  735. X    i = 0;
  736. X    while (read(SG_FileDes, &c, 1) != 0) {
  737. X        c &= 0177;
  738. X        if (c == ' ')
  739. X            break;
  740. X        ssize[i++] = c;
  741. X    }
  742. X    ssize[i] = '\0';
  743. X    if (i == 0)
  744. X        return (struct sig *)0;
  745. X    i = 0;
  746. X    while (read(SG_FileDes, &c, 1) != 0) {
  747. X        c &= 0177;
  748. X        if (c == '\n')
  749. X            break;
  750. X        sexp[i++] = c;
  751. X    }
  752. X    sexp[i] = '\0';
  753. X    if (i == 0)
  754. X        return (struct sig *)0;
  755. X    /* result of intermediate assignment used in read() to stifle lint */
  756. X    sg.sg_dsize = i = atoi(ssize);
  757. X    sg.sg_exptime = atoi(sexp);
  758. X    if (read(SG_FileDes, sg.sg_desc, i) != sg.sg_dsize)
  759. X        fatal1("%s: bad file format", SIGFILE);
  760. X    sg.sg_desc[sg.sg_dsize] = '\0';
  761. X    return(&sg);
  762. X}
  763. X
  764. Xstruct sig *
  765. Xgetsgnam(name)
  766. Xchar *name;
  767. X
  768. X{
  769. X    int indx, found;
  770. X
  771. X    indx = search_list(&SigList, name, ssigcmp, &found);
  772. X    if (found)
  773. X        return (struct sig *) SigList.l_list[indx];
  774. X    return (struct sig *) 0;
  775. X}
  776. @//E*O*F src/sig.c//
  777. if test 1855 -ne "`wc -c <'src/sig.c'`"; then
  778.     echo shar: error transmitting "'src/sig.c'" '(should have been 1855 characters)'
  779. fi
  780. fi # end of overwriting check
  781. echo shar: extracting "'src/sig.h'" '(298 characters)'
  782. if test -f 'src/sig.h' ; then 
  783.   echo shar: will not over-write existing file "'src/sig.h'"
  784. else
  785. sed 's/^X//' >src/sig.h <<'@//E*O*F src/sig.h//'
  786. Xstruct sig {
  787. X    char        *sg_name;
  788. X    off_t        sg_dsize;    /* description size (bytes) */
  789. X    time_t        sg_exptime;    /* expiration date (0=never) */
  790. X    char        *sg_desc;    /* pointer to description */
  791. X#ifdef SENDMAIL
  792. X    struct list    sg_aliases;     /* aliases sig is bound to */
  793. X#endif
  794. X};
  795. X
  796. Xstruct sig *getsgent(), *getsgnam();
  797. @//E*O*F src/sig.h//
  798. if test 298 -ne "`wc -c <'src/sig.h'`"; then
  799.     echo shar: error transmitting "'src/sig.h'" '(should have been 298 characters)'
  800. fi
  801. fi # end of overwriting check
  802. echo shar: extracting "'src/signals.c'" '(1569 characters)'
  803. if test -f 'src/signals.c' ; then 
  804.   echo shar: will not over-write existing file "'src/signals.c'"
  805. else
  806. sed 's/^X//' >src/signals.c <<'@//E*O*F src/signals.c//'
  807. X#include <stdio.h>
  808. X#include <setjmp.h>
  809. X#include <signal.h>
  810. X#include "sysdep.h"
  811. X#include "macros.h"
  812. X
  813. Xextern    jmp_buf interrupt;
  814. Xstatic    int critlevel, handling_yet;
  815. X#if CKPTIME > 0
  816. Xextern    int wakeup();
  817. X#endif
  818. X
  819. X#ifdef sun
  820. X#define    sighandler    (void (*)())
  821. X#else
  822. X#define    sighandler    (int (*)())
  823. X#endif
  824. X
  825. Xint_hand()
  826. X
  827. X{
  828. X    (void) fflush(stdout);
  829. X    longjmp(interrupt, SIGINT);
  830. X}
  831. X
  832. Xhup_hand()    { panic("Hangup received"); }
  833. Xterm_hand()    { panic("Terminate signal received"); }
  834. Xquit_hand()    { panic("Quit signal received"); }
  835. X
  836. Xsetsignals()
  837. X
  838. X{
  839. X    extern int root;
  840. X
  841. X    (void) signal(SIGQUIT, sighandler quit_hand);
  842. X    (void) signal(SIGINT, sighandler int_hand);
  843. X    if (root) {
  844. X        (void) signal(SIGHUP, sighandler hup_hand);
  845. X        (void) signal(SIGTERM, sighandler term_hand);
  846. X#if CKPTIME > 0
  847. X        (void) signal(SIGALRM, sighandler wakeup);
  848. X#endif
  849. X    }
  850. X    (void) sigsetmask(0);
  851. X    handling_yet = 1;
  852. X}
  853. X
  854. Xtstp()
  855. X
  856. X{
  857. X    (void) kill(getpid(), SIGTSTP);
  858. X    return;
  859. X}
  860. X
  861. X/*
  862. X * Keep user from interrupting the program during a critical section
  863. X * of code.  Used when updating interdependent data structures to insure
  864. X * consistency. Also used by the memory management routines to make sure
  865. X * allocations and free's are atomic.
  866. X */
  867. Xcritical()
  868. X
  869. X{
  870. X    if (!handling_yet) return;
  871. X    if (!critlevel++) {
  872. X        (void) signal(SIGINT, sighandler SIG_IGN);
  873. X        (void) sigsetmask(mask(SIGHUP)|mask(SIGTERM)|
  874. X                    mask(SIGQUIT)|mask(SIGALRM));
  875. X    }
  876. X    return;
  877. X}
  878. X
  879. X/*
  880. X * Critical's other half
  881. X */
  882. Xnon_critical()
  883. X
  884. X{
  885. X    if (!handling_yet) return;
  886. X    if (!--critlevel) {
  887. X        (void) signal(SIGINT, sighandler int_hand);
  888. X        (void) sigsetmask(0);
  889. X    }
  890. X    return;
  891. X}
  892. @//E*O*F src/signals.c//
  893. if test 1569 -ne "`wc -c <'src/signals.c'`"; then
  894.     echo shar: error transmitting "'src/signals.c'" '(should have been 1569 characters)'
  895. fi
  896. fi # end of overwriting check
  897. echo shar: extracting "'src/sort.c'" '(1838 characters)'
  898. if test -f 'src/sort.c' ; then 
  899.   echo shar: will not over-write existing file "'src/sort.c'"
  900. else
  901. sed 's/^X//' >src/sort.c <<'@//E*O*F src/sort.c//'
  902. X#include <sys/types.h>
  903. X#include <lastlog.h>
  904. X#include "sysdep.h"
  905. X#include "mem.h"
  906. X#include "lists.h"
  907. X#include "account.h"
  908. X#ifdef SENDMAIL
  909. X#include "alias.h"
  910. X#endif
  911. X#include "class.h"
  912. X#include "command.h"
  913. X#include "sig.h"
  914. X#include "range.h"
  915. X#include "groupmap.h"
  916. X
  917. X#ifdef SENDMAIL
  918. Xint aliascmp(a, aa)
  919. Xstruct alias **a, **aa;
  920. X
  921. X{
  922. X    return strcmp((char *)((*a)->al_name), (char *)((*aa)->al_name));
  923. X}
  924. X
  925. Xint saliascmp(s, a)
  926. Xchar *s;
  927. Xstruct alias *a;
  928. X
  929. X{
  930. X    return strcmp(s, a->al_name);
  931. X}
  932. X#endif
  933. X
  934. Xint acctcmp(a, aa)
  935. Xstruct account **a, **aa;
  936. X
  937. X{
  938. X    register int cmpval;
  939. X
  940. X    cmpval = (*a)->ac_uid - (*aa)->ac_uid;
  941. X    if (cmpval != 0) return cmpval;
  942. X    return strcmp((char *)((*a)->ac_name), (char *)((*aa)->ac_name));
  943. X}
  944. X
  945. Xint iacctcmp(n, a)
  946. Xint *n;
  947. Xstruct account *a;
  948. X
  949. X{
  950. X    return *n - a->ac_uid;
  951. X}
  952. X
  953. Xint commcmp(c, cc)
  954. Xstruct command *c, *cc;
  955. X
  956. X{
  957. X    return strcmp(c->c_name, cc->c_name);
  958. X}
  959. X
  960. Xint scommcmp(s, c)
  961. Xchar *s;
  962. Xstruct command *c;
  963. X
  964. X{
  965. X    return strcmp(s, c->c_name);
  966. X}
  967. X
  968. X
  969. Xint classcmp(c, cc)
  970. Xstruct class **c, **cc;
  971. X
  972. X{
  973. X    return strcmp((*c)->cs_name, (*cc)->cs_name);
  974. X}
  975. X
  976. Xint sclasscmp(s, c)
  977. Xchar *s;
  978. Xstruct class *c;
  979. X
  980. X{
  981. X    return strcmp(s, c->cs_name);
  982. X}
  983. X
  984. Xint gmapcmp(g, gg)
  985. Xstruct groupmap **g, **gg;
  986. X
  987. X{
  988. X    return (*g)->gm_gid - (*gg)->gm_gid;
  989. X}
  990. X
  991. Xint igmapcmp(n, g)
  992. Xint *n;
  993. Xstruct groupmap *g;
  994. X
  995. X{
  996. X    return *n - g->gm_gid;
  997. X}
  998. X
  999. Xint rangecmp(r, rr)
  1000. Xstruct range **r, **rr;
  1001. X
  1002. X{
  1003. X    return strcmp((*r)->rg_name, (*rr)->rg_name);
  1004. X}
  1005. X
  1006. Xint srangecmp(s, r)
  1007. Xchar *s;
  1008. Xstruct range *r;
  1009. X
  1010. X{
  1011. X    return strcmp(s, r->rg_name);
  1012. X}
  1013. X
  1014. Xint sigcmp(s, ss)
  1015. Xstruct sig **s, **ss;
  1016. X
  1017. X{
  1018. X    return strcmp((*s)->sg_name, (*ss)->sg_name);
  1019. X}
  1020. X
  1021. Xint ssigcmp(s, sg)
  1022. Xchar *s;
  1023. Xstruct sig *sg;
  1024. X
  1025. X{
  1026. X    return strcmp(s, sg->sg_name);
  1027. X}
  1028. X
  1029. Xpstrcmp(p, pp)
  1030. Xchar **p, **pp;
  1031. X
  1032. X{
  1033. X    return strcmp(*p, *pp);
  1034. X}
  1035. X
  1036. Xsort_list(l, compfunc)
  1037. Xstruct list *l;
  1038. Xint (*compfunc)();
  1039. X
  1040. X{
  1041. X    qsort((char *)l->l_list, l->l_count, sizeof (addr), compfunc);
  1042. X}
  1043. @//E*O*F src/sort.c//
  1044. if test 1838 -ne "`wc -c <'src/sort.c'`"; then
  1045.     echo shar: error transmitting "'src/sort.c'" '(should have been 1838 characters)'
  1046. fi
  1047. fi # end of overwriting check
  1048. echo shar: extracting "'src/sort.h'" '(243 characters)'
  1049. if test -f 'src/sort.h' ; then 
  1050.   echo shar: will not over-write existing file "'src/sort.h'"
  1051. else
  1052. sed 's/^X//' >src/sort.h <<'@//E*O*F src/sort.h//'
  1053. Xextern    int acctcmp(), iacctcmp(), commcmp(), scommcmp(), classcmp();
  1054. Xextern    int sclasscmp(), gmapcmp(), igmapcmp(), rangecmp(), srangecmp();
  1055. Xextern    int sigcmp(), ssigcmp(), pstrcmp();
  1056. X#ifdef SENDMAIL
  1057. Xextern    int aliascmp(), saliascmp();
  1058. X#endif
  1059. @//E*O*F src/sort.h//
  1060. if test 243 -ne "`wc -c <'src/sort.h'`"; then
  1061.     echo shar: error transmitting "'src/sort.h'" '(should have been 243 characters)'
  1062. fi
  1063. fi # end of overwriting check
  1064. echo shar: extracting "'src/sysdep.h'" '(10026 characters)'
  1065. if test -f 'src/sysdep.h' ; then 
  1066.   echo shar: will not over-write existing file "'src/sysdep.h'"
  1067. else
  1068. sed 's/^X//' >src/sysdep.h <<'@//E*O*F src/sysdep.h//'
  1069. X/****************************************************************************\
  1070. X*                                          *
  1071. X*     sysdep.h                                 *
  1072. X*                                          *
  1073. X* This file contains all the system dependent #define's.  In certain places  *
  1074. X* you may configure mcp to your liking by commenting out certain         *
  1075. X* definitions.                                     *
  1076. X*                                          *
  1077. X\****************************************************************************/
  1078. X
  1079. X/*
  1080. X * Define BSD4_3 if this is a 4.3 BSD system.  Currently all this entails
  1081. X * is that mcp must use mkpasswd(8) to create the .dir and .pag passwd
  1082. X * database files.
  1083. X */
  1084. X#define BSD4_3
  1085. X
  1086. X/*
  1087. X * If this is 4.3 BSD system then DBMPASSWORD must point to the mkpaswd(8)
  1088. X * command.
  1089. X */
  1090. X#ifdef BSD4_3
  1091. X#define DBMPASSWORD    "/etc/mkpasswd"
  1092. X#endif
  1093. X
  1094. X/*
  1095. X * DEF_VISUAL and DEF_EDITOR should define two different editors.
  1096. X * For dumb terminals 
  1097. X *     If getenv("EDITOR") returns NULL, DEF_EDITOR will be used when editing
  1098. X *     a class or sig description.
  1099. X * For smart terminals
  1100. X *     If getenv("VISUAL") returns NULL, DEF_VISUAL will be used when
  1101. X *     a class or sig description.
  1102. X * Smart terminals are anything but "dumb", "network", and "dialup"
  1103. X */
  1104. X#define    DEF_VISUAL    "/usr/new/jove"
  1105. X#define    DEF_EDITOR    "/bin/ed"
  1106. X
  1107. X/*
  1108. X * If for some ghastly reason TERM isn't defined, mcp will assume this.
  1109. X */
  1110. X#define    DEF_TERM    "dumb"
  1111. X
  1112. X/*
  1113. X * Disabling a user means changing his shell to be whatever DISABLED_SH
  1114. X * is defined to be.  An example disabled shell is in ../misc/sorry
  1115. X */
  1116. X#define    DISABLED_SH    "/usr/misc/sorry"
  1117. X
  1118. X/*
  1119. X * Freezing a user means changing his shell to be whatever FREEZE_SH
  1120. X * is defined to be.  An example shell for a frozen user is in
  1121. X * ../misc/freeze
  1122. X */
  1123. X#define    FREEZE_SH    "/usr/misc/freeze"
  1124. X
  1125. X/*
  1126. X * If defined HELPDIR should tell where the help files used in
  1127. X * describe-command wiil be installed.  If HELPDIR is not defined,
  1128. X * the help facilities will not be compiled in.
  1129. X */
  1130. X#define HELPDIR        "/usr/mcphelp"
  1131. X
  1132. X/*
  1133. X * DEF_PAGER is used to display the help pages from describe-command
  1134. X * if the environmental variable PAGER is not defined.
  1135. X * DEF_PAGER should understand nroff underlining sequences.
  1136. X * No need to define this if HELPDIR isn't defined.
  1137. X */
  1138. X#ifdef HELPDIR
  1139. X#define    DEF_PAGER    "/usr/ucb/more"
  1140. X#endif
  1141. X
  1142. X/*
  1143. X * If DOFILES is defined mcp will create home directories for new users,
  1144. X * remove home directories, mail, and secretmail of deleted users.  Also
  1145. X * if a user's uid is changed all his file ownerships will reflect this.
  1146. X * Otherwise it will be up to the system administrator to do these tasks.
  1147. X * Mcp will remind the SA of his responsibilities if DOFILES is undefined.
  1148. X */
  1149. X#define DOFILES
  1150. X
  1151. X/*
  1152. X * Mcp assumes that all user directories are under USERDIR as a default.
  1153. X * If this is a Sun system, code will be compiled in so that at runtime
  1154. X * mcp will check to see if USERDIR is mounted on a directory on another
  1155. X * host (a fileserver).  If so mcp will by necessity use
  1156. X * remote commands to manipulate the home directories of users.
  1157. X */
  1158. X#define    USERDIR        "/usr1"
  1159. X
  1160. X/*
  1161. X * If SENDMAIL is defined mcp will update the aliases data file and use
  1162. X * "newaliases" command as necessary to build the actual aliases database.
  1163. X * This includes the usual removal of users form aliases as accounts
  1164. X * are deleted, etc.
  1165. X *
  1166. X */
  1167. X#define SENDMAIL
  1168. X
  1169. X/*
  1170. X * This is the standard mail spool directory.  When users are deleted,
  1171. X * so is their mail if DOFILES is defined.
  1172. X */
  1173. X#define    MAILSPOOL    "/usr/spool/mail"
  1174. X/*
  1175. X * This is the standard secretmail spool.   I doubt if anyone actually
  1176. X * uses xsend and xget anymore but you never know...
  1177. X */
  1178. X#define    SMAILSPOOL    "/usr/spool/secretmail"
  1179. X
  1180. X/*
  1181. X * Directory for mcp to create it's temporary edit files in.  When adding
  1182. X * or updating class and sig descriptions mcp will put the description in
  1183. X * a temp file in this directory and invoke and either DEF_EDITOR or
  1184. X * DEF_VISUAL on it.
  1185. X */
  1186. X#define    TMPDIR        "/tmp"
  1187. X
  1188. X/*
  1189. X * New passwords created in add-user will be encrypted with this salt.
  1190. X * This is a convenience so that accounts with unchanged passwords can be
  1191. X * easily spotted by scanning the password file for this salt.
  1192. X */
  1193. X#define    CRYPT_SALT    "//"
  1194. X
  1195. X/*
  1196. X * DEF_GROUP will be the group offered as a default in add-user, so this
  1197. X * generally should be defined to be the name of the group with the most
  1198. X * members.
  1199. X */
  1200. X#define DEF_GROUP    "student"
  1201. X
  1202. X/*
  1203. X * DESCSIZE determines the maximum size that class and sig descriptions
  1204. X * will be allowed to be (in characters).  512 has proven to be more than
  1205. X * enough here.  Usually we can barely claw together 100.
  1206. X */
  1207. X#define DESCSIZE    512
  1208. X
  1209. X/*
  1210. X * If defined mcp will checkpoint changes in the accounting files each
  1211. X * CKPTIME minutes.  If not defined no automatic checkpointing will
  1212. X * be done although checkpoint files will still be written if mcp encounters
  1213. X * an unexpected signal.
  1214. X */
  1215. X#define    CKPTIME        5
  1216. X
  1217. X/****************************************************************************\
  1218. X*                                          *
  1219. X* These define the locations of the accounting files.  Each accounting file  *
  1220. X* (account, alias, class, group, passwd, range, sig, vig) also has a         *
  1221. X* #define for a backup file, a temporary file for storing intermediate         *
  1222. X* changes to the Accounts file, and a checkpoint file.  Mcp checkpoints any  *
  1223. X* changes it has made in memory to the checkpoint file once every CKPTIME    *
  1224. X* seconds.                                     *
  1225. X*                                          *
  1226. X* Each temporary file (e.g. ACTMP) MUST be in the same filesystem as its     *
  1227. X* respective accounting file because the save routines do a rename(2) call   *
  1228. X* from the temp file to the accounting file.                     *
  1229. X*                                          *
  1230. X\****************************************************************************/
  1231. X
  1232. X/*
  1233. X * the account file
  1234. X */
  1235. X#define    ACFILE        "/usr/adm/accts/Accounts"
  1236. X#define    ACBAK        "/usr/adm/accts/Accounts.bak"
  1237. X#define    ACTMP        "/usr/adm/accts/Accounts.tmp"
  1238. X#define    ACCKP        "/usr/adm/accts/Accounts.mcp"
  1239. X
  1240. X/*
  1241. X * the class file
  1242. X */
  1243. X#define    CSFILE        "/usr/adm/accts/Classes"
  1244. X#define    CSBAK        "/usr/adm/accts/Classes.bak"
  1245. X#define    CSTMP        "/usr/adm/accts/Classes.tmp"
  1246. X#define    CSCKP        "/usr/adm/accts/Classes.mcp"
  1247. X
  1248. X/*
  1249. X * the group file
  1250. X *
  1251. X * Note that since mcp uses getgrent(3) to read the
  1252. X * group file, changing the define here does no good in that respect.
  1253. X * However you can make mcp write out its version of the group file
  1254. X * anywhere you like by changing these, if you suspect mcp of mangling.
  1255. X */
  1256. X#define    GRPFILE        "/etc/group"
  1257. X#define    GRPBAK        "/etc/group.bak"
  1258. X#define    GRPTMP        "/etc/group.tmp"
  1259. X#define    GRPCKP        "/etc/group.mcp"
  1260. X
  1261. X/*
  1262. X * the passwd file
  1263. X *
  1264. X * Note that since mcp uses getpwent(3) to read the
  1265. X * passwd file, changing the define here does no good in that respect.
  1266. X * However you can make mcp write out it's version of the passwd file
  1267. X * anywhere you like by changing these, if you suspect mcp of mangling.
  1268. X */
  1269. X#define    PWDFILE        "/etc/passwd"
  1270. X#define    PWDBAK        "/etc/passwd.bak"
  1271. X#define    PWDTMP        "/etc/passwd.tmp"
  1272. X#define    PWDCKP        "/etc/passwd.mcp"
  1273. X#define    PWDLOCK        "/etc/ptmp"
  1274. X
  1275. X/*
  1276. X * the range file
  1277. X */
  1278. X#define    RANGEFILE    "/usr/adm/accts/Ranges"
  1279. X#define    RANGEBAK    "/usr/adm/accts/Ranges.bak"
  1280. X#define    RANGETMP    "/usr/adm/accts/Ranges.tmp"
  1281. X#define    RANGECKP    "/usr/adm/accts/Ranges.mcp"
  1282. X
  1283. X/*
  1284. X * the sig file
  1285. X */
  1286. X#define    SIGFILE        "/usr/adm/accts/Sigs"
  1287. X#define    SIGBAK        "/usr/adm/accts/Sigs.bak"
  1288. X#define    SIGTMP        "/usr/adm/accts/Sigs.tmp"
  1289. X#define    SIGCKP        "/usr/adm/accts/Sigs.mcp"
  1290. X
  1291. X/*
  1292. X * the vig file
  1293. X */
  1294. X#define    VIGFILE        "/usr/adm/accts/Vigs"
  1295. X#define    VIGBAK        "/usr/adm/accts/Vigs.bak"
  1296. X#define    VIGTMP        "/usr/adm/accts/Vigs.tmp"
  1297. X#define    VIGCKP        "/usr/adm/accts/Vigs.mcp"
  1298. X
  1299. X/*
  1300. X * These alias file definitions will be #ifdef'ed out if you have not
  1301. X * #define'd SENDMAIL above.  If you do plan to use mcp to manipulate the
  1302. X * sendmail aliases, check these definitions.  ALIASFILE *must* be the aliases
  1303. X * file that sendmail uses.
  1304. X */
  1305. X#ifdef SENDMAIL
  1306. X# define ALIASFILE    "/usr/lib/aliases"
  1307. X# define ALIASBAK    "/usr/lib/aliases.bak"
  1308. X# define ALIASTMP    "/usr/lib/aliases.tmp"
  1309. X# define ALIASCKP    "/usr/lib/aliases.mcp"
  1310. X# define ALBIND        "/usr/adm/accts/AliasBindings"
  1311. X# define ALBINDBAK    "/usr/adm/accts/AliasBindings.bak"
  1312. X# define ALBINDTMP    "/usr/adm/accts/AliasBindings.tmp"
  1313. X# define ALBINDCKP    "/usr/adm/accts/AliasBindings.mcp"
  1314. X/* path to the newaliases command to update the aliases database */
  1315. X# define NEWALIASES    "/usr/ucb/newaliases"
  1316. X#endif
  1317. X
  1318. X/**************************\
  1319. X*                *
  1320. X* Other file definitions.  *
  1321. X*                *
  1322. X\**************************/
  1323. X
  1324. X/*
  1325. X * Standard location for the lastlog, used by login(1) and finger(1).
  1326. X */
  1327. X#define    LASTLOG        "/usr/adm/lastlog"
  1328. X
  1329. X
  1330. X/*
  1331. X * Mcp gets the list of available shells from this file and builds a
  1332. X * completion list from it.  The file format is one shell per line
  1333. X * with the first line containing the shell that will be the default
  1334. X * in add-user.  For 4.3 BSD systems it is convenient to use /etc/shells,
  1335. X * since the passwd(1) command already uses this list.  Mcp will ignore the
  1336. X * comments in this file, for compatibility with /etc/shells on 4.3 BSD
  1337. X * systems.
  1338. X */
  1339. X#define    SHELLFILE    "/etc/shells"
  1340. X
  1341. X/****************************************************************************\
  1342. X*                                          *
  1343. X* These definitions are needed only if DOFILES is #define'd above.  For Sun  *
  1344. X* systems, the pathnames for the executables should be correct for the         *
  1345. X* fileserver and all the clients.  The paths given will work if the         *
  1346. X* commands have not been moved from the locations in which they were         *
  1347. X* distributed.                                     *
  1348. X*                                          *
  1349. X* Mcp uses these chiefly as remote commands on Sun systems.  FIND is used    *
  1350. X* to change the onwership of user files in all cases involving more than     *
  1351. X* one file.  Otherwise mcp will use the system primitives chmod(),         *
  1352. X* chown(), etc., instead of these commands.                     *
  1353. X*                                          *
  1354. X\****************************************************************************/
  1355. X
  1356. X#ifdef DOFILES
  1357. X#define MV    "/bin/mv"
  1358. X#define RM    "/bin/rm"
  1359. X#define MKDIR    "/bin/mkdir"
  1360. X#define CHGRP    "/bin/chgrp"
  1361. X#define CHOWN    "/etc/chown"
  1362. X#define CHMOD    "/bin/chmod"
  1363. X#define FIND    "/usr/bin/find"
  1364. X#define NICE    "/bin/nice"
  1365. X#endif
  1366. @//E*O*F src/sysdep.h//
  1367. if test 10026 -ne "`wc -c <'src/sysdep.h'`"; then
  1368.     echo shar: error transmitting "'src/sysdep.h'" '(should have been 10026 characters)'
  1369. fi
  1370. fi # end of overwriting check
  1371. echo shar: extracting "'src/tty.c'" '(431 characters)'
  1372. if test -f 'src/tty.c' ; then 
  1373.   echo shar: will not over-write existing file "'src/tty.c'"
  1374. else
  1375. sed 's/^X//' >src/tty.c <<'@//E*O*F src/tty.c//'
  1376. X#include <sys/ioctl.h>
  1377. X
  1378. Xextern int DevTty;
  1379. X
  1380. Xcbreak()
  1381. X
  1382. X{
  1383. X    struct sgttyb sg;
  1384. X
  1385. X    (void) ioctl(DevTty, TIOCGETP, (char *)&sg);
  1386. X    sg.sg_flags |= CBREAK;
  1387. X    sg.sg_flags &= ~(CRMOD|ECHO|RAW);
  1388. X    (void) ioctl(DevTty, TIOCSETP, (char *)&sg);
  1389. X    return;
  1390. X}
  1391. X
  1392. Xnocbreak()
  1393. X
  1394. X{
  1395. X    struct sgttyb sg;
  1396. X
  1397. X    (void) ioctl(DevTty, TIOCGETP, (char *)&sg);
  1398. X    sg.sg_flags &= ~CBREAK;
  1399. X    sg.sg_flags |= (CRMOD|ECHO);
  1400. X    (void) ioctl(DevTty, TIOCSETP, (char *)&sg);
  1401. X    return;
  1402. X}
  1403. @//E*O*F src/tty.c//
  1404. if test 431 -ne "`wc -c <'src/tty.c'`"; then
  1405.     echo shar: error transmitting "'src/tty.c'" '(should have been 431 characters)'
  1406. fi
  1407. fi # end of overwriting check
  1408. echo shar: extracting "'src/version.c'" '(577 characters)'
  1409. if test -f 'src/version.c' ; then 
  1410.   echo shar: will not over-write existing file "'src/version.c'"
  1411. else
  1412. sed 's/^X//' >src/version.c <<'@//E*O*F src/version.c//'
  1413. Xstatic    struct notice {
  1414. X    char    *n_version;
  1415. X    char    *n_copyright;
  1416. X};
  1417. Xstatic    struct notice Note = {
  1418. X"mcp version 1.0 (#2) ",
  1419. X"(c) 1986 by Kyle E. Jones\n\n\
  1420. XAll sources and documentation of this mcp distribution are\n\
  1421. Xincluded in this copyright, but permission is granted to\n\
  1422. Xcopy and redistribute any part of this distribution, provided\n\
  1423. Xthat this notice is a conspicuous part of the redistribution,\n\
  1424. Xand that no part of this distribution is sold.\n\n\
  1425. XThis software is distributed 'as is', without warranties of any kind.\n\
  1426. X"
  1427. X};
  1428. X    
  1429. X
  1430. XShowVersion()
  1431. X
  1432. X{
  1433. X    err(Note.n_version);
  1434. X}
  1435. @//E*O*F src/version.c//
  1436. if test 577 -ne "`wc -c <'src/version.c'`"; then
  1437.     echo shar: error transmitting "'src/version.c'" '(should have been 577 characters)'
  1438. fi
  1439. fi # end of overwriting check
  1440. echo shar: extracting "'src/yesno.c'" '(1858 characters)'
  1441. if test -f 'src/yesno.c' ; then 
  1442.   echo shar: will not over-write existing file "'src/yesno.c'"
  1443. else
  1444. sed 's/^X//' >src/yesno.c <<'@//E*O*F src/yesno.c//'
  1445. X#include <stdio.h>
  1446. X#include "sysdep.h"
  1447. X#include "mem.h"
  1448. X#include "lists.h"
  1449. X#include "gpa.h"
  1450. X
  1451. Xstatic    char *yn[4] = { "yes", "no", "YES!!!", "NO!!!" };
  1452. Xstatic    char *y[1] = { "yes" };
  1453. Xstatic    char *n[1] = { "no" };
  1454. X
  1455. Xstruct    list YesNo = {    4, 4, (addr *)yn };
  1456. X
  1457. Xstatic    struct list Yes = { 1, 1, (addr *)y };
  1458. Xstatic    struct list No = { 1, 1, (addr *)n };
  1459. X
  1460. X/*
  1461. X * Query for a yes or no answer.  Allows carriage return to default
  1462. X * yes.  Returns 1 if answer is yes, 0 for no.
  1463. X */
  1464. Xyes(prompt)
  1465. Xchar *prompt;
  1466. X
  1467. X{
  1468. X    addr *argv;
  1469. X    int argc;
  1470. X    char **cpp;
  1471. X
  1472. X    argv = get_gpa(2);
  1473. X    cpp = (char **) argv;
  1474. X    do {
  1475. X        GetLine(prompt, 1, &argc, argv, &Yes);
  1476. X        if (argc == 0 || **cpp == 'y' || **cpp == 'Y') {
  1477. X            pop_gpa(2);
  1478. X            return(1);
  1479. X        }
  1480. X        else if (**cpp == 'n' || **cpp == 'N') {
  1481. X            pop_gpa(2);
  1482. X            return(0);
  1483. X        }
  1484. X    } while (clear_gpa(argv, 2));
  1485. X    /* NOTREACHED */
  1486. X}
  1487. X
  1488. X
  1489. X/*
  1490. X * Query for a yes or no answer.  Allows carriage return to default
  1491. X * no.  Returns 1 if answer is no, 0 for yes.
  1492. X */
  1493. Xno(prompt)
  1494. Xchar *prompt;
  1495. X
  1496. X{
  1497. X    addr *argv;
  1498. X    int argc;
  1499. X    char **cpp;
  1500. X
  1501. X    argv = get_gpa(2);
  1502. X    cpp = (char **) argv;
  1503. X    do {
  1504. X        GetLine(prompt, 1, &argc, argv, &No);
  1505. X        if (argc == 0 || **cpp == 'n' || **cpp == 'N') {
  1506. X            pop_gpa(2);
  1507. X            return(1);
  1508. X        }
  1509. X        else if (**cpp == 'y' || **cpp == 'Y') {
  1510. X            pop_gpa(2);
  1511. X            return(0);
  1512. X        }
  1513. X    } while (clear_gpa(argv, 2));
  1514. X    /* NOTREACHED */
  1515. X}
  1516. X
  1517. X
  1518. X/*
  1519. X * Query for a yes or no answer.  Disallows carriage return default;
  1520. X * answer must be specified.  Returns 1 if answer is yes, 0 for no.
  1521. X */
  1522. Xyesno(prompt)
  1523. Xchar *prompt;
  1524. X
  1525. X{
  1526. X    addr *argv;
  1527. X    int argc;
  1528. X    char **cpp;
  1529. X
  1530. X    argv = get_gpa(2);
  1531. X    cpp = (char **) argv;
  1532. X    do {
  1533. X        GetLine(prompt, 1, &argc, argv, &YesNo);
  1534. X        if (argc == 0) continue;
  1535. X        if (**cpp == 'y' || **cpp == 'Y') {
  1536. X            pop_gpa(2);
  1537. X            return(1);
  1538. X        }
  1539. X        else if (**cpp == 'n' || **cpp == 'N') {
  1540. X            pop_gpa(2);
  1541. X            return(0);
  1542. X        }
  1543. X    } while (clear_gpa(argv, 2));
  1544. X    /* NOTREACHED */
  1545. X}
  1546. @//E*O*F src/yesno.c//
  1547. if test 1858 -ne "`wc -c <'src/yesno.c'`"; then
  1548.     echo shar: error transmitting "'src/yesno.c'" '(should have been 1858 characters)'
  1549. fi
  1550. fi # end of overwriting check
  1551. echo shar: extracting "'src/update.c'" '(22502 characters)'
  1552. if test -f 'src/update.c' ; then 
  1553.   echo shar: will not over-write existing file "'src/update.c'"
  1554. else
  1555. sed 's/^X//' >src/update.c <<'@//E*O*F src/update.c//'
  1556. X#include <stdio.h>
  1557. X#include <sys/types.h>
  1558. X#include <sys/stat.h>
  1559. X#include <strings.h>
  1560. X#include <ctype.h>
  1561. X#include <lastlog.h>
  1562. X#include "sysdep.h"
  1563. X#include "macros.h"
  1564. X#include "mem.h"
  1565. X#include "gpa.h"
  1566. X#include "lists.h"
  1567. X#include "account.h"
  1568. X#ifdef SENDMAIL
  1569. X#include "alias.h"
  1570. X#endif
  1571. X#include "class.h"
  1572. X#include "groupmap.h"
  1573. X#include "job.h"
  1574. X#include "range.h"
  1575. X#include "sig.h"
  1576. X#include "sort.h"
  1577. X#include "save.h"
  1578. X
  1579. X#define    DAY    (4*21600)
  1580. X
  1581. X#ifdef SENDMAIL
  1582. Xextern    struct list AliasList, Aliases;
  1583. X#endif
  1584. Xextern    struct list AccountList, Users, ClassList, Classes, GroupMapList;
  1585. Xextern    struct list Groups, RangeList, Ranges, Sigs, SigList, Vigs, Shells;
  1586. Xextern    struct list Null_List;
  1587. Xextern    int ModBits;
  1588. Xextern    addr makeusername(), DEF_SHELL;
  1589. Xextern    char *crypt(), *mktemp(), *sprintf(), *when(), *rsalt(), *makepass();
  1590. Xextern    time_t choosedate();
  1591. X
  1592. Xstatic    char *XXXXXX = "/mcpXXXXXX";
  1593. Xstatic    char desc[DESCSIZE+1];
  1594. X
  1595. X/* these are defined in add.c */
  1596. Xextern    struct    list idlist;
  1597. Xextern    struct    list rnlist;
  1598. Xextern    struct    list pwlist;
  1599. Xextern    struct    list mdlist;
  1600. X
  1601. X#ifdef SENDMAIL
  1602. X/*
  1603. X * Update an alias
  1604. X */
  1605. Xupdalias(c, v)
  1606. Xint c;
  1607. Xchar **v;
  1608. X
  1609. X{
  1610. X    struct alias *al, *a;
  1611. X    struct account *ac;
  1612. X    struct class *cs;
  1613. X    struct sig *sg;
  1614. X    struct groupmap *gm;
  1615. X    register int i;
  1616. X    int cc;
  1617. X    addr *namev;
  1618. X    char prompt[MEDIUM_BUF];
  1619. X
  1620. X    if (c > 2) {
  1621. X        err1("%s: too many arguments", (char *)v[0]);
  1622. X        return;
  1623. X    }
  1624. X    if (c < 2) {
  1625. X        err1("usage: %s <alias>", (char *)v[0]);
  1626. X        return;
  1627. X    }
  1628. X    al = getalnam((char *)v[1]);
  1629. X    if (!al) {
  1630. X        err1("%s: no such alias", (char *)v[1]);
  1631. X        return;
  1632. X    }
  1633. X
  1634. X    namev = get_gpa(2);
  1635. X    (void) sprintf(prompt, "Name [%s]: ", al->al_name);
  1636. X    GetLine(prompt, 1, &cc, namev, &Null_List);
  1637. X    if (cc == 0 || eq(*namev, al->al_name)) {
  1638. X        err("no change");
  1639. X        return;
  1640. X    }
  1641. X    if (aliasexists((char *)*namev)) {
  1642. X        err1("%s: alias exists", (char *)*namev);
  1643. X        return;
  1644. X    }
  1645. X
  1646. X    critical();
  1647. X
  1648. X    /*
  1649. X     * If this alias name appears in any of the other alias lists
  1650. X     * it must be changed there alias well.
  1651. X     */
  1652. X    for (i=0; i < AliasList.l_count; i++) {
  1653. X        a = (struct alias *) AliasList.l_list[i];
  1654. X        (void) strlistchg(&a->al_addresses, al->al_name, (char *)*namev);
  1655. X    }
  1656. X    for (i=0; i < AccountList.l_count; i++) {
  1657. X        ac = (struct account *) AccountList.l_list[i];
  1658. X        if (strlistchg(&ac->ac_aliases, al->al_name, (char *)*namev))
  1659. X        ModBits |= AC;
  1660. X    }
  1661. X    for (i=0; i < GroupMapList.l_count; i++) {
  1662. X        gm = (struct groupmap *) GroupMapList.l_list[i];
  1663. X        (void) strlistchg(&gm->gm_aliases, al->al_name, (char *)*namev);
  1664. X    }
  1665. X    for (i=0; i < ClassList.l_count; i++) {
  1666. X        cs = (struct class *) ClassList.l_list[i];
  1667. X        (void) strlistchg(&cs->cs_aliases, al->al_name, (char *)*namev);
  1668. X    }
  1669. X    for (i=0; i < SigList.l_count; i++) {
  1670. X        sg = (struct sig *) SigList.l_list[i];
  1671. X        (void) strlistchg(&sg->sg_aliases, al->al_name, (char *)*namev);
  1672. X    }
  1673. X
  1674. X    (void) strlistchg(&Aliases, al->al_name, (char *)*namev);
  1675. X    FREEMEM(al->al_name);
  1676. X    savestr(&al->al_name, (char *)*namev);
  1677. X    sort_list(&AliasList, aliascmp);
  1678. X    ModBits |= AL;
  1679. X    puts("updated");
  1680. X    non_critical();
  1681. X
  1682. X    return;
  1683. X}
  1684. X#endif
  1685. X
  1686. X/*
  1687. X * Update a class
  1688. X */
  1689. Xupdclass(c, v)
  1690. Xint c;
  1691. Xaddr *v;
  1692. X
  1693. X{
  1694. X    struct class cl, *cs;
  1695. X    struct account *ac;
  1696. X#ifdef SENDMAIL
  1697. X    struct alias *al;
  1698. X#endif
  1699. X    struct stat statbuf;
  1700. X    addr *namev;
  1701. X    char tempf[MEDIUM_BUF], errmsg[LONG_BUF], prompt[LONG_BUF];
  1702. X    FILE *f, *fopen();
  1703. X    time_t now;
  1704. X    int i, cc, changed = 0, ch;
  1705. X
  1706. X    if ( c > 2 ) {
  1707. X        err1("%s: too many arguments", (char *)v[0]);
  1708. X        return;
  1709. X    }
  1710. X    if ( c != 2 ) {
  1711. X        err1("usage: %s <class>", (char *)v[0]);
  1712. X        return;
  1713. X    }
  1714. X    cs = getcsnam((char *)v[1]);
  1715. X    if (!cs) {
  1716. X        err1("%s: no such class", (char *)v[1]);
  1717. X        return;
  1718. X    }
  1719. X    bcopy(&cl, cs, sizeof (struct class));
  1720. X
  1721. X    namev = get_gpa(2);
  1722. X
  1723. X    (void) sprintf(prompt, "Name [%s]: ",  cl.cs_name);
  1724. X    GetLine(prompt, 1, &cc, namev, &Null_List);
  1725. X    if (cc) {
  1726. X        if (eq(*namev, v[1]))
  1727. X            ; /* no change */
  1728. X        else if (classexists((char *)*namev)) {
  1729. X            err("that name is taken");
  1730. X            return;
  1731. X        }
  1732. X        else
  1733. X            changed = 1;
  1734. X    }
  1735. X    (void) printf("Class set to end %s\n", when(cl.cs_exptime));
  1736. X    if (no("Do you wish to change it? [no] ") == 0) {
  1737. X        if (!cl.cs_exptime || yesno("Should the class expire? ")) {
  1738. X        err("Set the expiration date.");
  1739. X        cl.cs_exptime = choosedate(cl.cs_exptime);
  1740. X        (void) printf("Class set to end %s\n", when(cl.cs_exptime));
  1741. X        }
  1742. X        else
  1743. X        cl.cs_exptime = 0;
  1744. X        if (cl.cs_exptime != cs->cs_exptime)
  1745. X        changed = 1;
  1746. X    }
  1747. X    i = no("Edit description? [no] ");
  1748. X
  1749. X    critical();
  1750. X    if (i)
  1751. X        goto finish;
  1752. X    (void) strcpy(tempf, TMPDIR);
  1753. X    (void) strcat(tempf, XXXXXX);
  1754. X    (void) mktemp(tempf);
  1755. X    f = fopen(tempf, "w");
  1756. X    if (f == NULL) {
  1757. X        err1("%s: cannot open (write)", tempf);
  1758. X        non_critical();
  1759. X        return;
  1760. X    }
  1761. X    fputs(cl.cs_desc, f);
  1762. X    (void) fclose(f);
  1763. X    (void) stat(tempf, &statbuf);
  1764. X    now = statbuf.st_mtime;
  1765. X    for (;;) {
  1766. X        edit(tempf);
  1767. X        if (stat(tempf, &statbuf) == -1) {
  1768. X            perr(tempf);
  1769. X            (void) unlink(tempf);
  1770. X            non_critical();
  1771. X            return;
  1772. X        }
  1773. X        if (statbuf.st_size > DESCSIZE) {
  1774. X            (void) sprintf(errmsg,
  1775. X                "description is %d characters too long",
  1776. X                DESCSIZE - statbuf.st_size);
  1777. X            err(errmsg);
  1778. X            continue;
  1779. X        }
  1780. X        break;
  1781. X    }
  1782. X    if (statbuf.st_mtime == now)
  1783. X        goto finish;
  1784. X    changed = 1;
  1785. X    f = fopen(tempf, "r");
  1786. X    if (f == NULL) {
  1787. X        err1("%s: cannot open (read)", tempf);
  1788. X        non_critical();
  1789. X        return;
  1790. X    }
  1791. X    FREEMEM(cl.cs_desc);
  1792. X    i = 0;
  1793. X    while ((ch = getc(f)) != EOF)
  1794. X        desc[i++] = ch;
  1795. X    desc[i] = '\0';
  1796. X    cl.cs_dsize = i;
  1797. X    savestr(&cl.cs_desc, desc);
  1798. X    (void) fclose(f);
  1799. X    (void) unlink(tempf);
  1800. X
  1801. Xfinish:
  1802. X    if (*namev != NIL && !eq(*namev, v[1])) {
  1803. X        FREEMEM(cl.cs_name);
  1804. X        savestr(&cl.cs_name, (char *)*namev);
  1805. X        for (i=0; i < AccountList.l_count; i++) {
  1806. X            ac = (struct account *)AccountList.l_list[i];
  1807. X            if (strlistchg(&ac->ac_classes, (char *)v[1], cl.cs_name))
  1808. X            ModBits |= AC;
  1809. X        }
  1810. X#ifdef SENDMAIL
  1811. X        for (i=0; i < AliasList.l_count; i++) {
  1812. X            al = (struct alias *) AliasList.l_list[i];
  1813. X            if (strlistchg(&al->al_classes, (char *)v[1], cl.cs_name))
  1814. X            ModBits |= AL;
  1815. X        }
  1816. X#endif
  1817. X        (void) strlistchg(&Classes, (char *)v[1], cl.cs_name);
  1818. X    }
  1819. X    if (changed) {
  1820. X        bcopy(cs, &cl, sizeof (struct class));
  1821. X        sort_list(&ClassList, classcmp);
  1822. X        ModBits |= CS;
  1823. X        puts("updated");
  1824. X    }
  1825. X    else
  1826. X        err("no change");
  1827. X    non_critical();
  1828. X
  1829. X    return;
  1830. X}
  1831. X
  1832. X/*
  1833. X * Update a sig
  1834. X */
  1835. Xupdsig(c, v)
  1836. Xint c;
  1837. Xaddr *v;
  1838. X
  1839. X{
  1840. X    struct sig s, *sg;
  1841. X#ifdef SENDMAIL
  1842. X    struct alias *al;
  1843. X#endif
  1844. X    struct account *ac;
  1845. X    struct stat statbuf;
  1846. X    addr *namev;
  1847. X    char tempf[MEDIUM_BUF], errmsg[LONG_BUF], prompt[LONG_BUF];
  1848. X    FILE *f, *fopen();
  1849. X    time_t now;
  1850. X    int i, cc, changed = 0, ch;
  1851. X
  1852. X    if ( c > 2 ) {
  1853. X        err1("%s: too many arguments", (char *)v[0]);
  1854. X        return;
  1855. X    }
  1856. X    if ( c != 2 ) {
  1857. X        err1("usage: %s <sig>", (char *)v[0]);
  1858. X        return;
  1859. X    }
  1860. X    sg = getsgnam((char *)v[1]);
  1861. X    if (!sg) {
  1862. X        err1("%s: no such sig", (char *)v[1]);
  1863. X        return;
  1864. X    }
  1865. X    bcopy(&s, sg, sizeof (struct sig));
  1866. X
  1867. X    namev = get_gpa(2);
  1868. X
  1869. X    (void) sprintf(prompt, "Name [%s]: ",  s.sg_name);
  1870. X    GetLine(prompt, 1, &cc, namev, &Null_List);
  1871. X    if (cc) {
  1872. X        if (eq(*namev, v[1]))
  1873. X            ; /* no change */
  1874. X        else if (sigexists((char *)*namev)) {
  1875. X            err("that name is taken");
  1876. X            return;
  1877. X        }
  1878. X        else
  1879. X            changed = 1;
  1880. X    }
  1881. X    (void) printf("Sig set to end %s\n", when(s.sg_exptime));
  1882. X    if (no("Do you wish to change it? [no] ") == 0) {
  1883. X        if (!s.sg_exptime || yesno("Should the sig expire? ")) {
  1884. X        err("Set the expiration date.");
  1885. X        s.sg_exptime = choosedate(s.sg_exptime);
  1886. X        (void) printf("Project set to end %s\n", when(s.sg_exptime));
  1887. X        }
  1888. X        else
  1889. X        s.sg_exptime = 0;
  1890. X        if (s.sg_exptime != sg->sg_exptime)
  1891. X        changed = 1;
  1892. X    }
  1893. X    i = no("Edit description? [no] ");
  1894. X    
  1895. X    critical();
  1896. X    if (i)
  1897. X        goto finish;
  1898. X    (void) strcpy(tempf, TMPDIR);
  1899. X    (void) strcat(tempf, XXXXXX);
  1900. X    (void) mktemp(tempf);
  1901. X    f = fopen(tempf, "w");
  1902. X    if (f == NULL) {
  1903. X        err1("%s: cannot open (write)", tempf);
  1904. X        non_critical();
  1905. X        return;
  1906. X    }
  1907. X    fputs(s.sg_desc, f);
  1908. X    (void) fclose(f);
  1909. X    (void) stat(tempf, &statbuf);
  1910. X    now = statbuf.st_mtime;
  1911. X    for (;;) {
  1912. X        edit(tempf);
  1913. X        if (stat(tempf, &statbuf) == -1) {
  1914. X            perr(tempf);
  1915. X            (void) unlink(tempf);
  1916. X            non_critical();
  1917. X            return;
  1918. X        }
  1919. X        if (statbuf.st_size > DESCSIZE) {
  1920. X            (void) sprintf(errmsg,
  1921. X                "description is %d characters too long",
  1922. X                DESCSIZE - statbuf.st_size);
  1923. X            err(errmsg);
  1924. X            continue;
  1925. X        }
  1926. X        break;
  1927. X    }
  1928. X    if (statbuf.st_mtime == now)
  1929. X        goto finish;
  1930. X    changed = 1;
  1931. X    f = fopen(tempf, "r");
  1932. X    if (f == NULL) {
  1933. X        err1("%s: cannot open (read)", tempf);
  1934. X        non_critical();
  1935. X        return;
  1936. X    }
  1937. X    FREEMEM(s.sg_desc);
  1938. X    i = 0;
  1939. X    while ((ch = getc(f)) != EOF)
  1940. X        desc[i++] = ch;
  1941. X    desc[i] = '\0';
  1942. X    s.sg_dsize = i;
  1943. X    savestr(&s.sg_desc, desc);
  1944. X    (void) fclose(f);
  1945. X    (void) unlink(tempf);
  1946. X
  1947. Xfinish:
  1948. X    if (*namev != NIL && !eq(*namev, v[1])) {
  1949. X        FREEMEM(s.sg_name);
  1950. X        savestr(&s.sg_name, (char *)*namev);
  1951. X        for (i=0; i < AccountList.l_count; i++) {
  1952. X            ac = (struct account *)AccountList.l_list[i];
  1953. X            if (strlistchg(&ac->ac_sigs, (char *)v[1], s.sg_name))
  1954. X            ModBits |= AC;
  1955. X        }
  1956. X#ifdef SENDMAIL
  1957. X        for (i=0; i < AliasList.l_count; i++) {
  1958. X            al = (struct alias *) AliasList.l_list[i];
  1959. X            if (strlistchg(&al->al_sigs, (char *)v[1], s.sg_name))
  1960. X            ModBits |= AL;
  1961. X        }
  1962. X#endif
  1963. X        (void) strlistchg(&Sigs, (char *)v[1], s.sg_name);
  1964. X    }
  1965. X    if (changed) {
  1966. X        bcopy(sg, &s, sizeof (struct sig));
  1967. X        sort_list(&SigList, sigcmp);
  1968. X        ModBits |= SG;
  1969. X        puts("updated");
  1970. X    }
  1971. X    else
  1972. X        err("no change");
  1973. X    non_critical();
  1974. X
  1975. X    return;
  1976. X}
  1977. X
  1978. X/*
  1979. X * Add a group
  1980. X */
  1981. Xupdgroup(c, v)
  1982. Xint c;
  1983. Xaddr *v;
  1984. X
  1985. X{
  1986. X    struct groupmap g, *gm;
  1987. X#ifdef SENDMAIL
  1988. X    struct alias *al;
  1989. X#endif
  1990. X    struct account *ac;
  1991. X    struct range *rg;
  1992. X    char prompt[SHORT_BUF];
  1993. X    addr *tempv, *namev;
  1994. X    int i, cc, gid, changed = 0;
  1995. X
  1996. X    if ( c > 2 ) {
  1997. X        err1("%s: too many arguments", (char *)v[0]);
  1998. X        return;
  1999. X    }
  2000. X    if (c != 2) {
  2001. X        err1("usage: %s <name>", (char *)v[0]);
  2002. X        return;
  2003. X    }
  2004. X    gm = getgmnam((char *)v[1]);
  2005. X    if (!gm) {
  2006. X        err1("%s: group exists", (char *)v[1]);
  2007. X        return;
  2008. X    }
  2009. X    bcopy(&g, gm, sizeof (struct groupmap));
  2010. X
  2011. X    namev = get_gpa(2);
  2012. X    tempv = get_gpa(2);
  2013. X
  2014. X    (void) sprintf(prompt, "Name [%s]: ",  g.gm_name);
  2015. X    GetLine(prompt, 1, &cc, namev, &Null_List);
  2016. X    if (cc) {
  2017. X        if (!eq(*namev, v[1]))
  2018. X            ; /* no change */
  2019. X        else if (groupexists((char *)*namev)) {
  2020. X            err("that name is taken");
  2021. X            return;
  2022. X        }
  2023. X        else
  2024. X            changed = 1;
  2025. X    }
  2026. X
  2027. X    (void) sprintf(prompt, "Gid [%d]: ", g.gm_gid);
  2028. X    GetLine(prompt, 1, &cc, tempv, &Null_List);
  2029. X    if (cc) {
  2030. X        if (!validint((char *)*tempv)) {
  2031. X            err1("%s makes no sense to me", (char *)tempv);
  2032. X            return;
  2033. X        }
  2034. X        gid = atoi((char *)*tempv);
  2035. X        if (gidexists(g.gm_gid)) {
  2036. X            err("that gid is taken");
  2037. X            return;
  2038. X        }
  2039. X        else {
  2040. X            g.gm_gid = gid;
  2041. X            changed = 1;
  2042. X        }
  2043. X    }
  2044. X
  2045. X    critical();
  2046. X    if (g.gm_gid != gm->gm_gid) {
  2047. X        changed = 1;
  2048. X        for (i=0; i < AccountList.l_count; i++) {
  2049. X            ac = (struct account *) AccountList.l_list[i];
  2050. X            if (ac->ac_gid == gm->gm_gid) {
  2051. X                ac->ac_gid = g.gm_gid;
  2052. X                ModBits |= AC;
  2053. X            }
  2054. X        }
  2055. X    }
  2056. X    if (*namev != NIL && !eq(*namev, v[1])) {
  2057. X        changed = 1;
  2058. X        FREEMEM(g.gm_name);
  2059. X        savestr(&g.gm_name, (char *)*namev);
  2060. X        (void) strlistchg(&Groups, (char *)v[1], g.gm_name);
  2061. X        for (i=0; i < AccountList.l_count; i++) {
  2062. X        ac = (struct account *) AccountList.l_list[i];
  2063. X        if (strlistchg(&ac->ac_groups, (char *)v[1], g.gm_name))
  2064. X            ModBits |= AC;
  2065. X        }
  2066. X#ifdef SENDMAIL
  2067. X        for (i=0; i < AliasList.l_count; i++) {
  2068. X        al = (struct alias *) AliasList.l_list[i];
  2069. X        if (strlistchg(&al->al_groups, (char *)v[1], g.gm_name))
  2070. X            ModBits |= AL;
  2071. X        }
  2072. X#endif
  2073. X        rg = getrgnam((char *)v[1]);
  2074. X        if (rg) {
  2075. X        FREEMEM(rg->rg_name);
  2076. X        savestr(&rg->rg_name, g.gm_name);
  2077. X        (void) strlistchg(&Ranges, (char *)v[1], g.gm_name);
  2078. X        sort_list(&RangeList, rangecmp);
  2079. X        ModBits |= RG;
  2080. X        }
  2081. X        if (vigexists((char *)v[1])) {
  2082. X        (void) strlistchg(&Vigs, (char *)v[1], g.gm_name);
  2083. X        ModBits |= VG;
  2084. X        }
  2085. X    }
  2086. X    if (changed) {
  2087. X        bcopy(gm, &g, sizeof (struct groupmap));
  2088. X        sort_list(&GroupMapList, gmapcmp);
  2089. X        ModBits |= GR;
  2090. X        puts("updated");
  2091. X    }
  2092. X    else
  2093. X        err("no change");
  2094. X
  2095. X    non_critical();
  2096. X    return;
  2097. X}
  2098. X
  2099. X/*
  2100. X * Update a range
  2101. X */
  2102. Xupdrange(c, v)
  2103. Xint c;
  2104. Xaddr *v;
  2105. X
  2106. X{
  2107. X    struct range r, *rr, *rg;
  2108. X    char prompt[SHORT_BUF];
  2109. X    addr *tempv, *namev;
  2110. X    int cc, indx, changed = 0;
  2111. X
  2112. X    if ( c > 2 ) {
  2113. X        err1("%s: too many arguments", (char *)v[0]);
  2114. X        return;
  2115. X    }
  2116. X    if (c != 2) {
  2117. X        err1("usage: %s <name>", (char *)v[0]);
  2118. X        return;
  2119. X    }
  2120. X    rr = getrgnam((char *)v[1]);
  2121. X    if (!rr) {
  2122. X        err1("%s: no such range", (char *)v[1]);
  2123. X        return;
  2124. X    }
  2125. X    bcopy(&r, rr, sizeof (struct range));
  2126. X
  2127. X    namev = get_gpa(2);
  2128. X    tempv = get_gpa(2);
  2129. X
  2130. X    /*
  2131. X     * New name?
  2132. X     */
  2133. X    (void) sprintf(prompt, "Name [%s]: ",  r.rg_name);
  2134. X    GetLine(prompt, 1, &cc, namev, &Groups);
  2135. X    if (cc) {
  2136. X        if (!groupexists((char *)*namev)) {
  2137. X            err1("%s: no such group", (char *)*namev);
  2138. X            return;
  2139. X        }
  2140. X        if (eq(*namev, v[1]))
  2141. X            ; /* no change */
  2142. X        else if (rangeexists((char *)namev)) {
  2143. X            err("that name is taken");
  2144. X            return;
  2145. X        }
  2146. X        else
  2147. X            changed = 1;
  2148. X    }
  2149. X
  2150. X    /*
  2151. X     * From?
  2152. X     */
  2153. X    (void) sprintf(prompt, "From [%d]: ", r.rg_from);
  2154. X    GetLine(prompt, 1, &cc, tempv, &Null_List);
  2155. X    if (cc) {
  2156. X        if (!validint((char *)*tempv)) {
  2157. X            err1("%s makes no sense to me", (char *)*tempv);
  2158. X            return;
  2159. X        }
  2160. X        r.rg_from = atoi((char *)*tempv);
  2161. X        (void) clear_gpa(tempv, 2);
  2162. X        changed = 1;
  2163. X    }
  2164. X
  2165. X    /*
  2166. X     * To?
  2167. X     */
  2168. X    (void) sprintf(prompt, "To [%d]: ", r.rg_to);
  2169. X    GetLine(prompt, 1, &cc, tempv, &Null_List);
  2170. X    if (cc) {
  2171. X        if (!validint((char *)*tempv)) {
  2172. X            err1("%s makes no sense to me", (char *)*tempv);
  2173. X            return;
  2174. X        }
  2175. X        r.rg_to = atoi((char *)*tempv);
  2176. X        (void) clear_gpa(tempv, 2);
  2177. X        changed = 1;
  2178. X    }
  2179. X
  2180. X    /*
  2181. X     * New mode?
  2182. X     */
  2183. X    (void) sprintf(prompt, "Mode [%s] : ",
  2184. X            (r.rg_mode == RG_SHARED ? "shared" : "exclusive"));
  2185. X    GetLine(prompt, 1, &cc, tempv, &mdlist);
  2186. X    if (!cc)
  2187. X        ; /* no change */
  2188. X    else if (eq(*tempv, "shared")) {
  2189. X        r.rg_mode = RG_SHARED;
  2190. X        changed = 1;
  2191. X    }
  2192. X    else if (eq(*tempv, "exclusive")) {
  2193. X        r.rg_mode = RG_EXCLUSIVE;
  2194. X        changed = 1;
  2195. X    }
  2196. X    else {
  2197. X        err1("%s: unknown mode", (char *)*tempv);
  2198. X        return;
  2199. X    }
  2200. X
  2201. X    /*
  2202. X     * Check to see if the new range conflicts with existing ranges
  2203. X     */
  2204. X    for (indx=0; indx < RangeList.l_count; indx++) {
  2205. X        rg = (struct range *) RangeList.l_list[indx];
  2206. X        if (rg == rr)
  2207. X            continue;
  2208. X        if (rg->rg_mode == RG_SHARED && r.rg_mode == RG_SHARED)
  2209. X            continue;
  2210. X        if (INRANGE(r.rg_from, rg->rg_from, rg->rg_to)) {
  2211. X            err1("conflicts with range of group %s", rg->rg_name);
  2212. X            return;
  2213. X        }
  2214. X        if (INRANGE(r.rg_to, rg->rg_from, rg->rg_to)) {
  2215. X            err1("conflicts with range of group %s", rg->rg_name);
  2216. X            return;
  2217. X        }
  2218. X    }
  2219. X
  2220. X    critical();
  2221. X    if (*namev != NIL && !eq(*namev, v[1])) {
  2222. X        FREEMEM(r.rg_name);
  2223. X        savestr(&r.rg_name, (char *)*tempv);
  2224. X        (void) strlistchg(&Ranges, (char *)v[1], r.rg_name);
  2225. X    }
  2226. X    if (changed) {
  2227. X        bcopy(rr, &r, sizeof (struct range));
  2228. X        sort_list(&RangeList, rangecmp);
  2229. X        ModBits |= RG;
  2230. X        puts("updated");
  2231. X    }
  2232. X    else
  2233. X        err("no change");
  2234. X    non_critical();
  2235. X
  2236. X    return;
  2237. X}
  2238. X
  2239. Xupduser(c, v)
  2240. Xint c;
  2241. Xchar **v;
  2242. X
  2243. X{
  2244. X    struct account *ac, *ac2;
  2245. X    struct groupmap *gm;
  2246. X#ifdef SENDMAIL
  2247. X    struct alias *al;
  2248. X    struct class *cs;
  2249. X    struct sig *sg;
  2250. X    int ogid, j;
  2251. X#endif
  2252. X    addr *namev, *realnamev, *idv, *uidv, *gidv, *dirv, *passwdv, *shellv;
  2253. X    int uid, gid, changed = 0;
  2254. X#ifdef DOFILES
  2255. X    int mvdir = 0;
  2256. X#endif
  2257. X    int cc;
  2258. X    register int i;
  2259. X    char *cp, prompt[LONG_BUF], errmsg[LONG_BUF];
  2260. X
  2261. X    if ( c > 2 ) {
  2262. X        err1("%s: too many arguments", (char *)v[0]);
  2263. X        return;
  2264. X    }
  2265. X    if ( c != 2 ) {
  2266. X        err1("usage: %s <user>", (char *)v[0]);
  2267. X        return;
  2268. X    }
  2269. X    ac = getacnam((char *)v[1]);
  2270. X    if (!ac) {
  2271. X        err1("%s: no such user", (char *)v[1]);
  2272. X        return;
  2273. X    }
  2274. X
  2275. X    namev = get_gpa(2);
  2276. X    realnamev = get_gpa(17);
  2277. X    idv = get_gpa(2);
  2278. X    passwdv = get_gpa(2);
  2279. X    uidv = get_gpa(2);
  2280. X    gidv = get_gpa(2);
  2281. X    dirv = get_gpa(2);
  2282. X    shellv = get_gpa(2);
  2283. X
  2284. X    /*
  2285. X     * Change login name?
  2286. X     */
  2287. X    (void) sprintf(prompt, "Login name [%s]: ", ac->ac_name);
  2288. X    GetLine(prompt, 1, &cc, namev, &Null_List);
  2289. X
  2290. X    /*
  2291. X     * Change real name?
  2292. X     */
  2293. X    (void) sprintf(prompt, "Real Name [%s]: ", ac->ac_realname);
  2294. X    GetLine(prompt, 16, &cc, realnamev, &Null_List);
  2295. X
  2296. X    /*
  2297. X     * Change id?
  2298. X     */
  2299. X    (void) sprintf(prompt, "Id [%s]: ", ac->ac_id);
  2300. X    GetLine(prompt, 1, &cc, idv, &idlist);
  2301. X
  2302. X    /*
  2303. X     * Change password?
  2304. X     */
  2305. X    (void) sprintf(prompt, "Password (RETURN means no change): ");
  2306. X    GetLine(prompt, 1, &cc, passwdv, &pwlist);
  2307. X
  2308. X    /*
  2309. X     * Change uid?
  2310. X     */
  2311. X    (void) sprintf(prompt, "Uid [%d]: ", ac->ac_uid);
  2312. X    GetLine(prompt, 1, &cc, uidv, &Null_List);
  2313. X    if (cc && !validint((char *)*uidv)) {
  2314. X        err1("%s makes no sense to me", (char *)*uidv);
  2315. X        return;
  2316. X    }
  2317. X
  2318. X    /*
  2319. X     * Change gid?
  2320. X     */
  2321. X    (void) sprintf(prompt, "Gid [%d]: ", ac->ac_gid);
  2322. X    GetLine(prompt, 1, &cc, gidv, &Null_List);
  2323. X    if (cc && !validint((char *)*gidv)) {
  2324. X        err1("%s makes no sense to me", (char *)*gidv);
  2325. X        return;
  2326. X    }
  2327. X
  2328. X    /*
  2329. X     * Rename home directory?
  2330. X     */
  2331. X    (void) sprintf(prompt, "Home [%s]: ", ac->ac_dir);
  2332. X    GetFilenames(prompt, 1, &cc, dirv);
  2333. X#ifdef DOFILES
  2334. X    if (cc && !eq(*dirv, ac->ac_dir) && fileexists((char *)*dirv))
  2335. X      err2("%s already exists, so I won't move %s", (char *)*dirv,
  2336. X           (char *)ac->ac_dir);
  2337. X    else
  2338. X      mvdir = 1;
  2339. X#endif
  2340. X
  2341. X    /*
  2342. X     * New shell?
  2343. X     */
  2344. X    (void) sprintf(prompt, "Shell [%s]: ", ac->ac_shell);
  2345. X    GetLine(prompt, 1, &cc, shellv, &Shells);
  2346. X    if (cc && !fileexists((char *)*shellv))
  2347. X        err1("Warning: %s does not exist", (char *)*shellv);
  2348. X
  2349. X    critical();
  2350. X
  2351. X    /*
  2352. X     * If given a different user name, use it.  No duplicate
  2353. X     * user names allowed (of course).
  2354. X     */
  2355. X    if (*namev != NIL && !eq(*namev, ac->ac_name)) {
  2356. X        if (!userexists((char *)*namev)) {
  2357. X        /*
  2358. X         * Update group member lists
  2359. X         */
  2360. X        for (i=0; i < GroupMapList.l_count; i++) {
  2361. X            gm = (struct groupmap *)GroupMapList.l_list[i];
  2362. X            if (strlistchg(&gm->gm_mem, (char *)v[1], (char *)*namev))
  2363. X            ModBits |= GR;
  2364. X        }
  2365. X#ifdef SENDMAIL
  2366. X        /*
  2367. X         * Update aliases
  2368. X         */
  2369. X        for (i=0; i < AliasList.l_count; i++) {
  2370. X            al = (struct alias *) AliasList.l_list[i];
  2371. X            if (strlistchg(&al->al_addresses, (char *)v[1],
  2372. X                (char *)*namev))
  2373. X            ModBits |= AL;
  2374. X        }
  2375. X        al = getalnam((char *)ac->ac_name);
  2376. X        if (al) {
  2377. X            ModBits |= AL;
  2378. X            for (i=0; i < AccountList.l_count; i++) {
  2379. X            ac2 = (struct account *) AccountList.l_list[i];
  2380. X            if (!strlistchg(&ac2->ac_aliases, al->al_name,
  2381. X                (char *)*namev))
  2382. X                continue;
  2383. X            ModBits |= AC;
  2384. X            }
  2385. X            for (i=0; i < GroupMapList.l_count; i++) {
  2386. X            gm = (struct groupmap *) GroupMapList.l_list[i];
  2387. X            (void) strlistchg(&gm->gm_aliases, al->al_name,
  2388. X                    (char *)*namev);
  2389. X            }
  2390. X            for (i=0; i < ClassList.l_count; i++) {
  2391. X            cs = (struct class *) ClassList.l_list[i];
  2392. X            (void) strlistchg(&cs->cs_aliases, al->al_name,
  2393. X                    (char *)*namev);
  2394. X            }
  2395. X            for (i=0; i < SigList.l_count; i++) {
  2396. X            sg = (struct sig *) SigList.l_list[i];
  2397. X            (void) strlistchg(&sg->sg_aliases, al->al_name,
  2398. X                    (char *)*namev);
  2399. X            }
  2400. X            (void) strlistchg(&Aliases, al->al_name, (char *)*namev);
  2401. X            FREEMEM(al->al_name);
  2402. X            savestr(&al->al_name, (char *)*namev);
  2403. X            sort_list(&AliasList, aliascmp);
  2404. X        }
  2405. X#endif
  2406. X        /*
  2407. X         * Now fix the accounts struct and the users
  2408. X         * completion list
  2409. X         */
  2410. X        (void) strlistchg(&Users, (char *)ac->ac_name, (char *)*namev);
  2411. X        FREEMEM((char *)ac->ac_name);
  2412. X        savestr((char **)&ac->ac_name, (char *)*namev);
  2413. X        ModBits |= (AC|PW);
  2414. X        changed++;
  2415. X        }
  2416. X        else {
  2417. X        err1("%s: user exists", (char *)*namev);
  2418. X        err("login name unchanged");
  2419. X        }
  2420. X    }
  2421. X
  2422. X    /*
  2423. X     * If given a new real name, use it.
  2424. X     */
  2425. X    if (*realnamev != NIL) {
  2426. X        cp = (char *)glob(realnamev);
  2427. X        if (!eq(cp, ac->ac_realname)) {
  2428. X            FREEMEM((char *)ac->ac_realname);
  2429. X            savestr((char **)&ac->ac_realname, cp);
  2430. X            ModBits |= AC;
  2431. X            changed++;
  2432. X        }
  2433. X    }
  2434. X
  2435. X    /*
  2436. X     * If id changed, record it.  Since the user already has an
  2437. X     * account we don't care if his id matches anyone else's
  2438. X     * The check for duplicate ids is done at when a user is added.
  2439. X     */
  2440. X    if (*idv != NIL && !eq(*idv, ac->ac_id)) {
  2441. X        FREEMEM((char *)ac->ac_id);
  2442. X        savestr((char **)&ac->ac_id, (char *)*idv);
  2443. X        ModBits |= AC;
  2444. X        changed++;
  2445. X    }
  2446. X
  2447. X    /*
  2448. X     * Handle change of password
  2449. X     */
  2450. X    if (*passwdv != NIL) {
  2451. X        FREEMEM((char *)ac->ac_passwd);
  2452. X        if (eq(*passwdv, "unused"))
  2453. X            savestr((char **)&ac->ac_passwd, "*");
  2454. X        else if (eq(*passwdv, "none"))
  2455. X            savestr((char **)&ac->ac_passwd, "");
  2456. X        else if (eq(*passwdv, "generate")) {
  2457. X            cp = makepass();
  2458. X            savestr((char **)&ac->ac_passwd, crypt(cp, rsalt()));
  2459. X            (void) printf("password is \"%s\"\n", cp);
  2460. X        }
  2461. X        else
  2462. X            savestr((char **)&ac->ac_passwd,
  2463. X                crypt((char *)*passwdv, rsalt()));
  2464. X        ModBits |= PW;
  2465. X        changed++;
  2466. X    }
  2467. X
  2468. X    /*
  2469. X     * Note home directory change, if any.  This must be before
  2470. X     * checking for a change in uid so that the omni_chown isn't
  2471. X     * suddenly left high and dry if user's directory is moved.
  2472. X     */
  2473. X    if (*dirv != NIL && !eq(*dirv, ac->ac_dir)) {
  2474. X#ifdef DOFILES
  2475. X        if (mvdir)
  2476. X            add_job(JB_MV, ac->ac_dir, *dirv, NIL);
  2477. X#else
  2478. X        err("Don't forget to move the user's home directory");
  2479. X#endif
  2480. X        FREEMEM((char *)ac->ac_dir);
  2481. X        savestr((char **)&ac->ac_dir, (char *)*dirv);
  2482. X        ModBits |= PW;
  2483. X        changed++;
  2484. X    }
  2485. X
  2486. X    /*
  2487. X     * Handle a change of uid.  This entails changing the ownership
  2488. X     * of this user's files when savechanges() is called.  Sharing
  2489. X     * of uids is permitted but a warning message is printed.
  2490. X     */
  2491. X    if (*uidv != NIL) {
  2492. X        uid = atoi((char *)*uidv);
  2493. X        if (uid <= 0)
  2494. X        err("uid is out of range");
  2495. X        else if (uid != ac->ac_uid && uid >= 0) {
  2496. X        ac2 = getacuid(uid);
  2497. X        if (ac2)
  2498. X            (void) printf("warning: uid %d is shared by %s\n",
  2499. X                uid, ac2->ac_name);
  2500. X#ifdef DOFILES
  2501. X        add_job(JB_OMNICHOWN, &ac->ac_uid, &uid, NIL);
  2502. X#else
  2503. X        err("Do not forget to chown the user files.");
  2504. X#endif
  2505. X        ac->ac_uid = uid;
  2506. X        sort_list(&AccountList, acctcmp);
  2507. X        ModBits |= (AC|PW);
  2508. X        add_job(JB_LASTLOG, &ac->ac_uid, (addr)&ac->ac_ll, NIL);
  2509. X        changed++;
  2510. X        }
  2511. X    }
  2512. X
  2513. X    /*
  2514. X     * Handle a change of gid.  Must make sure there is group
  2515. X     * associated with the gid.
  2516. X     */
  2517. X    if (*gidv != NIL) {
  2518. X        gid = atoi((char *)*gidv);
  2519. X        if (gid < 0)
  2520. X            err("gid is out of range");
  2521. X        else if (!(gm = getgmgid(gid))) {
  2522. X            (void) sprintf(errmsg, 
  2523. X                "no group associated with gid %d",
  2524. X                gid);
  2525. X            err(errmsg);
  2526. X        }
  2527. X        else if (gid != ac->ac_gid) {
  2528. X#ifdef SENDMAIL
  2529. X            ogid = ac->ac_gid;
  2530. X#endif
  2531. X            ac->ac_gid = gid;
  2532. X            ModBits |= (AC|PW);
  2533. X#ifdef SENDMAIL
  2534. X            if (gm->gm_aliases.l_count)
  2535. X                RXBindings(ac);
  2536. X            gm = getgmgid(ogid);
  2537. X            for (j=0; j < gm->gm_aliases.l_count; j++) {
  2538. X                al = getalnam((char *)gm->gm_aliases.l_list[j]);
  2539. X                if (!al) continue;    /* trouble */
  2540. X                if (!instrlist(&al->al_addresses, (char *)ac->ac_name)) {
  2541. X                strlistadd(&al->al_addresses, (char *)ac->ac_name);
  2542. X                sort_list(&al->al_addresses, pstrcmp);
  2543. X                ModBits |= AL;
  2544. X                }
  2545. X            }
  2546. X#endif
  2547. X            changed++;
  2548. X        }
  2549. X    }
  2550. X
  2551. X    /*
  2552. X     * Make change in shell if necessary.
  2553. X     */
  2554. X    if (*shellv != NIL && !eq(*shellv, ac->ac_shell)) {
  2555. X        FREEMEM((char *)ac->ac_shell);
  2556. X        savestr((char **)&ac->ac_shell, (char *)*shellv);
  2557. X        ModBits |= PW;
  2558. X        changed++;
  2559. X    }
  2560. X
  2561. X    if (changed)
  2562. X        puts("updated");
  2563. X    else
  2564. X        err("no change");
  2565. X    non_critical();
  2566. X
  2567. X    return;
  2568. X}
  2569. @//E*O*F src/update.c//
  2570. if test 22502 -ne "`wc -c <'src/update.c'`"; then
  2571.     echo shar: error transmitting "'src/update.c'" '(should have been 22502 characters)'
  2572. fi
  2573. fi # end of overwriting check
  2574. echo shar: "End of archive 8 (of 8)."
  2575. cp /dev/null ark8isdone
  2576. DONE=true
  2577. for I in 1 2 3 4 5 6 7 8; do
  2578.     if test -! f ark${I}isdone; then
  2579.         echo "You still need to run archive ${I}."
  2580.         DONE=false
  2581.     fi
  2582. done
  2583. case $DONE in
  2584.     true)
  2585.         echo "You have run all 8 archives."
  2586.         echo 'See the README file'
  2587.         ;;
  2588. esac
  2589. ##  End of shell archive.
  2590. exit 0
  2591.