home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume26 / shadow / part09 < prev    next >
Text File  |  1991-11-24  |  56KB  |  2,327 lines

  1. Newsgroups: comp.sources.misc
  2. From: jfh@rpp386.Cactus.ORG (John F Haugh II)
  3. Subject:  v26i062:  shadow - Shadow Password Suite, Part09/11
  4. Message-ID: <1991Nov24.185250.20627@sparky.imd.sterling.com>
  5. X-Md4-Signature: def19317ec34a91d2c7d3e01ef3a2a48
  6. Date: Sun, 24 Nov 1991 18:52:50 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: jfh@rpp386.Cactus.ORG (John F Haugh II)
  10. Posting-number: Volume 26, Issue 62
  11. Archive-name: shadow/part09
  12. Environment: UNIX
  13. Supersedes: shadow-2: Volume 06, Issue 22-24
  14.  
  15. #! /bin/sh
  16. # into a shell via "sh file" or similar.  To overwrite existing files,
  17. # type "sh file -c".
  18. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  19. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  20. # Contents:  config.h dialup.c failure.c getpass.c groups.c gsdbm.c
  21. #   gspack.c id.c login.1 pwdbm.c pwpack.c pwunconv.c scologin.c
  22. #   shadow.3 shell.c usermod.1
  23. # Wrapped by kent@sparky on Sun Nov 24 11:03:43 1991
  24. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  25. echo If this archive is complete, you will see the following message:
  26. echo '          "shar: End of archive 9 (of 11)."'
  27. if test -f 'config.h' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'config.h'\"
  29. else
  30.   echo shar: Extracting \"'config.h'\" \(3169 characters\)
  31.   sed "s/^X//" >'config.h' <<'END_OF_FILE'
  32. X/*
  33. X * Copyright 1989, 1990, 1991, John F. Haugh II
  34. X * All rights reserved.
  35. X *
  36. X * Permission is granted to copy and create derivative works for any
  37. X * non-commercial purpose, provided this copyright notice is preserved
  38. X * in all copies of source code, or included in human readable form
  39. X * and conspicuously displayed on all copies of object code or
  40. X * distribution media.
  41. X */
  42. X
  43. X/*
  44. X * Configuration file for login.
  45. X *
  46. X *    @(#)config.h    3.13    08:27:18    10/31/91
  47. X */
  48. X
  49. X
  50. X/*
  51. X * Pathname to the run-time configuration definitions file.
  52. X */
  53. X
  54. X#define LOGINDEFS "/etc/login.defs"
  55. X
  56. X/*
  57. X * Define SHADOWPWD to use shadow [ unreadable ] password file.
  58. X * Release 3 has a requirement that SHADOWPWD always be defined.
  59. X */
  60. X
  61. X#define    SHADOWPWD
  62. X
  63. X/*
  64. X * Define AUTOSHADOW to have root always copy sp_pwdp to pw_passwd
  65. X * for getpwuid() and getpwnam().  This provides compatibility for
  66. X * privileged applications which are shadow-ignorant.  YOU ARE
  67. X * ENCOURAGED TO NOT USE THIS OPTION UNLESS ABSOLUTELY NECESSARY.
  68. X */
  69. X
  70. X#undef    AUTOSHADOW
  71. X
  72. X/*
  73. X * Define SHADOWGRP to user shadowed group files.  This feature adds
  74. X * the concept of a group administrator.
  75. X */
  76. X
  77. X/* #define    SHADOWGRP /**/
  78. X
  79. X/*
  80. X * Define DOUBLESIZE to use 16 character passwords
  81. X */
  82. X
  83. X#define DOUBLESIZE
  84. X
  85. X/*
  86. X * Define AGING if you want the password aging checks made.
  87. X * Release 3 has a requirement that AGING always be defined.
  88. X */
  89. X
  90. X#define    AGING
  91. X
  92. X/*
  93. X * Pick your version of DBM.  If you define either DBM or NDBM, you must
  94. X * define GETPWENT.  If you define NDBM you must define GETGRENT as well.
  95. X */
  96. X
  97. X/* #define    DBM    /**/
  98. X/* #define    NDBM    /**/
  99. X
  100. X/*
  101. X * Define USE_SYSLOG if you want to have SYSLOG functions included in your code.
  102. X */
  103. X
  104. X#define    USE_SYSLOG
  105. X
  106. X/*
  107. X * Enable RLOGIN to support the "-r" and "-h" options.
  108. X * Also enable UT_HOST if your /etc/utmp provides for a host name.
  109. X */
  110. X
  111. X#define RLOGIN
  112. X#undef UT_HOST
  113. X
  114. X/*
  115. X * Select one of the following
  116. X */
  117. X
  118. X#define DIR_XENIX    /* include <sys/ndir.h>, use (struct direct)    */
  119. X/* #define DIR_BSD    /* include <ndir.h>, use (struct direct)    */
  120. X/* #define DIR_SYSV    /* include <dirent.h>, use (struct dirent)    */
  121. X
  122. X/*
  123. X * Various system environment definitions.
  124. X */
  125. X
  126. X#define    HAVE_ULIMIT    /* Define if your UNIX supports ulimit()    */
  127. X#define    GETPWENT    /* Define if you want my GETPWENT(3) routines    */
  128. X#define    GETGRENT    /* Define if you want my GETGRENT(3) routines    */
  129. X#define    NEED_AL64    /* Define if library does not include a64l()    */
  130. X#define    NEED_MKDIR    /* Define if system does not have mkdir()    */
  131. X#define    NEED_RMDIR    /* Define if system does not have rmdir()    */
  132. X#define    NEED_RENAME    /* Define if system does not have rename()    */
  133. X#define    NEED_STRSTR    /* Define if library does not include strstr()    */
  134. X#define    SIGTYPE    int    /* Type returned by signal()                    */
  135. X
  136. X/*
  137. X * These definitions MUST agree with the values defined in <pwd.h>.
  138. X */
  139. X
  140. X#undef    BSD_QUOTA    /* the pw_quota field exists */
  141. X#define    ATT_AGE        /* the pw_age field exists */
  142. X#define    ATT_COMMENT    /* the pw_comment field exists */
  143. X
  144. X/*
  145. X * Define NDEBUG for production versions
  146. X */
  147. X
  148. X#define    NDEBUG
  149. X
  150. X/*
  151. X * Define PWDFILE and GRPFILE to the names of the password and
  152. X * group files.
  153. X */
  154. X
  155. X#define    PWDFILE    "/etc/passwd"
  156. X#define    GRPFILE    "/etc/group"
  157. END_OF_FILE
  158.   if test 3169 -ne `wc -c <'config.h'`; then
  159.     echo shar: \"'config.h'\" unpacked with wrong size!
  160.   fi
  161.   # end of 'config.h'
  162. fi
  163. if test -f 'dialup.c' -a "${1}" != "-c" ; then 
  164.   echo shar: Will not clobber existing file \"'dialup.c'\"
  165. else
  166.   echo shar: Extracting \"'dialup.c'\" \(2697 characters\)
  167.   sed "s/^X//" >'dialup.c' <<'END_OF_FILE'
  168. X/*
  169. X * Copyright 1989, 1990, 1991, John F. Haugh II
  170. X * All rights reserved.
  171. X *
  172. X * Permission is granted to copy and create derivative works for any
  173. X * non-commercial purpose, provided this copyright notice is preserved
  174. X * in all copies of source code, or included in human readable form
  175. X * and conspicuously displayed on all copies of object code or
  176. X * distribution media.
  177. X */
  178. X
  179. X#include <stdio.h>
  180. X#ifndef    BSD
  181. X#include <string.h>
  182. X#else
  183. X#include <strings.h>
  184. X#define    strchr    index
  185. X#define    strrchr    rindex
  186. X#endif
  187. X#include "dialup.h"
  188. X
  189. X#ifndef    lint
  190. Xstatic    char    sccsid[] = "@(#)dialup.c    3.5    17:31:19    8/4/91";
  191. X#endif
  192. X
  193. Xstatic    FILE    *dialpwd;
  194. X
  195. Xvoid
  196. Xsetduent ()
  197. X{
  198. X    if (dialpwd)
  199. X        rewind (dialpwd);
  200. X    else
  201. X        dialpwd = fopen (DIALPWD, "r");
  202. X}
  203. X
  204. Xvoid
  205. Xendduent ()
  206. X{
  207. X    if (dialpwd)
  208. X        fclose (dialpwd);
  209. X
  210. X    dialpwd = (FILE *) 0;
  211. X}
  212. X
  213. Xstruct dialup *
  214. Xfgetduent (fp)
  215. XFILE    *fp;
  216. X{
  217. X    static    struct    dialup    dialup;    /* static structure to point to */
  218. X    static    char    shell[128];    /* some space for a login shell */
  219. X    static    char    passwd[128];    /* some space for dialup password */
  220. X    char    buf[BUFSIZ];
  221. X    char    *cp;
  222. X    char    *cp2;
  223. X
  224. X    if (! fp)
  225. X        return 0;
  226. X
  227. X    if (! fp || feof (fp))
  228. X        return ((struct dialup *) 0);
  229. X
  230. X    while (fgets (buf, BUFSIZ, fp) == buf && buf[0] == '#')
  231. X        ;
  232. X
  233. X    if (feof (fp))
  234. X        return ((struct dialup *) 0);
  235. X
  236. X    if (cp = strchr (buf, '\n'))
  237. X        *cp = '\0';
  238. X
  239. X    if (! (cp = strchr (buf, ':')))
  240. X        return ((struct dialup *) 0);
  241. X
  242. X    if (cp - buf > sizeof shell)    /* something is fishy ... */
  243. X        return ((struct dialup *) 0);
  244. X
  245. X    *cp++ = '\0';
  246. X    (void) strcpy (shell, buf);
  247. X    shell[cp - buf] = '\0';
  248. X
  249. X    if (cp2 = strchr (cp, ':'))
  250. X        *cp2 = '\0';
  251. X
  252. X    if (strlen (cp) + 1 > sizeof passwd) /* something is REALLY fishy */
  253. X        return ((struct dialup *) 0);
  254. X
  255. X    (void) strcpy (passwd, cp);
  256. X
  257. X    dialup.du_shell = shell;
  258. X    dialup.du_passwd = passwd;
  259. X
  260. X    return (&dialup);
  261. X}
  262. X
  263. Xstruct dialup *
  264. Xgetduent ()
  265. X{
  266. X    if (! dialpwd)
  267. X        setduent ();
  268. X
  269. X    return fgetduent (dialpwd);
  270. X}
  271. X
  272. Xstruct    dialup    *getdushell (shell)
  273. Xchar    *shell;
  274. X{
  275. X    struct    dialup    *dialup;
  276. X
  277. X    while (dialup = getduent ()) {
  278. X        if (strcmp (shell, dialup->du_shell) == 0)
  279. X            return (dialup);
  280. X
  281. X        if (strcmp (dialup->du_shell, "*") == 0)
  282. X            return (dialup);
  283. X    }
  284. X    return ((struct dialup *) 0);
  285. X}
  286. X
  287. Xint    isadialup (tty)
  288. Xchar    *tty;
  289. X{
  290. X    FILE    *fp;
  291. X    char    buf[BUFSIZ];
  292. X    int    dialup = 0;
  293. X
  294. X    if (! (fp = fopen (DIALUPS, "r")))
  295. X        return (0);
  296. X
  297. X    while (fgets (buf, BUFSIZ, fp) == buf) {
  298. X        if (buf[0] == '#')
  299. X            continue;
  300. X
  301. X        buf[strlen (buf) - 1] = '\0';
  302. X
  303. X        if (strcmp (buf, tty) == 0) {
  304. X            dialup = 1;
  305. X            break;
  306. X        }
  307. X    }
  308. X    fclose (fp);
  309. X
  310. X    return (dialup);
  311. X}
  312. X
  313. Xint
  314. Xputduent (dial, fp)
  315. Xstruct    dialup    *dial;
  316. XFILE    *fp;
  317. X{
  318. X    if (! fp || ! dial)
  319. X        return -1;
  320. X
  321. X    if (fprintf (fp, "%s:%s\n", dial->du_shell, dial->du_passwd) == EOF)
  322. X        return -1;
  323. X
  324. X    return 0;
  325. X}
  326. END_OF_FILE
  327.   if test 2697 -ne `wc -c <'dialup.c'`; then
  328.     echo shar: \"'dialup.c'\" unpacked with wrong size!
  329.   fi
  330.   # end of 'dialup.c'
  331. fi
  332. if test -f 'failure.c' -a "${1}" != "-c" ; then 
  333.   echo shar: Will not clobber existing file \"'failure.c'\"
  334. else
  335.   echo shar: Extracting \"'failure.c'\" \(3164 characters\)
  336.   sed "s/^X//" >'failure.c' <<'END_OF_FILE'
  337. X/*
  338. X * Copyright 1989, 1990, 1991, John F. Haugh II
  339. X * All rights reserved.
  340. X *
  341. X * Permission is granted to copy and create derivative works for any
  342. X * non-commercial purpose, provided this copyright notice is preserved
  343. X * in all copies of source code, or included in human readable form
  344. X * and conspicuously displayed on all copies of object code or
  345. X * distribution media.
  346. X */
  347. X
  348. X#include <sys/types.h>
  349. X#include <fcntl.h>
  350. X#include <time.h>
  351. X#ifndef    BSD
  352. X#include <string.h>
  353. X#include <memory.h>
  354. X#else
  355. X#include <strings.h>
  356. X#define    strchr    index
  357. X#define    strrchr    rindex
  358. X#endif
  359. X#include "faillog.h"
  360. X#include "config.h"
  361. X
  362. X#include <utmp.h>
  363. X
  364. X#ifndef    lint
  365. Xstatic    char    _sccsid[] = "@(#)failure.c    3.1    08:26:45    9/17/91";
  366. X#endif
  367. X
  368. X#define    DAY    (24L*3600L)
  369. X#define    YEAR    (365L*DAY)
  370. X#define    NOW    (time ((time_t *) 0))
  371. X
  372. Xextern    struct    tm    *localtime ();
  373. Xextern    char    *asctime ();
  374. Xextern    void    failprint ();
  375. Xextern    char    *getdef_str();
  376. X
  377. X/*
  378. X * failure - make failure entry
  379. X */
  380. X
  381. Xvoid
  382. Xfailure (uid, tty, faillog)
  383. Xint    uid;
  384. Xchar    *tty;
  385. Xstruct    faillog    *faillog;
  386. X{
  387. X    int    fd;
  388. X
  389. X    if ((fd = open (FAILFILE, O_RDWR)) < 0)
  390. X        return;
  391. X
  392. X    lseek (fd, (off_t) (sizeof *faillog) * uid, 0);
  393. X    if (read (fd, (char *) faillog, sizeof *faillog)
  394. X            != sizeof *faillog)
  395. X#ifndef    BSD
  396. X        memset ((void *) faillog, '\0', sizeof *faillog);
  397. X#else
  398. X        bzero ((char *) faillog, sizeof *faillog);
  399. X#endif
  400. X
  401. X    if (faillog->fail_max == 0 || faillog->fail_cnt < faillog->fail_max)
  402. X        faillog->fail_cnt++;
  403. X
  404. X    strncpy (faillog->fail_line, tty, sizeof faillog->fail_line);
  405. X    faillog->fail_time = time ((time_t *) 0);
  406. X
  407. X    lseek (fd, (off_t) (sizeof *faillog) * uid, 0);
  408. X    write (fd, (char *) faillog, sizeof *faillog);
  409. X    close (fd);
  410. X}
  411. X
  412. X/*
  413. X * failcheck - check for failures > allowable
  414. X *
  415. X * failcheck() is called AFTER the password has been validated.
  416. X */
  417. X
  418. Xint
  419. Xfailcheck (uid, faillog, failed)
  420. Xint    uid;
  421. Xstruct    faillog    *faillog;
  422. X{
  423. X    int    fd;
  424. X    int    okay = 1;
  425. X    struct    faillog    fail;
  426. X
  427. X    if ((fd = open (FAILFILE, O_RDWR)) < 0)
  428. X        return (1);
  429. X
  430. X    lseek (fd, (off_t) (sizeof *faillog) * uid, 0);
  431. X    if (read (fd, (char *) faillog, sizeof *faillog) == sizeof *faillog) {
  432. X        if (faillog->fail_max != 0
  433. X                && faillog->fail_cnt >= faillog->fail_max)
  434. X            okay = 0;
  435. X    }
  436. X    if (!failed && okay) {
  437. X        fail = *faillog;
  438. X        fail.fail_cnt = 0;
  439. X
  440. X        lseek (fd, (off_t) sizeof fail * uid, 0);
  441. X        write (fd, (char *) &fail, sizeof fail);
  442. X    }
  443. X    close (fd);
  444. X
  445. X    return (okay);
  446. X}
  447. X
  448. X/*
  449. X * failprint - print line of failure information
  450. X */
  451. X
  452. Xvoid
  453. Xfailprint (fail)
  454. Xstruct    faillog    *fail;
  455. X{
  456. X    struct    tm    *tp;
  457. X    char    *lasttime;
  458. X
  459. X    if (fail->fail_cnt == 0)
  460. X        return;
  461. X
  462. X    tp = localtime (&fail->fail_time);
  463. X    lasttime = asctime (tp);
  464. X    lasttime[24] = '\0';
  465. X
  466. X    if (NOW - fail->fail_time < YEAR)
  467. X        lasttime[19] = '\0';
  468. X    if (NOW - fail->fail_time < DAY)
  469. X        lasttime = lasttime + 11;
  470. X
  471. X    if (*lasttime == ' ')
  472. X        lasttime++;
  473. X
  474. X    printf ("%d %s since last login.  Last was %s on %s.\n",
  475. X        fail->fail_cnt, fail->fail_cnt > 1 ? "failures":"failure",
  476. X        lasttime, fail->fail_line);
  477. X}
  478. X
  479. Xvoid
  480. Xfailtmp (failent)
  481. Xstruct    utmp    *failent;
  482. X{
  483. X    int    fd;
  484. X    char    *ftmp;
  485. X
  486. X    if ((ftmp = getdef_str ("FTMP_FILE")) == 0)
  487. X        return;
  488. X
  489. X    if ((fd = open (ftmp, O_WRONLY|O_APPEND)) == -1)
  490. X        return;
  491. X
  492. X    write (fd, (char *) failent, sizeof *failent);
  493. X    close (fd);
  494. X}
  495. END_OF_FILE
  496.   if test 3164 -ne `wc -c <'failure.c'`; then
  497.     echo shar: \"'failure.c'\" unpacked with wrong size!
  498.   fi
  499.   # end of 'failure.c'
  500. fi
  501. if test -f 'getpass.c' -a "${1}" != "-c" ; then 
  502.   echo shar: Will not clobber existing file \"'getpass.c'\"
  503. else
  504.   echo shar: Extracting \"'getpass.c'\" \(3419 characters\)
  505.   sed "s/^X//" >'getpass.c' <<'END_OF_FILE'
  506. X/*
  507. X * Copyright 1990, 1991, John F. Haugh II
  508. X * All rights reserved.
  509. X *
  510. X * Permission is granted to copy and create derivative works for any
  511. X * non-commercial purpose, provided this copyright notice is preserved
  512. X * in all copies of source code, or included in human readable form
  513. X * and conspicuously displayed on all copies of object code or
  514. X * distribution media.
  515. X */
  516. X
  517. X#include <signal.h>
  518. X#include <stdio.h>
  519. X#include "config.h"
  520. X
  521. X#ifdef    BSD
  522. X#include <sgtty.h>
  523. X#include <strings.h>
  524. X#else
  525. X#include <termio.h>
  526. X#include <string.h>
  527. X#endif
  528. X
  529. X#ifndef    lint
  530. Xstatic    char    sccsid[] = "@(#)getpass.c    3.7    08:27:22    10/31/91";
  531. X#endif
  532. X
  533. X/*
  534. X * limits.h may be kind enough to specify the length of a prompted
  535. X * for password.
  536. X */
  537. X
  538. X#if __STDC__ || _POSIX_SOURCE
  539. X#include <limits.h>
  540. X#endif
  541. X
  542. X/*
  543. X * This is really a giant mess.  On the one hand, it would be nice
  544. X * if PASS_MAX were real big so that DOUBLESIZE isn't needed.  But
  545. X * if it is defined we must honor it because some idiot might use
  546. X * this in a routine expecting some standard behavior.
  547. X */
  548. X
  549. X#ifndef    PASS_MAX
  550. X#ifdef    DOUBLESIZE
  551. X#define    PASS_MAX    16
  552. X#else
  553. X#define    PASS_MAX    8
  554. X#endif
  555. X#endif
  556. X
  557. X#ifdef    BSD
  558. X#define    STTY(fd,termio)    stty(fd, termio)
  559. X#define    GTTY(fd,termio) gtty(fd, termio)
  560. X#define    TERMIO    struct    sgttyb
  561. X#define    INDEX    index
  562. X#else
  563. X#define    STTY(fd,termio) ioctl(fd, TCSETA, termio)
  564. X#define    GTTY(fd,termio) ioctl(fd, TCGETA, termio)
  565. X#define    TERMIO    struct    termio
  566. X#define    INDEX    strchr
  567. X#endif
  568. X
  569. Xstatic    int    sig_caught;
  570. X
  571. Xstatic void
  572. Xsig_catch ()
  573. X{
  574. X    sig_caught = 1;
  575. X}
  576. X
  577. Xchar *
  578. Xgetpass (prompt)
  579. Xchar    *prompt;
  580. X{
  581. X    static    char    input[PASS_MAX+1];
  582. X    char    *return_value = 0;
  583. X    char    *cp;
  584. X    FILE    *fp;
  585. X    int    tty_opened = 0;
  586. X    SIGTYPE    (*old_signal)();
  587. X    TERMIO    new_modes;
  588. X    TERMIO    old_modes;
  589. X
  590. X    /*
  591. X     * set a flag so the SIGINT signal can be re-sent if it
  592. X     * is caught
  593. X     */
  594. X
  595. X    sig_caught = 0;
  596. X
  597. X    /*
  598. X     * if /dev/tty can't be opened, getpass() needs to read
  599. X     * from stdin instead.
  600. X     */
  601. X
  602. X    if ((fp = fopen ("/dev/tty", "r")) == 0) {
  603. X        fp = stdin;
  604. X        setbuf (fp, (char *) 0);
  605. X    } else {
  606. X        tty_opened = 1;
  607. X    }
  608. X
  609. X    /*
  610. X     * the current tty modes must be saved so they can be
  611. X     * restored later on.  echo will be turned off, except
  612. X     * for the newline character (BSD has to punt on this)
  613. X     */
  614. X
  615. X    if (GTTY (fileno (fp), &new_modes))
  616. X        return 0;
  617. X
  618. X    old_modes = new_modes;
  619. X    old_signal = signal (SIGINT, sig_catch);
  620. X
  621. X#ifdef    BSD
  622. X    new_modes.sg_flags &= ~ECHO ;
  623. X#else
  624. X    new_modes.c_lflag &= ~(ECHO|ECHOE|ECHOK);
  625. X    new_modes.c_lflag |= ECHONL;
  626. X#endif
  627. X
  628. X    if (STTY (fileno (fp), &new_modes))
  629. X        goto out;
  630. X
  631. X    /*
  632. X     * the prompt is output, and the response read without
  633. X     * echoing.  the trailing newline must be removed.  if
  634. X     * the fgets() returns an error, a NULL pointer is
  635. X     * returned.
  636. X     */
  637. X
  638. X    if (fputs (prompt, stdout) == EOF)
  639. X        goto out;
  640. X
  641. X    (void) fflush (stdout);
  642. X
  643. X    if (fgets (input, sizeof input, fp) == input) {
  644. X        if (cp = INDEX (input, '\n'))
  645. X            *cp = '\0';
  646. X        else
  647. X            input[sizeof input - 1] = '\0';
  648. X
  649. X        return_value = input;
  650. X#ifdef    BSD
  651. X        putc ('\n', stdout);
  652. X#endif
  653. X    }
  654. Xout:
  655. X    /*
  656. X     * the old SIGINT handler is restored after the tty
  657. X     * modes.  then /dev/tty is closed if it was opened in
  658. X     * the beginning.  finally, if a signal was caught it
  659. X     * is sent to this process for normal processing.
  660. X     */
  661. X
  662. X    if (STTY (fileno (fp), &old_modes))
  663. X        return_value = 0;
  664. X
  665. X    (void) signal (SIGINT, old_signal);
  666. X
  667. X    if (tty_opened)
  668. X        (void) fclose (fp);
  669. X
  670. X    if (sig_caught) {
  671. X        kill (getpid (), SIGINT);
  672. X        return_value = 0;
  673. X    }
  674. X    return return_value;
  675. X}
  676. END_OF_FILE
  677.   if test 3419 -ne `wc -c <'getpass.c'`; then
  678.     echo shar: \"'getpass.c'\" unpacked with wrong size!
  679.   fi
  680.   # end of 'getpass.c'
  681. fi
  682. if test -f 'groups.c' -a "${1}" != "-c" ; then 
  683.   echo shar: Will not clobber existing file \"'groups.c'\"
  684. else
  685.   echo shar: Extracting \"'groups.c'\" \(2559 characters\)
  686.   sed "s/^X//" >'groups.c' <<'END_OF_FILE'
  687. X/*
  688. X * Copyright 1991, John F. Haugh II
  689. X * All rights reserved.
  690. X *
  691. X * Permission is granted to copy and create derivative works for any
  692. X * non-commercial purpose, provided this copyright notice is preserved
  693. X * in all copies of source code, or included in human readable form
  694. X * and conspicuously displayed on all copies of object code or
  695. X * distribution media.
  696. X */
  697. X
  698. Xstatic    char    sccsid[] = "@(#)groups.c    3.1    08:50:47    11/3/91";
  699. X
  700. X#include "stdio.h"
  701. X#include "pwd.h"
  702. X#include "grp.h"
  703. X
  704. X/*
  705. X * print_groups - print the groups which the named user is a member of
  706. X *
  707. X *    print_groups() scans the groups file for the list of groups
  708. X *    which the user is listed as being a member of.
  709. X */
  710. X
  711. Xprint_groups (member)
  712. Xchar    *member;
  713. X{
  714. X    int    i, groups = 0;
  715. X    struct    group    *grp;
  716. X    struct    group    *getgrent();
  717. X
  718. X    setgrent ();
  719. X
  720. X    while (grp = getgrent ()) {
  721. X        for (i = 0;grp->gr_mem[i];i++) {
  722. X            if (strcmp (grp->gr_mem[i], member) == 0) {
  723. X                if (groups++)
  724. X                    putchar (' ');
  725. X
  726. X                printf ("%s", grp->gr_name);
  727. X            }
  728. X        }
  729. X    }
  730. X    if (groups)
  731. X        putchar ('\n');
  732. X}
  733. X
  734. X/*
  735. X * groups - print out the groups a process is a member of
  736. X */
  737. X
  738. Xmain (argc, argv)
  739. Xint    argc;
  740. Xchar    **argv;
  741. X{
  742. X    int    ngroups;
  743. X#if NGROUPS > 0
  744. X#if NGROUPS > 100
  745. X    gid_t    *groups;
  746. X#else
  747. X    gid_t    groups[NGROUPS];
  748. X#endif
  749. X    int    i;
  750. X#else
  751. X    char    *logname;
  752. X#endif
  753. X    struct    group    *gr;
  754. X    struct    group    *getgrgid();
  755. X
  756. X    if (argc == 1) {
  757. X
  758. X        /*
  759. X         * Called with no arguments - give the group set
  760. X         * for the current user.
  761. X         */
  762. X
  763. X#if NGROUPS > 0
  764. X        /*
  765. X         * This system supports concurrent group sets, so
  766. X         * I can ask the system to tell me which groups are
  767. X         * currently set for this process.
  768. X         */
  769. X
  770. X        ngroups = getgroups (0, 0);
  771. X#if NGROUPS > 100
  772. X        groups = (gid_t *) malloc (ngroups * sizeof (int *));
  773. X#endif
  774. X        getgroups (ngroups, groups);
  775. X
  776. X        /*
  777. X         * Print out the name of every group in the current
  778. X         * group set.  Unknown groups are printed as their
  779. X         * decimal group ID values.
  780. X         */
  781. X
  782. X        for (i = 0;i < ngroups;i++) {
  783. X            if (i)
  784. X                putchar (' ');
  785. X
  786. X            if (gr = getgrgid (groups[i]))
  787. X                printf ("%s", gr->gr_name);
  788. X            else
  789. X                printf ("%d", groups[i]);
  790. X        }
  791. X        putchar ('\n');
  792. X#else
  793. X        /*
  794. X         * This system does not have the getgroups() system
  795. X         * call, so I must check the groups file directly.
  796. X         */
  797. X
  798. X        if (logname = getlogin ())
  799. X            print_groups (logname);
  800. X        else
  801. X            exit (1);
  802. X#endif
  803. X    } else {
  804. X
  805. X        /*
  806. X         * The invoker wanted to know about some other
  807. X         * user.  Use that name to look up the groups instead.
  808. X         */
  809. X
  810. X        if (getpwnam (argv[1]) == 0) {
  811. X            fprintf (stderr, "unknown user %s\n", argv[1]);
  812. X            exit (1);
  813. X        }
  814. X        print_groups (argv[1]);
  815. X    }
  816. X    exit (0);
  817. X}
  818. END_OF_FILE
  819.   if test 2559 -ne `wc -c <'groups.c'`; then
  820.     echo shar: \"'groups.c'\" unpacked with wrong size!
  821.   fi
  822.   # end of 'groups.c'
  823. fi
  824. if test -f 'gsdbm.c' -a "${1}" != "-c" ; then 
  825.   echo shar: Will not clobber existing file \"'gsdbm.c'\"
  826. else
  827.   echo shar: Extracting \"'gsdbm.c'\" \(2700 characters\)
  828.   sed "s/^X//" >'gsdbm.c' <<'END_OF_FILE'
  829. X/*
  830. X * Copyright 1990, 1991, John F. Haugh II
  831. X * All rights reserved.
  832. X *
  833. X * Permission is granted to copy and create derivative works for any
  834. X * non-commercial purpose, provided this copyright notice is preserved
  835. X * in all copies of source code, or included in human readable form
  836. X * and conspicuously displayed on all copies of object code or
  837. X * distribution media.
  838. X */
  839. X
  840. X#ifndef    lint
  841. Xstatic    char    sccsid[] = "@(#)gsdbm.c    3.5    08:45:49    9/12/91";
  842. X#endif
  843. X
  844. X#include <string.h>
  845. X#include <stdio.h>
  846. X#include "shadow.h"
  847. X#include "config.h"
  848. X
  849. X#ifdef    NDBM
  850. X#include <ndbm.h>
  851. XDBM    *sgr_dbm;
  852. X
  853. X#define    GRP_FRAG    256
  854. X
  855. X/*
  856. X * sgr_dbm_update
  857. X *
  858. X * Updates the DBM password files, if they exist.
  859. X */
  860. X
  861. Xint
  862. Xsgr_dbm_update (sgr)
  863. Xstruct    sgrp    *sgr;
  864. X{
  865. X    datum    key;
  866. X    datum    content;
  867. X    char    data[BUFSIZ*8];
  868. X    char    sgrpkey[60];
  869. X    char    *cp;
  870. X    int    len;
  871. X    int    i;
  872. X    int    cnt;
  873. X    static    int    once;
  874. X
  875. X    if (! once) {
  876. X        if (! sgr_dbm)
  877. X            setsgent ();
  878. X
  879. X        once++;
  880. X    }
  881. X    if (! sgr_dbm)
  882. X        return 0;
  883. X
  884. X    len = sgr_pack (sgr, data);
  885. X
  886. X    if (len <= GRP_FRAG) {
  887. X        content.dsize = len;
  888. X        content.dptr = data;
  889. X
  890. X        key.dsize = strlen (sgr->sg_name);
  891. X        key.dptr = sgr->sg_name;
  892. X        if (dbm_store (sgr_dbm, key, content, DBM_REPLACE))
  893. X            return 0;
  894. X    } else {
  895. X        content.dsize = sizeof cnt;
  896. X        content.dptr = (char *) &cnt;
  897. X        cnt = (len + (GRP_FRAG-1)) / GRP_FRAG;
  898. X
  899. X        key.dsize = strlen (sgr->sg_name);
  900. X        key.dptr = sgr->sg_name;
  901. X        if (dbm_store (sgr_dbm, key, content, DBM_REPLACE))
  902. X            return 0;
  903. X
  904. X        for (cp = data, i = 0;i < cnt;i++) {
  905. X            content.dsize = len > GRP_FRAG ? GRP_FRAG:len;
  906. X            len -= content.dsize;
  907. X            content.dptr = cp;
  908. X            cp += content.dsize;
  909. X
  910. X            key.dsize = sizeof i + strlen (sgr->sg_name);
  911. X            key.dptr = sgrpkey;
  912. X            memcpy (sgrpkey, (char *) &i, sizeof i);
  913. X            strcpy (sgrpkey + sizeof i, sgr->sg_name);
  914. X            if (dbm_store (sgr_dbm, key, content, DBM_REPLACE))
  915. X                return 0;
  916. X        }
  917. X    }
  918. X    return 1;
  919. X}
  920. X
  921. X/*
  922. X * sgr_dbm_remove
  923. X *
  924. X * Deletes the DBM shadow group file entries, if they exist.
  925. X */
  926. X
  927. Xint
  928. Xsgr_dbm_remove (name)
  929. Xchar    *name;
  930. X{
  931. X    datum    key;
  932. X    datum    content;
  933. X    char    grpkey[60];
  934. X    int    i;
  935. X    int    cnt;
  936. X    int    errors = 0;
  937. X    static    int    once;
  938. X
  939. X    if (! once) {
  940. X        if (! sgr_dbm)
  941. X            setsgent ();
  942. X
  943. X        once++;
  944. X    }
  945. X    if (! sgr_dbm)
  946. X        return 0;
  947. X
  948. X    key.dsize = strlen (name);
  949. X    key.dptr = name;
  950. X    content = dbm_fetch (sgr_dbm, key);
  951. X    if (content.dptr == 0)
  952. X        ++errors;
  953. X    else {
  954. X        if (content.dsize == sizeof (int)) {
  955. X            memcpy ((char *) &cnt, content.dptr, sizeof cnt);
  956. X
  957. X            for (i = 0;i < cnt;i++) {
  958. X                key.dsize = sizeof i + strlen (name);
  959. X                key.dptr = grpkey;
  960. X                memcpy (grpkey, (char *) &i, sizeof i);
  961. X                strcpy (grpkey + sizeof i, name);
  962. X                if (dbm_delete (sgr_dbm, key))
  963. X                    ++errors;
  964. X            }
  965. X        } else {
  966. X            if (dbm_delete (sgr_dbm, key))
  967. X                ++errors;
  968. X        }
  969. X    }
  970. X    return errors ? 0:1;
  971. X}
  972. X#endif
  973. END_OF_FILE
  974.   if test 2700 -ne `wc -c <'gsdbm.c'`; then
  975.     echo shar: \"'gsdbm.c'\" unpacked with wrong size!
  976.   fi
  977.   # end of 'gsdbm.c'
  978. fi
  979. if test -f 'gspack.c' -a "${1}" != "-c" ; then 
  980.   echo shar: Will not clobber existing file \"'gspack.c'\"
  981. else
  982.   echo shar: Extracting \"'gspack.c'\" \(2890 characters\)
  983.   sed "s/^X//" >'gspack.c' <<'END_OF_FILE'
  984. X/*
  985. X * Copyright 1990, John F. Haugh II
  986. X * All rights reserved.
  987. X *
  988. X * Permission is granted to copy and create derivative works for any
  989. X * non-commercial purpose, provided this copyright notice is preserved
  990. X * in all copies of source code, or included in human readable form
  991. X * and conspicuously displayed on all copies of object code or
  992. X * distribution media.
  993. X */
  994. X
  995. X#include <stdio.h>
  996. X#include "shadow.h"
  997. X#ifdef    BSD
  998. X#include <strings.h>
  999. X#else
  1000. X#include <string.h>
  1001. X#endif
  1002. X
  1003. X#ifndef    lint
  1004. Xstatic    char    sccsid[] = "@(#)gspack.c    3.1    09:13:50    12/13/90";
  1005. X#endif
  1006. X
  1007. X/*
  1008. X * sgr_pack - convert a shadow group structure to a packed
  1009. X *          shadow group record
  1010. X *
  1011. X *    sgr_pack takes the shadow group structure and packs
  1012. X *    the components in a record.  this record will be
  1013. X *    unpacked later by sgr_unpack.
  1014. X */
  1015. X
  1016. Xint
  1017. Xsgr_pack (sgrp, buf)
  1018. Xstruct    sgrp    *sgrp;
  1019. Xchar    *buf;
  1020. X{
  1021. X    char    *cp;
  1022. X    int    i;
  1023. X
  1024. X    /*
  1025. X     * The name and password are both easy - append each string
  1026. X     * to the buffer.  These are always the first two strings
  1027. X     * in a record.
  1028. X     */
  1029. X
  1030. X    cp = buf;
  1031. X    strcpy (cp, sgrp->sg_name);
  1032. X    cp += strlen (cp) + 1;
  1033. X
  1034. X    strcpy (cp, sgrp->sg_passwd);
  1035. X    cp += strlen (cp) + 1;
  1036. X
  1037. X    /*
  1038. X     * The arrays of administrators and members are slightly
  1039. X     * harder.  Each element is appended as a string, with a
  1040. X     * final '\0' appended to serve as a blank string.  The
  1041. X     * number of elements is not known in advance, so the
  1042. X     * entire collection of administrators must be scanned to
  1043. X     * find the start of the members.
  1044. X     */
  1045. X
  1046. X    for (i = 0;sgrp->sg_adm[i];i++) {
  1047. X        strcpy (cp, sgrp->sg_adm[i]);
  1048. X        cp += strlen (cp) + 1;
  1049. X    }
  1050. X    *cp++ = '\0';
  1051. X
  1052. X    for (i = 0;sgrp->sg_mem[i];i++) {
  1053. X        strcpy (cp, sgrp->sg_mem[i]);
  1054. X        cp += strlen (cp) + 1;
  1055. X    }
  1056. X    *cp++ = '\0';
  1057. X
  1058. X    return cp - buf;
  1059. X}
  1060. X
  1061. X/*
  1062. X * sgr_unpack - convert a packed shadow group record to an
  1063. X *            unpacked record
  1064. X *
  1065. X *    sgr_unpack converts a record which was packed by sgr_pack
  1066. X *    into the normal shadow group structure format.
  1067. X */
  1068. X
  1069. Xint
  1070. Xsgr_unpack (buf, len, sgrp)
  1071. Xchar    *buf;
  1072. Xint    len;
  1073. Xstruct    sgrp    *sgrp;
  1074. X{
  1075. X    char    *org = buf;
  1076. X    int    i;
  1077. X
  1078. X    /*
  1079. X     * The name and password are both easy - they are the first
  1080. X     * two strings in the record.
  1081. X     */
  1082. X
  1083. X    sgrp->sg_name = buf;
  1084. X    buf += strlen (buf) + 1;
  1085. X    if (buf - org > len)
  1086. X        return -1;
  1087. X
  1088. X    sgrp->sg_passwd = buf;
  1089. X    buf += strlen (buf) + 1;
  1090. X    if (buf - org > len)
  1091. X        return -1;
  1092. X
  1093. X    /*
  1094. X     * The administrators and members are slightly more difficult.
  1095. X     * The arrays are lists of strings.  Each list is terminated
  1096. X     * by a string of length zero.  This string is detected by
  1097. X     * looking for an initial character of '\0'.
  1098. X     */
  1099. X
  1100. X    for (i = 0;*buf && i < 1024;i++) {
  1101. X        sgrp->sg_adm[i] = buf;
  1102. X        buf += strlen (buf) + 1;
  1103. X
  1104. X        if (buf - org > len)
  1105. X            return -1;
  1106. X    }
  1107. X    sgrp->sg_adm[i] = (char *) 0;
  1108. X    if (! *buf)
  1109. X        buf++;
  1110. X
  1111. X    for (i = 0;*buf && i < 1024;i++) {
  1112. X        sgrp->sg_mem[i] = buf;
  1113. X        buf += strlen (buf) + 1;
  1114. X
  1115. X        if (buf - org > len)
  1116. X            return -1;
  1117. X    }
  1118. X    sgrp->sg_mem[i] = (char *) 0;
  1119. X
  1120. X    return 0;
  1121. X}
  1122. END_OF_FILE
  1123.   if test 2890 -ne `wc -c <'gspack.c'`; then
  1124.     echo shar: \"'gspack.c'\" unpacked with wrong size!
  1125.   fi
  1126.   # end of 'gspack.c'
  1127. fi
  1128. if test -f 'id.c' -a "${1}" != "-c" ; then 
  1129.   echo shar: Will not clobber existing file \"'id.c'\"
  1130. else
  1131.   echo shar: Extracting \"'id.c'\" \(3225 characters\)
  1132.   sed "s/^X//" >'id.c' <<'END_OF_FILE'
  1133. X/*
  1134. X * Copyright 1991, John F. Haugh II
  1135. X * All rights reserved.
  1136. X *
  1137. X * Permission is granted to copy and create derivative works for any
  1138. X * non-commercial purpose, provided this copyright notice is preserved
  1139. X * in all copies of source code, or included in human readable form
  1140. X * and conspicuously displayed on all copies of object code or
  1141. X * distribution media.
  1142. X */
  1143. X
  1144. X/*
  1145. X * id - print current process user identification information
  1146. X *
  1147. X *    Print the current process identifiers.  This includes the
  1148. X *    UID, GID, effective-UID and effective-GID.  Optionally print
  1149. X *    the concurrent group set if the current system supports it.
  1150. X */
  1151. X
  1152. X#include <sys/types.h>
  1153. X#include <stdio.h>
  1154. X#include <grp.h>
  1155. X#include "pwd.h"
  1156. X
  1157. X#ifndef    lint
  1158. Xstatic    char    sccsid[] = "@(#)id.c    3.4    08:43:37    9/12/91";
  1159. X#endif
  1160. X
  1161. Xusage ()
  1162. X{
  1163. X#if NGROUPS > 0
  1164. X    fprintf (stderr, "usage: id [ -a ]\n");
  1165. X#else
  1166. X    fprintf (stderr, "usage: id\n");
  1167. X#endif
  1168. X    exit (1);
  1169. X}
  1170. X
  1171. X/*ARGSUSED*/
  1172. Xmain (argc, argv)
  1173. Xint    argc;
  1174. Xchar    **argv;
  1175. X{
  1176. X    int    id;
  1177. X#if NGROUPS > 0
  1178. X#if NGROUPS > 100
  1179. X    int    *groups;
  1180. X#else
  1181. X    int    groups[NGROUPS];
  1182. X#endif
  1183. X    int    ngroups;
  1184. X    int    aflg = 0;
  1185. X#endif
  1186. X    struct    passwd    *pw,
  1187. X            *getpwuid();
  1188. X    struct    group    *gr,
  1189. X            *getgrgid();
  1190. X
  1191. X#if NGROUPS > 0
  1192. X    /*
  1193. X     * See if the -a flag has been given to print out the
  1194. X     * concurrent group set.
  1195. X     */
  1196. X
  1197. X    if (argc > 1) {
  1198. X        if (argc > 2 || strcmp (argv[1], "-a"))
  1199. X            usage ();
  1200. X        else
  1201. X            aflg = 1;
  1202. X    }
  1203. X#else
  1204. X    if (argc > 1)
  1205. X        usage ();
  1206. X#endif
  1207. X
  1208. X    /*
  1209. X     * Print out the real user ID and group ID.  If the user or
  1210. X     * group does not exist, just give the numerical value.
  1211. X     */
  1212. X
  1213. X    if (pw = getpwuid (id = getuid ()))
  1214. X        printf ("uid=%d(%s)", id, pw->pw_name);
  1215. X    else
  1216. X        printf ("uid=%d", id);
  1217. X
  1218. X    if (gr = getgrgid (id = getgid ()))
  1219. X        printf (" gid=%d(%s)", id, gr->gr_name);
  1220. X    else
  1221. X        printf (" gid=%d", id);
  1222. X
  1223. X    /*
  1224. X     * Print out the effective user ID and group ID if they are
  1225. X     * different from the real values.
  1226. X     */
  1227. X
  1228. X    if (getuid () != geteuid ()) {
  1229. X        if (pw = getpwuid (id = geteuid ()))
  1230. X            printf (" euid=%d(%s)", id, pw->pw_name);
  1231. X        else
  1232. X            printf (" euid=%d", id);
  1233. X    }
  1234. X    if (getgid () != getegid ()) {
  1235. X        if (gr = getgrgid (id = getegid ()))
  1236. X            printf (" egid=%d(%s)", id, gr->gr_name);
  1237. X        else
  1238. X            printf (" egid=%d", id);
  1239. X    }
  1240. X#if NGROUPS > 0
  1241. X
  1242. X    /*
  1243. X     * Print out the concurrent group set if the user has requested
  1244. X     * it.  The group numbers will be printed followed by their
  1245. X     * names.
  1246. X     */
  1247. X
  1248. X    if (aflg && (ngroups = getgroups (0, 0)) != -1) {
  1249. X
  1250. X#if NGROUPS > 100
  1251. X        /*
  1252. X         * The size of the group set is determined so an array
  1253. X         * large enough to hold it can be allocated.
  1254. X         */
  1255. X
  1256. X        if (groups = (int *) malloc (ngroups * sizeof *groups)) {
  1257. X            putchar ('\n');
  1258. X            perror ("out of memory");
  1259. X            exit (1);
  1260. X        }
  1261. X#endif
  1262. X        /*
  1263. X         * Start off the group message.  It will be of the format
  1264. X         *
  1265. X         *    groups=###(aaa),###(aaa),###(aaa)
  1266. X         *
  1267. X         * where "###" is a numerical value and "aaa" is the
  1268. X         * corresponding name for each respective numerical value.
  1269. X         */
  1270. X
  1271. X        getgroups (ngroups, groups);
  1272. X        printf (" groups=");
  1273. X        for (i = 0;i < ngroups;i++) {
  1274. X            if (i)
  1275. X                putchar (',');
  1276. X
  1277. X            if (gr = getgrgid (groups[i]))
  1278. X                printf ("%d(%s)", groups[i], gr->gr_name);
  1279. X            else
  1280. X                printf ("%d", groups[i]);
  1281. X        }
  1282. X    }
  1283. X#endif
  1284. X
  1285. X    /*
  1286. X     * Finish off the line.
  1287. X     */
  1288. X
  1289. X    putchar ('\n');
  1290. X    exit (0);
  1291. X    /*NOTREACHED*/
  1292. X}
  1293. END_OF_FILE
  1294.   if test 3225 -ne `wc -c <'id.c'`; then
  1295.     echo shar: \"'id.c'\" unpacked with wrong size!
  1296.   fi
  1297.   # end of 'id.c'
  1298. fi
  1299. if test -f 'login.1' -a "${1}" != "-c" ; then 
  1300.   echo shar: Will not clobber existing file \"'login.1'\"
  1301. else
  1302.   echo shar: Extracting \"'login.1'\" \(3344 characters\)
  1303.   sed "s/^X//" >'login.1' <<'END_OF_FILE'
  1304. X.\" Copyright 1989, 1990, John F. Haugh II
  1305. X.\" All rights reserved.
  1306. X.\"
  1307. X.\" Use, duplication, and disclosure prohibited without
  1308. X.\" the express written permission of the author.
  1309. X.\"
  1310. X.\"    @(#)login.1    3.1    09:34:21    11/21/90
  1311. X.\"
  1312. X.TH LOGIN 1
  1313. X.SH NAME
  1314. Xlogin \- Begin session on the system
  1315. X.SH SYNOPSIS
  1316. X.B login
  1317. X[ username [ environmental-variables ] ]
  1318. X.SH DESCRIPTION
  1319. X.I login
  1320. Xis used to establish a new session with the system.
  1321. XIt is normally invoked automatically by responding to the
  1322. X.B login:
  1323. Xprompt on the user\'s terminal.
  1324. X.I login
  1325. Xmay be special to the shell and may not be invoked as a sub-process.
  1326. XTypically,
  1327. X.I login
  1328. Xis treated by the shell as \fBexec login\fR which causes the user
  1329. Xto exit from the current shell.
  1330. XAttempting to execute \fIlogin\fR from any shell but the login shell
  1331. Xwill produce an error message.
  1332. X.PP
  1333. XWhen invoked from the \fBlogin:\fR prompt, the user may enter
  1334. Xenvironmental variables after the username.
  1335. XThese variables are entered in the form \fBNAME=VALUE\fR.
  1336. XNot all variables may be set in the fashion, notably \fBPATH\fR,
  1337. X\fBHOME\fR and \fBSHELL\fR.
  1338. XAdditionally, \fBIFS\fR may be inhibited if the user\'s login
  1339. Xshell is \fB/bin/sh\fR.
  1340. X.PP
  1341. XThe user is then prompted for a password, where appropriate.
  1342. XEchoing is disabled to prevent revealing the password.
  1343. XOnly a small number of password failures are permitted before
  1344. X\fIlogin\fR exits and the communications link is severed.
  1345. X.PP
  1346. XIf password aging has been enabled for your account, you may be
  1347. Xprompted for a new password before proceeding.
  1348. XYou will be forced to provide your old password and the new
  1349. Xpassword before continuing.
  1350. XPlease refer to \fIpasswd(1)\fR for more information.
  1351. X.PP
  1352. XAfter a successful login,
  1353. Xyou will be informed of any system messages and the presence
  1354. Xof mail.
  1355. XYou may turn off the printing of the system message file,
  1356. X\fI/etc/motd\fR, by creating a zero-length file \fI.hushlogin\fR
  1357. Xin your login directory.
  1358. XThe mail message will be one of "\fIYou have new mail.\fR",
  1359. X"\fIYou have mail.\fR", or "\fINo Mail.\fR" according to
  1360. Xthe condition of your mailbox.
  1361. X.PP
  1362. XYour user and group ID will be set according to their values in
  1363. Xthe \fI/etc/passwd\fR file.
  1364. XThe value for \fB$HOME\fR, \fB$SHELL\fR, \fB$PATH\fR, \fB$LOGNAME\fR,
  1365. Xand \fB$MAIL\fR are set according to the appropriate fields in the
  1366. Xpassword entry.
  1367. XUlimit, umask and nice values may also be set according to
  1368. Xentries in the GECOS field.
  1369. X.PP
  1370. XOn some installations, the environmental variable \fB$TERM\fR will be
  1371. Xinitialize to the terminal type on your tty line, as specified in
  1372. X\fI/etc/ttytype\fR.
  1373. X.PP
  1374. XAn initialization script for your command interpreter may also be
  1375. Xexecuted.
  1376. XPlease see the appropriate manual section for more information on
  1377. Xthis function.
  1378. X.SH CAVEATS
  1379. X.PP
  1380. XThis version of \fIlogin\fR has many compilation options, only some of which
  1381. Xmay be in use at any particular site.
  1382. X.SH Files
  1383. X/etc/utmp \- list of current login sessions
  1384. X.br
  1385. X/etc/wtmp \- list of previous login sessions
  1386. X.br
  1387. X/etc/passwd \- user account information
  1388. X.br
  1389. X/etc/shadow \- encrypted passwords and age information
  1390. X.br
  1391. X/etc/motd \- system message file
  1392. X.br
  1393. X/etc/ttytype \- list of terminal types
  1394. X.br
  1395. X$HOME/.profile \- initialization script for default shell
  1396. X.br
  1397. X$HOME/.hushlogin \- suppress printing of system messages
  1398. X.br
  1399. X.SH See Also
  1400. X.PP
  1401. Xgetty(1M),
  1402. Xmail(1),
  1403. Xpasswd(1),
  1404. Xsh(1),
  1405. Xsu(1),
  1406. Xd_passwd(4),
  1407. Xpasswd(4)
  1408. END_OF_FILE
  1409.   if test 3344 -ne `wc -c <'login.1'`; then
  1410.     echo shar: \"'login.1'\" unpacked with wrong size!
  1411.   fi
  1412.   # end of 'login.1'
  1413. fi
  1414. if test -f 'pwdbm.c' -a "${1}" != "-c" ; then 
  1415.   echo shar: Will not clobber existing file \"'pwdbm.c'\"
  1416. else
  1417.   echo shar: Extracting \"'pwdbm.c'\" \(2489 characters\)
  1418.   sed "s/^X//" >'pwdbm.c' <<'END_OF_FILE'
  1419. X/*
  1420. X * Copyright 1990, 1991, John F. Haugh II
  1421. X * All rights reserved.
  1422. X *
  1423. X * Permission is granted to copy and create derivative works for any
  1424. X * non-commercial purpose, provided this copyright notice is preserved
  1425. X * in all copies of source code, or included in human readable form
  1426. X * and conspicuously displayed on all copies of object code or
  1427. X * distribution media.
  1428. X */
  1429. X
  1430. X#ifndef    lint
  1431. Xstatic    char    sccsid[] = "@(#)pwdbm.c    3.5    09:29:30    6/6/91";
  1432. X#endif
  1433. X
  1434. X#ifdef    BSD
  1435. X#include <strings.h>
  1436. X#define    strchr    index
  1437. X#define    strrchr    rindex
  1438. X#else
  1439. X#include <string.h>
  1440. X#endif
  1441. X#include <stdio.h>
  1442. X#include "pwd.h"
  1443. X#include "config.h"
  1444. X
  1445. X#if defined(DBM) || defined(NDBM) /*{*/
  1446. X
  1447. X#ifdef    DBM
  1448. X#include <dbm.h>
  1449. X#endif
  1450. X#ifdef    NDBM
  1451. X#include <ndbm.h>
  1452. XDBM    *pw_dbm;
  1453. X#endif
  1454. X
  1455. X/*
  1456. X * pw_dbm_update
  1457. X *
  1458. X * Updates the DBM password files, if they exist.
  1459. X */
  1460. X
  1461. Xint
  1462. Xpw_dbm_update (pw)
  1463. Xstruct    passwd    *pw;
  1464. X{
  1465. X    datum    key;
  1466. X    datum    content;
  1467. X    char    data[BUFSIZ];
  1468. X    int    len;
  1469. X    static    int    once;
  1470. X
  1471. X    if (! once) {
  1472. X#ifdef    NDBM
  1473. X        if (! pw_dbm)
  1474. X            setpwent ();
  1475. X#else
  1476. X        setpwent ();
  1477. X#endif
  1478. X        once++;
  1479. X    }
  1480. X#ifdef    DBM
  1481. X    strcpy (data, PWDFILE);
  1482. X    strcat (data, ".pag");
  1483. X    if (access (data, 0))
  1484. X        return 0;
  1485. X#endif
  1486. X#ifdef    NDBM
  1487. X    if (! pw_dbm)
  1488. X        return 0;
  1489. X#endif
  1490. X    len = pw_pack (pw, data);
  1491. X    content.dsize = len;
  1492. X    content.dptr = data;
  1493. X
  1494. X    key.dsize = strlen (pw->pw_name);
  1495. X    key.dptr = pw->pw_name;
  1496. X#ifdef    DBM
  1497. X    if (store (key, content))
  1498. X        return 0;
  1499. X#endif
  1500. X#ifdef    NDBM
  1501. X    if (dbm_store (pw_dbm, key, content, DBM_REPLACE))
  1502. X        return 0;
  1503. X#endif
  1504. X
  1505. X    key.dsize = sizeof pw->pw_uid;
  1506. X    key.dptr = (char *) &pw->pw_uid;
  1507. X#ifdef    DBM
  1508. X    if (store (key, content))
  1509. X        return 0;
  1510. X#endif
  1511. X#ifdef    NDBM
  1512. X    if (dbm_store (pw_dbm, key, content, DBM_REPLACE))
  1513. X        return 0;
  1514. X#endif
  1515. X    return 1;
  1516. X}
  1517. X
  1518. X/*
  1519. X * pw_dbm_remove
  1520. X *
  1521. X * Removes the DBM password entry, if it exists.
  1522. X */
  1523. X
  1524. Xint
  1525. Xpw_dbm_remove (pw)
  1526. Xstruct    passwd    *pw;
  1527. X{
  1528. X    datum    key;
  1529. X    static    int    once;
  1530. X
  1531. X    if (! once) {
  1532. X#ifdef    NDBM
  1533. X        if (! pw_dbm)
  1534. X            setpwent ();
  1535. X#else
  1536. X        setpwent ();
  1537. X#endif
  1538. X        once++;
  1539. X    }
  1540. X#ifdef    DBM
  1541. X    strcpy (data, PWDFILE);
  1542. X    strcat (data, ".pag");
  1543. X    if (access (data, 0))
  1544. X        return 0;
  1545. X#endif
  1546. X#ifdef    NDBM
  1547. X    if (! pw_dbm)
  1548. X        return 0;
  1549. X#endif
  1550. X    key.dsize = strlen (pw->pw_name);
  1551. X    key.dptr = pw->pw_name;
  1552. X#ifdef    DBM
  1553. X    if (delete (key))
  1554. X        return 0;
  1555. X#endif
  1556. X#ifdef    NDBM
  1557. X    if (dbm_delete (pw_dbm, key))
  1558. X        return 0;
  1559. X#endif
  1560. X    key.dsize = sizeof pw->pw_uid;
  1561. X    key.dptr = (char *) &pw->pw_uid;
  1562. X#ifdef    DBM
  1563. X    if (delete (key))
  1564. X        return 0;
  1565. X#endif
  1566. X#ifdef    NDBM
  1567. X    if (dbm_delete (pw_dbm, key))
  1568. X        return 0;
  1569. X#endif
  1570. X    return 1;
  1571. X}
  1572. X
  1573. X#endif    /*} defined(NDBM) || defined(DBM) */
  1574. END_OF_FILE
  1575.   if test 2489 -ne `wc -c <'pwdbm.c'`; then
  1576.     echo shar: \"'pwdbm.c'\" unpacked with wrong size!
  1577.   fi
  1578.   # end of 'pwdbm.c'
  1579. fi
  1580. if test -f 'pwpack.c' -a "${1}" != "-c" ; then 
  1581.   echo shar: Will not clobber existing file \"'pwpack.c'\"
  1582. else
  1583.   echo shar: Extracting \"'pwpack.c'\" \(2994 characters\)
  1584.   sed "s/^X//" >'pwpack.c' <<'END_OF_FILE'
  1585. X/*
  1586. X * Copyright 1990, John F. Haugh II
  1587. X * All rights reserved.
  1588. X *
  1589. X * Permission is granted to copy and create derivative works for any
  1590. X * non-commercial purpose, provided this copyright notice is preserved
  1591. X * in all copies of source code, or included in human readable form
  1592. X * and conspicuously displayed on all copies of object code or
  1593. X * distribution media.
  1594. X */
  1595. X
  1596. X#include <stdio.h>
  1597. X#include "pwd.h"
  1598. X#ifdef    BSD
  1599. X#include <strings.h>
  1600. X#define    strchr    index
  1601. X#define    strrchr    rindex
  1602. X#else
  1603. X#include <string.h>
  1604. X#endif
  1605. X#include "config.h"
  1606. X
  1607. X#ifndef    lint
  1608. Xstatic    char    sccsid[] = "@(#)pwpack.c    3.3    12:31:23    12/12/90";
  1609. X#endif
  1610. X
  1611. X/*
  1612. X * pw_pack - convert a (struct pwd) to a packed record
  1613. X */
  1614. X
  1615. Xint
  1616. Xpw_pack (passwd, buf)
  1617. Xstruct    passwd    *passwd;
  1618. Xchar    *buf;
  1619. X{
  1620. X    char    *cp;
  1621. X
  1622. X    cp = buf;
  1623. X    strcpy (cp, passwd->pw_name);
  1624. X    cp += strlen (cp) + 1;
  1625. X
  1626. X    strcpy (cp, passwd->pw_passwd);
  1627. X#ifdef    ATT_AGE
  1628. X    if (passwd->pw_age[0]) {
  1629. X        *cp++ = ',';
  1630. X        strcat (cp, passwd->pw_age);
  1631. X    }
  1632. X#endif
  1633. X    cp += strlen (cp) + 1;
  1634. X
  1635. X    memcpy (cp, (void *) &passwd->pw_uid, sizeof passwd->pw_uid);
  1636. X    cp += sizeof passwd->pw_uid;
  1637. X
  1638. X    memcpy (cp, (void *) &passwd->pw_gid, sizeof passwd->pw_gid);
  1639. X    cp += sizeof passwd->pw_gid;
  1640. X#ifdef    BSD_QUOTAS
  1641. X    memcpy (cp, (void *) &passwd->pw_quota, sizeof passwd->pw_quota);
  1642. X    cp += sizeof passwd->pw_quota;
  1643. X#endif
  1644. X#ifdef    ATT_COMMENT
  1645. X    if (passwd->pw_comment) {
  1646. X        strcpy (cp, passwd->pw_comment);
  1647. X        cp += strlen (cp) + 1;
  1648. X    } else
  1649. X        *cp++ = '\0';
  1650. X#endif
  1651. X    strcpy (cp, passwd->pw_gecos);
  1652. X    cp += strlen (cp) + 1;
  1653. X
  1654. X    strcpy (cp, passwd->pw_dir);
  1655. X    cp += strlen (cp) + 1;
  1656. X
  1657. X    strcpy (cp, passwd->pw_shell);
  1658. X        cp += strlen (cp) + 1;
  1659. X
  1660. X    return cp - buf;
  1661. X}
  1662. X
  1663. X/*
  1664. X * pw_unpack - convert a packed (struct pwd) record to a (struct pwd)
  1665. X */
  1666. X
  1667. Xint
  1668. Xpw_unpack (buf, len, passwd)
  1669. Xchar    *buf;
  1670. Xint    len;
  1671. Xstruct    passwd    *passwd;
  1672. X{
  1673. X    char    *org = buf;
  1674. X    char    *cp;
  1675. X
  1676. X    memset ((void *) passwd, 0, sizeof *passwd);
  1677. X
  1678. X    passwd->pw_name = buf;
  1679. X    buf += strlen (buf) + 1;
  1680. X    if (buf - org > len)
  1681. X        return -1;
  1682. X
  1683. X    passwd->pw_passwd = buf;
  1684. X    buf += strlen (buf) + 1;
  1685. X    if (buf - org > len)
  1686. X        return -1;
  1687. X
  1688. X#ifdef    ATT_AGE
  1689. X    if (cp = strchr (passwd->pw_passwd, ',')) {
  1690. X        *cp++ = '\0';
  1691. X        passwd->pw_age = cp;
  1692. X    } else
  1693. X        passwd->pw_age = "";
  1694. X#endif
  1695. X
  1696. X    memcpy ((void *) &passwd->pw_uid, (void *) buf, sizeof passwd->pw_uid);
  1697. X    buf += sizeof passwd->pw_uid;
  1698. X    if (buf - org > len)
  1699. X        return -1;
  1700. X
  1701. X    memcpy ((void *) &passwd->pw_gid, (void *) buf, sizeof passwd->pw_gid);
  1702. X    buf += sizeof passwd->pw_gid;
  1703. X    if (buf - org > len)
  1704. X        return -1;
  1705. X
  1706. X#ifdef    BSD_QUOTAS
  1707. X    memcpy ((void *) &passwd->pw_quota, (void *) buf,
  1708. X        sizeof passwd->pw_quota);
  1709. X    buf += sizeof passwd->pw_quota;
  1710. X    if (buf - org > len)
  1711. X        return -1;
  1712. X#endif
  1713. X#ifdef    ATT_COMMENT
  1714. X    passwd->pw_comment = buf;
  1715. X    buf += strlen (buf) + 1;
  1716. X    if (buf - org > len)
  1717. X        return -1;
  1718. X#endif
  1719. X    passwd->pw_gecos = buf;
  1720. X    buf += strlen (buf) + 1;
  1721. X    if (buf - org > len)
  1722. X        return -1;
  1723. X
  1724. X    passwd->pw_dir = buf;
  1725. X    buf += strlen (buf) + 1;
  1726. X    if (buf - org > len)
  1727. X        return -1;
  1728. X
  1729. X    passwd->pw_shell = buf;
  1730. X    buf += strlen (buf) + 1;
  1731. X    if (buf - org > len)
  1732. X        return -1;
  1733. X
  1734. X    return 0;
  1735. X}
  1736. END_OF_FILE
  1737.   if test 2994 -ne `wc -c <'pwpack.c'`; then
  1738.     echo shar: \"'pwpack.c'\" unpacked with wrong size!
  1739.   fi
  1740.   # end of 'pwpack.c'
  1741. fi
  1742. if test -f 'pwunconv.c' -a "${1}" != "-c" ; then 
  1743.   echo shar: Will not clobber existing file \"'pwunconv.c'\"
  1744. else
  1745.   echo shar: Extracting \"'pwunconv.c'\" \(3159 characters\)
  1746.   sed "s/^X//" >'pwunconv.c' <<'END_OF_FILE'
  1747. X/*
  1748. X * Copyright 1989, 1990, 1991, John F. Haugh II
  1749. X * All rights reserved.
  1750. X *
  1751. X * Permission is granted to copy and create derivative works for any
  1752. X * non-commercial purpose, provided this copyright notice is preserved
  1753. X * in all copies of source code, or included in human readable form
  1754. X * and conspicuously displayed on all copies of object code or
  1755. X * distribution media.
  1756. X *
  1757. X * pwunconv - restore old password file from shadow password file.
  1758. X *
  1759. X *    Pwunconv copies the password file information from the shadow
  1760. X *    password file, merging entries from an optional existing shadow
  1761. X *    file.
  1762. X *
  1763. X *    The new password file is left in npasswd.  There is no new
  1764. X *    shadow file.  Password aging information is translated where
  1765. X *    possible.
  1766. X */
  1767. X
  1768. X#include <sys/types.h>
  1769. X#include <stdio.h>
  1770. X#include <fcntl.h>
  1771. X#include "pwd.h"
  1772. X#include "config.h"
  1773. X#include "shadow.h"
  1774. X
  1775. X#ifndef    lint
  1776. Xstatic    char    sccsid[] = "@(#)pwunconv.c    3.3    09:08:06    5/28/91";
  1777. X#endif
  1778. X
  1779. X#ifdef    ITI_AGING
  1780. X#define    WEEK    (7L*24L*3600L)
  1781. X#else
  1782. X#define    WEEK    (7)
  1783. X#endif
  1784. X
  1785. Xchar    buf[BUFSIZ];
  1786. Xchar    *l64a ();
  1787. X
  1788. Xint    main ()
  1789. X{
  1790. X    struct    passwd    *pw;
  1791. X    struct    passwd    *sgetpwent ();
  1792. X    FILE    *pwd;
  1793. X    FILE    *npwd;
  1794. X    struct    spwd    *spwd;
  1795. X    int    fd;
  1796. X    char    newage[5];
  1797. X
  1798. X    if (! (pwd = fopen (PWDFILE, "r"))) {
  1799. X        perror (PWDFILE);
  1800. X        return (1);
  1801. X    }
  1802. X    unlink ("npasswd");
  1803. X    if ((fd = open ("npasswd", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 ||
  1804. X            ! (npwd = fdopen (fd, "w"))) {
  1805. X        perror ("npasswd");
  1806. X        return (1);
  1807. X    }
  1808. X    while (fgets (buf, BUFSIZ, pwd) == buf) {
  1809. X        buf[strlen (buf) - 1] = '\0'; /* remove '\n' character */
  1810. X
  1811. X        if (buf[0] == '#') {    /* comment line */
  1812. X            (void) fprintf (npwd, "%s\n", buf);
  1813. X            continue;
  1814. X        }
  1815. X        if (! (pw = sgetpwent (buf))) { /* copy bad lines verbatim */
  1816. X            (void) fprintf (npwd, "%s\n", buf);
  1817. X            continue;
  1818. X        }
  1819. X        setspent ();        /* rewind shadow file */
  1820. X
  1821. X        if (! (spwd = getspnam (pw->pw_name))) {
  1822. X            (void) fprintf (npwd, "%s\n", buf);
  1823. X            continue;
  1824. X        }
  1825. X        pw->pw_passwd = spwd->sp_pwdp;
  1826. X
  1827. X    /*
  1828. X     * Password aging works differently in the two different systems.
  1829. X     * With shadow password files you apparently must have some aging
  1830. X     * information.  The maxweeks or minweeks may not map exactly.
  1831. X     * In pwconv we set max == 10000, which is about 30 years.  Here
  1832. X     * we have to undo that kludge.  So, if maxdays == 10000, no aging
  1833. X     * information is put into the new file.  Otherwise, the days are
  1834. X     * converted to weeks and so on.
  1835. X     */
  1836. X
  1837. X#ifdef    ATT_AGE
  1838. X        if (spwd->sp_max > (63*WEEK) && spwd->sp_max < 10000)
  1839. X            spwd->sp_max = (63*WEEK); /* 10000 is infinity */
  1840. X
  1841. X        if (spwd->sp_min >= 0 && spwd->sp_min <= 63*7 &&
  1842. X                spwd->sp_max >= 0 && spwd->sp_max <= 63*7) {
  1843. X            if (spwd->sp_lstchg == -1)
  1844. X                spwd->sp_lstchg = 0;
  1845. X
  1846. X            spwd->sp_max /= WEEK;    /* turn it into weeks */
  1847. X            spwd->sp_min /= WEEK;
  1848. X            spwd->sp_lstchg /= WEEK;
  1849. X
  1850. X            strncpy (newage, l64a (spwd->sp_lstchg * (64L*64L) +
  1851. X                  spwd->sp_min * (64L) + spwd->sp_max), 5);
  1852. X            pw->pw_age = newage;
  1853. X        } else
  1854. X            pw->pw_age = "";
  1855. X#endif    /* ATT_AGE */
  1856. X        if (putpwent (pw, npwd)) {
  1857. X            perror ("pwunconv: write error");
  1858. X            exit (1);
  1859. X        }
  1860. X    }
  1861. X    endspent ();
  1862. X
  1863. X    if (ferror (npwd)) {
  1864. X        perror ("pwunconv");
  1865. X        (void) unlink ("npasswd");
  1866. X    }
  1867. X    (void) fclose (npwd);
  1868. X    (void) fclose (pwd);
  1869. X    return (0);
  1870. X}
  1871. END_OF_FILE
  1872.   if test 3159 -ne `wc -c <'pwunconv.c'`; then
  1873.     echo shar: \"'pwunconv.c'\" unpacked with wrong size!
  1874.   fi
  1875.   # end of 'pwunconv.c'
  1876. fi
  1877. if test -f 'scologin.c' -a "${1}" != "-c" ; then 
  1878.   echo shar: Will not clobber existing file \"'scologin.c'\"
  1879. else
  1880.   echo shar: Extracting \"'scologin.c'\" \(1834 characters\)
  1881.   sed "s/^X//" >'scologin.c' <<'END_OF_FILE'
  1882. X/*
  1883. X * Copyright 1991, John F. Haugh II and Chip Rosenthal
  1884. X * All rights reserved.
  1885. X *
  1886. X * Permission is granted to copy and create derivative works for any
  1887. X * non-commercial purpose, provided this copyright notice is preserved
  1888. X * in all copies of source code, or included in human readable form
  1889. X * and conspicuously displayed on all copies of object code or
  1890. X * distribution media.
  1891. X */
  1892. X
  1893. X#ifndef lint
  1894. Xstatic    char    sccsid[] = "@(#)scologin.c    3.2    14:38:24    10/27/91";
  1895. X#endif
  1896. X
  1897. X#include <stdio.h>
  1898. X#include "pwd.h"
  1899. X
  1900. X#define USAGE    "usage: %s [ -r remote_host remote_user local_user [ term_type ] ]\n"
  1901. X#define LOGIN    "/etc/login"
  1902. X
  1903. Xextern int errno;
  1904. Xextern char *sys_errlist[];
  1905. Xextern char **environ;
  1906. X
  1907. Xmain(argc, argv)
  1908. Xint argc;
  1909. Xchar *argv[];
  1910. X{
  1911. X    char *rhost, *ruser, *luser;
  1912. X    char term[1024], *nargv[8], *nenvp[2];
  1913. X    int root_user, i;
  1914. X    struct passwd *pw;
  1915. X
  1916. X    if (argc == 1) {
  1917. X
  1918. X        /*
  1919. X         * Called from telnetd.
  1920. X         */
  1921. X        nargv[0] = "login";
  1922. X        nargv[1] = "-p";
  1923. X        nargv[2] = NULL;
  1924. X
  1925. X    } else if (strcmp(argv[1], "-r") == 0 && argc >= 6) {
  1926. X
  1927. X        /*
  1928. X         * Called from rlogind.
  1929. X         */
  1930. X
  1931. X        rhost = argv[2];
  1932. X        ruser = argv[3];
  1933. X        luser = argv[4];
  1934. X        root_user = ((pw = getpwnam(luser)) != NULL && pw->pw_uid == 0);
  1935. X
  1936. X        i = 0;
  1937. X        if ( argc == 6 ) {
  1938. X            strcpy(term, "TERM=");
  1939. X            strncat(term+sizeof("TERM=")-1,
  1940. X                argv[5], sizeof(term)-sizeof("TERM="));
  1941. X            term[sizeof(term)-1] = '\0';
  1942. X            nenvp[i++] = term;
  1943. X        }
  1944. X        nenvp[i++] = NULL;
  1945. X        environ = nenvp;
  1946. X
  1947. X        i = 0;
  1948. X        nargv[i++] = "login";
  1949. X        nargv[i++] = "-p";
  1950. X        nargv[i++] = "-h";
  1951. X        nargv[i++] = rhost;
  1952. X        if (ruserok(rhost, root_user, ruser, luser) == 0)
  1953. X            nargv[i++] = "-f";
  1954. X        nargv[i++] = luser;
  1955. X        nargv[i++] = NULL;
  1956. X
  1957. X    } else {
  1958. X
  1959. X        fprintf(stderr, USAGE, argv[0]);
  1960. X        exit(1);
  1961. X
  1962. X    }
  1963. X
  1964. X    (void) execv(LOGIN, nargv);
  1965. X    fprintf(stderr, "%s: could not exec '%s' [%s]\n",
  1966. X        argv[0], LOGIN, sys_errlist[errno]);
  1967. X    exit(1);
  1968. X    /*NOTREACHED*/
  1969. X}
  1970. END_OF_FILE
  1971.   if test 1834 -ne `wc -c <'scologin.c'`; then
  1972.     echo shar: \"'scologin.c'\" unpacked with wrong size!
  1973.   fi
  1974.   # end of 'scologin.c'
  1975. fi
  1976. if test -f 'shadow.3' -a "${1}" != "-c" ; then 
  1977.   echo shar: Will not clobber existing file \"'shadow.3'\"
  1978. else
  1979.   echo shar: Extracting \"'shadow.3'\" \(2801 characters\)
  1980.   sed "s/^X//" >'shadow.3' <<'END_OF_FILE'
  1981. X.\" Copyright 1989, 1990, John F. Haugh II
  1982. X.\" All rights reserved.
  1983. X.\"
  1984. X.\" Use, duplication, and disclosure prohibited without
  1985. X.\" the express written permission of the author.
  1986. X.\"
  1987. X.\"    @(#)shadow.3    3.1    23:49:42    11/11/90
  1988. X.\"
  1989. X.TH SHADOW 3
  1990. X.SH NAME
  1991. Xshadow \- encrypted password file routines
  1992. X.SH Syntax
  1993. X.IP "" .5i
  1994. X#include <shadow.h>
  1995. X.IP "" .5i
  1996. Xstruct spwd *getspent();
  1997. X.br
  1998. Xstruct spwd *getspnam(char * name);
  1999. X.br
  2000. Xvoid setspent();
  2001. X.br
  2002. Xvoid endspent();
  2003. X.br
  2004. Xstruct spwd *fgetspent(FILE *fp);
  2005. X.br
  2006. Xstruct spwd *sgetspent(char *cp);
  2007. X.br
  2008. Xint putspent(struct spwd *p,FILE *fp);
  2009. X.SH DESCRIPTION
  2010. X.I shadow
  2011. Xmanipulates the contents of the shadow password file,
  2012. X\fB/etc/shadow\fR.
  2013. XThe structure in the \fI#include\fR file is
  2014. X.IP "" .5i
  2015. Xstruct spwd {
  2016. X.br
  2017. X    char    *sp_namp; /* user login name */
  2018. X.br
  2019. X    char    *sp_pwdp; /* encrypted password */
  2020. X.br
  2021. X    long    sp_lstchg; /* last password change */
  2022. X.br
  2023. X    int    sp_min; /* days until change allowed. */
  2024. X.br
  2025. X    int    sp_max; /* days before change required */
  2026. X.br
  2027. X    int    sp_warn; /* days warning for expiration */
  2028. X.br
  2029. X    int    sp_inact; /* days before account inactive */
  2030. X.br
  2031. X    int    sp_expire; /* date when account expires */
  2032. X.br
  2033. X    int    sp_flag; /* reserved for future use */
  2034. X.br
  2035. X}
  2036. X.PP
  2037. XThe meanings of each field are
  2038. X.IP "" .5i
  2039. Xsp_namp \- pointer to null-terminated user name.
  2040. X.IP "" .5i
  2041. Xsp_pwdp \- pointer to null-terminated password.
  2042. X.IP "" .5i
  2043. Xsp_lstchg \- days since Jan 1, 1970 password was last changed.
  2044. X.IP "" .5i
  2045. Xsp_min \- days before which password may not be changed.
  2046. X.IP "" .5i
  2047. Xsp_max \- days after which password must be changed.
  2048. X.IP "" .5i
  2049. Xsp_warn \- days before password is to expire that user is warned
  2050. Xof pending password expiration.
  2051. X.IP "" .5i
  2052. Xsp_inact \- days after password expires that account is considered
  2053. Xinactive and disabled.
  2054. X.IP "" .5i
  2055. Xsp_expire \- days since Jan 1, 1970 that account will be disabled.
  2056. X.IP "" .5i
  2057. Xsp_flag \- reserved for future use.
  2058. X.SH Description
  2059. X\fIgetspent\fR, \fIgetspname\fR, \fIfgetspent\fR, and \fIsgetspent\fR
  2060. Xeach return a pointer to a \fBstruct spwd\fR.
  2061. X\fIgetspent\fR returns the
  2062. Xnext entry from the file, and \fIfgetspent\fR returns the next
  2063. Xentry from the given stream, which is assumed to be a file of
  2064. Xthe proper format.
  2065. X\fIsgetspent\fR returns a pointer to a \fBstruct spwd\fR using the
  2066. Xprovided string as input.
  2067. X\fIgetspnam\fR searches from the current position in the file for
  2068. Xan entry matching \fIname\fR.
  2069. X.PP
  2070. X\fIsetspent\fR and \fIendspent\fR may be used to begin and end,
  2071. Xrespectively, access to the shadow password file.
  2072. X.SH Diagnostics
  2073. XRoutines return NULL if no more entries are available or if an
  2074. Xerror occurs during processing.
  2075. X.SH Caveats
  2076. XThese routines may only be used by the super user as access to
  2077. Xthe shadow password file is restricted.
  2078. X.SH Files
  2079. X/etc/shadow \- encrypted user passwords
  2080. X.SH See Also
  2081. Xgetpwent(3),
  2082. Xshadow(4)
  2083. END_OF_FILE
  2084.   if test 2801 -ne `wc -c <'shadow.3'`; then
  2085.     echo shar: \"'shadow.3'\" unpacked with wrong size!
  2086.   fi
  2087.   # end of 'shadow.3'
  2088. fi
  2089. if test -f 'shell.c' -a "${1}" != "-c" ; then 
  2090.   echo shar: Will not clobber existing file \"'shell.c'\"
  2091. else
  2092.   echo shar: Extracting \"'shell.c'\" \(2527 characters\)
  2093.   sed "s/^X//" >'shell.c' <<'END_OF_FILE'
  2094. X/*
  2095. X * Copyright 1989, 1990, 1991, John F. Haugh II
  2096. X * All rights reserved.
  2097. X *
  2098. X * Use, duplication, and disclosure prohibited without
  2099. X * the express written permission of the author.
  2100. X */
  2101. X
  2102. X#include <stdio.h>
  2103. X#include <errno.h>
  2104. X#ifndef    BSD
  2105. X#include <string.h>
  2106. X#include <memory.h>
  2107. X#else
  2108. X#include <strings.h>
  2109. X#define    strchr    index
  2110. X#define    strrchr    rindex
  2111. X#endif
  2112. X#include "config.h"
  2113. X
  2114. X#ifndef    lint
  2115. Xstatic    char    _sccsid[] = "@(#)shell.c    3.2    07:55:08    2/6/91";
  2116. X#endif
  2117. X
  2118. Xextern    char    *newenvp[];
  2119. X
  2120. X/*
  2121. X * shell - execute the named program
  2122. X *
  2123. X *    shell begins by trying to figure out what argv[0] is going to
  2124. X *    be for the named process.  The user may pass in that argument,
  2125. X *    or it will be the last pathname component of the file with a
  2126. X *    '-' prepended.  The first attempt is to just execute the named
  2127. X *    file.  If the errno comes back "ENOEXEC", the file is assumed
  2128. X *    at first glance to be a shell script.  The first two characters
  2129. X *    must be "#!", in which case "/bin/sh" is executed to process
  2130. X *    the file.  If all that fails, give up in disgust ...
  2131. X */
  2132. X
  2133. Xvoid    shell (file, arg)
  2134. Xchar    *file;
  2135. Xchar    *arg;
  2136. X{
  2137. X    char    arg0[BUFSIZ];
  2138. X    FILE    *fp;
  2139. X    char    *path;
  2140. X    int    err;
  2141. X
  2142. X    if (file == (char *) 0)
  2143. X        exit (1);
  2144. X
  2145. X    /*
  2146. X     * The argv[0]'th entry is usually the path name, but
  2147. X     * for various reasons the invoker may want to override
  2148. X     * that.  So, we determine the 0'th entry only if they
  2149. X     * don't want to tell us what it is themselves.
  2150. X     */
  2151. X
  2152. X    if (arg == (char *) 0) {
  2153. X        if (path = strrchr (file, '/'))
  2154. X            path++;
  2155. X        else
  2156. X            path = file;
  2157. X
  2158. X        (void) strcpy (arg0 + 1, path);
  2159. X        arg0[0] = '-';
  2160. X        arg = arg0;
  2161. X    }
  2162. X#ifndef    NDEBUG
  2163. X    printf ("Executing shell %s\n", file);
  2164. X#endif
  2165. X
  2166. X    /*
  2167. X     * First we try the direct approach.  The system should be
  2168. X     * able to figure out what we are up to without too much
  2169. X     * grief.
  2170. X     */
  2171. X
  2172. X    execle (file, arg, (char *) 0, newenvp);
  2173. X    err = errno;
  2174. X
  2175. X    /*
  2176. X     * It is perfectly OK to have a shell script for a login
  2177. X     * shell, and this code attempts to support that.  It
  2178. X     * relies on the standard shell being able to make sense
  2179. X     * of the "#!" magic number.
  2180. X     */
  2181. X
  2182. X    if (err == ENOEXEC) {
  2183. X        if (fp = fopen (file, "r")) {
  2184. X            if (getc (fp) == '#' && getc (fp) == '!') {
  2185. X                fclose (fp);
  2186. X                execle ("/bin/sh", "sh",
  2187. X                    file, (char *) 0, newenvp);
  2188. X                err = errno;
  2189. X            } else {
  2190. X                fclose (fp);
  2191. X            }
  2192. X        }
  2193. X    }
  2194. X
  2195. X    /*
  2196. X     * Obviously something is really wrong - I can't figure out
  2197. X     * how to execute this stupid shell, so I might as well give
  2198. X     * up in disgust ...
  2199. X     */
  2200. X
  2201. X    sprintf (arg0, "Cannot execute %s", file);
  2202. X    errno = err;
  2203. X    perror (arg0);
  2204. X    exit (err);
  2205. X}
  2206. END_OF_FILE
  2207.   if test 2527 -ne `wc -c <'shell.c'`; then
  2208.     echo shar: \"'shell.c'\" unpacked with wrong size!
  2209.   fi
  2210.   # end of 'shell.c'
  2211. fi
  2212. if test -f 'usermod.1' -a "${1}" != "-c" ; then 
  2213.   echo shar: Will not clobber existing file \"'usermod.1'\"
  2214. else
  2215.   echo shar: Extracting \"'usermod.1'\" \(3224 characters\)
  2216.   sed "s/^X//" >'usermod.1' <<'END_OF_FILE'
  2217. X.\" Copyright 1991, John F. Haugh II
  2218. X.\" All rights reserved.
  2219. X.\"
  2220. X.\" Permission is granted to copy and create derivative works for any
  2221. X.\" non-commercial purpose, provided this copyright notice is preserved
  2222. X.\" in all copies of source code, or included in human readable form
  2223. X.\" and conspicuously displayed on all copies of object code or
  2224. X.\" distribution media.
  2225. X.\"
  2226. X.\"    @(#)usermod.1    3.1    07:46:06    7/13/91
  2227. X.\"
  2228. X.TH USERMOD 1M
  2229. X.SH NAME
  2230. Xusermod \- Modify a user account
  2231. X.SH SYNOPSIS
  2232. X.B usermod
  2233. X[ \fB-c\fI comment\fR ]
  2234. X[ \fB-d\fI home_dir \fR[ \fB-m\fR ] ]
  2235. X[ \fB-e\fI expire_date\fR ]
  2236. X[ \fB-f\fI inactive_time\fR ]
  2237. X[ \fB-g\fI initial_group\fR ]
  2238. X[ \fB-G\fI group[,...]\fR ]
  2239. X[ \fB-l\fI login_name \fR ]
  2240. X[ \fB-s\fI shell\fR ]
  2241. X[ \fB-u\fI uid \fR[ \fB-o\fR ]
  2242. X.I login
  2243. X.SH DESCRIPTION
  2244. XThe \fIusermod\fR command modifies the system account files to reflect
  2245. Xthe changes that are specified on the command line.
  2246. XThe options which apply to the \fIusermod\fR command are
  2247. X.IP "\fB-c \fIcomment\fR"
  2248. XThe new value of the user's password file comment field.
  2249. XIt is normally modified using the \fBchfn(1)\fR utility.
  2250. X.IP "\fB-d \fIhome_dir\fR"
  2251. XThe user's new login directory.
  2252. XIf the \fB-m\fR option is given the contents of the current home directory
  2253. Xwill be moved to the new home directory, which is created if it does not
  2254. Xalready exist.
  2255. X.IP "\fB-e \fIexpire_date\fR"
  2256. XThe date on which the user account will be disabled.
  2257. XThe date is specified in the format \fIMM/DD/YY\fR.
  2258. X.IP "\fB-f \fIinactive_days\fR"
  2259. XThe number of days after a password expires until the account
  2260. Xis permanently disabled.
  2261. XA value of 0 disables the account as soon as the password has
  2262. Xexpired, and a value of -1 disables the feature.
  2263. XThe default value is -1.
  2264. X.IP "\fB-g \fIinitial_group\fR"
  2265. XThe group name or number of the user's new initial login group.
  2266. XThe group name must exist.  A group number must refer to an
  2267. Xalready existing group.
  2268. XThe default group number is 1.
  2269. X.IP "\fB-G \fIgroup,[...]\fR"
  2270. XA list of supplementary groups which the user is also a member
  2271. Xof.
  2272. XEach group is separated from the next by a comma, with no
  2273. Xintervening whitespace.
  2274. XThe groups are subject to the same restrictions as the group
  2275. Xgiven with the \fB-g\fR option.
  2276. XIf the user is currently a member of a group which is not listed,
  2277. Xthe user will be removed from the group
  2278. X.IP "\fB-l \fIlogin_name\fR"
  2279. XThe name of the user will be changed from \fIlogin\fR to
  2280. X\fIlogin_name\fR.
  2281. XNothing else is changed.
  2282. XIn particular, the user's home directory name should probably
  2283. Xbe changed to reflect the new login name.
  2284. X.IP "\fB-s \fIshell\fR"
  2285. XThe name of the user's new login shell.
  2286. XSetting this field to blank causes the system
  2287. Xto select the default login shell.
  2288. X.IP "\fB-u \fIuid\fR"
  2289. XThe numerical value of the user's ID.
  2290. XThis value must be unique, unless the \fI-o\fR option is used.
  2291. XThe value must be non-negative.
  2292. XValues between 0 and 99 are typically reserved for system accounts.
  2293. XAny files which the user owned must have the file user ID changed
  2294. Xmanually.
  2295. X.SH Files
  2296. X/etc/passwd \- user account information
  2297. X.br
  2298. X/etc/shadow \- secure user account information
  2299. X.br
  2300. X/etc/group \- group information
  2301. X.SH SEE ALSO
  2302. X\fBchfn(1), chsh(1), groupadd(1M), groupdel(1M), groupmod(1M),
  2303. Xpasswd(1), useradd(1M), userdel(1M)
  2304. END_OF_FILE
  2305.   if test 3224 -ne `wc -c <'usermod.1'`; then
  2306.     echo shar: \"'usermod.1'\" unpacked with wrong size!
  2307.   fi
  2308.   # end of 'usermod.1'
  2309. fi
  2310. echo shar: End of archive 9 \(of 11\).
  2311. cp /dev/null ark9isdone
  2312. MISSING=""
  2313. for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
  2314.     if test ! -f ark${I}isdone ; then
  2315.     MISSING="${MISSING} ${I}"
  2316.     fi
  2317. done
  2318. if test "${MISSING}" = "" ; then
  2319.     echo You have unpacked all 11 archives.
  2320.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2321. else
  2322.     echo You still must unpack the following archives:
  2323.     echo "        " ${MISSING}
  2324. fi
  2325. exit 0
  2326. exit 0 # Just in case...
  2327.