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

  1. /*
  2.  * Copyright 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 <grp.h>
  14. #ifdef    BSD
  15. #include <strings.h>
  16. #define    strchr    index
  17. #define    strrchr    rindex
  18. #else    /* !BSD */
  19. #include <string.h>
  20. #endif    /* BSD */
  21. #include "config.h"
  22.  
  23. #ifdef    AUTOSHADOW
  24. #include "shadow.h"
  25. #endif    /* AUTOSHADOW */
  26.  
  27. #ifdef    NDBM
  28. #include <ndbm.h>
  29. #include <fcntl.h>
  30. DBM    *gr_dbm;
  31. int    gr_dbm_mode = -1;
  32. #endif    /* NDBM */
  33.  
  34. #ifndef    lint
  35. static    char    sccsid[] = "@(#)grent.c    3.7    08:03:08    12/20/90";
  36. #endif    /* !lint */
  37.  
  38. #define    NFIELDS    4
  39. #define    MAXMEM    1024
  40.  
  41. static    char    grpbuf[4*BUFSIZ];
  42. static    char    *grpfields[NFIELDS];
  43. static    char    *members[MAXMEM+1];
  44. static    struct    group    grent;
  45.  
  46. static    FILE    *grpfp;
  47. static    char    *grpfile = GRPFILE;
  48. #ifdef    NDBM
  49. static    int    dbmopened;
  50. static    int    dbmerror;
  51. #endif    /* NDBM */
  52.  
  53. char *
  54. fgetsx (buf, cnt, f)
  55. char    *buf;
  56. int    cnt;
  57. FILE    *f;
  58. {
  59.     int    c;
  60.     char    *cp = buf;
  61.     char    *ep;
  62.  
  63.     while (cnt > 0) {
  64.         if (fgets (cp, cnt, f) == 0)
  65.             if (cp == buf)
  66.                 return 0;
  67.             else
  68.                 break;
  69.  
  70.         if ((ep = strrchr (cp, '\\')) && *(ep + 1) == '\n') {
  71.             if ((cnt -= ep - cp) > 0)
  72.                 *(cp = ep) = '\0';
  73.         } else
  74.             break;
  75.     }
  76.     return buf;
  77. }
  78.  
  79. int
  80. fputsx (s, stream)
  81. char    *s;
  82. FILE    *stream;
  83. {
  84.     int    i;
  85.  
  86.     for (i = 0;*s;i++, s++) {
  87.         if (putc (*s, stream) == EOF)
  88.             return EOF;
  89.  
  90.         if (i > (BUFSIZ/2)) {
  91.             if (putc ('\\', stream) == EOF ||
  92.                 putc ('\n', stream) == EOF)
  93.                 return EOF;
  94.  
  95.             i = 0;
  96.         }
  97.     }
  98.     return 0;
  99. }
  100.  
  101. static char **
  102. list (s)
  103. char    *s;
  104. {
  105.     int    nmembers = 0;
  106.  
  107.     while (*s) {
  108.         members[nmembers++] = s;
  109.         if (s = strchr (s, ','))
  110.             *s++ = '\0';
  111.     }
  112.     members[nmembers] = (char *) 0;
  113.     return members;
  114. }
  115.  
  116. struct    group    *sgetgrent (buf)
  117. char    *buf;
  118. {
  119.     int    i;
  120.     char    *cp;
  121.  
  122.     strncpy (grpbuf, buf, sizeof grpbuf);
  123.     grpbuf[sizeof grpbuf - 1] = '\0';
  124.     if (cp = strrchr (grpbuf, '\n'))
  125.         *cp = '\0';
  126.  
  127.     for (cp = grpbuf, i = 0;i < NFIELDS && cp;i++) {
  128.         grpfields[i] = cp;
  129.         if (cp = strchr (cp, ':'))
  130.             *cp++ = 0;
  131.     }
  132.     if (i < (NFIELDS-1) || *grpfields[2] == '\0')
  133.         return ((struct group *) 0);
  134.  
  135.     grent.gr_name = grpfields[0];
  136.     grent.gr_passwd = grpfields[1];
  137.     grent.gr_gid = atoi (grpfields[2]);
  138.     grent.gr_mem = list (grpfields[3]);
  139.  
  140.     return (&grent);
  141. }
  142.  
  143. int
  144. putgrent (g, f)
  145. struct    group    *g;
  146. FILE    *f;
  147. {
  148.     int    i;
  149.     char    *cp;
  150.     char    buf[BUFSIZ*4];
  151.  
  152.     if (! g || ! f)
  153.         return -1;
  154.  
  155.     sprintf (buf, "%s:%s:%d:", g->gr_name, g->gr_passwd, g->gr_gid);
  156.     if (g->gr_mem) {
  157.         cp = strchr (buf, '\0');
  158.         for (i = 0;g->gr_mem[i];i++) {
  159.             if ((cp - buf) + strlen (g->gr_mem[i]) + 2
  160.                     >= sizeof buf)
  161.                 return -1;
  162.  
  163.             if (i > 0) {
  164.                 strcpy (cp, ",");
  165.                 cp++;
  166.             }
  167.             strcpy (cp, g->gr_mem[i]);
  168.             cp = strchr (cp, '\0');
  169.         }
  170.         strcat (cp, "\n");
  171.     } else
  172.         strcat (buf, "\n");
  173.  
  174.     if (fputsx (buf, f) == EOF || ferror (f))
  175.         return -1;
  176.  
  177.     return 0;
  178. }
  179.  
  180. /*
  181.  * fgetgrent - get a group file entry from a stream
  182.  *
  183.  * fgetgrent() reads the next line from a group file formatted stream
  184.  * and returns a pointer to the group structure for that line.
  185.  */
  186.  
  187. struct    group    *fgetgrent (fp)
  188. FILE    *fp;
  189. {
  190.     char    buf[BUFSIZ*4];
  191.     char    *cp;
  192.  
  193.     if (fgetsx (buf, sizeof buf, fp) != (char *) 0) {
  194.         if (cp = strchr (buf, '\n'))
  195.             *cp = '\0';
  196.  
  197.         return (sgetgrent (buf));
  198.     }
  199.     return 0;
  200. }
  201.  
  202. /*
  203.  * endgrent - close a group file
  204.  *
  205.  * endgrent() closes the group file if open.
  206.  */
  207.  
  208. int    endgrent ()
  209. {
  210.     if (grpfp)
  211.         if (fclose (grpfp))
  212.             return -1;
  213.  
  214.     grpfp = 0;
  215. #ifdef    NDBM
  216.     if (dbmopened && gr_dbm) {
  217.         dbm_close (gr_dbm);
  218.         gr_dbm = 0;
  219.     }
  220.     dbmopened = 0;
  221.     dbmerror = 0;
  222. #endif    /* NDBM */
  223.     return 0;
  224. }
  225.  
  226. /*
  227.  * getgrent - get a group entry from the group file
  228.  *
  229.  * getgrent() opens the group file, if not already opened, and reads
  230.  * a single entry.  NULL is returned if any errors are encountered reading
  231.  * the group file.
  232.  */
  233.  
  234. struct    group    *getgrent ()
  235. {
  236.     if (! grpfp && setgrent ())
  237.         return 0;
  238.  
  239.     return fgetgrent (grpfp);
  240. }
  241.  
  242. /*
  243.  * getgrgid - locate the group entry for a given GID
  244.  *
  245.  * getgrgid() locates the first group file entry for the given GID.
  246.  * If there is a valid DBM file, the DBM files are queried first for
  247.  * the entry.  Otherwise, a linear search is begun of the group file
  248.  * searching for an entry which matches the provided GID.
  249.  */
  250.  
  251. struct    group    *getgrgid (gid)
  252. int    gid;
  253. {
  254.     struct    group    *grp;
  255. #ifdef NDBM
  256.     datum    key;
  257.     datum    content;
  258.     int    cnt;
  259.     int    i;
  260.     char    *cp;
  261.     char    grpkey[64];
  262. #endif    /* NDBM */
  263. #ifdef    AUTOSHADOW
  264.     struct    sgrp    *sgrp;
  265. #endif    /* AUTOSHADOW */
  266.  
  267.     if (setgrent ())
  268.         return 0;
  269.  
  270. #ifdef NDBM
  271.  
  272.     /*
  273.      * If the DBM file are now open, create a key for this GID and
  274.      * try to fetch the entry from the database.  A matching record
  275.      * will be unpacked into a static structure and returned to
  276.      * the user.
  277.      */
  278.  
  279.     if (dbmopened) {
  280.         grent.gr_gid = gid;
  281.         key.dsize = sizeof grent.gr_gid;
  282.         key.dptr = (char *) &grent.gr_gid;
  283.         content = dbm_fetch (gr_dbm, key);
  284.         if (content.dptr == 0)
  285.             return 0;
  286.  
  287.         if (content.dsize == sizeof (int)) {
  288.             memcpy (&cnt, content.dptr, content.dsize);
  289.             for (cp = grpbuf, i = 0;i < cnt;i++) {
  290.                 memcpy (grpkey, &i, sizeof i);
  291.                 memcpy (grpkey + sizeof i, &grent.gr_gid,
  292.                     sizeof grent.gr_gid);
  293.  
  294.                 key.dsize = sizeof i + sizeof grent.gr_gid;
  295.                 key.dptr = grpkey;
  296.  
  297.                 content = dbm_fetch (gr_dbm, key);
  298.                 if (content.dptr == 0)
  299.                     return 0;
  300.  
  301.                 memcpy (cp, content.dptr, content.dsize);
  302.                 cp += content.dsize;
  303.             }
  304.             grent.gr_mem = members;
  305.             gr_unpack (grpbuf, cp - grpbuf, &grent);
  306. #ifdef    AUTOSHADOW
  307.             if (sgrp = getsgnam (grent.gr_name)) {
  308.                 grent.gr_passwd = sgrp->sg_passwd;
  309.                 grent.gr_mem = sgrp->sg_mem;
  310.             }
  311. #endif    /* AUTOSHADOW */
  312.             return &grent;
  313.         } else {
  314.             grent.gr_mem = members;
  315.             memcpy (grpbuf, content.dptr, content.dsize);
  316.             gr_unpack (grpbuf, content.dsize, &grent);
  317. #ifdef    AUTOSHADOW
  318.             if (sgrp = getsgnam (grent.gr_name)) {
  319.                 grent.gr_passwd = sgrp->sg_passwd;
  320.                 grent.gr_mem = sgrp->sg_mem;
  321.             }
  322. #endif    /* AUTOSHADOW */
  323.             return &grent;
  324.         }
  325.     }
  326. #endif    /* NDBM */
  327.     /*
  328.      * Search for an entry which matches the GID.  Return the
  329.      * entry when a match is found.
  330.      */
  331.  
  332.     while (grp = getgrent ())
  333.         if (grp->gr_gid == gid)
  334.             break;
  335.  
  336. #ifdef    AUTOSHADOW
  337.     if (grp) {
  338.         if (sgrp = getsgnam (grent.gr_name)) {
  339.             grp->gr_passwd = sgrp->sg_passwd;
  340.             grp->gr_mem = sgrp->sg_mem;
  341.         }
  342.     }
  343. #endif    /* AUTOSHADOW */
  344.     return grp;
  345. }
  346.  
  347. struct    group    *getgrnam (name)
  348. char    *name;
  349. {
  350.     struct    group    *grp;
  351. #ifdef NDBM
  352.     datum    key;
  353.     datum    content;
  354.     int    cnt;
  355.     int    i;
  356.     char    *cp;
  357.     char    grpkey[64];
  358. #endif    /* NDBM */
  359. #ifdef    AUTOSHADOW
  360.     struct    sgrp    *sgrp;
  361. #endif    /* AUTOSHADOW */
  362.  
  363.     if (setgrent ())
  364.         return 0;
  365.  
  366. #ifdef NDBM
  367.  
  368.     /*
  369.      * If the DBM file are now open, create a key for this GID 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.         content = dbm_fetch (gr_dbm, key);
  379.         if (content.dptr == 0)
  380.             return 0;
  381.  
  382.         if (content.dsize == sizeof (int)) {
  383.             memcpy (&cnt, content.dptr, content.dsize);
  384.             for (cp = grpbuf, i = 0;i < cnt;i++) {
  385.                 memcpy (grpkey, &i, sizeof i);
  386.                 strcpy (grpkey + sizeof i, name);
  387.  
  388.                 key.dsize = sizeof i + strlen (name);
  389.                 key.dptr = grpkey;
  390.  
  391.                 content = dbm_fetch (gr_dbm, key);
  392.                 if (content.dptr == 0)
  393.                     return 0;
  394.  
  395.                 memcpy (cp, content.dptr, content.dsize);
  396.                 cp += content.dsize;
  397.             }
  398.             grent.gr_mem = members;
  399.             gr_unpack (grpbuf, cp - grpbuf, &grent);
  400. #ifdef    AUTOSHADOW
  401.             if (sgrp = getsgnam (grent.gr_name)) {
  402.                 grent.gr_passwd = sgrp->sg_passwd;
  403.                 grent.gr_mem = sgrp->sg_mem;
  404.             }
  405. #endif    /* AUTOSHADOW */
  406.             return &grent;
  407.         } else {
  408.             grent.gr_mem = members;
  409.             memcpy (grpbuf, content.dptr, content.dsize);
  410.             gr_unpack (grpbuf, content.dsize, &grent);
  411. #ifdef    AUTOSHADOW
  412.             if (sgrp = getsgnam (grent.gr_name)) {
  413.                 grent.gr_passwd = sgrp->sg_passwd;
  414.                 grent.gr_mem = sgrp->sg_mem;
  415.             }
  416. #endif    /* AUTOSHADOW */
  417.             return &grent;
  418.         }
  419.     }
  420. #endif    /* NDBM */
  421.     /*
  422.      * Search for an entry which matches the name.  Return the
  423.      * entry when a match is found.
  424.      */
  425.  
  426.     while (grp = getgrent ())
  427.         if (strcmp (grp->gr_name, name) == 0)
  428.             break;
  429.  
  430. #ifdef    AUTOSHADOW
  431.     if (grp) {
  432.         if (sgrp = getsgnam (grent.gr_name)) {
  433.             grp->gr_passwd = sgrp->sg_passwd;
  434.             grp->gr_mem = sgrp->sg_mem;
  435.         }
  436.     }
  437. #endif    /* AUTOSHADOW */
  438.     return 0;
  439. }
  440.  
  441. /*
  442.  * setgrent - open the group file
  443.  *
  444.  * setgrent() opens the system group file, and the DBM group files
  445.  * if they are present.  The system group file is rewound if it was
  446.  * open already.
  447.  */
  448.  
  449. int
  450. setgrent ()
  451. {
  452. #ifdef    NDBM
  453.     int    mode;
  454. #endif    /* NDBM */
  455.  
  456.     if (! grpfp) {
  457.         if (! (grpfp = fopen (grpfile, "r")))
  458.             return -1;
  459.     } else {
  460.         if (fseek (grpfp, 0L, 0) != 0)
  461.             return -1;
  462.     }
  463.  
  464.     /*
  465.      * Attempt to open the DBM files if they have never been opened
  466.      * and an error has never been returned.
  467.      */
  468.  
  469. #ifdef NDBM
  470.     if (! dbmerror && ! dbmopened) {
  471.         char    dbmfiles[BUFSIZ];
  472.  
  473.         strcpy (dbmfiles, grpfile);
  474.         strcat (dbmfiles, ".pag");
  475.         if (gr_dbm_mode == -1)
  476.             mode = O_RDONLY;
  477.         else
  478.             mode = (gr_dbm_mode == O_RDONLY ||
  479.                 gr_dbm_mode == O_RDWR) ? gr_dbm_mode:O_RDONLY;
  480.  
  481.         if (access (dbmfiles, 0) ||
  482.             (! (gr_dbm = dbm_open (grpfile, mode, 0))))
  483.             dbmerror = 1;
  484.         else
  485.             dbmopened = 1;
  486.     }
  487. #endif    /* NDBM */
  488.     return 0;
  489. }
  490.