home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / net / passwd-aging.3 < prev    next >
Internet Message Format  |  1988-03-14  |  32KB

  1. From gww@beatnix.UUCP Sat Mar 12 19:01:59 1988
  2. Path: uunet!lll-winken!lll-tis!elxsi!beatnix!gww
  3. From: gww@beatnix.UUCP (Gary Winiger)
  4. Newsgroups: alt.sources
  5. Subject: Password aging package for 4.3BSD  Part 3 of 3.
  6. Message-ID: <745@elxsi.UUCP>
  7. Date: 13 Mar 88 00:01:59 GMT
  8. Sender: nobody@elxsi.UUCP
  9. Reply-To: gww@beatnix.UUCP (Gary Winiger)
  10. Organization: ELXSI Super Computers, San Jose
  11. Lines: 1297
  12.  
  13.  
  14. #    This is a shell archive.
  15. #    Remove everything above and including the cut line.
  16. #    Then run the rest of the file through sh.
  17. -----cut here-----cut here-----cut here-----cut here-----
  18. #!/bin/sh
  19. # shar:    Shell Archiver
  20. #    Run the following text with /bin/sh to create:
  21. #    mkshadow.c
  22. #    pwadm.c
  23. # This archive created: Sat Mar 12 14:58:23 1988
  24. echo shar: extracting mkshadow.c '(6629 characters)'
  25. sed 's/^XX//' << \SHAR_EOF > mkshadow.c
  26. XX/*
  27. XX * $Log:    mkshadow.c,v $
  28. XX * Revision 1.1  87/12/24  12:21:31  gww
  29. XX * Initial revision
  30. XX * 
  31. XX */
  32. XX
  33. XX/*    mkshadow - Make a shadow password file from a password file.
  34. XX *
  35. XX *        G.Winiger    ELXSI    87/12/25.
  36. XX *
  37. XX *    Copyright (c) 1987 by ELXSI.
  38. XX *
  39. XX *    This software was written by Gary Winiger at ELXSI. It may be
  40. XX *    distributed within the following restrictions:
  41. XX *        (1) It may not be sold at a profit.
  42. XX *        (2) This credit and Copyright notice must remain intact.
  43. XX *    This software may be distributed with other software by a commercial
  44. XX *    vendor, provided that it is included at no additional charge.
  45. XX *
  46. XX *    Please report bugs to "...!{sun,uunet}!elxsi!gww".
  47. XX *
  48. XX */
  49. XX
  50. XX/*
  51. XX *        Mkshadow will take a normal BSD password file and create a
  52. XX *    shadow password file from it.  The user passwords are removed from
  53. XX *    /etc/passwd and placed in the shadow password file.  The shadow
  54. XX *    password file is read only by root.
  55. XX *        This program is meant to be used once when setting up the
  56. XX *    shadow password file.  A guard is made against subsequent use which
  57. XX *    would destroy the password information in the shadow password file.
  58. XX *
  59. XX *    Entry    /etc/passwd = Normal BSD password file.
  60. XX *
  61. XX *    Exit    1 = Unsuccessful.
  62. XX *        0 = Successful and:
  63. XX *        /etc/passwd = Password file sorted by uid and username with
  64. XX *                  password removed.
  65. XX *        SHADOWPW = Shadow password file sorted by uid and username
  66. XX *               with the passwords extracted from /etc/passwd and
  67. XX *               the GECOS field formated for different password 
  68. XX *               criteria and password aging.
  69. XX *
  70. XX *    Messages
  71. XX *        "A shadow password file already exists, remaking will destroy
  72. XX *         existing passwords"
  73. XX *        "Mkshadow aborted" = A shadow password file already exists,
  74. XX *                     if mkshadow were to run, it would loose
  75. XX *                     the existing passwords.
  76. XX */
  77. XX
  78. XX#ifndef    lint
  79. XXstatic char *ERcsId = "$Header: mkshadow.c,v 1.1 87/12/24 12:21:31 gww Exp $ ENIX BSD";
  80. XX#endif    lint
  81. XX
  82. XX#include <sys/types.h>
  83. XX#include <sys/stat.h>
  84. XX#include <sys/file.h>
  85. XX
  86. XX#include <stdio.h>
  87. XX#include <errno.h>
  88. XX#include <signal.h>
  89. XX#include <pwd.h>
  90. XX
  91. XXchar    *passwd = "/etc/passwd";
  92. XXchar    *passwd_pag = "/etc/passwd.pag";
  93. XXchar    *passwd_dir = "/etc/passwd.dir";
  94. XXchar    *temp = "/etc/ptmp";
  95. XXchar    *temp_pag = "/etc/ptmp.pag";
  96. XXchar    *temp_dir = "/etc/ptmp.dir";
  97. XXchar    *shadow = SHADOWPW;
  98. XXchar    *shadow_pag = SHADOWPW_PAG;
  99. XXchar    *shadow_dir = SHADOWPW_DIR;
  100. XXchar    *stemp = "/etc/sptmp";
  101. XXchar    *stemp_pag = "/etc/sptmp.pag";
  102. XXchar    *stemp_dir = "/etc/sptmp.dir";
  103. XXchar    *temps = "/etc/ptmps";
  104. XXchar    sort[80];    /* command line to sort password files into uid order */
  105. XX
  106. XXFILE     *ft, *sft;  /* passwd temp, shadow temp */
  107. XX
  108. XXextern    int errno;
  109. XX
  110. XXmain ()
  111. XX{
  112. XX
  113. XX    struct    passwd *pwd;
  114. XX
  115. XX    if (access(SHADOWPW, F_OK) == 0) {
  116. XX        fprintf(stderr, "%s%s%s",
  117. XX            "\nA shadow password file already exists, ",
  118. XX            "remaking will destroy existing passwords\n",
  119. XX            "Mkshadow aborted\n");
  120. XX        exit(1);
  121. XX    }
  122. XX
  123. XX    if (mk_tmp(temp, stemp) != 0)
  124. XX        goto abort;
  125. XX
  126. XX    /* copy passwd to temp files modifying desired fields */
  127. XX
  128. XX    setpwfile(passwd);
  129. XX    while ((pwd = getpwent()) != NULL) {
  130. XX        fprintf(ft, "%s:***:%d:%d:%s:%s:%s\n",
  131. XX            pwd->pw_name,
  132. XX            pwd->pw_uid,
  133. XX            pwd->pw_gid,
  134. XX            pwd->pw_gecos,
  135. XX            pwd->pw_dir,
  136. XX            pwd->pw_shell);
  137. XX
  138. XX        fprintf(sft, "%s:%s:%d:%d:%d,0,0,0,*******:%s:%s\n",
  139. XX            pwd->pw_name,
  140. XX            pwd->pw_passwd,
  141. XX            pwd->pw_uid,
  142. XX            pwd->pw_gid,
  143. XX            BSD_CRIT,
  144. XX            pwd->pw_dir,
  145. XX            pwd->pw_shell);
  146. XX
  147. XX    }
  148. XX    fclose(ft);
  149. XX    fclose(sft);
  150. XX
  151. XX    /* sort password files into uid order */
  152. XX
  153. XX    sprintf(sort, "sort -t: +2n -3 +0 -1 %s > %s", temp, temps);
  154. XX    system(sort);
  155. XX    if (rename(temps, temp) < 0) {
  156. XX        fprintf(stderr, "mkshadow: "), perror(temps);
  157. XX        unlink(temps);
  158. XX        goto abort;
  159. XX    }
  160. XX    sprintf(sort, "sort -t: +2n -3 +0 -1 %s > %s", stemp, temps);
  161. XX    system(sort);
  162. XX    if (rename(temps, stemp) < 0) {
  163. XX        fprintf(stderr, "mkshadow: "), perror(temps);
  164. XX        unlink(temps);
  165. XX        goto abort;
  166. XX    }
  167. XX
  168. XX    /* make hash files and rename temp files */
  169. XX
  170. XX    if (make_db(temp) < 0)
  171. XX        fprintf(stderr, "mkshadow: mkpasswd failed\n");
  172. XX    else if (make_db(stemp) < 0)
  173. XX        fprintf(stderr, "mkshadow: smkpasswd failed\n");
  174. XX    else if (rename(temp_pag, passwd_pag) < 0)
  175. XX        fprintf(stderr, "mkshadow: "), perror(temp_pag);
  176. XX    else if (rename(stemp_pag, shadow_pag) < 0)
  177. XX        fprintf(stderr, "mkshadow: "), perror(stemp_pag);
  178. XX    else if (rename(temp_dir, passwd_dir) < 0)
  179. XX        fprintf(stderr, "mkshadow: "), perror(temp_dir);
  180. XX    else if (rename(stemp_dir, shadow_dir) < 0)
  181. XX        fprintf(stderr, "mkshadow: "), perror(stemp_dir);
  182. XX    else if (rename(temp, passwd) < 0)
  183. XX        fprintf(stderr, "mkshadow: "), perror("rename");
  184. XX    else if (rename(stemp, shadow) < 0)
  185. XX        fprintf(stderr, "mkshadow: "), perror("shadow rename");
  186. XX    else  {
  187. XX        chmod(passwd_pag, 0644);
  188. XX        chmod(passwd_dir, 0644);
  189. XX        chmod(passwd, 0644);
  190. XX        chmod(shadow_pag, 0600);
  191. XX        chmod(shadow_dir, 0600);
  192. XX        chmod(shadow, 0600);
  193. XX        
  194. XX        exit(0);
  195. XX    }
  196. XX
  197. XX    /* unsuccessful password file change */
  198. XX
  199. XXabort:
  200. XX    unlink(stemp_pag);
  201. XX    unlink(stemp_dir);
  202. XX    unlink(stemp);
  203. XX    unlink(temp_pag);
  204. XX    unlink(temp_dir);
  205. XX    unlink(temp);
  206. XX    exit(1);
  207. XX
  208. XX}
  209. XX
  210. XX/*    mk_tmp - Make temporary files for password file.
  211. XX *
  212. XX *    Entry    temp = Name of passwd temporary file to be created.
  213. XX *        stemp = Name of shadow temporary file to be created.
  214. XX *
  215. XX *    Exit    0 = ft and sft created as passwd and shadow temp files.
  216. XX *        -1 = Error, message displayed.
  217. XX *        To exit(1), if unable to lock temp file.  Message
  218. XX *            displayed.
  219. XX *    
  220. XX *    Uses    ft, sft.
  221. XX *
  222. XX *    Calls    exit, fclose, fdopen, fgets, fprintf, fputs, open.
  223. XX *
  224. XX */
  225. XX
  226. XXstatic
  227. XXmk_tmp(temp, stemp)
  228. XXchar    *temp,        /* name of passwd temp file */
  229. XX    *stemp;        /* name of shadow temp file */
  230. XX
  231. XX{
  232. XX
  233. XX    int fd;
  234. XX
  235. XX    if ((fd = open(temp, O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0) {
  236. XX        if (errno == EEXIST) {
  237. XX            fprintf(stderr, "mkshadow: password file busy\n");
  238. XX        } else {
  239. XX            fprintf(stderr, "mkshadow: "); perror(temp);
  240. XX        }
  241. XX        exit(1);
  242. XX    }
  243. XX    if ((ft = fdopen(fd, "w")) == NULL) {
  244. XX        fprintf(stderr, "mkshadow: "); perror(temp);
  245. XX        return(-1);
  246. XX    }
  247. XX    if ((fd = open(stemp, O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0) {
  248. XX        if (errno == EEXIST) {
  249. XX            fprintf(stderr, "mkshadow: shadow file busy\n");
  250. XX        } else {
  251. XX            fprintf(stderr, "mkshadow: "); perror(stemp);
  252. XX        }
  253. XX        return(-1);
  254. XX    }
  255. XX    if ((sft = fdopen(fd, "w")) == NULL) {
  256. XX        fprintf(stderr, "mkshadow: "); perror(stemp);
  257. XX        return(-1);
  258. XX    }
  259. XX
  260. XX    return(0);
  261. XX}
  262. XX
  263. XX/*    make_db - Make the ndbm data base files for a password file.
  264. XX *
  265. XX *    Entry    file = File to be turned into an ndbm data base.
  266. XX *
  267. XX *    Exit    0, If successful.
  268. XX *        !=0, If failure.
  269. XX *
  270. XX *    Uses    None.
  271. XX *
  272. XX *    Calls    /etc/mkpasswd, execl, _exit, fork, wait.
  273. XX */
  274. XX
  275. XXstatic
  276. XXmake_db(file)
  277. XXchar *file;
  278. XX
  279. XX{
  280. XX    int status, pid, w;
  281. XX
  282. XX    if ((pid = vfork()) == 0) {
  283. XX        execl("/etc/mkpasswd", "mkpasswd", file, 0);
  284. XX        _exit(127);
  285. XX    }
  286. XX    while ((w = wait(&status)) != pid && w != -1)
  287. XX        continue;
  288. XX    if (w == -1 || status != 0)
  289. XX        status = -1;
  290. XX    return(status);
  291. XX}
  292. SHAR_EOF
  293. if test 6629 -ne "`wc -c mkshadow.c`"
  294. then
  295. echo shar: error transmitting mkshadow.c '(should have been 6629 characters)'
  296. fi
  297. echo shar: extracting pwadm.c '(21694 characters)'
  298. sed 's/^XX//' << \SHAR_EOF > pwadm.c
  299. XX/*
  300. XX * $Log:    pwadm.c,v $
  301. XX * Revision 1.2  88/01/13  16:46:50  gww
  302. XX * Ignore exempt users in multi user range, only query if single user range.
  303. XX * 
  304. XX * Revision 1.1  87/12/24  12:21:34  gww
  305. XX * Initial revision
  306. XX * 
  307. XX */
  308. XX
  309. XX/*    pwadm - Administer the shadow password file.
  310. XX *
  311. XX *        G.Winiger    ELXSI    87/12/25.
  312. XX *
  313. XX *    Copyright (c) 1987 by ELXSI.
  314. XX *
  315. XX *    This software was written by Gary Winiger at ELXSI. It may be
  316. XX *    distributed within the following restrictions:
  317. XX *        (1) It may not be sold at a profit.
  318. XX *        (2) This credit and Copyright notice must remain intact.
  319. XX *    This software may be distributed with other software by a commercial
  320. XX *    vendor, provided that it is included at no additional charge.
  321. XX *
  322. XX *    Please report bugs to "...!{sun,uunet}!elxsi!gww".
  323. XX *
  324. XX */
  325. XX
  326. XX/*        Pwadm allows a system administrator to list or modify the
  327. XX *    contents of the shadow password file.  It operates on the specified
  328. XX *    user range (the default is all users, except those listed in the exempt
  329. XX *    file, EXEMPTPW - /etc/exemptpw, if no exempt file exists, ``root'' and
  330. XX *    ``uucp'' are declared exempt) providing an interface to the password
  331. XX *    criteria that are maintained in the GECOS field of the shadow password
  332. XX *    file.  The available commands are:
  333. XX *
  334. XX *        -c         Clear the password aging history.
  335. XX *        -l        List shadow password file contents.
  336. XX *        -r        Reset the last password changed time to 
  337. XX *                force a change at next login.
  338. XX *        -s        Set (enable) password aging.
  339. XX *        -p days        Define the aging period to be ``days'' days.
  340. XX *        -t criteria    Define the valid password criteria to be of
  341. XX *                ``criteria'' type (b=BSD_CRIT, s=SRT_CRIT).
  342. XX *
  343. XX *    Only one of -c, -l, -r, or -s may be specified at a time.  An aging
  344. XX *    period of zero (0) days disables password aging.  The default aging
  345. XX *    period is 90 days for the -s (Set) command, for all other commands it
  346. XX *    is the aging period currently specified.  The password criteria will
  347. XX *    only be changed if the -t command is used, the default is the normal
  348. XX *    BSD criteria.
  349. XX *
  350. XX *    The user range to be acted on may be specified as a single user or 
  351. XX *    user1-user2.  Where user is either a ``uid'' or ``user name''.  If
  352. XX *    more than one user has the same ``uid'', and ``uid'' is specified,
  353. XX *    all users with that ``uid'' will be effected.
  354. XX *
  355. XX *    Entry    SHADOWPW = Shadow password file.
  356. XX *
  357. XX *    Exit    SHADOWPW = Updated.
  358. XX */
  359. XX
  360. XX#ifndef    lint
  361. XXstatic char *ERcsId = "$Header: pwadm.c,v 1.2 88/01/13 16:46:50 gww Exp $ ENIX BSD";
  362. XX#endif    lint
  363. XX
  364. XX#include <sys/types.h>
  365. XX#include <sys/file.h>
  366. XX#include <pwd.h>
  367. XX#include <errno.h>
  368. XX#include <setjmp.h>
  369. XX#include <signal.h>
  370. XX#include <stdio.h>
  371. XX#include <strings.h>
  372. XX
  373. XXchar    *temp = "/etc/ptmp";
  374. XXchar    *shadow = SHADOWPW;
  375. XXchar    *shadow_pag = SHADOWPW_PAG;
  376. XXchar    *shadow_dir = SHADOWPW_DIR;
  377. XXchar    *stemp = "/etc/sptmp";
  378. XXchar    *stemp_pag = "/etc/sptmp.pag";
  379. XXchar    *stemp_dir = "/etc/sptmp.dir";
  380. XX
  381. XXFILE     *ft, *sft;  /* passwd temp, shadow temp */
  382. XX
  383. XX#define    LINELEN  80
  384. XX
  385. XXint    minuid;            /* minimum uid to act on */
  386. XXchar    minname[LINELEN];    /* minimum user name to act on */
  387. XXint    maxuid;            /* maximum uid to act on */
  388. XXchar    maxname[LINELEN];    /* maximum user name to act on */
  389. XXint    range_type;        /* type of action range         */
  390. XX                /* 0, all password file entries */
  391. XX                /* 1, minuid only               */
  392. XX                 /* 2, minname only              */
  393. XX                 /* 3, minuid through maxuid     */
  394. XX                 /* 4, minname through maxuid    */
  395. XX                 /* 5, minuid through maxname    */
  396. XX                 /* 6, minname through maxname   */
  397. XXint    maxname_found;        /* 0, max name not found for this user range */
  398. XXint    minname_found;         /* 0, min name not found for this user range */
  399. XXjmp_buf    sigret;            /* return from caught signal */
  400. XX
  401. XXextern    int errno;
  402. XX
  403. XX#define CLEARSFT 0
  404. XX#define    CLEARFLG 1<<CLEARSFT
  405. XX#define CRITSFT  1
  406. XX#define CRITFLG  1<<CRITSFT
  407. XX#define RESETSFT 2
  408. XX#define    RESETFLG 1<<RESETSFT
  409. XX#define SETSFT   3
  410. XX#define SETFLG   1<<SETSFT
  411. XX#define LIMSFT   4
  412. XX#define LIMFLG   1<<LIMSFT
  413. XX#define    FLGMASK  CLEARFLG||CRITFLG||RESETFLG||SETFLG
  414. XX
  415. XXmain(argc,argv)
  416. XXint    argc;
  417. XXchar    **argv;
  418. XX
  419. XX{
  420. XX
  421. XXint    i;            /* loop index */
  422. XXint    actionflg = 0;        /* action to take on aging entries */
  423. XXint    listflg      = 0;        /* list aging entries */
  424. XXint    criteria  = BSD_CRIT;    /* type of password criteria */
  425. XXlong    period      = 90*24*60*60;/* default aging period, 90 days */
  426. XXstruct    passwd *pwd;        /* a shadow password file entry */
  427. XXchar    *exempt[MAX_EXEMPT+1];    /* exempt user names */
  428. XXint    exempt_lim;        /* number of entries in exempt[] */
  429. XX
  430. XXint    catch();
  431. XX
  432. XX    /* Parse switches */
  433. XX
  434. XX    argc--; argv++;
  435. XX
  436. XX    while (argc && argv[0][0] == '-' ) {
  437. XX
  438. XX        switch (argv[0][1]) {
  439. XX
  440. XX        case 'c':
  441. XX            actionflg |= CLEARFLG;
  442. XX            break;
  443. XX
  444. XX        case 'l':
  445. XX            listflg = 1;
  446. XX            break;
  447. XX
  448. XX        case 'p':
  449. XX            argc--;
  450. XX            if ((argc < 1) || (period = atol(*++argv)) < 0) {
  451. XX                fprintf(stderr, "Bad aging period %s.\n",
  452. XX                        *argv);
  453. XX                exit(1);
  454. XX            }
  455. XX            period *= 24*60*60;    /* days to seconds */
  456. XX            actionflg |= LIMFLG;
  457. XX            break;
  458. XX
  459. XX        case 'r':
  460. XX            actionflg |= RESETFLG;
  461. XX            break;
  462. XX
  463. XX        case 's':
  464. XX            actionflg |= SETFLG;
  465. XX            break;
  466. XX
  467. XX        case 't':
  468. XX            actionflg |= CRITFLG;
  469. XX            argc--;
  470. XX            if (argc < 1)
  471. XX                goto bad_crit;
  472. XX            argv++;
  473. XX            switch (argv[0][0]) {
  474. XX
  475. XX            case 'b':
  476. XX                criteria = BSD_CRIT;
  477. XX                break;
  478. XX
  479. XX            case 's':
  480. XX                criteria = STR_CRIT;
  481. XX                break;
  482. XX
  483. XX            default:
  484. XXbad_crit:            fprintf(stderr, "Bad password criteria %s.\n",
  485. XX                        *argv);
  486. XX                exit(1);
  487. XX            }
  488. XX            break;
  489. XX
  490. XX        default:
  491. XX            fprintf(stderr, "Unrecognized switch %s.\n", *argv);
  492. XX            exit(1);
  493. XX        }
  494. XX        argc--; argv++;
  495. XX    }
  496. XX
  497. XX    if (!actionflg && !listflg) {
  498. XX        fprintf(stderr,
  499. XX            "Usage: pwadm [-c | -l | -r | -s] [-p days] [-t criteria] [user[-user] ...]\n");
  500. XX        exit(1);
  501. XX    }
  502. XX    if (((actionflg&CLEARFLG)>>CLEARSFT) +
  503. XX        ((actionflg&RESETFLG)>>RESETSFT) +
  504. XX        ((actionflg&SETFLG)>>SETSFT)     +
  505. XX        listflg > 1) {
  506. XX        fprintf(stderr, "Conflicting actions requested.\n");
  507. XX        exit(1);
  508. XX    }
  509. XX
  510. XX    if (access(shadow, F_OK) != 0) {
  511. XX        fprintf(stderr, "No shadow password file exists.\n");
  512. XX        exit(1);
  513. XX    }
  514. XX    setpwfile(shadow);
  515. XX
  516. XX    get_exempt(exempt, &exempt_lim);  /* get list of exempt user names */
  517. XX
  518. XX    /* Catch all signals so we can unlock the lock files. */
  519. XX
  520. XX    for (i = 1; i < NSIG; i++)
  521. XX        if (!(i == SIGTSTP || i == SIGCONT || i == SIGCHLD))
  522. XX            signal(i, catch);
  523. XX    
  524. XX    if (setjmp(sigret))
  525. XX        unlink_files(1);
  526. XX
  527. XX    /* May modify shadow password file, lock passwd and shadow */
  528. XX
  529. XX    mk_tmp(temp, stemp);
  530. XX
  531. XX    do {
  532. XX    get_user_range(argc, argv);
  533. XX
  534. XX    argc--; argv++;
  535. XX
  536. XX    /* Check validity of range */
  537. XX
  538. XX    switch (range_type) {
  539. XX
  540. XX    case 0:
  541. XX    case 1:
  542. XX    case 2:
  543. XX        break;
  544. XX
  545. XX    case 3:
  546. XX        if (minuid > maxuid) {
  547. XX            int t;
  548. XX
  549. XX            fprintf(stderr,
  550. XX                "End of range less than beginning, range reversed.\n");
  551. XX            t = minuid;
  552. XX            minuid = maxuid;
  553. XX            maxuid = t;
  554. XX        }
  555. XX        break;
  556. XX
  557. XX    case 4:
  558. XX        pwd = getpwnam(minname);
  559. XX        if (pwd->pw_uid > maxuid) {
  560. XX            fprintf(stderr,
  561. XX                "End of range less than beginning, range reversed.\n");
  562. XX            range_type = 5;
  563. XX            minuid = maxuid;
  564. XX            strcpy(maxname, minname);
  565. XX        }
  566. XX        break;
  567. XX
  568. XX    case 5:
  569. XX        pwd = getpwnam(maxname);
  570. XX        if (minuid > pwd->pw_uid) {
  571. XX            fprintf(stderr,
  572. XX                "End of range less than beginning, range reversed.\n");
  573. XX            range_type = 4;
  574. XX            maxuid = minuid;
  575. XX            strcpy(minname, maxname);
  576. XX        }
  577. XX        break;
  578. XX    case 6:
  579. XX        { char t[sizeof(minname)];
  580. XX            pwd = getpwnam(minname);
  581. XX            minuid = pwd->pw_uid;
  582. XX            pwd = getpwnam(maxname);
  583. XX            if (minuid > pwd->pw_uid) {
  584. XX                fprintf(stderr,
  585. XX                    "End of range less than beginning, range reversed.\n");
  586. XX                strcpy(t, minname);
  587. XX                strcpy(minname, maxname);
  588. XX                strcpy(maxname, t);
  589. XX            }
  590. XX        }
  591. XX        break;
  592. XX    }
  593. XX
  594. XX    if (listflg) {        /* Just list the current aging information. */
  595. XX        list_aging();
  596. XX        continue;
  597. XX    }
  598. XX
  599. XX    if (period == 0) {
  600. XX        char line[LINELEN];
  601. XX
  602. XX        switch (range_type) {
  603. XX
  604. XX        case 0:
  605. XX            sprintf(line, "all users");
  606. XX            break;
  607. XX        case 1:
  608. XX            sprintf(line, "userid %d", minuid);
  609. XX            break;
  610. XX        case 2:
  611. XX            sprintf(line, "user %s", minname);
  612. XX            break;
  613. XX        case 3:
  614. XX            sprintf(line, "userid %d through userid %d", minuid,
  615. XX                    maxuid);
  616. XX            break;
  617. XX        case 4:
  618. XX            sprintf(line, "user %s through userid %d", minname,
  619. XX                    maxuid);
  620. XX            break;
  621. XX        case 5:
  622. XX            sprintf(line, "userid %d through user %s", minuid, 
  623. XX                    maxname);
  624. XX            break;
  625. XX        case 6:
  626. XX            sprintf(line, "user %s through user %s", minname,
  627. XX                    maxname);
  628. XX            break;
  629. XX        }
  630. XX        fprintf(stderr,
  631. XX            "An aging period of zero (0) days is requested.\n");
  632. XX        fprintf(stderr,
  633. XX            "This will disable password aging for %s.\n",
  634. XX            line);
  635. XX        fprintf(stderr, "Do it anyway [yn] (n) ");
  636. XX
  637. XX        fgets(line, LINELEN, stdin);
  638. XX
  639. XX        switch(line[0]) {
  640. XX
  641. XX        case 'y':
  642. XX        case 'Y':
  643. XX            break;
  644. XX        default:
  645. XX            unlink_files(1);
  646. XX        }
  647. XX    }
  648. XX
  649. XX    /* Copy shadow password to stemp while updating entries */
  650. XX
  651. XX    while ((pwd = getpwent()) != NULL) {
  652. XX        if (check_action(pwd)) {
  653. XX            switch (check_exempt(pwd, exempt, exempt_lim)) {
  654. XX
  655. XX            case 0:
  656. XX                change_aging(&pwd->pw_gecos, criteria, period,
  657. XX                         actionflg);
  658. XX                break;
  659. XX
  660. XX            case 1:
  661. XX                if (yesno(pwd, actionflg))
  662. XX                    change_aging(&pwd->pw_gecos, criteria,
  663. XX                             period, actionflg);
  664. XX                break;
  665. XX
  666. XX            case 2:
  667. XX            default:
  668. XX                break;
  669. XX            }
  670. XX        }
  671. XX
  672. XX        fprintf(sft, "%s:%s:%d:%d:%s:%s:%s\n",
  673. XX            pwd->pw_name,
  674. XX            pwd->pw_passwd,
  675. XX            pwd->pw_uid,
  676. XX            pwd->pw_gid,
  677. XX            pwd->pw_gecos,
  678. XX            pwd->pw_dir,
  679. XX            pwd->pw_shell);
  680. XX    }
  681. XX    endpwent();
  682. XX    rewind(sft);
  683. XX    } while (argc > 0);
  684. XX
  685. XX    if (listflg)        /* all done, just exit */
  686. XX        unlink_files(0);
  687. XX
  688. XX    fclose(sft);
  689. XX
  690. XX    /* make hash shadow password files and rename temp files */
  691. XX
  692. XX    if (make_db(stemp) < 0)
  693. XX        fprintf(stderr, "pwadm: smkpasswd failed\n");
  694. XX    else if (rename(stemp_pag, shadow_pag) < 0)
  695. XX        fprintf(stderr, "pwadm: "), perror(stemp_pag);
  696. XX    else if (rename(stemp_dir, shadow_dir) < 0)
  697. XX        fprintf(stderr, "pwadm: "), perror(stemp_dir);
  698. XX    else if (rename(stemp, shadow) < 0)
  699. XX        fprintf(stderr, "pwadm: "), perror("shadow rename");
  700. XX    else  {
  701. XX        chmod(shadow_pag, 0600);
  702. XX        chmod(shadow_dir, 0600);
  703. XX        chmod(shadow, 0600);
  704. XX        unlink(temp);
  705. XX        
  706. XX        exit(0);
  707. XX    }
  708. XX}
  709. XX
  710. XX/*    get_exempt - Get list of exempt user names.
  711. XX *
  712. XX *    Entry    exempt = Array of exempt user names to be filled in.
  713. XX *        exempt_lim = Limit index on exempt to be filled in.
  714. XX *
  715. XX *    Exit    exempt = Array filled in from EXEMPTPW file.
  716. XX *        exempt_lim = Limit of entries made in exempt.
  717. XX *
  718. XX *    Uses    exempt, exempt_lim.
  719. XX *
  720. XX *    Calls    fclose, fopen, malloc, strcpy, strlen.
  721. XX */
  722. XX
  723. XXextern char *malloc();
  724. XX
  725. XXstatic
  726. XXget_exempt(exempt, exempt_lim)
  727. XXchar    **exempt;
  728. XXint    *exempt_lim;
  729. XX
  730. XX{
  731. XX    FILE     *eft;
  732. XX    char    line[LINELEN];
  733. XX    char    *lp;
  734. XX
  735. XX    *exempt_lim = 0;
  736. XX
  737. XX    if ((eft = fopen(EXEMPTPW, "r")) == NULL) { /* No file, set defaults */
  738. XX        exempt[0] = malloc(sizeof("root")+1);
  739. XX        strcpy(exempt[0], "root");
  740. XX        exempt[1] = malloc(sizeof("uucp")+1);
  741. XX        strcpy(exempt[1], "uucp");
  742. XX        exempt[2] = (char *)0;    /* for safety */
  743. XX        *exempt_lim = 2;
  744. XX        return;
  745. XX    }
  746. XX
  747. XX    while (fgets(line, LINELEN, eft) != NULL) {
  748. XX        if (lp = index(line, '\n'))    /* remove newline */
  749. XX            *lp = '\0';
  750. XX        if (line[0] != '#') {    /* not a comment line */
  751. XX            if (!(exempt[*exempt_lim] = malloc(strlen(line)+1))) {
  752. XX                fprintf(stderr,
  753. XX                    "Out of memory after %d exempt users, remainder ignored.\n",
  754. XX                    *exempt_lim);
  755. XX                break;
  756. XX            }
  757. XX            strcpy(exempt[*exempt_lim], line);
  758. XX            *exempt_lim += 1;
  759. XX            if (*exempt_lim >= MAX_EXEMPT) {
  760. XX                fprintf(stderr,
  761. XX                    "More than %d exempt users, remainder ignored.\n",
  762. XX                    MAX_EXEMPT);
  763. XX                break;
  764. XX            }
  765. XX        }
  766. XX    }
  767. XX
  768. XX    fclose(eft);
  769. XX
  770. XX    exempt[*exempt_lim] = (char *)0;    /* for safety */
  771. XX}
  772. XX
  773. XX/*    mk_tmp - Make temporary files for password file.
  774. XX *
  775. XX *    Entry    temp = Name of passwd temporary file to be created.
  776. XX *        stemp = Name of shadow temporary file to be created.
  777. XX *
  778. XX *    Exit    ft and sft created as passwd and shadow temp files.
  779. XX *        To exit(1), if unable to lock temp file.  Message
  780. XX *            displayed.
  781. XX *    
  782. XX *    Uses    ft, sft.
  783. XX *
  784. XX *    Calls    exit, fclose, fdopen, fgets, fprintf, fputs, open, unlink.
  785. XX *
  786. XX */
  787. XX
  788. XXstatic
  789. XXmk_tmp(temp, stemp)
  790. XXchar    *temp,        /* name of passwd temp file */
  791. XX    *stemp;    /* name of shadow temp file */
  792. XX
  793. XX{
  794. XX
  795. XX    int fd;
  796. XX
  797. XX    if ((fd = open(temp, O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0) {
  798. XX        if (errno == EEXIST) {
  799. XX            fprintf(stderr, "pwadm: password file busy\n");
  800. XX        } else {
  801. XX            fprintf(stderr, "pwadm: "); perror(temp);
  802. XX        }
  803. XX        exit(1);
  804. XX    }
  805. XX    if ((ft = fdopen(fd, "w")) == NULL) {
  806. XX        fprintf(stderr, "pwadm: "); perror(temp);
  807. XX        unlink(temp);
  808. XX        exit(1);
  809. XX    }
  810. XX    if ((fd = open(stemp, O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0) {
  811. XX        if (errno == EEXIST) {
  812. XX            fprintf(stderr, "pwadm: shadow file busy\n");
  813. XX        } else {
  814. XX            fprintf(stderr, "pwadm: "); perror(stemp);
  815. XX        }
  816. XX        unlink(temp);
  817. XX        exit(1);
  818. XX    }
  819. XX    if ((sft = fdopen(fd, "w")) == NULL) {
  820. XX        fprintf(stderr, "pwadm: "); perror(stemp);
  821. XX        unlink(temp);
  822. XX        unlink(stemp);
  823. XX        exit(1);
  824. XX    }
  825. XX}
  826. XX
  827. XX/*    get_user_range - Get range of users to modify.
  828. XX *
  829. XX *    Entry    argc = Number of command line arguments remaining.
  830. XX *        argv = Remaining argument vector.
  831. XX *
  832. XX *    Exit    minuid  = Minimum uid to modify, 0 if none specified.
  833. XX *        minname = Minimum user name to modify, 0 if none specified.
  834. XX *        maxuid  = Maximum uid to modify, 0 if none specified.
  835. XX *        maxname = Maximum user name to modify, 0 if none specified.
  836. XX *        minname_found = 0, reset.
  837. XX *        maxname_found = 0, reset.
  838. XX *        range_type = 0, all password file entries;
  839. XX *                 1, minuid only;
  840. XX *                 2, minname only;
  841. XX *                 3, minuid through maxuid;
  842. XX *                 4, minname through maxuid;
  843. XX *                 5, minuid through maxname;
  844. XX *                 6, minname through maxname.
  845. XX *
  846. XX *    Uses    maxname, maxname_found, maxuid, minname, minname_found,
  847. XX *        minuid, range_type.
  848. XX *
  849. XX *    Calls    atoi, index, strncpy, unlink_files.
  850. XX */
  851. XX
  852. XXstatic
  853. XXget_user_range(argc, argv)
  854. XXint    argc;
  855. XXchar    **argv;
  856. XX
  857. XX{
  858. XX    char    *max;
  859. XX    struct    passwd *pwd;
  860. XX
  861. XX    minuid = maxuid = 0;
  862. XX    minname[0] = maxname[0] = '\0';
  863. XX    range_type = 0;
  864. XX    minname_found = maxname_found = 0;
  865. XX
  866. XX    if (argc <= 0)
  867. XX        return;
  868. XX    
  869. XX    if ((max = index(argv[0], '-')) != 0)
  870. XX        *max = '\0';
  871. XX    
  872. XX    if ((pwd = getpwnam(argv[0])) != NULL) {
  873. XX        strncpy(minname, pwd->pw_name, sizeof(minname));
  874. XX        range_type = 2;
  875. XX    } else {
  876. XX        minuid = atoi(argv[0]);
  877. XX        range_type = 1;
  878. XX    }
  879. XX    if (pwd == NULL && (minuid == 0 && *argv[0] != '0')) {
  880. XX        fprintf(stderr, "Unknown user specification %s.\n", argv[0]);
  881. XX        unlink_files(1);
  882. XX    }
  883. XX
  884. XX    if ((int)max == 0)
  885. XX        return;
  886. XX
  887. XX    max++;
  888. XX    if ((pwd = getpwnam(max)) != NULL) {
  889. XX        strncpy(maxname, pwd->pw_name, sizeof(maxname));
  890. XX        range_type += 4;
  891. XX    } else {
  892. XX        maxuid = atoi(max);
  893. XX        range_type += 2;
  894. XX    }
  895. XX    if (pwd == NULL && (maxuid == 0 && *max != '0')) {
  896. XX        fprintf(stderr, "Unknown user specification %s.\n", max);
  897. XX        unlink_files(1);
  898. XX    }
  899. XX    return;
  900. XX}
  901. XX
  902. XX/*    list_aging - List the password aging information.
  903. XX *
  904. XX *    Entry    setpwfile  = Initialized.
  905. XX *        range_type = Type of user range to list.
  906. XX *        minuid, maxuid, minname, maxname = User range information.
  907. XX *
  908. XX *    Exit    Password aging information listed.
  909. XX *
  910. XX *    Uses    None.
  911. XX *
  912. XX *    Calls    check_action, endpwent, getpwent, printf, sscanf.
  913. XX */
  914. XX
  915. XXstatic
  916. XXlist_aging()
  917. XX
  918. XX{
  919. XX    struct    passwd *pwd;
  920. XX    int    criteria;
  921. XX    long    age_limit;
  922. XX    long    last_time;
  923. XX    long    old_time;
  924. XX    long    current_time;
  925. XX
  926. XX    (void)time(¤t_time);
  927. XX
  928. XX    printf("User Name  Uid Criteria Period Current Password Expires   Old Password Expires\n");
  929. XX
  930. XX    while ((pwd = getpwent()) != NULL) {
  931. XX        if (!check_action(pwd))
  932. XX            continue;
  933. XX
  934. XX        /* User Name and Uid */
  935. XX
  936. XX        printf("%-9s%5d", pwd->pw_name, pwd->pw_uid);
  937. XX
  938. XX        sscanf(pwd->pw_gecos, "%d,%ld,%ld,%ld,", &criteria, &age_limit,
  939. XX                &last_time, &old_time);
  940. XX
  941. XX        /* Password Criteria */
  942. XX
  943. XX        switch (criteria) {
  944. XX
  945. XX        case BSD_CRIT:
  946. XX            printf(" %-8s", "BSD");
  947. XX            break;
  948. XX
  949. XX        case STR_CRIT:
  950. XX            printf(" %-8s", "STRICT");
  951. XX            break;
  952. XX
  953. XX        default:
  954. XX            printf(" %-8s", "Unknown");
  955. XX            break;
  956. XX        }
  957. XX
  958. XX        /* Aging Period */
  959. XX
  960. XX        if (age_limit == 0) {
  961. XX            printf(" No aging set\n");
  962. XX            continue;
  963. XX        }
  964. XX        printf("%7ld", age_limit/(24*60*60));
  965. XX
  966. XX        /* Password aging information */
  967. XX
  968. XX        if (last_time == 0) {
  969. XX            printf(" Password Never Changed\n");
  970. XX            continue;
  971. XX        }
  972. XX
  973. XX        if (current_time > (last_time += age_limit)) {
  974. XX            printf(" Password Expired\n");
  975. XX            continue;
  976. XX        }
  977. XX
  978. XX        old_time += age_limit;
  979. XX        printf(" %.24s", ctime(&last_time));
  980. XX        printf(" %.24s\n", ctime(&old_time));
  981. XX    }
  982. XX    endpwent();
  983. XX}
  984. XX
  985. XX/*    check_action - Check to see if this user is to be acted upon.
  986. XX *
  987. XX *    Entry    pwd = Password entry.
  988. XX *        range_type, minuid, maxuid, minname, maxname = User range
  989. XX *            information.
  990. XX *        maxname_found = 0, Max user name not found for this range.
  991. XX *        minname_found = 0, Min user name not found for this range.
  992. XX *
  993. XX *    Exit    1, if user to be acted upon.
  994. XX *        0, if user is not to be acted upon.
  995. XX *        maxname_found, minname_found = Updated when found.
  996. XX *    
  997. XX *    Uses    maxname_found, minname_found.
  998. XX *    
  999. XX *    Calls    strcmp.
  1000. XX */
  1001. XX
  1002. XXstatic
  1003. XXcheck_action(pwd)
  1004. XXstruct passwd *pwd;
  1005. XX
  1006. XX{
  1007. XX    switch (range_type) {
  1008. XX
  1009. XX    case 0:
  1010. XX        return(1);
  1011. XX
  1012. XX    case 1:
  1013. XX        if (pwd->pw_uid == minuid)
  1014. XX            return(1);
  1015. XX        return(0);
  1016. XX
  1017. XX    case 2:
  1018. XX        if (strcmp(pwd->pw_name, minname) == 0)
  1019. XX            return(1);
  1020. XX        return(0);
  1021. XX
  1022. XX    case 3:
  1023. XX        if (minuid <= pwd->pw_uid && pwd->pw_uid <= maxuid)
  1024. XX            return(1);
  1025. XX        return(0);
  1026. XX
  1027. XX    case 4:
  1028. XX        if (minname_found && pwd->pw_uid <= maxuid)
  1029. XX            return(1);
  1030. XX        else if (strcmp(pwd->pw_name, minname) == 0) {
  1031. XX            minname_found++;
  1032. XX            return(1);
  1033. XX        }
  1034. XX        return(0);
  1035. XX
  1036. XX    case 5:
  1037. XX        if (maxname_found)
  1038. XX            return(0);
  1039. XX        if (minuid <= pwd->pw_uid) {
  1040. XX            if (strcmp(pwd->pw_name, maxname) == 0)
  1041. XX                maxname_found++;
  1042. XX            return(1);
  1043. XX        }
  1044. XX        return(0);
  1045. XX
  1046. XX    case 6:
  1047. XX        if (minname_found && maxname_found)
  1048. XX            return(0);
  1049. XX        if (minname_found) {
  1050. XX            if (strcmp(pwd->pw_name, maxname) == 0)
  1051. XX                maxname_found++;
  1052. XX            return(1);
  1053. XX        } else if (strcmp(pwd->pw_name, minname) == 0) {
  1054. XX            minname_found++;
  1055. XX            return(1);
  1056. XX        }
  1057. XX        return(0);
  1058. XX    }
  1059. XX}
  1060. XX
  1061. XX/*    check_exempt - Check user for aging exemption.
  1062. XX *
  1063. XX *    Entry    pwd = Password entry.
  1064. XX *        exempt = List of exempt user names.
  1065. XX *        exempt_lim = Limit on exemption list.
  1066. XX *        range_type = Type of user range being processed.
  1067. XX *
  1068. XX *    Exit    0, if user not in exemption list.
  1069. XX *        1, if user in exemption list and to be queried.
  1070. XX *        2, if user in exemption list and skipped.
  1071. XX *
  1072. XX *    Uses    None.
  1073. XX *
  1074. XX *    Calls    strcmp.
  1075. XX */
  1076. XX
  1077. XXstatic
  1078. XXcheck_exempt(pwd, exempt, exempt_lim)
  1079. XXstruct passwd *pwd;
  1080. XXchar    *exempt[];
  1081. XXint    exempt_lim;
  1082. XX
  1083. XX{
  1084. XX    int i;
  1085. XX
  1086. XX    for (i = 0; i < exempt_lim ; i++)
  1087. XX        if(strcmp(pwd->pw_name, exempt[i]) == 0) {
  1088. XX            if (range_type != 1 && range_type != 2) {
  1089. XX                fprintf(stderr,
  1090. XX                    "User %s, uid %d in exemption list skipped.\n",
  1091. XX                    pwd->pw_name, pwd->pw_uid);
  1092. XX                return(2);
  1093. XX            } else {
  1094. XX                return(1);
  1095. XX            }
  1096. XX        }
  1097. XX    return(0);
  1098. XX}
  1099. XX
  1100. XX/*    yesno - Ask for confirmation of action.
  1101. XX *
  1102. XX *    Entry    pwd = Password entry.
  1103. XX *        flg = Type of action to be taken.
  1104. XX *              (CLEARFLG, RESETFLG, SETFLG)
  1105. XX *
  1106. XX *    Exit    0, Do not take action.
  1107. XX *        1, Take action.
  1108. XX *
  1109. XX *    Uses    None.
  1110. XX *
  1111. XX *    Calls    fgets, fprintf.
  1112. XX */
  1113. XX
  1114. XXstatic
  1115. XXyesno(pwd, flg)
  1116. XXstruct    passwd *pwd;
  1117. XXint    flg;
  1118. XX
  1119. XX {
  1120. XX    char    line[LINELEN];
  1121. XX
  1122. XX    fprintf(stderr, "User %s, uid %d in exemption list %s anyway [yn] (n) ",
  1123. XX            pwd->pw_name, pwd->pw_uid,
  1124. XX            flg&RESETFLG ? "reset" : flg&CLEARFLG ? "clear" : "set");
  1125. XX    fgets(line, LINELEN, stdin);
  1126. XX
  1127. XX    switch(line[0]) {
  1128. XX
  1129. XX    case 'y':
  1130. XX    case 'Y':
  1131. XX        fprintf(stderr, "User %s modified.\n", pwd->pw_name);
  1132. XX        return(1);
  1133. XX
  1134. XX    default:
  1135. XX        fprintf(stderr, "User %s skipped.\n", pwd->pw_name);
  1136. XX        return(0);
  1137. XX    }
  1138. XX
  1139. XX }
  1140. XX
  1141. XX/*    change_aging - Change the password aging information for this user.
  1142. XX *
  1143. XX *    Entry    aging    = Password aging entry string.
  1144. XX *        period    = Aging period in seconds.
  1145. XX *        flg    = Type of action to be taken.
  1146. XX *              (CLEARFLG, CRITFLG, LIMFLG, RESETFLG, SETFLG)
  1147. XX *
  1148. XX *    Exit    aging = Updated.
  1149. XX *
  1150. XX *    Uses    None.
  1151. XX *
  1152. XX *    Calls    sprintf, sscanf.
  1153. XX */
  1154. XX
  1155. XXstatic
  1156. XXchange_aging(aging, criteria, period, flg)
  1157. XXchar    **aging;
  1158. XXint    criteria;
  1159. XXlong    period;
  1160. XXint    flg;
  1161. XX
  1162. XX{
  1163. XX    static    char line[LINELEN];
  1164. XX    int    old_criteria;
  1165. XX    long    limit;
  1166. XX    long    last_time;
  1167. XX    long    old_time;
  1168. XX    char    password[LINELEN];
  1169. XX
  1170. XX    sscanf(*aging, "%d,%ld,%ld,%ld,%s", &old_criteria, &limit, &last_time,
  1171. XX            &old_time, password);
  1172. XX
  1173. XX    if (flg&CLEARFLG) {
  1174. XX        last_time = 0;
  1175. XX        old_time = 0;
  1176. XX        strcpy(password, "*******");
  1177. XX    }
  1178. XX    if (flg&CRITFLG)
  1179. XX        old_criteria = criteria;
  1180. XX    if ((flg&LIMFLG) || ((limit == 0) && (flg&SETFLG)))
  1181. XX        limit = period;
  1182. XX    /* order is dependent here, RESETFLG must follow LIMFLG */
  1183. XX    if (flg&RESETFLG)
  1184. XX        last_time -= limit;
  1185. XX
  1186. XX    sprintf(line, "%d,%ld,%ld,%ld,%s",
  1187. XX            old_criteria,
  1188. XX            limit,
  1189. XX            last_time,
  1190. XX            old_time,
  1191. XX            password);
  1192. XX
  1193. XX    *aging = line;
  1194. XX}
  1195. XX
  1196. XX/*    catch - Catch signals so we can clean up.
  1197. XX *
  1198. XX *    Entry    sig    = Signal number caught.
  1199. XX *        sigret = jmpbuf to return to.
  1200. XX *
  1201. XX *    Exit    To sigret to abort pwadm.
  1202. XX *
  1203. XX *    Uses    None.
  1204. XX *    
  1205. XX *    Calls    fflush, fprintf, longjmp.
  1206. XX */
  1207. XX
  1208. XXstatic
  1209. XXcatch(sig)
  1210. XXint    sig;    /* signal number caught */
  1211. XX
  1212. XX{
  1213. XX    static char *sigmsg[] = {
  1214. XX            "",
  1215. XX            "hangup",
  1216. XX            "interrupt",
  1217. XX            "quit",
  1218. XX            "illegal instruction",
  1219. XX            "trace trap",
  1220. XX            "IOT instruction",
  1221. XX            "EMT instruction",
  1222. XX            "floating point exception",
  1223. XX            "kill",
  1224. XX            "bus error",
  1225. XX            "segmentation violation",
  1226. XX            "bad argument to system call",
  1227. XX            "write on a pipe with no one to read it",
  1228. XX            "alarm clock",
  1229. XX            "software termination",
  1230. XX            "urgent condition present on socket",
  1231. XX            "stop",
  1232. XX            "stop from keyboard",
  1233. XX            "continue after stop",
  1234. XX            "child status has changed",
  1235. XX            "background read from control tty",
  1236. XX            "background write to control tty",
  1237. XX            "I/O",
  1238. XX            "cpu time limit",
  1239. XX            "file size limit",
  1240. XX            "virtual time alarm",
  1241. XX            "profiling timer alarm",
  1242. XX            "window size change",
  1243. XX            "user defined 1",
  1244. XX            "user defined 2"
  1245. XX            };
  1246. XX
  1247. XX    fprintf(stderr, "\nCaught %s signal, pwadm aborted.\n", sigmsg[sig]);
  1248. XX    fflush(stderr);
  1249. XX    longjmp(sigret, 1);
  1250. XX}
  1251. XX
  1252. XX/*    make_db - Make the ndbm data base files for a password file.
  1253. XX *
  1254. XX *    Entry    file = File to be turned into an ndbm data base.
  1255. XX *
  1256. XX *    Exit    0, If successful.
  1257. XX *        !=0, If failure.
  1258. XX *
  1259. XX *    Uses    None.
  1260. XX *
  1261. XX *    Calls    /etc/mkpasswd, execl, _exit, fork, wait.
  1262. XX */
  1263. XX
  1264. XXstatic
  1265. XXmake_db(file)
  1266. XXchar *file;
  1267. XX
  1268. XX{
  1269. XX    int status, pid, w;
  1270. XX
  1271. XX    if ((pid = fork()) == 0) {
  1272. XX        execl("/etc/mkpasswd", "mkpasswd", file, 0);
  1273. XX        _exit(127);
  1274. XX    }
  1275. XX    while ((w = wait(&status)) != pid && w != -1)
  1276. XX        continue;
  1277. XX    if (w == -1 || status != 0)
  1278. XX        status = -1;
  1279. XX    return(status);
  1280. XX}
  1281. XX
  1282. XX/*    unlink_files - Unlink possible open files and exit.
  1283. XX *
  1284. XX *    Entry    stemp, stemp_dir, stemp_pag, temp possible open.
  1285. XX *        status = exit status.
  1286. XX *
  1287. XX *    Exit    stemp, stemp_dir, stemp_pag, temp unlinked.
  1288. XX *
  1289. XX *    Uses    None.
  1290. XX *
  1291. XX *    Calls    exit, unlink.
  1292. XX */
  1293. XX
  1294. XXstatic
  1295. XXunlink_files(status)
  1296. XXint status;
  1297. XX{
  1298. XX    unlink(stemp_pag);
  1299. XX    unlink(stemp_dir);
  1300. XX    unlink(stemp);
  1301. XX    unlink(temp);
  1302. XX    exit(status);
  1303. XX}
  1304. SHAR_EOF
  1305. if test 21694 -ne "`wc -c pwadm.c`"
  1306. then
  1307. echo shar: error transmitting pwadm.c '(should have been 21694 characters)'
  1308. fi
  1309. #    End of shell archive
  1310. exit 0
  1311.  
  1312.  
  1313.