home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume38 / shadow / part12 < prev    next >
Encoding:
Text File  |  1993-08-14  |  60.5 KB  |  2,512 lines

  1. Newsgroups: comp.sources.misc
  2. From: jfh@rpp386.cactus.org (John F. Haugh II)
  3. Subject: v38i131:  shadow - Shadow Password Suite, v3.3, Part12/14
  4. Message-ID: <1993Aug14.192639.9904@sparky.sterling.com>
  5. X-Md4-Signature: 9748911e35054f7bb36d3df1730aeea4
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Sat, 14 Aug 1993 19:26:39 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: jfh@rpp386.cactus.org (John F. Haugh II)
  12. Posting-number: Volume 38, Issue 131
  13. Archive-name: shadow/part12
  14. Environment: UNIX
  15. Supersedes: shadow: Volume 26, Issue 54-64
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # Contents:  dialup.c encrypt.c faillog.8 groups.c grpck.1 gsdbm.c
  22. #   gspack.c lastlog.c log.c login.c passwd.4 pwck.1 pwd.h.m4 pwdbm.c
  23. #   pwpack.c pwunconv.c shell.c sppack.c valid.c
  24. # Wrapped by kent@sparky on Sat Aug 14 14:11:41 1993
  25. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  26. echo If this archive is complete, you will see the following message:
  27. echo '          "shar: End of archive 12 (of 14)."'
  28. if test -f 'dialup.c' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'dialup.c'\"
  30. else
  31.   echo shar: Extracting \"'dialup.c'\" \(2702 characters\)
  32.   sed "s/^X//" >'dialup.c' <<'END_OF_FILE'
  33. X/*
  34. X * Copyright 1989, 1990, 1991, John F. Haugh II
  35. X * All rights reserved.
  36. X *
  37. X * Permission is granted to copy and create derivative works for any
  38. X * non-commercial purpose, provided this copyright notice is preserved
  39. X * in all copies of source code, or included in human readable form
  40. X * and conspicuously displayed on all copies of object code or
  41. X * distribution media.
  42. X */
  43. X
  44. X#include <stdio.h>
  45. X#ifndef    BSD
  46. X#include <string.h>
  47. X#else
  48. X#include <strings.h>
  49. X#define    strchr    index
  50. X#define    strrchr    rindex
  51. X#endif
  52. X#include "dialup.h"
  53. X
  54. X#ifndef    lint
  55. Xstatic    char    sccsid[] = "@(#)dialup.c    3.5    17:31:19    04 Aug 1991";
  56. X#endif
  57. X
  58. Xstatic    FILE    *dialpwd;
  59. X
  60. Xvoid
  61. Xsetduent ()
  62. X{
  63. X    if (dialpwd)
  64. X        rewind (dialpwd);
  65. X    else
  66. X        dialpwd = fopen (DIALPWD, "r");
  67. X}
  68. X
  69. Xvoid
  70. Xendduent ()
  71. X{
  72. X    if (dialpwd)
  73. X        fclose (dialpwd);
  74. X
  75. X    dialpwd = (FILE *) 0;
  76. X}
  77. X
  78. Xstruct dialup *
  79. Xfgetduent (fp)
  80. XFILE    *fp;
  81. X{
  82. X    static    struct    dialup    dialup;    /* static structure to point to */
  83. X    static    char    shell[128];    /* some space for a login shell */
  84. X    static    char    passwd[128];    /* some space for dialup password */
  85. X    char    buf[BUFSIZ];
  86. X    char    *cp;
  87. X    char    *cp2;
  88. X
  89. X    if (! fp)
  90. X        return 0;
  91. X
  92. X    if (! fp || feof (fp))
  93. X        return ((struct dialup *) 0);
  94. X
  95. X    while (fgets (buf, BUFSIZ, fp) == buf && buf[0] == '#')
  96. X        ;
  97. X
  98. X    if (feof (fp))
  99. X        return ((struct dialup *) 0);
  100. X
  101. X    if (cp = strchr (buf, '\n'))
  102. X        *cp = '\0';
  103. X
  104. X    if (! (cp = strchr (buf, ':')))
  105. X        return ((struct dialup *) 0);
  106. X
  107. X    if (cp - buf > sizeof shell)    /* something is fishy ... */
  108. X        return ((struct dialup *) 0);
  109. X
  110. X    *cp++ = '\0';
  111. X    (void) strcpy (shell, buf);
  112. X    shell[cp - buf] = '\0';
  113. X
  114. X    if (cp2 = strchr (cp, ':'))
  115. X        *cp2 = '\0';
  116. X
  117. X    if (strlen (cp) + 1 > sizeof passwd) /* something is REALLY fishy */
  118. X        return ((struct dialup *) 0);
  119. X
  120. X    (void) strcpy (passwd, cp);
  121. X
  122. X    dialup.du_shell = shell;
  123. X    dialup.du_passwd = passwd;
  124. X
  125. X    return (&dialup);
  126. X}
  127. X
  128. Xstruct dialup *
  129. Xgetduent ()
  130. X{
  131. X    if (! dialpwd)
  132. X        setduent ();
  133. X
  134. X    return fgetduent (dialpwd);
  135. X}
  136. X
  137. Xstruct    dialup    *getdushell (shell)
  138. Xchar    *shell;
  139. X{
  140. X    struct    dialup    *dialup;
  141. X
  142. X    while (dialup = getduent ()) {
  143. X        if (strcmp (shell, dialup->du_shell) == 0)
  144. X            return (dialup);
  145. X
  146. X        if (strcmp (dialup->du_shell, "*") == 0)
  147. X            return (dialup);
  148. X    }
  149. X    return ((struct dialup *) 0);
  150. X}
  151. X
  152. Xint    isadialup (tty)
  153. Xchar    *tty;
  154. X{
  155. X    FILE    *fp;
  156. X    char    buf[BUFSIZ];
  157. X    int    dialup = 0;
  158. X
  159. X    if (! (fp = fopen (DIALUPS, "r")))
  160. X        return (0);
  161. X
  162. X    while (fgets (buf, BUFSIZ, fp) == buf) {
  163. X        if (buf[0] == '#')
  164. X            continue;
  165. X
  166. X        buf[strlen (buf) - 1] = '\0';
  167. X
  168. X        if (strcmp (buf, tty) == 0) {
  169. X            dialup = 1;
  170. X            break;
  171. X        }
  172. X    }
  173. X    fclose (fp);
  174. X
  175. X    return (dialup);
  176. X}
  177. X
  178. Xint
  179. Xputduent (dial, fp)
  180. Xstruct    dialup    *dial;
  181. XFILE    *fp;
  182. X{
  183. X    if (! fp || ! dial)
  184. X        return -1;
  185. X
  186. X    if (fprintf (fp, "%s:%s\n", dial->du_shell, dial->du_passwd) == EOF)
  187. X        return -1;
  188. X
  189. X    return 0;
  190. X}
  191. END_OF_FILE
  192.   if test 2702 -ne `wc -c <'dialup.c'`; then
  193.     echo shar: \"'dialup.c'\" unpacked with wrong size!
  194.   fi
  195.   # end of 'dialup.c'
  196. fi
  197. if test -f 'encrypt.c' -a "${1}" != "-c" ; then 
  198.   echo shar: Will not clobber existing file \"'encrypt.c'\"
  199. else
  200.   echo shar: Extracting \"'encrypt.c'\" \(2196 characters\)
  201.   sed "s/^X//" >'encrypt.c' <<'END_OF_FILE'
  202. X/*
  203. X * Copyright 1990, 1993, John F. Haugh II
  204. X * All rights reserved.
  205. X *
  206. X * Permission is granted to copy and create derivative works for any
  207. X * non-commercial purpose, provided this copyright notice is preserved
  208. X * in all copies of source code, or included in human readable form
  209. X * and conspicuously displayed on all copies of object code or
  210. X * distribution media.
  211. X *
  212. X * This software is provided on an AS-IS basis and the author makes
  213. X * no warrantee of any kind.
  214. X */
  215. X
  216. X#include <string.h>
  217. X#include "config.h"
  218. X
  219. X#ifndef lint
  220. Xstatic    char    sccsid[] = "@(#)encrypt.c    3.5    07:45:28    22 Apr 1993";
  221. X#endif
  222. X
  223. Xextern    char    *crypt();
  224. X
  225. Xchar *
  226. Xpw_encrypt (clear, salt)
  227. Xchar    *clear;
  228. Xchar    *salt;
  229. X{
  230. X#ifdef    SW_CRYPT
  231. X    static    char    cipher[128];
  232. X#else
  233. X    static    char    cipher[32];
  234. X#endif
  235. X    static    int    count;
  236. X    char    newsalt[2];
  237. X    char    *cp;
  238. X    long    now;
  239. X
  240. X    /*
  241. X     * See if a new salt is needed and get a few random
  242. X     * bits of information.  The amount of randomness is
  243. X     * probably not all that crucial since the salt only
  244. X     * serves to thwart a dictionary attack.
  245. X     */
  246. X
  247. X    if (salt == (char *) 0) {
  248. X        now = time ((long *) 0) + count++;
  249. X        now ^= clock ();
  250. X        now ^= getpid ();
  251. X        now = ((now >> 12) ^ (now)) & 07777;
  252. X        newsalt[0] = i64c ((now >> 6) & 077);
  253. X        newsalt[1] = i64c (now & 077);
  254. X        salt = newsalt;
  255. X    }
  256. X#ifdef    SW_CRYPT
  257. X    /*
  258. X     * Copy over the salt.  It is always the first two
  259. X     * characters of the string.
  260. X     */
  261. X
  262. X    cipher[0] = salt[0];
  263. X    cipher[1] = salt[1];
  264. X    cipher[2] = '\0';
  265. X
  266. X    /*
  267. X     * Loop up to ten times on the cleartext password.
  268. X     * This is because the input limit for passwords is
  269. X     * 80 characters.
  270. X     *
  271. X     * The initial salt is that provided by the user, or the
  272. X     * one generated above.  The subsequent salts are gotten
  273. X     * from the first two characters of the previous encrypted
  274. X     * block of characters.
  275. X     */
  276. X
  277. X    for (count = 0;count < 10;count++) {
  278. X        cp = crypt (clear, salt);
  279. X        strcat (cipher, cp + 2);
  280. X        salt = cipher + 11 * count + 2;
  281. X
  282. X        if (strlen (clear) > 8)
  283. X            clear += 8;
  284. X        else
  285. X            break;
  286. X    }
  287. X#else
  288. X    cp = crypt (clear, salt);
  289. X    strcpy (cipher, cp);
  290. X
  291. X#ifdef    DOUBLESIZE
  292. X    if (strlen (clear) > 8) {
  293. X        cp = crypt (clear + 8, salt);
  294. X        strcat (cipher, cp + 2);
  295. X    }
  296. X#endif    /* DOUBLESIZE */
  297. X#endif    /* SW_CRYPT */
  298. X    return cipher;
  299. X}
  300. END_OF_FILE
  301.   if test 2196 -ne `wc -c <'encrypt.c'`; then
  302.     echo shar: \"'encrypt.c'\" unpacked with wrong size!
  303.   fi
  304.   # end of 'encrypt.c'
  305. fi
  306. if test -f 'faillog.8' -a "${1}" != "-c" ; then 
  307.   echo shar: Will not clobber existing file \"'faillog.8'\"
  308. else
  309.   echo shar: Extracting \"'faillog.8'\" \(2516 characters\)
  310.   sed "s/^X//" >'faillog.8' <<'END_OF_FILE'
  311. X.\" Copyright 1989, 1990, 1992, John F. Haugh II
  312. X.\" All rights reserved.
  313. X.\"
  314. X.\" Use, duplication, and disclosure prohibited without
  315. X.\" the express written permission of the author.
  316. X.\"
  317. X.\"    @(#)faillog.8    3.2    20:36:19    07 Mar 1992
  318. X.\"
  319. X.TH FAILLOG 8
  320. X.SH NAME
  321. Xfaillog \- examine faillog and set login failure limits
  322. X.SH SYNOPSIS
  323. X/etc/faillog [ -u uid ] [ -a ] [ -t days ] [ -m max ] [ -pr ] 
  324. X.SH DESCRIPTION
  325. X\fIfaillog\fR formats the contents of the failure log,
  326. X\fI/usr/adm/faillog\fR, and maintains failure counts and
  327. Xlimits.
  328. XThe order of the arguments to \fIfaillog\fR is significant.
  329. XEach argument is processed immediately in the order given.
  330. X.PP
  331. XThe \fB-p\fR flag causes failure entries to be printed in UID
  332. Xorder.
  333. XEntering \fB-u login-name\fR flag will
  334. Xcause the failure record for \fBlogin-name\fR only to be printed.
  335. XEntering \fB-t days\fR will cause only the
  336. Xfailures more recent than \fBdays\fR to be printed.
  337. XThe \fB-t\fR flag overrides the use of \fB-u\fR.
  338. XThe \fB-a\fR flag causes all users to be selected.
  339. XWhen used with the \fB-p\fR flag, this option selects all users
  340. Xwho have ever had a login failure.
  341. XIt is meaningless with the \fB-r\fR flag.
  342. X.PP
  343. XThe \fB-r\fR flag is used to reset the count of login failures.
  344. XWrite access to \fI/usr/adm/faillog\fR is required for
  345. Xthis option.
  346. XEntering \fB-u login-name\fR will cause only the failure count
  347. Xfor \fBlogin-name\fR to be reset.
  348. X.PP
  349. XThe \fB-m\fR flag is used to set the maximum number of login
  350. Xfailures before the account is disabled.
  351. XWrite access to \fB/usr/adm/faillog\fR is required for this
  352. Xoption.
  353. XEntering \fB-m max\fR will cause all accounts to be disabled
  354. Xafter \fBmax\fR failed logins occur.
  355. XThis may be modified with \fB-u login-name\fR to limit this
  356. Xfunction to \fBlogin-name\fR only.
  357. XSelecting a \fBmax\fR value of 0 has the effect of not placing
  358. Xa limit on the number of failed logins.
  359. XThe maximum failure count
  360. Xshould always be 0 for \fBroot\fR to prevent
  361. Xa denial of services attack against the system.
  362. X.PP
  363. XOptions may be combined in virtually any fashion.
  364. XEach \fB-p\fR, \fB-r\fR, and \fB-m\fR option will cause
  365. Ximmediate execution using any \fB-u\fR or \fB-t\fR modifier.
  366. X.SH Bugs
  367. X\fIfaillog\fR only prints out users with no successful login since
  368. Xthe last failure.
  369. XTo print out a user who has had a successful login since their last
  370. Xfailure, you must explicitly request the user with the \fB-u\fR flag,
  371. Xor print out all users with the \fB-a\fR flag.
  372. X.SH Files
  373. X/usr/adm/faillog \- failure logging file
  374. X.SH See Also
  375. Xlogin(1),
  376. Xfaillog(4)
  377. END_OF_FILE
  378.   if test 2516 -ne `wc -c <'faillog.8'`; then
  379.     echo shar: \"'faillog.8'\" unpacked with wrong size!
  380.   fi
  381.   # end of 'faillog.8'
  382. fi
  383. if test -f 'groups.c' -a "${1}" != "-c" ; then 
  384.   echo shar: Will not clobber existing file \"'groups.c'\"
  385. else
  386.   echo shar: Extracting \"'groups.c'\" \(2582 characters\)
  387.   sed "s/^X//" >'groups.c' <<'END_OF_FILE'
  388. X/*
  389. X * Copyright 1991, John F. Haugh II
  390. X * All rights reserved.
  391. X *
  392. X * Permission is granted to copy and create derivative works for any
  393. X * non-commercial purpose, provided this copyright notice is preserved
  394. X * in all copies of source code, or included in human readable form
  395. X * and conspicuously displayed on all copies of object code or
  396. X * distribution media.
  397. X */
  398. X
  399. Xstatic    char    sccsid[] = "@(#)groups.c    3.2    09:47:19    25 Nov 1991";
  400. X
  401. X#include "stdio.h"
  402. X#include "pwd.h"
  403. X#include "grp.h"
  404. X
  405. X/*
  406. X * print_groups - print the groups which the named user is a member of
  407. X *
  408. X *    print_groups() scans the groups file for the list of groups
  409. X *    which the user is listed as being a member of.
  410. X */
  411. X
  412. Xprint_groups (member)
  413. Xchar    *member;
  414. X{
  415. X    int    i, groups = 0;
  416. X    struct    group    *grp;
  417. X    struct    group    *getgrent();
  418. X
  419. X    setgrent ();
  420. X
  421. X    while (grp = getgrent ()) {
  422. X        for (i = 0;grp->gr_mem[i];i++) {
  423. X            if (strcmp (grp->gr_mem[i], member) == 0) {
  424. X                if (groups++)
  425. X                    putchar (' ');
  426. X
  427. X                printf ("%s", grp->gr_name);
  428. X            }
  429. X        }
  430. X    }
  431. X    if (groups)
  432. X        putchar ('\n');
  433. X}
  434. X
  435. X/*
  436. X * groups - print out the groups a process is a member of
  437. X */
  438. X
  439. Xmain (argc, argv)
  440. Xint    argc;
  441. Xchar    **argv;
  442. X{
  443. X    int    ngroups;
  444. X#if NGROUPS > 0
  445. X#if NGROUPS > 100
  446. X    gid_t    *groups;
  447. X#else
  448. X    gid_t    groups[NGROUPS];
  449. X#endif
  450. X    int    i;
  451. X#else
  452. X    char    *logname;
  453. X    char    *getlogin();
  454. X#endif
  455. X    struct    group    *gr;
  456. X    struct    group    *getgrgid();
  457. X
  458. X    if (argc == 1) {
  459. X
  460. X        /*
  461. X         * Called with no arguments - give the group set
  462. X         * for the current user.
  463. X         */
  464. X
  465. X#if NGROUPS > 0
  466. X        /*
  467. X         * This system supports concurrent group sets, so
  468. X         * I can ask the system to tell me which groups are
  469. X         * currently set for this process.
  470. X         */
  471. X
  472. X        ngroups = getgroups (0, 0);
  473. X#if NGROUPS > 100
  474. X        groups = (gid_t *) malloc (ngroups * sizeof (int *));
  475. X#endif
  476. X        getgroups (ngroups, groups);
  477. X
  478. X        /*
  479. X         * Print out the name of every group in the current
  480. X         * group set.  Unknown groups are printed as their
  481. X         * decimal group ID values.
  482. X         */
  483. X
  484. X        for (i = 0;i < ngroups;i++) {
  485. X            if (i)
  486. X                putchar (' ');
  487. X
  488. X            if (gr = getgrgid (groups[i]))
  489. X                printf ("%s", gr->gr_name);
  490. X            else
  491. X                printf ("%d", groups[i]);
  492. X        }
  493. X        putchar ('\n');
  494. X#else
  495. X        /*
  496. X         * This system does not have the getgroups() system
  497. X         * call, so I must check the groups file directly.
  498. X         */
  499. X
  500. X        if (logname = getlogin ())
  501. X            print_groups (logname);
  502. X        else
  503. X            exit (1);
  504. X#endif
  505. X    } else {
  506. X
  507. X        /*
  508. X         * The invoker wanted to know about some other
  509. X         * user.  Use that name to look up the groups instead.
  510. X         */
  511. X
  512. X        if (getpwnam (argv[1]) == 0) {
  513. X            fprintf (stderr, "unknown user %s\n", argv[1]);
  514. X            exit (1);
  515. X        }
  516. X        print_groups (argv[1]);
  517. X    }
  518. X    exit (0);
  519. X}
  520. END_OF_FILE
  521.   if test 2582 -ne `wc -c <'groups.c'`; then
  522.     echo shar: \"'groups.c'\" unpacked with wrong size!
  523.   fi
  524.   # end of 'groups.c'
  525. fi
  526. if test -f 'grpck.1' -a "${1}" != "-c" ; then 
  527.   echo shar: Will not clobber existing file \"'grpck.1'\"
  528. else
  529.   echo shar: Extracting \"'grpck.1'\" \(2692 characters\)
  530.   sed "s/^X//" >'grpck.1' <<'END_OF_FILE'
  531. X.\" Copyright 1992, 1993, John F. Haugh II
  532. X.\" All rights reserved.
  533. X.\"
  534. X.\" Permission is granted to copy and create derivative works for any
  535. X.\" non-commercial purpose, provided this copyright notice is preserved
  536. X.\" in all copies of source code, or included in human readable form
  537. X.\" and conspicuously displayed on all copies of object code or
  538. X.\" distribution media.
  539. X.\"
  540. X.\" This software is provided on an AS-IS basis and the author makes
  541. X.\" no warrantee of any kind.
  542. X.\"
  543. X.\"    @(#)grpck.1    3.2    08:47:26    29 Apr 1993
  544. X.\"
  545. X.TH GRPCK 1
  546. X.SH NAME
  547. Xgrpck \- verify integrity of group files
  548. X.SH SYNOPSIS
  549. X\fBgrpck\fR [ \fB-r\fR ] [ \fIgroup\fR \fIshadow\fR ]
  550. X.SH DESCRIPTION
  551. X\fBgrpck\fR verifies the integrity of the system authentication information.
  552. XAll entries in the \fB/etc/group\fR and \fB/etc/gshadow\fR are checked to
  553. Xsee that the entry has the proper format and valid data in each field.
  554. XThe user is prompted to delete entries that are improperly formatted or
  555. Xwhich have other incorrectable errors.
  556. X.P
  557. XChecks are made to verify that each entry has
  558. X.sp
  559. X.in +.5i
  560. X- the correct number of fields
  561. X.br
  562. X- a unique group name
  563. X.br
  564. X- a valid list of members and administrators
  565. X.in -.5i
  566. X.sp
  567. X.P
  568. XThe checks for correct number of fields and unique group name are fatal.
  569. XIf the entry has the wrong number of fields, the user will be prompted to
  570. Xdelete the entire line.
  571. XIf the user does not answer affirmatively, all further checks are bypassed.
  572. XAn entry with a duplicated group name is prompted for deletion, but the
  573. Xremaining checks will still be made.
  574. XAll other errors are warnings and the user is encouraged to run the
  575. X\fBgroupmod\fR command to correct the error.
  576. X.P
  577. XThe commands which operate on the \fB/etc/group\fR file are not able to
  578. Xalter corrupted or duplicated entries.
  579. X\fBgrpck\fR should be used in those circumstances to remove the offending
  580. Xentry.
  581. X.SH OPTIONS
  582. XBy default, \fBgrpck\fR operates on the files \fB/etc/group\fR and
  583. X\fB/etc/gshadow\fR.
  584. XThe user may select alternate files with the \fIgroup\fR and \fIshadow\fR
  585. Xparameters.
  586. XAdditionally, the user may execute the command in read-only mode by
  587. Xspecifying the \fB-r\fR flag.
  588. XThis causes all questions regarding changes to be answered \fBno\fR
  589. Xwithout user intervention.
  590. X.SH FILES
  591. X/etc/group \- group account information
  592. X.br
  593. X/etc/gshadow \- encrypted passwords and group administrator information
  594. X.br
  595. X/etc/passwd \- user information
  596. X.SH SEE ALSO
  597. Xgroupmod(1), group(4), passwd(4), shadow(4)
  598. X.SH DIAGNOSTICS
  599. XThe \fIgrpck\fR command exits with the following values:
  600. X.IP 0 5
  601. XSuccess
  602. X.IP 1 5
  603. XSyntax Error
  604. X.IP 2 5
  605. XOne or more bad group entries
  606. X.IP 3 5
  607. XCannot open group files
  608. X.IP 4 5
  609. XCannot lock group files
  610. X.IP 5 5
  611. XCannot update group files
  612. END_OF_FILE
  613.   if test 2692 -ne `wc -c <'grpck.1'`; then
  614.     echo shar: \"'grpck.1'\" unpacked with wrong size!
  615.   fi
  616.   # end of 'grpck.1'
  617. fi
  618. if test -f 'gsdbm.c' -a "${1}" != "-c" ; then 
  619.   echo shar: Will not clobber existing file \"'gsdbm.c'\"
  620. else
  621.   echo shar: Extracting \"'gsdbm.c'\" \(2795 characters\)
  622.   sed "s/^X//" >'gsdbm.c' <<'END_OF_FILE'
  623. X/*
  624. X * Copyright 1990, 1991, 1992, John F. Haugh II
  625. X * All rights reserved.
  626. X *
  627. X * Permission is granted to copy and create derivative works for any
  628. X * non-commercial purpose, provided this copyright notice is preserved
  629. X * in all copies of source code, or included in human readable form
  630. X * and conspicuously displayed on all copies of object code or
  631. X * distribution media.
  632. X *
  633. X * This software is provided on an AS-IS basis and the author makes
  634. X * no warrantee of any kind.
  635. X */
  636. X
  637. X#ifndef    lint
  638. Xstatic    char    sccsid[] = "@(#)gsdbm.c    3.6    11:32:14    28 Jul 1992";
  639. X#endif
  640. X
  641. X#include <string.h>
  642. X#include <stdio.h>
  643. X#include "shadow.h"
  644. X#include "config.h"
  645. X
  646. X#ifdef    NDBM
  647. X#include <ndbm.h>
  648. XDBM    *sg_dbm;
  649. X
  650. X#define    GRP_FRAG    256
  651. X
  652. X/*
  653. X * sg_dbm_update
  654. X *
  655. X * Updates the DBM password files, if they exist.
  656. X */
  657. X
  658. Xint
  659. Xsg_dbm_update (sgr)
  660. Xstruct    sgrp    *sgr;
  661. X{
  662. X    datum    key;
  663. X    datum    content;
  664. X    char    data[BUFSIZ*8];
  665. X    char    sgrpkey[60];
  666. X    char    *cp;
  667. X    int    len;
  668. X    int    i;
  669. X    int    cnt;
  670. X    static    int    once;
  671. X
  672. X    if (! once) {
  673. X        if (! sg_dbm)
  674. X            setsgent ();
  675. X
  676. X        once++;
  677. X    }
  678. X    if (! sg_dbm)
  679. X        return 0;
  680. X
  681. X    len = sgr_pack (sgr, data);
  682. X
  683. X    if (len <= GRP_FRAG) {
  684. X        content.dsize = len;
  685. X        content.dptr = data;
  686. X
  687. X        key.dsize = strlen (sgr->sg_name);
  688. X        key.dptr = sgr->sg_name;
  689. X        if (dbm_store (sg_dbm, key, content, DBM_REPLACE))
  690. X            return 0;
  691. X    } else {
  692. X        content.dsize = sizeof cnt;
  693. X        content.dptr = (char *) &cnt;
  694. X        cnt = (len + (GRP_FRAG-1)) / GRP_FRAG;
  695. X
  696. X        key.dsize = strlen (sgr->sg_name);
  697. X        key.dptr = sgr->sg_name;
  698. X        if (dbm_store (sg_dbm, key, content, DBM_REPLACE))
  699. X            return 0;
  700. X
  701. X        for (cp = data, i = 0;i < cnt;i++) {
  702. X            content.dsize = len > GRP_FRAG ? GRP_FRAG:len;
  703. X            len -= content.dsize;
  704. X            content.dptr = cp;
  705. X            cp += content.dsize;
  706. X
  707. X            key.dsize = sizeof i + strlen (sgr->sg_name);
  708. X            key.dptr = sgrpkey;
  709. X            memcpy (sgrpkey, (char *) &i, sizeof i);
  710. X            strcpy (sgrpkey + sizeof i, sgr->sg_name);
  711. X            if (dbm_store (sg_dbm, key, content, DBM_REPLACE))
  712. X                return 0;
  713. X        }
  714. X    }
  715. X    return 1;
  716. X}
  717. X
  718. X/*
  719. X * sg_dbm_remove
  720. X *
  721. X * Deletes the DBM shadow group file entries, if they exist.
  722. X */
  723. X
  724. Xint
  725. Xsg_dbm_remove (name)
  726. Xchar    *name;
  727. X{
  728. X    datum    key;
  729. X    datum    content;
  730. X    char    grpkey[60];
  731. X    int    i;
  732. X    int    cnt;
  733. X    int    errors = 0;
  734. X    static    int    once;
  735. X
  736. X    if (! once) {
  737. X        if (! sg_dbm)
  738. X            setsgent ();
  739. X
  740. X        once++;
  741. X    }
  742. X    if (! sg_dbm)
  743. X        return 0;
  744. X
  745. X    key.dsize = strlen (name);
  746. X    key.dptr = name;
  747. X    content = dbm_fetch (sg_dbm, key);
  748. X    if (content.dptr == 0)
  749. X        ++errors;
  750. X    else {
  751. X        if (content.dsize == sizeof (int)) {
  752. X            memcpy ((char *) &cnt, content.dptr, sizeof cnt);
  753. X
  754. X            for (i = 0;i < cnt;i++) {
  755. X                key.dsize = sizeof i + strlen (name);
  756. X                key.dptr = grpkey;
  757. X                memcpy (grpkey, (char *) &i, sizeof i);
  758. X                strcpy (grpkey + sizeof i, name);
  759. X                if (dbm_delete (sg_dbm, key))
  760. X                    ++errors;
  761. X            }
  762. X        } else {
  763. X            if (dbm_delete (sg_dbm, key))
  764. X                ++errors;
  765. X        }
  766. X    }
  767. X    return errors ? 0:1;
  768. X}
  769. X#endif
  770. END_OF_FILE
  771.   if test 2795 -ne `wc -c <'gsdbm.c'`; then
  772.     echo shar: \"'gsdbm.c'\" unpacked with wrong size!
  773.   fi
  774.   # end of 'gsdbm.c'
  775. fi
  776. if test -f 'gspack.c' -a "${1}" != "-c" ; then 
  777.   echo shar: Will not clobber existing file \"'gspack.c'\"
  778. else
  779.   echo shar: Extracting \"'gspack.c'\" \(2893 characters\)
  780.   sed "s/^X//" >'gspack.c' <<'END_OF_FILE'
  781. X/*
  782. X * Copyright 1990, John F. Haugh II
  783. X * All rights reserved.
  784. X *
  785. X * Permission is granted to copy and create derivative works for any
  786. X * non-commercial purpose, provided this copyright notice is preserved
  787. X * in all copies of source code, or included in human readable form
  788. X * and conspicuously displayed on all copies of object code or
  789. X * distribution media.
  790. X */
  791. X
  792. X#include <stdio.h>
  793. X#include "shadow.h"
  794. X#ifdef    BSD
  795. X#include <strings.h>
  796. X#else
  797. X#include <string.h>
  798. X#endif
  799. X
  800. X#ifndef    lint
  801. Xstatic    char    sccsid[] = "@(#)gspack.c    3.1    09:13:50    13 Dec 1990";
  802. X#endif
  803. X
  804. X/*
  805. X * sgr_pack - convert a shadow group structure to a packed
  806. X *          shadow group record
  807. X *
  808. X *    sgr_pack takes the shadow group structure and packs
  809. X *    the components in a record.  this record will be
  810. X *    unpacked later by sgr_unpack.
  811. X */
  812. X
  813. Xint
  814. Xsgr_pack (sgrp, buf)
  815. Xstruct    sgrp    *sgrp;
  816. Xchar    *buf;
  817. X{
  818. X    char    *cp;
  819. X    int    i;
  820. X
  821. X    /*
  822. X     * The name and password are both easy - append each string
  823. X     * to the buffer.  These are always the first two strings
  824. X     * in a record.
  825. X     */
  826. X
  827. X    cp = buf;
  828. X    strcpy (cp, sgrp->sg_name);
  829. X    cp += strlen (cp) + 1;
  830. X
  831. X    strcpy (cp, sgrp->sg_passwd);
  832. X    cp += strlen (cp) + 1;
  833. X
  834. X    /*
  835. X     * The arrays of administrators and members are slightly
  836. X     * harder.  Each element is appended as a string, with a
  837. X     * final '\0' appended to serve as a blank string.  The
  838. X     * number of elements is not known in advance, so the
  839. X     * entire collection of administrators must be scanned to
  840. X     * find the start of the members.
  841. X     */
  842. X
  843. X    for (i = 0;sgrp->sg_adm[i];i++) {
  844. X        strcpy (cp, sgrp->sg_adm[i]);
  845. X        cp += strlen (cp) + 1;
  846. X    }
  847. X    *cp++ = '\0';
  848. X
  849. X    for (i = 0;sgrp->sg_mem[i];i++) {
  850. X        strcpy (cp, sgrp->sg_mem[i]);
  851. X        cp += strlen (cp) + 1;
  852. X    }
  853. X    *cp++ = '\0';
  854. X
  855. X    return cp - buf;
  856. X}
  857. X
  858. X/*
  859. X * sgr_unpack - convert a packed shadow group record to an
  860. X *            unpacked record
  861. X *
  862. X *    sgr_unpack converts a record which was packed by sgr_pack
  863. X *    into the normal shadow group structure format.
  864. X */
  865. X
  866. Xint
  867. Xsgr_unpack (buf, len, sgrp)
  868. Xchar    *buf;
  869. Xint    len;
  870. Xstruct    sgrp    *sgrp;
  871. X{
  872. X    char    *org = buf;
  873. X    int    i;
  874. X
  875. X    /*
  876. X     * The name and password are both easy - they are the first
  877. X     * two strings in the record.
  878. X     */
  879. X
  880. X    sgrp->sg_name = buf;
  881. X    buf += strlen (buf) + 1;
  882. X    if (buf - org > len)
  883. X        return -1;
  884. X
  885. X    sgrp->sg_passwd = buf;
  886. X    buf += strlen (buf) + 1;
  887. X    if (buf - org > len)
  888. X        return -1;
  889. X
  890. X    /*
  891. X     * The administrators and members are slightly more difficult.
  892. X     * The arrays are lists of strings.  Each list is terminated
  893. X     * by a string of length zero.  This string is detected by
  894. X     * looking for an initial character of '\0'.
  895. X     */
  896. X
  897. X    for (i = 0;*buf && i < 1024;i++) {
  898. X        sgrp->sg_adm[i] = buf;
  899. X        buf += strlen (buf) + 1;
  900. X
  901. X        if (buf - org > len)
  902. X            return -1;
  903. X    }
  904. X    sgrp->sg_adm[i] = (char *) 0;
  905. X    if (! *buf)
  906. X        buf++;
  907. X
  908. X    for (i = 0;*buf && i < 1024;i++) {
  909. X        sgrp->sg_mem[i] = buf;
  910. X        buf += strlen (buf) + 1;
  911. X
  912. X        if (buf - org > len)
  913. X            return -1;
  914. X    }
  915. X    sgrp->sg_mem[i] = (char *) 0;
  916. X
  917. X    return 0;
  918. X}
  919. END_OF_FILE
  920.   if test 2893 -ne `wc -c <'gspack.c'`; then
  921.     echo shar: \"'gspack.c'\" unpacked with wrong size!
  922.   fi
  923.   # end of 'gspack.c'
  924. fi
  925. if test -f 'lastlog.c' -a "${1}" != "-c" ; then 
  926.   echo shar: Will not clobber existing file \"'lastlog.c'\"
  927. else
  928.   echo shar: Extracting \"'lastlog.c'\" \(3128 characters\)
  929.   sed "s/^X//" >'lastlog.c' <<'END_OF_FILE'
  930. X/*
  931. X * Copyright 1989, 1990, 1992, John F. Haugh II
  932. X * All rights reserved.
  933. X *
  934. X * Permission is granted to copy and create derivative works for any
  935. X * non-commercial purpose, provided this copyright notice is preserved
  936. X * in all copies of source code, or included in human readable form
  937. X * and conspicuously displayed on all copies of object code or
  938. X * distribution media.
  939. X *
  940. X * Modified from faillog.c by Philip Street
  941. X * Installation:  Maine National Guard
  942. X */
  943. X
  944. X#include <sys/types.h>
  945. X#include <sys/stat.h>
  946. X#include <stdio.h>
  947. X#include "pwd.h"
  948. X#include <time.h>
  949. X#ifndef    BSD
  950. X#include <string.h>
  951. X#include <memory.h>
  952. X#else
  953. X#include <strings.h>
  954. X#define    strchr    index
  955. X#define    strrchr    rindex
  956. X#endif
  957. X
  958. X#define LASTFILE "/usr/adm/lastlog"
  959. X
  960. X#include "config.h"
  961. X#include "lastlog.h"
  962. X
  963. X#ifndef    lint
  964. Xstatic    char    sccsid[] = "@(#)lastlog.c    3.2    10:30:33    18 Jul 1993";
  965. X#endif
  966. X
  967. XFILE    *lastlogfile;    /* lastlog file stream */
  968. Xoff_t    user;        /* one single user, specified on command line */
  969. Xint    days;        /* number of days to consider for print command */
  970. Xtime_t    seconds;    /* that number of days in seconds */
  971. X
  972. Xint    uflg;        /* set if user is a valid user id */
  973. Xint    tflg;        /* print is restricted to most recent days */
  974. Xstruct    lastlog    lastlog; /* scratch structure to play with ... */
  975. Xstruct    stat    statbuf; /* fstat buffer for file size */
  976. X
  977. Xint freadcode;
  978. X
  979. Xextern    int    optind;
  980. Xextern    char    *optarg;
  981. Xextern    char    *asctime ();
  982. Xextern    struct    passwd    *getpwuid ();
  983. Xextern    struct    passwd    *getpwnam ();
  984. Xextern    struct    passwd    *getpwent ();
  985. Xextern    struct    tm    *localtime ();
  986. X
  987. X#define    DAY    (24L*3600L)
  988. X#define    NOW    (time ((time_t *) 0))
  989. X
  990. Xmain (argc, argv)
  991. Xint    argc;
  992. Xchar    **argv;
  993. X{
  994. X    int    c;
  995. X    struct    passwd    *pwent;
  996. X
  997. X    if ((lastlogfile = fopen (LASTFILE,"r")) == (FILE *) 0) {
  998. X        perror (LASTFILE);
  999. X        exit (1);
  1000. X    }
  1001. X    while ((c = getopt (argc, argv, "u:t:")) != EOF) {
  1002. X        switch (c) {
  1003. X            case 'u':
  1004. X                pwent = getpwnam (optarg);
  1005. X                if (! pwent) {
  1006. X                    fprintf (stderr, "Unknown User: %s\n", optarg);
  1007. X                    exit (1);
  1008. X                }
  1009. X                uflg++;
  1010. X                user = pwent->pw_uid;
  1011. X                break;
  1012. X            case 't':
  1013. X                days = atoi (optarg);
  1014. X                seconds = days * DAY;
  1015. X                tflg++;
  1016. X                break;
  1017. X        }
  1018. X    }
  1019. X    print ();
  1020. X    fclose (lastlogfile);
  1021. X    exit (0);
  1022. X    /*NOTREACHED*/
  1023. X}
  1024. X
  1025. Xprint ()
  1026. X{
  1027. X    int    uid;
  1028. X    off_t    offset;
  1029. X
  1030. X    if (uflg) {
  1031. X        offset = user * sizeof lastlog;
  1032. X        fstat (fileno (lastlogfile), &statbuf);
  1033. X        if (offset >= statbuf.st_size)
  1034. X            return;
  1035. X
  1036. X        fseek (lastlogfile, (off_t) user * sizeof lastlog, 0);
  1037. X        if (fread ((char *) &lastlog, sizeof lastlog, 1, lastlogfile) == 1)
  1038. X            print_one (user);
  1039. X        else
  1040. X            perror (LASTFILE);
  1041. X    } else {
  1042. X        for (uid = 0;
  1043. X            fread ((char *) &lastlog, sizeof lastlog, 1, lastlogfile) == 1;
  1044. X                uid++) {
  1045. X
  1046. X            if (tflg && NOW - lastlog.ll_time > seconds)
  1047. X                continue;
  1048. X
  1049. X            print_one (uid);
  1050. X        }
  1051. X    }
  1052. X}
  1053. X
  1054. Xprint_one (uid)
  1055. Xint    uid;
  1056. X{
  1057. X    static    int    once;
  1058. X    char    *cp;
  1059. X    struct    tm    *tm;
  1060. X    struct    passwd    *pwent;
  1061. X
  1062. X    if (! once) {
  1063. X        printf ("Username\t\tPort\tLatest\n");
  1064. X        once++;
  1065. X    }
  1066. X    pwent = getpwuid (uid);
  1067. X    tm = localtime (&lastlog.ll_time);
  1068. X    cp = asctime (tm);
  1069. X    cp[24] = '\0';
  1070. X
  1071. X    if(lastlog.ll_time == (time_t) 0)
  1072. X        cp = "**Never logged in**\0";
  1073. X
  1074. X    if (pwent) {
  1075. X        printf ("%-16s\t%s\t%s\n",pwent->pw_name,lastlog.ll_line,cp);
  1076. X    }
  1077. X}
  1078. END_OF_FILE
  1079.   if test 3128 -ne `wc -c <'lastlog.c'`; then
  1080.     echo shar: \"'lastlog.c'\" unpacked with wrong size!
  1081.   fi
  1082.   # end of 'lastlog.c'
  1083. fi
  1084. if test -f 'log.c' -a "${1}" != "-c" ; then 
  1085.   echo shar: Will not clobber existing file \"'log.c'\"
  1086. else
  1087.   echo shar: Extracting \"'log.c'\" \(2569 characters\)
  1088.   sed "s/^X//" >'log.c' <<'END_OF_FILE'
  1089. X/*
  1090. X * Copyright 1989, 1990, 1991, 1992, 1993, John F. Haugh II
  1091. X * All rights reserved.
  1092. X *
  1093. X * Permission is granted to copy and create derivative works for any
  1094. X * non-commercial purpose, provided this copyright notice is preserved
  1095. X * in all copies of source code, or included in human readable form
  1096. X * and conspicuously displayed on all copies of object code or
  1097. X * distribution media.
  1098. X *
  1099. X * This software is provided on an AS-IS basis and the author makes
  1100. X * no warrantee of any kind.
  1101. X */
  1102. X
  1103. X#include <sys/types.h>
  1104. X#include <utmp.h>
  1105. X#ifdef    SVR4
  1106. X#include <utmpx.h>
  1107. X#endif
  1108. X#include "pwd.h"
  1109. X#include <fcntl.h>
  1110. X#include <time.h>
  1111. X#ifndef    BSD
  1112. X#include <string.h>
  1113. X#include <memory.h>
  1114. X#else
  1115. X#include <strings.h>
  1116. X#define    strchr    index
  1117. X#define    strrchr    rindex
  1118. X#endif
  1119. X#include "config.h"
  1120. X
  1121. X#ifndef    lint
  1122. Xstatic    char    sccsid[] = "@(#)log.c    3.7    08:07:11    19 Jul 1993";
  1123. X#endif
  1124. X
  1125. X#include "lastlog.h"
  1126. X
  1127. X#ifndef    LASTLOG_FILE
  1128. X#ifdef    SVR4
  1129. X#define    LASTLOG_FILE    "/var/adm/lastlog"
  1130. X#else
  1131. X#define    LASTLOG_FILE    "/usr/adm/lastlog"
  1132. X#endif    /* SVR4 */
  1133. X#endif    /* LASTLOG_FILE */
  1134. X
  1135. Xextern    struct    utmp    utent;
  1136. X#ifdef    SVR4
  1137. Xextern    struct    utmpx    utxent;
  1138. X#endif
  1139. Xextern    struct    passwd    pwent;
  1140. Xextern    struct    lastlog    lastlog;
  1141. Xextern    char    **environ;
  1142. X
  1143. Xlong    lseek ();
  1144. Xtime_t    time ();
  1145. X
  1146. X/* 
  1147. X * log - create lastlog entry
  1148. X *
  1149. X *    A "last login" entry is created for the user being logged in.  The
  1150. X *    UID is extracted from the global (struct passwd) entry and the
  1151. X *    TTY information is gotten from the (struct utmp).
  1152. X */
  1153. X
  1154. Xvoid    log ()
  1155. X{
  1156. X    int    fd;
  1157. X    off_t    offset;
  1158. X    struct    lastlog    newlog;
  1159. X
  1160. X    /*
  1161. X     * If the file does not exist, don't create it.
  1162. X     */
  1163. X
  1164. X    if ((fd = open (LASTLOG_FILE, O_RDWR)) == -1)
  1165. X        return;
  1166. X
  1167. X    /*
  1168. X     * The file is indexed by UID number.  Seek to the record
  1169. X     * for this UID.  Negaive UID's will create problems, but ...
  1170. X     */
  1171. X
  1172. X    offset = pwent.pw_uid * sizeof lastlog;
  1173. X
  1174. X    if (lseek (fd, offset, 0) != offset) {
  1175. X        (void) close (fd);
  1176. X        return;
  1177. X    }
  1178. X
  1179. X    /*
  1180. X     * Read the old entry so we can tell the user when they last
  1181. X     * logged in.  Then construct the new entry and write it out
  1182. X     * the way we read the old one in.
  1183. X     */
  1184. X
  1185. X    if (read (fd, (char *) &lastlog, sizeof lastlog) != sizeof lastlog)
  1186. X#ifndef    BSD
  1187. X        memset ((char *) &lastlog, sizeof lastlog, 0);
  1188. X#else
  1189. X        bzero ((char *) &lastlog, sizeof lastlog);
  1190. X#endif
  1191. X    newlog = lastlog;
  1192. X
  1193. X    (void) time (&newlog.ll_time);
  1194. X    (void) strncpy (newlog.ll_line, utent.ut_line, sizeof newlog.ll_line);
  1195. X#ifdef    SVR4
  1196. X    (void) strncpy (newlog.ll_host, utxent.ut_host, sizeof newlog.ll_host);
  1197. X#endif
  1198. X    (void) lseek (fd, offset, 0);
  1199. X    (void) write (fd, (char *) &newlog, sizeof newlog);
  1200. X    (void) close (fd);
  1201. X}
  1202. END_OF_FILE
  1203.   if test 2569 -ne `wc -c <'log.c'`; then
  1204.     echo shar: \"'log.c'\" unpacked with wrong size!
  1205.   fi
  1206.   # end of 'log.c'
  1207. fi
  1208. if test -f 'login.c' -a "${1}" != "-c" ; then 
  1209.   echo shar: Will not clobber existing file \"'login.c'\"
  1210. else
  1211.   echo shar: Extracting \"'login.c'\" \(3264 characters\)
  1212.   sed "s/^X//" >'login.c' <<'END_OF_FILE'
  1213. X/*
  1214. X * Copyright 1989, 1990, 1991, 1992, 1993, John F. Haugh II
  1215. X * All rights reserved.
  1216. X *
  1217. X * Permission is granted to copy and create derivative works for any
  1218. X * non-commercial purpose, provided this copyright notice is preserved
  1219. X * in all copies of source code, or included in human readable form
  1220. X * and conspicuously displayed on all copies of object code or
  1221. X * distribution media.
  1222. X *
  1223. X * This software is provided on an AS-IS basis and the author makes
  1224. X * no warrantee of any kind.
  1225. X */
  1226. X
  1227. X#include <stdio.h>
  1228. X#include <signal.h>
  1229. X#include <ctype.h>
  1230. X#ifndef    BSD
  1231. X#include <string.h>
  1232. X#include <memory.h>
  1233. X#else
  1234. X#include <strings.h>
  1235. X#define    strchr    index
  1236. X#define    strrchr    rindex
  1237. X#endif
  1238. X#include "config.h"
  1239. X
  1240. X#ifndef    lint
  1241. Xstatic    char    sccsid[] = "@(#)login.c    3.4    12:21:53    01 May 1993";
  1242. X#endif
  1243. X
  1244. Xvoid    setenv ();
  1245. X
  1246. X/*
  1247. X * login - prompt the user for their login name
  1248. X *
  1249. X * login() displays the standard login prompt.  If the option
  1250. X * ISSUE_FILE_ENAB is set, the file /etc/issue is displayed
  1251. X * before the prompt.
  1252. X */
  1253. X
  1254. Xvoid
  1255. Xlogin (name, prompt)
  1256. Xchar    *name;
  1257. Xchar    *prompt;
  1258. X{
  1259. X    char    buf[BUFSIZ];
  1260. X    char    *envp[32];
  1261. X    int    envc;
  1262. X    char    *cp;
  1263. X    int    i;
  1264. X    FILE    *fp;
  1265. X    SIGTYPE    (*sigquit)();
  1266. X#ifdef    SIGTSTP
  1267. X    SIGTYPE    (*sigtstp)();
  1268. X#endif
  1269. X    extern    void    exit();
  1270. X
  1271. X    /*
  1272. X     * There is a small chance that a QUIT character will be part of
  1273. X     * some random noise during a prompt.  Deal with this by exiting
  1274. X     * instead of core dumping.  If SIGTSTP is defined, do the same
  1275. X     * thing for that signal.
  1276. X     */
  1277. X
  1278. X    sigquit = signal (SIGQUIT, exit);
  1279. X#ifdef    SIGTSTP
  1280. X    sigtstp = signal (SIGTSTP, exit);
  1281. X#endif
  1282. X
  1283. X    /*
  1284. X     * See if the user has configured the /etc/issue file to
  1285. X     * be displayed and display it before the prompt.
  1286. X     */
  1287. X
  1288. X    if (prompt) {
  1289. X        if (getdef_bool ("ISSUE_FILE_ENAB")) {
  1290. X            if (fp = fopen ("/etc/issue", "r")) {
  1291. X                while ((i = getc (fp)) != EOF)
  1292. X                    putc (i, stdout);
  1293. X
  1294. X                fflush (stdout);
  1295. X                fclose (fp);
  1296. X            }
  1297. X        }
  1298. X        fputs (prompt, stdout);
  1299. X    }
  1300. X
  1301. X    /* 
  1302. X     * Read the user's response.  The trailing newline will be
  1303. X     * removed.
  1304. X     */
  1305. X
  1306. X#ifndef    BSD
  1307. X    (void) memset (buf, '\0', sizeof buf);
  1308. X#else
  1309. X    bzero (buf, sizeof buf);
  1310. X#endif
  1311. X    if (fgets (buf, BUFSIZ, stdin) != buf)
  1312. X        exit (1);
  1313. X
  1314. X    buf[strlen (buf) - 1] = '\0';    /* remove \n [ must be there ] */
  1315. X
  1316. X    /*
  1317. X     * Skip leading whitespace.  This makes "  username" work right.
  1318. X     * Then copy the rest (up to the end or the first "non-graphic"
  1319. X     * character into the username.
  1320. X     */
  1321. X
  1322. X    for (cp = buf;*cp == ' ' || *cp == '\t';cp++)
  1323. X        ;
  1324. X
  1325. X    for (i = 0;i < BUFSIZ - 1 && isgraph (*cp);name[i++] = *cp++)
  1326. X        ;
  1327. X
  1328. X    if (*cp)
  1329. X        cp++;
  1330. X
  1331. X    name[i] = '\0';
  1332. X
  1333. X    /*
  1334. X     * This is a disaster, at best.  The user may have entered extra
  1335. X     * environmental variables at the prompt.  There are several ways
  1336. X     * to do this, and I just take the easy way out.
  1337. X     */
  1338. X
  1339. X    if (*cp != '\0') {        /* process new variables */
  1340. X        static    int    count;
  1341. X        char    var[BUFSIZ];
  1342. X
  1343. X        for (envc = 0;envc < 32;envc++) {
  1344. X            envp[envc] = strtok (envc == 0 ? cp:(char *) 0, " \t,");
  1345. X            if (envp[envc] == (char *) 0)
  1346. X                break;
  1347. X
  1348. X            if (! strchr (envp[envc], '=')) {
  1349. X                sprintf (var, "L%d=%s", count++, envp[envc]);
  1350. X                envp[envc] = strdup (var);
  1351. X            }
  1352. X        }
  1353. X        setenv (envc, envp);
  1354. X    }
  1355. X
  1356. X    /*
  1357. X     * Set the SIGQUIT handler back to its original value
  1358. X     */
  1359. X
  1360. X    (void) signal (SIGQUIT, sigquit);
  1361. X#ifdef    SIGTSTP
  1362. X    (void) signal (SIGTSTP, sigtstp);
  1363. X#endif
  1364. X}
  1365. END_OF_FILE
  1366.   if test 3264 -ne `wc -c <'login.c'`; then
  1367.     echo shar: \"'login.c'\" unpacked with wrong size!
  1368.   fi
  1369.   # end of 'login.c'
  1370. fi
  1371. if test -f 'passwd.4' -a "${1}" != "-c" ; then 
  1372.   echo shar: Will not clobber existing file \"'passwd.4'\"
  1373. else
  1374.   echo shar: Extracting \"'passwd.4'\" \(2523 characters\)
  1375.   sed "s/^X//" >'passwd.4' <<'END_OF_FILE'
  1376. X.\" Copyright 1989, 1990, John F. Haugh II
  1377. X.\" All rights reserved.
  1378. X.\"
  1379. X.\" Use, duplication, and disclosure prohibited without
  1380. X.\" the express written permission of the author.
  1381. X.\"
  1382. X.\"    @(#)passwd.4    3.1    09:34:24    21 Nov 1990
  1383. X.\"
  1384. X.TH PASSWD 4
  1385. X.SH NAME
  1386. Xpasswd \- The password file
  1387. X.SH DESCRIPTION
  1388. X.I passwd
  1389. Xcontains various pieces of information for each user account.
  1390. XIncluded is
  1391. X.IP "" .5i
  1392. XLogin name
  1393. X.IP "" .5i
  1394. XOptional encrypted password
  1395. X.IP "" .5i
  1396. XNumerical user ID
  1397. X.IP "" .5i
  1398. XNumerical group ID
  1399. X.IP "" .5i
  1400. XUser name or comment field
  1401. X.IP "" .5i
  1402. XUser home directory
  1403. X.IP "" .5i
  1404. XUser command interpreter
  1405. X.PP
  1406. XThe password field may not be filled if shadow passwords
  1407. Xhave been enabled.
  1408. XIf shadow passwords are being used, the encrypted password will
  1409. Xbe found in \fB/etc/shadow\fR.
  1410. XThe encryped password consists of 13 characters from the
  1411. X64 character alphabet
  1412. Xa thru z, A thru Z, 0 thru 9, \. and /.
  1413. XRefer to \fIcrypt(3)\fR for details on how this string is
  1414. Xinterpreted.
  1415. X.PP
  1416. XAn optional password age string may follow the encrypted
  1417. Xpassword, separated by a comma, from the same alphabet
  1418. Xas the password itself.
  1419. XThe first character gives the number of weeks during which the
  1420. Xpassword is valid.
  1421. XThe second character gives the number of weeks which must pass
  1422. Xbefore the user is permitted to change the password.
  1423. XThe last two characters give the week since Jan 1970 when the
  1424. Xpassword was last changed.
  1425. XWhen the number of weeks during which the password is valid
  1426. Xhave passed, the user will be required to provide a new
  1427. Xpassword.
  1428. X.PP
  1429. XThe comment field is used by various system utilities, such as
  1430. X\fIfinger(1)\fR.
  1431. XThree additional values may be present in the comment field.
  1432. XThey are
  1433. X.IP "" .5i
  1434. Xpri= \- set initial value of nice
  1435. X.IP "" .5i
  1436. Xumask= \- set initial value of umask
  1437. X.IP "" .5i
  1438. Xulimit= \- set initial value of ulimit
  1439. X.PP
  1440. XThese fields are separated from each other and from any other
  1441. Xcomment field by a comma.
  1442. X.PP
  1443. XThe home directory field provides the name of the initial
  1444. Xworking directory.
  1445. X\fILogin\fR uses this information to set the value of
  1446. Xthe \fBHOME\fR environmental variable.
  1447. X.PP
  1448. XThe command interpreter field provides the name of the user's
  1449. Xcommand language interpreter, or the name of the initial program
  1450. Xto execute.
  1451. X\fILogin\fR uses this information to set the value of the
  1452. X\fBSHELL\fR environmental variable.
  1453. XIf this field is empty, it defaults to the value \fB/bin/sh\fR.
  1454. X.SH Files
  1455. X/etc/passwd \- user account information
  1456. X.SH See Also
  1457. Xlogin(1),
  1458. Xpasswd(1),
  1459. Xsu(1),
  1460. Xsulogin(1M),
  1461. Xshadow(4),
  1462. Xpwconv(8),
  1463. Xpwunconv(8)
  1464. END_OF_FILE
  1465.   if test 2523 -ne `wc -c <'passwd.4'`; then
  1466.     echo shar: \"'passwd.4'\" unpacked with wrong size!
  1467.   fi
  1468.   # end of 'passwd.4'
  1469. fi
  1470. if test -f 'pwck.1' -a "${1}" != "-c" ; then 
  1471.   echo shar: Will not clobber existing file \"'pwck.1'\"
  1472. else
  1473.   echo shar: Extracting \"'pwck.1'\" \(2738 characters\)
  1474.   sed "s/^X//" >'pwck.1' <<'END_OF_FILE'
  1475. X.\" Copyright 1992, John F. Haugh II
  1476. X.\" All rights reserved.
  1477. X.\"
  1478. X.\" Permission is granted to copy and create derivative works for any
  1479. X.\" non-commercial purpose, provided this copyright notice is preserved
  1480. X.\" in all copies of source code, or included in human readable form
  1481. X.\" and conspicuously displayed on all copies of object code or
  1482. X.\" distribution media.
  1483. X.\"
  1484. X.\" This software is provided on an AS-IS basis and the author makes
  1485. X.\" no warrantee of any kind.
  1486. X.\"
  1487. X.\"    @(#)pwck.1    3.2    17:43:54    01 May 1993
  1488. X.\"
  1489. X.TH PWCK 1
  1490. X.SH NAME
  1491. Xpwck \- verify integrity of password files
  1492. X.SH SYNOPSIS
  1493. X\fBpwck\fR [ \fB-r\fR ] [ \fIpasswd\fR \fIshadow\fR ]
  1494. X.SH DESCRIPTION
  1495. X\fBpwck\fR verifies the integrity of the system authentication information.
  1496. XAll entries in the \fB/etc/passwd\fR and \fB/etc/shadow\fR are checked to
  1497. Xsee that the entry has the proper format and valid data in each field.
  1498. XThe user is prompted to delete entries that are improperly formatted or
  1499. Xwhich have other incorrectable errors.
  1500. X.P
  1501. XChecks are made to verify that each entry has
  1502. X.sp
  1503. X.in +.5i
  1504. X- the correct number of fields
  1505. X.br
  1506. X- a unique user name
  1507. X.br
  1508. X- a valid user and group identifier
  1509. X.br
  1510. X- a valid primary group
  1511. X.br
  1512. X- a valid home directory
  1513. X.br
  1514. X- a valid login shell
  1515. X.in -.5i
  1516. X.sp
  1517. X.P
  1518. XThe checks for correct number of fields and unique user name are fatal.
  1519. XIf the entry has the wrong number of fields, the user will be prompted to
  1520. Xdelete the entire line.
  1521. XIf the user does not answer affirmatively, all further checks are bypassed.
  1522. XAn entry with a duplicated user name is prompted for deletion, but the
  1523. Xremaining checks will still be made.
  1524. XAll other errors are warning and the user is encouraged to run the
  1525. X\fBusermod\fR command to correct the error.
  1526. X.P
  1527. XThe commands which operate on the \fB/etc/passwd\fR file are not able to
  1528. Xalter corrupted or duplicated entries.
  1529. X\fBpwck\fR should be used in those circumstances to remove the offending
  1530. Xentry.
  1531. X.SH OPTIONS
  1532. XBy default, \fBpwck\fR operates on the files \fB/etc/passwd\fR and
  1533. X\fB/etc/shadow\fR.
  1534. XThe user may select alternate files with the \fIpasswd\fR and \fIshadow\fR
  1535. Xparameters.
  1536. XAdditionally, the user may execute the command in read-only mode by
  1537. Xspecifying the \fB-r\fR flag.
  1538. XThis causes all questions regarding changes to be answered \fBno\fR
  1539. Xwithout user intervention.
  1540. X.SH FILES
  1541. X/etc/passwd \- user account information
  1542. X.br
  1543. X/etc/shadow \- encrypted password information
  1544. X.br
  1545. X/etc/group \- group information
  1546. X.SH SEE ALSO
  1547. Xusermod(1), group(4), passwd(4), shadow(4)
  1548. X.SH DIAGNOSTICS
  1549. XThe \fIpwck\fR command exits with the following values:
  1550. X.IP 0 5
  1551. XSuccess
  1552. X.IP 1 5
  1553. XSyntax Error
  1554. X.IP 2 5
  1555. XOne or more bad password entries
  1556. X.IP 3 5
  1557. XCannot open password files
  1558. X.IP 4 5
  1559. XCannot lock password files
  1560. X.IP 5 5
  1561. XCannot update password files
  1562. END_OF_FILE
  1563.   if test 2738 -ne `wc -c <'pwck.1'`; then
  1564.     echo shar: \"'pwck.1'\" unpacked with wrong size!
  1565.   fi
  1566.   # end of 'pwck.1'
  1567. fi
  1568. if test -f 'pwd.h.m4' -a "${1}" != "-c" ; then 
  1569.   echo shar: Will not clobber existing file \"'pwd.h.m4'\"
  1570. else
  1571.   echo shar: Extracting \"'pwd.h.m4'\" \(2897 characters\)
  1572.   sed "s/^X//" >'pwd.h.m4' <<'END_OF_FILE'
  1573. X/*
  1574. X * Copyright 1990, 1991, 1992, John F. Haugh II and Steve Simmons
  1575. X * All rights reserved.
  1576. X *
  1577. X * Permission is granted to copy and create derivative works for any
  1578. X * non-commercial purpose, provided this copyright notice is preserved
  1579. X * in all copies of source code, or included in human readable form
  1580. X * and conspicuously displayed on all copies of object code or
  1581. X * distribution media.
  1582. X *
  1583. X * This software is provided on an AS-IS basis and the author makes
  1584. X * no warrantee of any kind.
  1585. X */
  1586. X
  1587. X/*
  1588. X * Standard definitions for password files.  This is an independant
  1589. X * reimplementation of the definitions used by AT&T, BSD, and POSIX.
  1590. X * It is not derived from any of those sources.  Note that it can be
  1591. X * site-defined to have non-POSIX features as well.  Ideally this file
  1592. X * is simply replaced by the standard system supplied /usr/include/pwd.h
  1593. X * file.
  1594. X *
  1595. X *    @(#)pwd.h.m4    3.4.1.2    08:07:12    19 Jul 1993
  1596. X */
  1597. X
  1598. X#ifndef    PWD_H
  1599. X#define    PWD_H
  1600. X
  1601. X#ifdef    M_XENIX
  1602. Xtypedef int uid_t;
  1603. Xtypedef int gid_t;
  1604. X#endif
  1605. X
  1606. X#if defined(SUN) || defined(SUN4)
  1607. X#include <sys/types.h>
  1608. X#endif
  1609. X
  1610. X#ifdef    SVR4
  1611. X#include <sys/types.h>
  1612. X#ifndef    _POSIX_SOURCE
  1613. X#define    _POSIX_SOURCE
  1614. X#include <limits.h>
  1615. X#undef    _POSIX_SOURCE
  1616. X#else    /* _POSIX_SOURCE */
  1617. X#include <limits.h>
  1618. X#endif    /* !_POSIX_SOURCE */
  1619. X#define NGROUPS NGROUPS_MAX
  1620. X#endif    /* SVR4 */
  1621. X
  1622. Xifdef(`SUN4', `#define    ATT_AGE')
  1623. Xifdef(`SUN4', `#define  ATT_COMMENT')
  1624. Xifdef(`SUN', `#define    BSD_QUOTAS')
  1625. Xifdef(`BSD', `#define    BSD_QUOTAS')
  1626. Xifdef(`USG', `#define    ATT_AGE')
  1627. Xifdef(`USG', `#define    ATT_COMMENT')
  1628. X
  1629. X/*
  1630. X * This is the data structure returned by the getpw* functions.  The
  1631. X * names of the elements and the structure are taken from traditional
  1632. X * usage.
  1633. X */
  1634. X
  1635. Xstruct passwd    {
  1636. X    char    *pw_name ;    /* User login name */
  1637. X    char    *pw_passwd ;    /* Encrypted passwd or dummy field */
  1638. X    uid_t    pw_uid ;    /* User uid number */
  1639. X    gid_t    pw_gid ;    /* User group id number */
  1640. X#ifdef    BSD_QUOTAS
  1641. X    /* Most BSD systems have quotas, most USG ones don't    */
  1642. X    int    pw_quota ;    /* The BSD magic doodah */
  1643. X#endif
  1644. X#ifdef    ATT_AGE
  1645. X    /* Use ATT-style password aging    */
  1646. X    char    *pw_age ;    /* ATT radix-64 encoded data */
  1647. X#endif
  1648. X#ifdef    ATT_COMMENT
  1649. X    /* Provide the unused comment field */
  1650. X    char    *pw_comment;    /* Unused comment field */
  1651. X#endif
  1652. X    char    *pw_gecos ;    /* ASCII user name, other data */
  1653. X    char    *pw_dir ;    /* User home directory */
  1654. X    char    *pw_shell ;    /* User startup shell */
  1655. X} ;
  1656. X
  1657. X#ifdef    ATT_COMMENT
  1658. X/* Provide the unused comment structure */
  1659. Xstruct comment {
  1660. X    char    *c_dept;
  1661. X    char    *c_name;
  1662. X    char    *c_acct;
  1663. X    char    *c_bin;
  1664. X};
  1665. X#endif
  1666. X
  1667. X#if    __STDC__
  1668. X
  1669. Xextern    struct    passwd    *getpwent( void ) ;
  1670. Xextern    struct    passwd    *getpwuid( uid_t user_uid ) ;
  1671. Xextern    struct    passwd    *getpwnam( char *name ) ;
  1672. Xint    setpwent( void );
  1673. Xint    endpwent( void );
  1674. X
  1675. X#else
  1676. X
  1677. Xextern    struct    passwd    *getpwent();
  1678. Xextern    struct    passwd    *getpwuid();
  1679. Xextern    struct    passwd    *getpwnam();
  1680. Xint    setpwent();
  1681. Xint    endpwent();
  1682. X
  1683. X#endif    /* of if __STDC__ */
  1684. X
  1685. X#endif    /* of ifdef PWD_H */
  1686. END_OF_FILE
  1687.   if test 2897 -ne `wc -c <'pwd.h.m4'`; then
  1688.     echo shar: \"'pwd.h.m4'\" unpacked with wrong size!
  1689.   fi
  1690.   # end of 'pwd.h.m4'
  1691. fi
  1692. if test -f 'pwdbm.c' -a "${1}" != "-c" ; then 
  1693.   echo shar: Will not clobber existing file \"'pwdbm.c'\"
  1694. else
  1695.   echo shar: Extracting \"'pwdbm.c'\" \(2514 characters\)
  1696.   sed "s/^X//" >'pwdbm.c' <<'END_OF_FILE'
  1697. X/*
  1698. X * Copyright 1990, 1991, John F. Haugh II
  1699. X * All rights reserved.
  1700. X *
  1701. X * Permission is granted to copy and create derivative works for any
  1702. X * non-commercial purpose, provided this copyright notice is preserved
  1703. X * in all copies of source code, or included in human readable form
  1704. X * and conspicuously displayed on all copies of object code or
  1705. X * distribution media.
  1706. X */
  1707. X
  1708. X#ifndef    lint
  1709. Xstatic    char    sccsid[] = "@(#)pwdbm.c    3.6    12:10:31    28 Dec 1991";
  1710. X#endif
  1711. X
  1712. X#ifdef    BSD
  1713. X#include <strings.h>
  1714. X#define    strchr    index
  1715. X#define    strrchr    rindex
  1716. X#else
  1717. X#include <string.h>
  1718. X#endif
  1719. X#include <stdio.h>
  1720. X#include "pwd.h"
  1721. X#include "config.h"
  1722. X
  1723. X#if defined(DBM) || defined(NDBM) /*{*/
  1724. X
  1725. X#ifdef    DBM
  1726. X#include <dbm.h>
  1727. X#endif
  1728. X#ifdef    NDBM
  1729. X#include <ndbm.h>
  1730. XDBM    *pw_dbm;
  1731. X#endif
  1732. X
  1733. X/*
  1734. X * pw_dbm_update
  1735. X *
  1736. X * Updates the DBM password files, if they exist.
  1737. X */
  1738. X
  1739. Xint
  1740. Xpw_dbm_update (pw)
  1741. Xstruct    passwd    *pw;
  1742. X{
  1743. X    datum    key;
  1744. X    datum    content;
  1745. X    char    data[BUFSIZ];
  1746. X    int    len;
  1747. X    static    int    once;
  1748. X
  1749. X    if (! once) {
  1750. X#ifdef    NDBM
  1751. X        if (! pw_dbm)
  1752. X            setpwent ();
  1753. X#else
  1754. X        setpwent ();
  1755. X#endif
  1756. X        once++;
  1757. X    }
  1758. X#ifdef    DBM
  1759. X    strcpy (data, PWDFILE);
  1760. X    strcat (data, ".pag");
  1761. X    if (access (data, 0))
  1762. X        return 0;
  1763. X#endif
  1764. X#ifdef    NDBM
  1765. X    if (! pw_dbm)
  1766. X        return 0;
  1767. X#endif
  1768. X    len = pw_pack (pw, data);
  1769. X    content.dsize = len;
  1770. X    content.dptr = data;
  1771. X
  1772. X    key.dsize = strlen (pw->pw_name);
  1773. X    key.dptr = pw->pw_name;
  1774. X#ifdef    DBM
  1775. X    if (store (key, content))
  1776. X        return 0;
  1777. X#endif
  1778. X#ifdef    NDBM
  1779. X    if (dbm_store (pw_dbm, key, content, DBM_REPLACE))
  1780. X        return 0;
  1781. X#endif
  1782. X
  1783. X    key.dsize = sizeof pw->pw_uid;
  1784. X    key.dptr = (char *) &pw->pw_uid;
  1785. X#ifdef    DBM
  1786. X    if (store (key, content))
  1787. X        return 0;
  1788. X#endif
  1789. X#ifdef    NDBM
  1790. X    if (dbm_store (pw_dbm, key, content, DBM_REPLACE))
  1791. X        return 0;
  1792. X#endif
  1793. X    return 1;
  1794. X}
  1795. X
  1796. X/*
  1797. X * pw_dbm_remove
  1798. X *
  1799. X * Removes the DBM password entry, if it exists.
  1800. X */
  1801. X
  1802. Xint
  1803. Xpw_dbm_remove (pw)
  1804. Xstruct    passwd    *pw;
  1805. X{
  1806. X    datum    key;
  1807. X    static    int    once;
  1808. X    char    data[BUFSIZ];
  1809. X
  1810. X    if (! once) {
  1811. X#ifdef    NDBM
  1812. X        if (! pw_dbm)
  1813. X            setpwent ();
  1814. X#else
  1815. X        setpwent ();
  1816. X#endif
  1817. X        once++;
  1818. X    }
  1819. X#ifdef    DBM
  1820. X    strcpy (data, PWDFILE);
  1821. X    strcat (data, ".pag");
  1822. X    if (access (data, 0))
  1823. X        return 0;
  1824. X#endif
  1825. X#ifdef    NDBM
  1826. X    if (! pw_dbm)
  1827. X        return 0;
  1828. X#endif
  1829. X    key.dsize = strlen (pw->pw_name);
  1830. X    key.dptr = pw->pw_name;
  1831. X#ifdef    DBM
  1832. X    if (delete (key))
  1833. X        return 0;
  1834. X#endif
  1835. X#ifdef    NDBM
  1836. X    if (dbm_delete (pw_dbm, key))
  1837. X        return 0;
  1838. X#endif
  1839. X    key.dsize = sizeof pw->pw_uid;
  1840. X    key.dptr = (char *) &pw->pw_uid;
  1841. X#ifdef    DBM
  1842. X    if (delete (key))
  1843. X        return 0;
  1844. X#endif
  1845. X#ifdef    NDBM
  1846. X    if (dbm_delete (pw_dbm, key))
  1847. X        return 0;
  1848. X#endif
  1849. X    return 1;
  1850. X}
  1851. X
  1852. X#endif    /*} defined(NDBM) || defined(DBM) */
  1853. END_OF_FILE
  1854.   if test 2514 -ne `wc -c <'pwdbm.c'`; then
  1855.     echo shar: \"'pwdbm.c'\" unpacked with wrong size!
  1856.   fi
  1857.   # end of 'pwdbm.c'
  1858. fi
  1859. if test -f 'pwpack.c' -a "${1}" != "-c" ; then 
  1860.   echo shar: Will not clobber existing file \"'pwpack.c'\"
  1861. else
  1862.   echo shar: Extracting \"'pwpack.c'\" \(3003 characters\)
  1863.   sed "s/^X//" >'pwpack.c' <<'END_OF_FILE'
  1864. X/*
  1865. X * Copyright 1990, 1991, John F. Haugh II
  1866. X * All rights reserved.
  1867. X *
  1868. X * Permission is granted to copy and create derivative works for any
  1869. X * non-commercial purpose, provided this copyright notice is preserved
  1870. X * in all copies of source code, or included in human readable form
  1871. X * and conspicuously displayed on all copies of object code or
  1872. X * distribution media.
  1873. X */
  1874. X
  1875. X#include "config.h"
  1876. X#include <stdio.h>
  1877. X#include "pwd.h"
  1878. X#ifdef    BSD
  1879. X#include <strings.h>
  1880. X#define    strchr    index
  1881. X#define    strrchr    rindex
  1882. X#else
  1883. X#include <string.h>
  1884. X#endif
  1885. X
  1886. X#ifndef    lint
  1887. Xstatic    char    sccsid[] = "@(#)pwpack.c    3.4    11:50:31    28 Dec 1991";
  1888. X#endif
  1889. X
  1890. X/*
  1891. X * pw_pack - convert a (struct pwd) to a packed record
  1892. X */
  1893. X
  1894. Xint
  1895. Xpw_pack (passwd, buf)
  1896. Xstruct    passwd    *passwd;
  1897. Xchar    *buf;
  1898. X{
  1899. X    char    *cp;
  1900. X
  1901. X    cp = buf;
  1902. X    strcpy (cp, passwd->pw_name);
  1903. X    cp += strlen (cp) + 1;
  1904. X
  1905. X    strcpy (cp, passwd->pw_passwd);
  1906. X#ifdef    ATT_AGE
  1907. X    if (passwd->pw_age[0]) {
  1908. X        *cp++ = ',';
  1909. X        strcat (cp, passwd->pw_age);
  1910. X    }
  1911. X#endif
  1912. X    cp += strlen (cp) + 1;
  1913. X
  1914. X    memcpy (cp, (void *) &passwd->pw_uid, sizeof passwd->pw_uid);
  1915. X    cp += sizeof passwd->pw_uid;
  1916. X
  1917. X    memcpy (cp, (void *) &passwd->pw_gid, sizeof passwd->pw_gid);
  1918. X    cp += sizeof passwd->pw_gid;
  1919. X#ifdef    BSD_QUOTAS
  1920. X    memcpy (cp, (void *) &passwd->pw_quota, sizeof passwd->pw_quota);
  1921. X    cp += sizeof passwd->pw_quota;
  1922. X#endif
  1923. X#ifdef    ATT_COMMENT
  1924. X    if (passwd->pw_comment) {
  1925. X        strcpy (cp, passwd->pw_comment);
  1926. X        cp += strlen (cp) + 1;
  1927. X    } else
  1928. X        *cp++ = '\0';
  1929. X#endif
  1930. X    strcpy (cp, passwd->pw_gecos);
  1931. X    cp += strlen (cp) + 1;
  1932. X
  1933. X    strcpy (cp, passwd->pw_dir);
  1934. X    cp += strlen (cp) + 1;
  1935. X
  1936. X    strcpy (cp, passwd->pw_shell);
  1937. X        cp += strlen (cp) + 1;
  1938. X
  1939. X    return cp - buf;
  1940. X}
  1941. X
  1942. X/*
  1943. X * pw_unpack - convert a packed (struct pwd) record to a (struct pwd)
  1944. X */
  1945. X
  1946. Xint
  1947. Xpw_unpack (buf, len, passwd)
  1948. Xchar    *buf;
  1949. Xint    len;
  1950. Xstruct    passwd    *passwd;
  1951. X{
  1952. X    char    *org = buf;
  1953. X    char    *cp;
  1954. X
  1955. X    memset ((void *) passwd, 0, sizeof *passwd);
  1956. X
  1957. X    passwd->pw_name = buf;
  1958. X    buf += strlen (buf) + 1;
  1959. X    if (buf - org > len)
  1960. X        return -1;
  1961. X
  1962. X    passwd->pw_passwd = buf;
  1963. X    buf += strlen (buf) + 1;
  1964. X    if (buf - org > len)
  1965. X        return -1;
  1966. X
  1967. X#ifdef    ATT_AGE
  1968. X    if (cp = strchr (passwd->pw_passwd, ',')) {
  1969. X        *cp++ = '\0';
  1970. X        passwd->pw_age = cp;
  1971. X    } else
  1972. X        passwd->pw_age = "";
  1973. X#endif
  1974. X
  1975. X    memcpy ((void *) &passwd->pw_uid, (void *) buf, sizeof passwd->pw_uid);
  1976. X    buf += sizeof passwd->pw_uid;
  1977. X    if (buf - org > len)
  1978. X        return -1;
  1979. X
  1980. X    memcpy ((void *) &passwd->pw_gid, (void *) buf, sizeof passwd->pw_gid);
  1981. X    buf += sizeof passwd->pw_gid;
  1982. X    if (buf - org > len)
  1983. X        return -1;
  1984. X
  1985. X#ifdef    BSD_QUOTAS
  1986. X    memcpy ((void *) &passwd->pw_quota, (void *) buf,
  1987. X        sizeof passwd->pw_quota);
  1988. X    buf += sizeof passwd->pw_quota;
  1989. X    if (buf - org > len)
  1990. X        return -1;
  1991. X#endif
  1992. X#ifdef    ATT_COMMENT
  1993. X    passwd->pw_comment = buf;
  1994. X    buf += strlen (buf) + 1;
  1995. X    if (buf - org > len)
  1996. X        return -1;
  1997. X#endif
  1998. X    passwd->pw_gecos = buf;
  1999. X    buf += strlen (buf) + 1;
  2000. X    if (buf - org > len)
  2001. X        return -1;
  2002. X
  2003. X    passwd->pw_dir = buf;
  2004. X    buf += strlen (buf) + 1;
  2005. X    if (buf - org > len)
  2006. X        return -1;
  2007. X
  2008. X    passwd->pw_shell = buf;
  2009. X    buf += strlen (buf) + 1;
  2010. X    if (buf - org > len)
  2011. X        return -1;
  2012. X
  2013. X    return 0;
  2014. X}
  2015. END_OF_FILE
  2016.   if test 3003 -ne `wc -c <'pwpack.c'`; then
  2017.     echo shar: \"'pwpack.c'\" unpacked with wrong size!
  2018.   fi
  2019.   # end of 'pwpack.c'
  2020. fi
  2021. if test -f 'pwunconv.c' -a "${1}" != "-c" ; then 
  2022.   echo shar: Will not clobber existing file \"'pwunconv.c'\"
  2023. else
  2024.   echo shar: Extracting \"'pwunconv.c'\" \(3163 characters\)
  2025.   sed "s/^X//" >'pwunconv.c' <<'END_OF_FILE'
  2026. X/*
  2027. X * Copyright 1989, 1990, 1991, John F. Haugh II
  2028. X * All rights reserved.
  2029. X *
  2030. X * Permission is granted to copy and create derivative works for any
  2031. X * non-commercial purpose, provided this copyright notice is preserved
  2032. X * in all copies of source code, or included in human readable form
  2033. X * and conspicuously displayed on all copies of object code or
  2034. X * distribution media.
  2035. X *
  2036. X * pwunconv - restore old password file from shadow password file.
  2037. X *
  2038. X *    Pwunconv copies the password file information from the shadow
  2039. X *    password file, merging entries from an optional existing shadow
  2040. X *    file.
  2041. X *
  2042. X *    The new password file is left in npasswd.  There is no new
  2043. X *    shadow file.  Password aging information is translated where
  2044. X *    possible.
  2045. X */
  2046. X
  2047. X#include "config.h"
  2048. X#include <sys/types.h>
  2049. X#include <stdio.h>
  2050. X#include <fcntl.h>
  2051. X#include "pwd.h"
  2052. X#include "shadow.h"
  2053. X
  2054. X#ifndef    lint
  2055. Xstatic    char    sccsid[] = "@(#)pwunconv.c    3.4    11:59:24    28 Dec 1991";
  2056. X#endif
  2057. X
  2058. X#ifdef    ITI_AGING
  2059. X#define    WEEK    (7L*24L*3600L)
  2060. X#else
  2061. X#define    WEEK    (7)
  2062. X#endif
  2063. X
  2064. Xchar    buf[BUFSIZ];
  2065. Xchar    *l64a ();
  2066. X
  2067. Xint    main ()
  2068. X{
  2069. X    struct    passwd    *pw;
  2070. X    struct    passwd    *sgetpwent ();
  2071. X    FILE    *pwd;
  2072. X    FILE    *npwd;
  2073. X    struct    spwd    *spwd;
  2074. X    int    fd;
  2075. X    char    newage[5];
  2076. X
  2077. X    if (! (pwd = fopen (PWDFILE, "r"))) {
  2078. X        perror (PWDFILE);
  2079. X        return (1);
  2080. X    }
  2081. X    unlink ("npasswd");
  2082. X    if ((fd = open ("npasswd", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 ||
  2083. X            ! (npwd = fdopen (fd, "w"))) {
  2084. X        perror ("npasswd");
  2085. X        return (1);
  2086. X    }
  2087. X    while (fgets (buf, BUFSIZ, pwd) == buf) {
  2088. X        buf[strlen (buf) - 1] = '\0'; /* remove '\n' character */
  2089. X
  2090. X        if (buf[0] == '#') {    /* comment line */
  2091. X            (void) fprintf (npwd, "%s\n", buf);
  2092. X            continue;
  2093. X        }
  2094. X        if (! (pw = sgetpwent (buf))) { /* copy bad lines verbatim */
  2095. X            (void) fprintf (npwd, "%s\n", buf);
  2096. X            continue;
  2097. X        }
  2098. X        setspent ();        /* rewind shadow file */
  2099. X
  2100. X        if (! (spwd = getspnam (pw->pw_name))) {
  2101. X            (void) fprintf (npwd, "%s\n", buf);
  2102. X            continue;
  2103. X        }
  2104. X        pw->pw_passwd = spwd->sp_pwdp;
  2105. X
  2106. X    /*
  2107. X     * Password aging works differently in the two different systems.
  2108. X     * With shadow password files you apparently must have some aging
  2109. X     * information.  The maxweeks or minweeks may not map exactly.
  2110. X     * In pwconv we set max == 10000, which is about 30 years.  Here
  2111. X     * we have to undo that kludge.  So, if maxdays == 10000, no aging
  2112. X     * information is put into the new file.  Otherwise, the days are
  2113. X     * converted to weeks and so on.
  2114. X     */
  2115. X
  2116. X#ifdef    ATT_AGE
  2117. X        if (spwd->sp_max > (63*WEEK) && spwd->sp_max < 10000)
  2118. X            spwd->sp_max = (63*WEEK); /* 10000 is infinity */
  2119. X
  2120. X        if (spwd->sp_min >= 0 && spwd->sp_min <= 63*7 &&
  2121. X                spwd->sp_max >= 0 && spwd->sp_max <= 63*7) {
  2122. X            if (spwd->sp_lstchg == -1)
  2123. X                spwd->sp_lstchg = 0;
  2124. X
  2125. X            spwd->sp_max /= WEEK;    /* turn it into weeks */
  2126. X            spwd->sp_min /= WEEK;
  2127. X            spwd->sp_lstchg /= WEEK;
  2128. X
  2129. X            strncpy (newage, l64a (spwd->sp_lstchg * (64L*64L) +
  2130. X                  spwd->sp_min * (64L) + spwd->sp_max), 5);
  2131. X            pw->pw_age = newage;
  2132. X        } else
  2133. X            pw->pw_age = "";
  2134. X#endif    /* ATT_AGE */
  2135. X        if (putpwent (pw, npwd)) {
  2136. X            perror ("pwunconv: write error");
  2137. X            exit (1);
  2138. X        }
  2139. X    }
  2140. X    endspent ();
  2141. X
  2142. X    if (ferror (npwd)) {
  2143. X        perror ("pwunconv");
  2144. X        (void) unlink ("npasswd");
  2145. X    }
  2146. X    (void) fclose (npwd);
  2147. X    (void) fclose (pwd);
  2148. X    return (0);
  2149. X}
  2150. END_OF_FILE
  2151.   if test 3163 -ne `wc -c <'pwunconv.c'`; then
  2152.     echo shar: \"'pwunconv.c'\" unpacked with wrong size!
  2153.   fi
  2154.   # end of 'pwunconv.c'
  2155. fi
  2156. if test -f 'shell.c' -a "${1}" != "-c" ; then 
  2157.   echo shar: Will not clobber existing file \"'shell.c'\"
  2158. else
  2159.   echo shar: Extracting \"'shell.c'\" \(2532 characters\)
  2160.   sed "s/^X//" >'shell.c' <<'END_OF_FILE'
  2161. X/*
  2162. X * Copyright 1989, 1990, 1991, John F. Haugh II
  2163. X * All rights reserved.
  2164. X *
  2165. X * Use, duplication, and disclosure prohibited without
  2166. X * the express written permission of the author.
  2167. X */
  2168. X
  2169. X#include <stdio.h>
  2170. X#include <errno.h>
  2171. X#ifndef    BSD
  2172. X#include <string.h>
  2173. X#include <memory.h>
  2174. X#else
  2175. X#include <strings.h>
  2176. X#define    strchr    index
  2177. X#define    strrchr    rindex
  2178. X#endif
  2179. X#include "config.h"
  2180. X
  2181. X#ifndef    lint
  2182. Xstatic    char    _sccsid[] = "@(#)shell.c    3.2    07:55:08    06 Feb 1991";
  2183. X#endif
  2184. X
  2185. Xextern    char    *newenvp[];
  2186. X
  2187. X/*
  2188. X * shell - execute the named program
  2189. X *
  2190. X *    shell begins by trying to figure out what argv[0] is going to
  2191. X *    be for the named process.  The user may pass in that argument,
  2192. X *    or it will be the last pathname component of the file with a
  2193. X *    '-' prepended.  The first attempt is to just execute the named
  2194. X *    file.  If the errno comes back "ENOEXEC", the file is assumed
  2195. X *    at first glance to be a shell script.  The first two characters
  2196. X *    must be "#!", in which case "/bin/sh" is executed to process
  2197. X *    the file.  If all that fails, give up in disgust ...
  2198. X */
  2199. X
  2200. Xvoid    shell (file, arg)
  2201. Xchar    *file;
  2202. Xchar    *arg;
  2203. X{
  2204. X    char    arg0[BUFSIZ];
  2205. X    FILE    *fp;
  2206. X    char    *path;
  2207. X    int    err;
  2208. X
  2209. X    if (file == (char *) 0)
  2210. X        exit (1);
  2211. X
  2212. X    /*
  2213. X     * The argv[0]'th entry is usually the path name, but
  2214. X     * for various reasons the invoker may want to override
  2215. X     * that.  So, we determine the 0'th entry only if they
  2216. X     * don't want to tell us what it is themselves.
  2217. X     */
  2218. X
  2219. X    if (arg == (char *) 0) {
  2220. X        if (path = strrchr (file, '/'))
  2221. X            path++;
  2222. X        else
  2223. X            path = file;
  2224. X
  2225. X        (void) strcpy (arg0 + 1, path);
  2226. X        arg0[0] = '-';
  2227. X        arg = arg0;
  2228. X    }
  2229. X#ifndef    NDEBUG
  2230. X    printf ("Executing shell %s\n", file);
  2231. X#endif
  2232. X
  2233. X    /*
  2234. X     * First we try the direct approach.  The system should be
  2235. X     * able to figure out what we are up to without too much
  2236. X     * grief.
  2237. X     */
  2238. X
  2239. X    execle (file, arg, (char *) 0, newenvp);
  2240. X    err = errno;
  2241. X
  2242. X    /*
  2243. X     * It is perfectly OK to have a shell script for a login
  2244. X     * shell, and this code attempts to support that.  It
  2245. X     * relies on the standard shell being able to make sense
  2246. X     * of the "#!" magic number.
  2247. X     */
  2248. X
  2249. X    if (err == ENOEXEC) {
  2250. X        if (fp = fopen (file, "r")) {
  2251. X            if (getc (fp) == '#' && getc (fp) == '!') {
  2252. X                fclose (fp);
  2253. X                execle ("/bin/sh", "sh",
  2254. X                    file, (char *) 0, newenvp);
  2255. X                err = errno;
  2256. X            } else {
  2257. X                fclose (fp);
  2258. X            }
  2259. X        }
  2260. X    }
  2261. X
  2262. X    /*
  2263. X     * Obviously something is really wrong - I can't figure out
  2264. X     * how to execute this stupid shell, so I might as well give
  2265. X     * up in disgust ...
  2266. X     */
  2267. X
  2268. X    sprintf (arg0, "Cannot execute %s", file);
  2269. X    errno = err;
  2270. X    perror (arg0);
  2271. X    exit (err);
  2272. X}
  2273. END_OF_FILE
  2274.   if test 2532 -ne `wc -c <'shell.c'`; then
  2275.     echo shar: \"'shell.c'\" unpacked with wrong size!
  2276.   fi
  2277.   # end of 'shell.c'
  2278. fi
  2279. if test -f 'sppack.c' -a "${1}" != "-c" ; then 
  2280.   echo shar: Will not clobber existing file \"'sppack.c'\"
  2281. else
  2282.   echo shar: Extracting \"'sppack.c'\" \(2190 characters\)
  2283.   sed "s/^X//" >'sppack.c' <<'END_OF_FILE'
  2284. X/*
  2285. X * Copyright 1990, 1991, John F. Haugh II
  2286. X * All rights reserved.
  2287. X *
  2288. X * Permission is granted to copy and create derivative works for any
  2289. X * non-commercial purpose, provided this copyright notice is preserved
  2290. X * in all copies of source code, or included in human readable form
  2291. X * and conspicuously displayed on all copies of object code or
  2292. X * distribution media.
  2293. X */
  2294. X
  2295. X#include <stdio.h>
  2296. X#ifdef    BSD
  2297. X#include <strings.h>
  2298. X#else
  2299. X#include <string.h>
  2300. X#endif
  2301. X
  2302. X#include "shadow.h"
  2303. X
  2304. X#ifndef    lint
  2305. Xstatic    char    sccsid[] = "@(#)sppack.c    3.2    08:46:24    12 Sep 1991";
  2306. X#endif
  2307. X
  2308. Xint    spw_pack (spwd, buf)
  2309. Xstruct    spwd    *spwd;
  2310. Xchar    *buf;
  2311. X{
  2312. X    char    *cp;
  2313. X
  2314. X    cp = buf;
  2315. X    strcpy (cp, spwd->sp_namp);
  2316. X    cp += strlen (cp) + 1;
  2317. X
  2318. X    strcpy (cp, spwd->sp_pwdp);
  2319. X    cp += strlen (cp) + 1;
  2320. X
  2321. X    memcpy (cp, &spwd->sp_min, sizeof spwd->sp_min);
  2322. X    cp += sizeof spwd->sp_min;
  2323. X
  2324. X    memcpy (cp, &spwd->sp_max, sizeof spwd->sp_max);
  2325. X    cp += sizeof spwd->sp_max;
  2326. X
  2327. X    memcpy (cp, &spwd->sp_lstchg, sizeof spwd->sp_lstchg);
  2328. X    cp += sizeof spwd->sp_lstchg;
  2329. X
  2330. X    memcpy (cp, &spwd->sp_warn, sizeof spwd->sp_warn);
  2331. X    cp += sizeof spwd->sp_warn;
  2332. X
  2333. X    memcpy (cp, &spwd->sp_inact, sizeof spwd->sp_inact);
  2334. X    cp += sizeof spwd->sp_inact;
  2335. X
  2336. X    memcpy (cp, &spwd->sp_expire, sizeof spwd->sp_expire);
  2337. X    cp += sizeof spwd->sp_expire;
  2338. X
  2339. X    memcpy (cp, &spwd->sp_flag, sizeof spwd->sp_flag);
  2340. X    cp += sizeof spwd->sp_flag;
  2341. X
  2342. X    return cp - buf;
  2343. X}
  2344. X
  2345. Xint    spw_unpack (buf, len, spwd)
  2346. Xchar    *buf;
  2347. Xint    len;
  2348. Xstruct    spwd    *spwd;
  2349. X{
  2350. X    char    *org = buf;
  2351. X
  2352. X    spwd->sp_namp = buf;
  2353. X    buf += strlen (buf) + 1;
  2354. X
  2355. X    spwd->sp_pwdp = buf;
  2356. X    buf += strlen (buf) + 1;
  2357. X
  2358. X    memcpy (&spwd->sp_min, buf, sizeof spwd->sp_min);
  2359. X    buf += sizeof spwd->sp_min;
  2360. X
  2361. X    memcpy (&spwd->sp_max, buf, sizeof spwd->sp_max);
  2362. X    buf += sizeof spwd->sp_max;
  2363. X
  2364. X    memcpy (&spwd->sp_lstchg, buf, sizeof spwd->sp_lstchg);
  2365. X    buf += sizeof spwd->sp_lstchg;
  2366. X
  2367. X    memcpy (&spwd->sp_warn, buf, sizeof spwd->sp_warn);
  2368. X    buf += sizeof spwd->sp_warn;
  2369. X
  2370. X    memcpy (&spwd->sp_inact, buf, sizeof spwd->sp_inact);
  2371. X    buf += sizeof spwd->sp_inact;
  2372. X
  2373. X    memcpy (&spwd->sp_expire, buf, sizeof spwd->sp_expire);
  2374. X    buf += sizeof spwd->sp_expire;
  2375. X
  2376. X    memcpy (&spwd->sp_flag, buf, sizeof spwd->sp_flag);
  2377. X    buf += sizeof spwd->sp_flag;
  2378. X
  2379. X    if (buf - org > len)
  2380. X        return -1;
  2381. X
  2382. X    return 0;
  2383. X}
  2384. END_OF_FILE
  2385.   if test 2190 -ne `wc -c <'sppack.c'`; then
  2386.     echo shar: \"'sppack.c'\" unpacked with wrong size!
  2387.   fi
  2388.   # end of 'sppack.c'
  2389. fi
  2390. if test -f 'valid.c' -a "${1}" != "-c" ; then 
  2391.   echo shar: Will not clobber existing file \"'valid.c'\"
  2392. else
  2393.   echo shar: Extracting \"'valid.c'\" \(2456 characters\)
  2394.   sed "s/^X//" >'valid.c' <<'END_OF_FILE'
  2395. X/*
  2396. X * Copyright 1989, 1990, 1991, 1993, John F. Haugh II
  2397. X * All rights reserved.
  2398. X *
  2399. X * Permission is granted to copy and create derivative works for any
  2400. X * non-commercial purpose, provided this copyright notice is preserved
  2401. X * in all copies of source code, or included in human readable form
  2402. X * and conspicuously displayed on all copies of object code or
  2403. X * distribution media.
  2404. X *
  2405. X * This software is provided on an AS-IS basis and the author makes
  2406. X * no warrantee of any kind.
  2407. X */
  2408. X
  2409. X#include <sys/types.h>
  2410. X#include <stdio.h>
  2411. X#ifdef    BSD
  2412. X#include <strings.h>
  2413. X#define    strchr    index
  2414. X#define    strrchr    rindex
  2415. X#else
  2416. X#include <string.h>
  2417. X#include <memory.h>
  2418. X#endif
  2419. X#include "config.h"
  2420. X#include "pwd.h"
  2421. X
  2422. X#ifndef    lint
  2423. Xstatic    char    _sccsid[] = "@(#)valid.c    3.5    22:04:54    02 Jun 1993";
  2424. X#endif
  2425. X
  2426. X/*
  2427. X * valid - compare encrypted passwords
  2428. X *
  2429. X *    Valid() compares the DES encrypted password from the password file
  2430. X *    against the password which the user has entered after it has been
  2431. X *    encrypted using the same salt as the original.  Entries which do
  2432. X *    not have a password file entry have a NULL pw_name field and this
  2433. X *    is used to indicate that a dummy salt must be used to encrypt the
  2434. X *    password anyway.
  2435. X */
  2436. X
  2437. Xint
  2438. Xvalid (password, entry)
  2439. Xchar    *password;
  2440. Xstruct    passwd    *entry;
  2441. X{
  2442. X    char    *encrypt;
  2443. X    char    *salt;
  2444. X    char    *pw_encrypt ();
  2445. X
  2446. X    /*
  2447. X     * Start with blank or empty password entries.  Always encrypt
  2448. X     * a password if no such user exists.  Only if the ID exists and
  2449. X     * the password is really empty do you return quickly.  This
  2450. X     * routine is meant to waste CPU time.
  2451. X     */
  2452. X
  2453. X    if (entry->pw_name && ! entry->pw_passwd[0]) {
  2454. X        if (! password[0])
  2455. X            return (1);    /* user entered nothing */
  2456. X        else
  2457. X            return (0);    /* user entered something! */
  2458. X    }
  2459. X
  2460. X    /*
  2461. X     * If there is no entry then we need a salt to use.
  2462. X     */
  2463. X
  2464. X    if (entry->pw_name == (char *) 0 || entry->pw_passwd[0] == '\0')
  2465. X        salt = "xx";
  2466. X    else
  2467. X        salt = entry->pw_passwd;
  2468. X
  2469. X    /*
  2470. X     * Now, perform the encryption using the salt from before on
  2471. X     * the users input.  Since we always encrypt the string, it
  2472. X     * should be very difficult to determine if the user exists by
  2473. X     * looking at execution time.
  2474. X     */
  2475. X
  2476. X    encrypt = pw_encrypt (password, salt);
  2477. X
  2478. X    /*
  2479. X     * One last time we must deal with there being no password file
  2480. X     * entry for the user.  We use the pw_passwd == NULL idiom to
  2481. X     * cause non-existent users to not be validated.
  2482. X     */
  2483. X
  2484. X    if (entry->pw_name && strcmp (encrypt, entry->pw_passwd) == 0)
  2485. X        return (1);
  2486. X    else
  2487. X        return (0);
  2488. X}
  2489. END_OF_FILE
  2490.   if test 2456 -ne `wc -c <'valid.c'`; then
  2491.     echo shar: \"'valid.c'\" unpacked with wrong size!
  2492.   fi
  2493.   # end of 'valid.c'
  2494. fi
  2495. echo shar: End of archive 12 \(of 14\).
  2496. cp /dev/null ark12isdone
  2497. MISSING=""
  2498. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
  2499.     if test ! -f ark${I}isdone ; then
  2500.     MISSING="${MISSING} ${I}"
  2501.     fi
  2502. done
  2503. if test "${MISSING}" = "" ; then
  2504.     echo You have unpacked all 14 archives.
  2505.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2506. else
  2507.     echo You still must unpack the following archives:
  2508.     echo "        " ${MISSING}
  2509. fi
  2510. exit 0
  2511. exit 0 # Just in case...
  2512.