home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1610 / getpwent.c next >
C/C++ Source or Header  |  1990-12-28  |  7KB  |  301 lines

  1. /*
  2.  * Copyright 1990, John F. Haugh II
  3.  * All rights reserved.
  4.  *
  5.  * Use, duplication, and disclosure prohibited without
  6.  * the express written permission of the author.
  7.  *
  8.  * Duplication is permitted for non-commercial [ non-profit making ]
  9.  * purposes provided this and other copyright notices remain
  10.  * intact.
  11.  */
  12.  
  13. #include <stdio.h>
  14. #include <pwd.h>
  15. #include <string.h>
  16. #include <dbm.h>
  17.  
  18. #define    SBUFSIZ    64
  19. #define    NFIELDS    7
  20.  
  21. static    FILE    *pwdfp;
  22. static    char    pwdbuf[BUFSIZ];
  23. static    char    *pwdfile = "/etc/passwd";
  24. static    int    dbmopened;
  25. static    int    dbmerror;
  26. static    char    *pwdfields[NFIELDS];
  27. static    struct    passwd    pwent;
  28.  
  29. /*
  30.  * sgetpwent - convert a string to a (struct passwd)
  31.  *
  32.  * sgetpwent() parses a string into the parts required for a password
  33.  * structure.  Strict checking is made for the UID and GID fields and
  34.  * presence of the correct number of colons.  Any failing tests result
  35.  * in a NULL pointer being returned.
  36.  */
  37.  
  38. struct    passwd    *sgetpwent (buf)
  39. char    *buf;
  40. {
  41.     int    i;
  42.     char    *cp;
  43.  
  44.     /*
  45.      * Copy the string to a static buffer so the pointers into
  46.      * the password structure remain valid.
  47.      */
  48.  
  49.     strncpy (pwdbuf, buf, BUFSIZ);
  50.     pwdbuf[BUFSIZ-1] = '\0';
  51.  
  52.     /*
  53.      * Save a pointer to the start of each colon separated
  54.      * field.  The fields are converted into NUL terminated strings.
  55.      */
  56.  
  57.     for (cp = pwdbuf, i = 0;i < NFIELDS && cp;i++) {
  58.         pwdfields[i] = cp;
  59.         if (cp = strchr (cp, ':'))
  60.             *cp++ = 0;
  61.     }
  62.  
  63.     /*
  64.      * There must be exactly NFIELDS colon separated fields or
  65.      * the entry is invalid.  Also, the UID and GID must be non-blank.
  66.      */
  67.  
  68.     if (i != NFIELDS || *pwdfields[2] == '\0' || *pwdfields[3] == '\0')
  69.         return 0;
  70.  
  71.     /*
  72.      * Each of the fields is converted the appropriate data type
  73.      * and the result assigned to the password structure.  If the
  74.      * UID or GID does not convert to an integer value, a NULL
  75.      * pointer is returned.
  76.      */
  77.  
  78.     pwent.pw_name = pwdfields[0];
  79.     pwent.pw_passwd = pwdfields[1];
  80.     if ((pwent.pw_uid = strtol (pwdfields[2], &cp, 10)) == 0 && *cp)
  81.         return 0;
  82.  
  83.     if ((pwent.pw_gid = strtol (pwdfields[3], &cp, 10)) == 0 && *cp)
  84.         return 0;
  85.  
  86.     if (cp = strchr (pwent.pw_passwd, ',')) {
  87.         pwent.pw_age = cp + 1;
  88.         *cp = '\0';
  89.     }
  90.     pwent.pw_gecos = pwdfields[4];
  91.     pwent.pw_dir = pwdfields[5];
  92.     pwent.pw_shell = pwdfields[6];
  93.  
  94.     return (&pwent);
  95. }
  96.  
  97. /*
  98.  * fgetpwent - get a password file entry from a stream
  99.  *
  100.  * fgetpwent() reads the next line from a password file formatted stream
  101.  * and returns a pointer to the password structure for that line.
  102.  */
  103.  
  104. struct    passwd    *fgetpwent (fp)
  105. FILE    *fp;
  106. {
  107.     char    buf[BUFSIZ];
  108.     char    *cp;
  109.  
  110.     if (! fgets (buf, BUFSIZ, fp))
  111.         return 0;
  112.  
  113.     if (cp = strrchr (buf, '\n'))
  114.         *cp = '\0';
  115.  
  116.     return sgetpwent (buf);
  117. }
  118.  
  119. /*
  120.  * endpwent - close a password file
  121.  *
  122.  * endpwent() closes the password file if open.
  123.  */
  124.  
  125. int    endpwent ()
  126. {
  127.     if (pwdfp)
  128.         if (fclose (pwdfp))
  129.             return -1;
  130.  
  131.     return 0;
  132. }
  133.  
  134. /*
  135.  * getpwent - get a password entry from the password file
  136.  *
  137.  * getpwent() opens the password file, if not already opened, and reads
  138.  * a single entry.  NULL is returned if any errors are encountered reading
  139.  * the password file.
  140.  */
  141.  
  142. struct    passwd    *getpwent ()
  143. {
  144.     if (! pwdfp && setpwent ())
  145.         return 0;
  146.  
  147.     return fgetpwent (pwdfp);
  148. }
  149.  
  150. /*
  151.  * getpwuid - locate the password entry for a given UID
  152.  *
  153.  * getpwuid() locates the first password file entry for the given UID.
  154.  * If there is a valid DBM file, the DBM files are queried first for
  155.  * the entry.  Otherwise, a linear search is begun of the password file
  156.  * searching for an entry which matches the provided UID.
  157.  */
  158.  
  159. struct    passwd    *getpwuid (uid)
  160. int    uid;
  161. {
  162.     struct    passwd    *pwd;
  163.     datum    key;
  164.     datum    content;
  165.  
  166.     /*
  167.      * Attempt to open the DBM files if they have never been opened
  168.      * and an error has never been returned.
  169.      */
  170.  
  171.     if (! dbmerror && ! dbmopened)
  172.         if (dbminit (pwdfile) == 0)
  173.             dbmopened = 1;
  174.         else
  175.             dbmerror = 1;
  176.  
  177.     /*
  178.      * If the DBM file are now open, create a key for this UID and
  179.      * try to fetch the entry from the database.  A matching record
  180.      * will be unpacked into a static structure and returned to
  181.      * the user.
  182.      */
  183.  
  184.     if (dbmopened) {
  185.         pwent.pw_uid = uid;
  186.         key.dsize = sizeof pwent.pw_uid;
  187.         key.dptr = (char *) &pwent.pw_uid;
  188.         content = fetch (key);
  189.         if (content.dptr != 0) {
  190.             memcpy (pwdbuf, content.dptr, content.dsize);
  191.             pw_unpack (pwdbuf, content.dsize, &pwent);
  192.             return &pwent;
  193.         }
  194.     }
  195.  
  196.     /*
  197.      * Rewind the database and begin searching for an entry which
  198.      * matches the UID.  Return the entry when a match is found.
  199.      */
  200.  
  201.     if (setpwent ())
  202.         return 0;
  203.  
  204.     while (pwd = getpwent ())
  205.         if (pwd->pw_uid == uid)
  206.             return pwd;
  207.  
  208.     return 0;
  209. }
  210.  
  211. /*
  212.  * getpwuid - locate the password entry for a given name
  213.  *
  214.  * getpwuid() locates the first password file entry for the given name.
  215.  * If there is a valid DBM file, the DBM files are queried first for
  216.  * the entry.  Otherwise, a linear search is begun of the password file
  217.  * searching for an entry which matches the provided name.
  218.  */
  219.  
  220. struct    passwd    *getpwnam (name)
  221. char    *name;
  222. {
  223.     struct    passwd    *pwd;
  224.     datum    key;
  225.     datum    content;
  226.  
  227.     /*
  228.      * Attempt to open the DBM files if they have never been opened
  229.      * and an error has never been returned.
  230.      */
  231.  
  232.     if (! dbmerror && ! dbmopened)
  233.         if (dbminit (pwdfile) == 0)
  234.             dbmopened = 1;
  235.         else
  236.             dbmerror = 1;
  237.  
  238.     /*
  239.      * If the DBM file are now open, create a key for this name and
  240.      * try to fetch the entry from the database.  A matching record
  241.      * will be unpacked into a static structure and returned to
  242.      * the user.
  243.      */
  244.  
  245.     if (dbmopened) {
  246.         key.dsize = strlen (name);
  247.         key.dptr = name;
  248.         content = fetch (key);
  249.         if (content.dptr != 0) {
  250.             memcpy (pwdbuf, content.dptr, content.dsize);
  251.             pw_unpack (pwdbuf, content.dsize, &pwent);
  252.             return &pwent;
  253.         }
  254.     }
  255.  
  256.     /*
  257.      * Rewind the database and begin searching for an entry which
  258.      * matches the name.  Return the entry when a match is found.
  259.      */
  260.  
  261.     if (setpwent ())
  262.         return 0;
  263.  
  264.     while (pwd = getpwent ())
  265.         if (strcmp (pwd->pw_name, name) == 0)
  266.             return pwd;
  267.  
  268.     return 0;
  269. }
  270.  
  271. /*
  272.  * setpwent - open the password file
  273.  *
  274.  * setpwent() opens the system password file, and the DBM password files
  275.  * if they are present.  The system password file is rewound if it was
  276.  * open already.
  277.  */
  278.  
  279. int    setpwent ()
  280. {
  281.     if (! pwdfp) {
  282.         if (! (pwdfp = fopen (pwdfile, "r")))
  283.             return -1;
  284.     } else {
  285.         if (fseek (pwdfp, 0L, 0) != 0)
  286.             return -1;
  287.     }
  288.  
  289.     /*
  290.      * Attempt to open the DBM files if they have never been opened
  291.      * and an error has never been returned.
  292.      */
  293.  
  294.     if (! dbmerror && ! dbmopened)
  295.         if (dbminit (pwdfile) == 0)
  296.             dbmopened = 1;
  297.         else
  298.             dbmerror = 1;
  299.     return 0;
  300. }
  301.