home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3343 / pwent.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-17  |  9.5 KB  |  474 lines

  1. /*
  2.  * Copyright 1989, 1990, John F. Haugh II
  3.  * All rights reserved.
  4.  *
  5.  * Permission is granted to copy and create derivative works for any
  6.  * non-commercial purpose, provided this copyright notice is preserved
  7.  * in all copies of source code, or included in human readable form
  8.  * and conspicuously displayed on all copies of object code or
  9.  * distribution media.
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include "pwd.h"
  14. #ifdef    BSD
  15. #include <strings.h>
  16. #define    strchr    index
  17. #define    strrchr    rindex
  18. #else
  19. #include <string.h>
  20. #endif
  21. #include "config.h"
  22.  
  23. /*
  24.  * If AUTOSHADOW is enable, the getpwnam and getpwuid calls will
  25.  * fill in the pw_passwd and pw_age fields from the passwd and
  26.  * shadow files.
  27.  */
  28.  
  29. #if defined(AUTOSHADOW) && !defined(SHADOWPWD)
  30. #undef    AUTOSHADOW
  31. #endif
  32. #ifdef    AUTOSHADOW
  33. #include "shadow.h"
  34. #endif
  35.  
  36. /*
  37.  * If DBM or NDBM is enabled, the getpwnam and getpwuid calls will
  38.  * go to the database files to look for the requested entries.
  39.  */
  40.  
  41. #ifdef    DBM
  42. #include <dbm.h>
  43. #endif
  44. #ifdef    NDBM
  45. #include <ndbm.h>
  46. #include <fcntl.h>
  47. DBM    *pw_dbm;
  48. int    pw_dbm_mode = -1;
  49. #endif
  50.  
  51. /*
  52.  * ITI-style aging uses time_t's as the time fields, while
  53.  * AT&T-style aging uses long numbers of days.
  54.  */
  55.  
  56. #ifdef    ITI_AGING
  57. #define    WEEK    (7L*24L*3600L)
  58. #else
  59. #define    WEEK    7
  60. #endif
  61.  
  62. #ifndef    lint
  63. static    char    sccsid[] = "@(#)pwent.c    3.5    12:53:57    12/19/90";
  64. #endif
  65.  
  66. #define    SBUFSIZ    64
  67. #define    NFIELDS    7
  68.  
  69. static    FILE    *pwdfp;
  70. static    char    pwdbuf[BUFSIZ];
  71. static    char    *pwdfile = PWDFILE;
  72. #if defined(DBM) || defined(NDBM)
  73. static    int    dbmopened;
  74. static    int    dbmerror;
  75. #endif
  76. static    char    *pwdfields[NFIELDS];
  77. static    struct    passwd    pwent;
  78.  
  79. #if defined(AUTOSHADOW) && defined(ATT_AGE)
  80. /*
  81.  * sptopwage - convert shadow ages to AT&T-style pw_age ages
  82.  *
  83.  *    sptopwage() converts the values in the shadow password
  84.  *    entry to the format used in the old-style password
  85.  *    entry.
  86.  */
  87.  
  88. static char *
  89. sptopwage (spwd)
  90. struct    spwd    *spwd;
  91. {
  92.     static    char    age[5];
  93.     long    min;
  94.     long    max;
  95.     long    last;
  96.  
  97.     if ((min = (spwd->sp_min / WEEK)) < 0)
  98.         min = 0;
  99.     else if (min >= 64)
  100.         min = 63;
  101.  
  102.     if ((max = (spwd->sp_max / WEEK)) < 0)
  103.         max = 0;
  104.     else if (max >= 64)
  105.         max = 63;
  106.  
  107.     if ((last = (spwd->sp_lstchg / WEEK)) < 0)
  108.         last = 0;
  109.     else if (last >= 4096)
  110.         last = 4095;
  111.  
  112.     age[0] = i64c (max);
  113.     age[1] = i64c (min);
  114.     age[2] = i64c (last % 64);
  115.     age[3] = i64c (last / 64);
  116.     age[4] = '\0';
  117.     return age;
  118. }
  119. #endif
  120.  
  121. /*
  122.  * sgetpwent - convert a string to a (struct passwd)
  123.  *
  124.  * sgetpwent() parses a string into the parts required for a password
  125.  * structure.  Strict checking is made for the UID and GID fields and
  126.  * presence of the correct number of colons.  Any failing tests result
  127.  * in a NULL pointer being returned.
  128.  */
  129.  
  130. struct passwd *
  131. sgetpwent (buf)
  132. char    *buf;
  133. {
  134.     int    i;
  135.     char    *cp;
  136.  
  137.     /*
  138.      * Copy the string to a static buffer so the pointers into
  139.      * the password structure remain valid.
  140.      */
  141.  
  142.     strncpy (pwdbuf, buf, BUFSIZ);
  143.     pwdbuf[BUFSIZ-1] = '\0';
  144.  
  145.     /*
  146.      * Save a pointer to the start of each colon separated
  147.      * field.  The fields are converted into NUL terminated strings.
  148.      */
  149.  
  150.     for (cp = pwdbuf, i = 0;i < NFIELDS && cp;i++) {
  151.         pwdfields[i] = cp;
  152.         if (cp = strchr (cp, ':'))
  153.             *cp++ = 0;
  154.     }
  155.  
  156.     /*
  157.      * There must be exactly NFIELDS colon separated fields or
  158.      * the entry is invalid.  Also, the UID and GID must be non-blank.
  159.      */
  160.  
  161.     if (i != NFIELDS || *pwdfields[2] == '\0' || *pwdfields[3] == '\0')
  162.         return 0;
  163.  
  164.     /*
  165.      * Each of the fields is converted the appropriate data type
  166.      * and the result assigned to the password structure.  If the
  167.      * UID or GID does not convert to an integer value, a NULL
  168.      * pointer is returned.
  169.      */
  170.  
  171.     pwent.pw_name = pwdfields[0];
  172.     pwent.pw_passwd = pwdfields[1];
  173.     if ((pwent.pw_uid = strtol (pwdfields[2], &cp, 10)) == 0 && *cp)
  174.         return 0;
  175.  
  176.     if ((pwent.pw_gid = strtol (pwdfields[3], &cp, 10)) == 0 && *cp)
  177.         return 0;
  178. #ifdef    ATT_AGE
  179.     if (cp = strchr (pwent.pw_passwd, ',')) {
  180.         pwent.pw_age = cp + 1;
  181.         *cp = '\0';
  182.     } else
  183.         pwent.pw_age = "";
  184. #endif
  185.     pwent.pw_gecos = pwdfields[4];
  186. #ifdef    ATT_COMMENT
  187.     pwent.pw_comment = "";
  188. #endif
  189.     pwent.pw_dir = pwdfields[5];
  190.     pwent.pw_shell = pwdfields[6];
  191.  
  192.     return (&pwent);
  193. }
  194.  
  195. /*
  196.  * fgetpwent - get a password file entry from a stream
  197.  *
  198.  * fgetpwent() reads the next line from a password file formatted stream
  199.  * and returns a pointer to the password structure for that line.
  200.  */
  201.  
  202. struct passwd *
  203. fgetpwent (fp)
  204. FILE    *fp;
  205. {
  206.     char    buf[BUFSIZ];
  207.  
  208.     while (fgets (buf, BUFSIZ, fp) != (char *) 0) {
  209.         buf[strlen (buf) - 1] = '\0';
  210.         return (sgetpwent (buf));
  211.     }
  212.     return 0;
  213. }
  214.  
  215. /*
  216.  * endpwent - close a password file
  217.  *
  218.  * endpwent() closes the password file if open.  if autoshadowing is
  219.  * enabled the system must also end access to the shadow files since
  220.  * the user is probably unaware it was ever accessed.
  221.  */
  222.  
  223. int
  224. endpwent ()
  225. {
  226.     if (pwdfp)
  227.         if (fclose (pwdfp))
  228.             return -1;
  229.  
  230.     pwdfp = 0;
  231. #ifdef    NDBM
  232.     if (dbmopened && pw_dbm) {
  233.         dbm_close (pw_dbm);
  234.         dbmopened = 0;
  235.         dbmerror = 0;
  236.         pw_dbm = 0;
  237.     }
  238. #endif
  239. #ifdef    AUTOSHADOW
  240.     endspent ();
  241. #endif
  242.     return 0;
  243. }
  244.  
  245. /*
  246.  * getpwent - get a password entry from the password file
  247.  *
  248.  * getpwent() opens the password file, if not already opened, and reads
  249.  * a single entry.  NULL is returned if any errors are encountered reading
  250.  * the password file.
  251.  */
  252.  
  253. struct passwd *
  254. getpwent ()
  255. {
  256.     if (! pwdfp && setpwent ())
  257.         return 0;
  258.  
  259.     return fgetpwent (pwdfp);
  260. }
  261.  
  262. /*
  263.  * getpwuid - locate the password entry for a given UID
  264.  *
  265.  * getpwuid() locates the first password file entry for the given UID.
  266.  * If there is a valid DBM file, the DBM files are queried first for
  267.  * the entry.  Otherwise, a linear search is begun of the password file
  268.  * searching for an entry which matches the provided UID.
  269.  */
  270.  
  271. struct passwd *
  272. getpwuid (uid)
  273. int    uid;
  274. {
  275.     struct    passwd    *pwd;
  276. #if defined(DBM) || defined(NDBM)
  277.     datum    key;
  278.     datum    content;
  279. #endif
  280. #ifdef    AUTOSHADOW
  281.     struct    spwd    *spwd;
  282. #endif
  283.  
  284.     if (setpwent ())
  285.         return 0;
  286.  
  287. #if defined(DBM) || defined(NDBM)
  288.  
  289.     /*
  290.      * If the DBM file are now open, create a key for this UID and
  291.      * try to fetch the entry from the database.  A matching record
  292.      * will be unpacked into a static structure and returned to
  293.      * the user.
  294.      */
  295.  
  296.     if (dbmopened) {
  297.         pwent.pw_uid = uid;
  298.         key.dsize = sizeof pwent.pw_uid;
  299.         key.dptr = (char *) &pwent.pw_uid;
  300. #ifdef    DBM
  301.         content = fetch (key);
  302. #endif
  303. #ifdef    NDBM
  304.         content = dbm_fetch (pw_dbm, key);
  305. #endif
  306.         if (content.dptr != 0) {
  307.             memcpy (pwdbuf, content.dptr, content.dsize);
  308.             pw_unpack (pwdbuf, content.dsize, &pwent);
  309. #ifdef    AUTOSHADOW
  310.             if (spwd = getspnam (pwent.pw_name)) {
  311.                 pwent.pw_passwd = spwd->sp_pwdp;
  312. #ifdef    ATT_AGE
  313.                 pwent.pw_age = sptopwage (spwd);
  314. #endif
  315.             }
  316. #endif
  317.             return &pwent;
  318.         }
  319.     }
  320. #endif
  321.     /*
  322.      * Search for an entry which matches the UID.  Return the
  323.      * entry when a match is found.
  324.      */
  325.  
  326.     while (pwd = getpwent ())
  327.         if (pwd->pw_uid == uid)
  328.             break;
  329.  
  330. #ifdef    AUTOSHADOW
  331.     if (pwd && (spwd = getspnam (pwd->pw_name))) {
  332.         pwd->pw_passwd = spwd->sp_pwdp;
  333. #ifdef    ATT_AGE
  334.         pwd->pw_age = sptopwage (spwd);
  335. #endif
  336.     }
  337. #endif
  338.     return pwd;
  339. }
  340.  
  341. /*
  342.  * getpwnam - locate the password entry for a given name
  343.  *
  344.  * getpwnam() locates the first password file entry for the given name.
  345.  * If there is a valid DBM file, the DBM files are queried first for
  346.  * the entry.  Otherwise, a linear search is begun of the password file
  347.  * searching for an entry which matches the provided name.
  348.  */
  349.  
  350. struct passwd *
  351. getpwnam (name)
  352. char    *name;
  353. {
  354.     struct    passwd    *pwd;
  355. #if defined(DBM) || defined(NDBM)
  356.     datum    key;
  357.     datum    content;
  358. #endif
  359. #ifdef    AUTOSHADOW
  360.     struct    spwd    *spwd;
  361. #endif
  362.  
  363.     if (setpwent ())
  364.         return 0;
  365.  
  366. #if defined(DBM) || defined(NDBM)
  367.  
  368.     /*
  369.      * If the DBM file are now open, create a key for this UID and
  370.      * try to fetch the entry from the database.  A matching record
  371.      * will be unpacked into a static structure and returned to
  372.      * the user.
  373.      */
  374.  
  375.     if (dbmopened) {
  376.         key.dsize = strlen (name);
  377.         key.dptr = name;
  378. #ifdef    DBM
  379.         content = fetch (key);
  380. #endif
  381. #ifdef    NDBM
  382.         content = dbm_fetch (pw_dbm, key);
  383. #endif
  384.         if (content.dptr != 0) {
  385.             memcpy (pwdbuf, content.dptr, content.dsize);
  386.             pw_unpack (pwdbuf, content.dsize, &pwent);
  387. #ifdef    AUTOSHADOW
  388.             if (spwd = getspnam (pwent.pw_name)) {
  389.                 pwent.pw_passwd = spwd->sp_pwdp;
  390. #ifdef    ATT_AGE
  391.                 pwent.pw_age = sptopwage (spwd);
  392. #endif
  393.             }
  394. #endif
  395.             return &pwent;
  396.         }
  397.     }
  398. #endif
  399.     /*
  400.      * Search for an entry which matches the name.  Return the
  401.      * entry when a match is found.
  402.      */
  403.  
  404.     while (pwd = getpwent ())
  405.         if (strcmp (pwd->pw_name, name) == 0)
  406.             break;
  407.  
  408. #ifdef    AUTOSHADOW
  409.     if (pwd && (spwd = getspnam (pwd->pw_name))) {
  410.         pwd->pw_passwd = spwd->sp_pwdp;
  411. #ifdef    ATT_AGE
  412.         pwd->pw_age = sptopwage (spwd);
  413. #endif
  414.     }
  415. #endif
  416.     return pwd;
  417. }
  418.  
  419. /*
  420.  * setpwent - open the password file
  421.  *
  422.  * setpwent() opens the system password file, and the DBM password files
  423.  * if they are present.  The system password file is rewound if it was
  424.  * open already.
  425.  */
  426.  
  427. int
  428. setpwent ()
  429. {
  430. #ifdef    NDBM
  431.     int    mode;
  432. #endif
  433.  
  434.     if (! pwdfp) {
  435.         if (! (pwdfp = fopen (pwdfile, "r")))
  436.             return -1;
  437.     } else {
  438.         if (fseek (pwdfp, 0L, 0) != 0)
  439.             return -1;
  440.     }
  441.  
  442.     /*
  443.      * Attempt to open the DBM files if they have never been opened
  444.      * and an error has never been returned.
  445.      */
  446.  
  447. #if defined (DBM) || defined (NDBM)
  448.     if (! dbmerror && ! dbmopened) {
  449.         char    dbmfiles[BUFSIZ];
  450.  
  451.         strcpy (dbmfiles, pwdfile);
  452.         strcat (dbmfiles, ".pag");
  453. #ifdef    NDBM
  454.         if (pw_dbm_mode == -1)
  455.             mode = O_RDONLY;
  456.         else
  457.             mode = (pw_dbm_mode == O_RDONLY ||
  458.                 pw_dbm_mode == O_RDWR) ? pw_dbm_mode:O_RDONLY;
  459. #endif
  460. #ifdef    DBM
  461.         if (access (dbmfiles, 0) || dbminit (pwdfile))
  462. #endif
  463. #ifdef    NDBM
  464.         if (access (dbmfiles, 0) ||
  465.             (! (pw_dbm = dbm_open (pwdfile, mode, 0))))
  466. #endif
  467.             dbmerror = 1;
  468.         else
  469.             dbmopened = 1;
  470.     }
  471. #endif
  472.     return 0;
  473. }
  474.