home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / comm / tcp / amitcp / src / devs / netinfo / groupunit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-19  |  7.8 KB  |  317 lines

  1. RCS_ID_C="$Id: groupunit.c,v 3.2 1994/05/19 04:29:29 ppessi Exp $";
  2. /*
  3.  * groupunit.c --- unit for groups
  4.  *
  5.  * Author: ppessi <Pekka.Pessi@hut.fi>
  6.  *
  7.  * This file is part of the AmiTCP/IP netinfo.device.
  8.  *
  9.  * Copyright © 1993 AmiTCP/IP Group, <AmiTCP-Group@hut.fi>
  10.  *                  Helsinki University of Technology, Finland.
  11.  *
  12.  * Created      : Wed Sep 15 01:25:26 1993 ppessi
  13.  * Last modified: Thu May 19 04:01:42 1994 ppessi
  14.  */
  15.  
  16. #include "entries.h"
  17. #include <assert.h>
  18. #include <string.h>
  19.  
  20. static void *CopyEntToGroup(struct NetInfoReq *req, struct Ent *e);
  21. static struct Ent *CopyGroupToEnt(BASE, struct NetInfoReq *req);
  22. static struct Ent *ParseGroup(BASE, register UBYTE *p);
  23. static int PrintGroup(BASE, BPTR file, struct Ent *e);
  24. static void GetGroups(BASE, struct NetInfoReq *req, struct NetInfoMap *nim);
  25.  
  26. const static struct MapMethods group_methods[1] = 
  27. {
  28.   {
  29.     /* Other methods */
  30.     ParseGroup,
  31.     PrintGroup,
  32.     CopyEntToGroup,
  33.     CopyGroupToEnt,
  34.     EntCleanup,
  35.     GetGroups,
  36.     EntHandleNotify,
  37.   },
  38. };
  39.  
  40. /*
  41.  * Allocate and initialize group map
  42.  */
  43. struct NetInfoMap *InitGroupMap(BASE)
  44. {
  45.   struct NetInfoMap *nim = AllocVec(sizeof(*nim), MEMF_CLEAR|MEMF_PUBLIC);
  46.  
  47.   if (nim) {
  48.     nim->nim_Methods = group_methods;
  49.     nim->nim_Name = "group";
  50.     nim->nim_Filename = _PATH_GROUP;
  51.   }
  52.  
  53.   return nim;
  54. }
  55.  
  56. /*
  57.  * Copy an GroupEnt structure to group structure 
  58.  */
  59. static void *CopyEntToGroup(struct NetInfoReq *req, struct Ent *e)
  60. {
  61.   struct GroupEnt *ge = (struct GroupEnt *)e;
  62.   struct NetInfoGroup *gr = req->io_Data;
  63.   STRPTR *mto = (STRPTR *)(gr + 1);
  64.   UBYTE  *to = (UBYTE *)(mto + ge->ge_nmembers);
  65.  
  66.   ULONG size = req->io_Length;
  67.   ULONG actual = sizeof(*gr) + ge->ge_tlen + ge->ge_nmembers * sizeof(UBYTE *);
  68.  
  69.   UBYTE **mfrom;
  70.  
  71.   req->io_Actual = actual;
  72.   
  73.   if (size < actual) {
  74.     return NULL;
  75.   }
  76.  
  77.   /* copy group strings */
  78.   to = stpcopy(gr->gr_name = to, ge->ge_group->gr_name);
  79.   to = stpcopy(gr->gr_passwd = to, ge->ge_group->gr_passwd);
  80.   /* .. and id */
  81.   gr->gr_gid = ge->ge_group->gr_gid;
  82.  
  83.   /* .. and members */
  84.   for (gr->gr_mem = mto, mfrom = ge->ge_group->gr_mem; 
  85.        *mfrom && (*mto++ = to); ) {
  86.     to = stpcopy(to, *mfrom++);
  87.   }
  88.   *mto = NULL;
  89.   assert(to <= (UBYTE *)req->io_Data + req->io_Length);
  90.  
  91.   return gr;
  92. }
  93.  
  94. /*
  95.  * Copy an group structure into a internal entry
  96.  */
  97. static struct Ent *CopyGroupToEnt(BASE, struct NetInfoReq *req)
  98. {
  99.   struct NetInfoGroup *gr = (struct NetInfoGroup*)req->io_Data;
  100.   struct GroupEnt *ge;
  101.   UBYTE *to, **mem, **mto;
  102.   short nmem = 1;
  103.   ULONG txtlen = 0;
  104.   
  105.   /*
  106.    * These cause EFAULT
  107.    */
  108.   if (gr == NULL || (1 & (LONG)gr) != 0 ||
  109.       gr->gr_name == NULL || 
  110.       gr->gr_passwd == NULL ||
  111.       gr->gr_mem == NULL || (1 & (LONG)gr->gr_mem)) {
  112.     req->io_Error = IOERR_BADADDRESS;
  113.     return NULL;
  114.   }
  115.  
  116.   for (mem = gr->gr_mem; *mem; mem++, nmem++) {
  117.     if (*mem == NULL) {
  118.       req->io_Error = IOERR_BADADDRESS;
  119.       return NULL;
  120.     }
  121.     txtlen += strlen(*mem) + 1;
  122.   }
  123.  
  124.   txtlen += strlen(gr->gr_name) + strlen(gr->gr_passwd) + 2;
  125.  
  126.   ge = AllocVec(sizeof(*ge) + nmem * sizeof(*mem) + txtlen, MEMF_CLEAR);
  127.   if (ge == NULL) {
  128.     req->io_Error = NIERR_NOMEM;
  129.     return NULL;
  130.   }
  131.  
  132.   ge->ge_node.ln_Type = ENT_GROUP;
  133.   ge->ge_node.ln_Pri  = ENT_CHANGED;
  134.   ge->ge_tlen = txtlen;
  135.   ge->ge_group->gr_gid = gr->gr_gid;
  136.  
  137.   ge->ge_nmembers = nmem;
  138.   ge->ge_group->gr_mem = mto = (UBYTE **)(ge + 1);
  139.   to = (UBYTE *)(mto + nmem);
  140.   /* Copy normal strings.. */
  141.   to = stpcopy(ge->ge_group->gr_name   = to, gr->gr_name);
  142.   to = stpcopy(ge->ge_group->gr_passwd = to, gr->gr_passwd);
  143.   /* ..and members */
  144.   for (mem = gr->gr_mem; *mem; mem++) {
  145.     to = stpcopy(*mto++ = to, *mem);
  146.     nmem--;
  147.   }
  148.   *mem = NULL;
  149.   assert(to == ge->ge_group->gr_name + txtlen);
  150.   assert(nmem == 1);
  151.  
  152.   return (struct Ent *)ge;
  153. }
  154.  
  155. /****** netinfo.device/group ***********************************************
  156.  
  157.    NAME
  158.         group - format of the group permissions file
  159.  
  160.    DESCRIPTION     
  161.         The file <AmiTCP:db/group> consists of newline separated ASCII
  162.         records, one per group, containing four bar `|' separated fields.
  163.         These fields are as follows:
  164.  
  165.               group     Name of the group.
  166.               passwd    Group's encrypted password.
  167.               gid       The group's decimal ID.
  168.               member    Group members.
  169.  
  170.         The group field is the group name used for granting file access to
  171.         users who are members of the group.  The gid field is the number
  172.         associated with the group name.  They should both be unique across
  173.         the system (and often across a group of systems) since they control
  174.         file access.  The passwd field is an optional encrypted password.
  175.         This field is rarely used and an asterisk is normally placed in it
  176.         rather than leaving it blank.  The member field contains the names
  177.         of users granted the priviledges of group. The member names are
  178.         separated by commas with out spaces or newlines.  A user is
  179.         automatically in a group if that group was specified in their
  180.         AmiTCP:db/passwd entry and does not need to be added to that group
  181.         in the AmiTCP:db/group file.
  182.  
  183.    FILES
  184.         AmiTCP:db/group
  185.  
  186.    SEE ALSO
  187.         passwd
  188.  
  189.    HISTORY
  190.         A group file format appeared in Version 6 AT&T UNIX.
  191.  
  192. ****************************************************************************
  193. */
  194.  
  195. /* 
  196.  * Parse the group entry
  197.  */
  198. static struct Ent *ParseGroup(BASE, register UBYTE *p)
  199. {
  200.   int l;
  201.   UBYTE *np, *name, *pass, *id_s, *memlist, **members;
  202.   ULONG nmembers;
  203.   LONG gid, txtlen = 0;
  204.  
  205.   struct GroupEnt *ge;
  206.  
  207.   np = p;
  208.  
  209.   name = strsep(&np, "|\n");
  210.   pass = strsep(&np, "|\n");
  211.   id_s = strsep(&np, "|\n");
  212.   memlist = np;
  213.   if ((l = StrToLong(id_s, &gid)) <= 0 || id_s[l] != '\0')
  214.     return NULL;
  215.   for (nmembers = 1; (p = strsep(&np, ", \n")) && np;) {
  216.     if (*p) nmembers++;
  217.     else txtlen--;
  218.     if (*np == '\0')
  219.       break;
  220.   }
  221.  
  222.   assert(np != NULL);
  223.  
  224.   if (!name || !pass || !id_s || !np)
  225.     return NULL;
  226.  
  227.   txtlen += np - name - (memlist - id_s);
  228.   ge = AllocVec(sizeof(*ge) + nmembers * sizeof(UBYTE*) + txtlen, MEMF_CLEAR);
  229.   if (!ge)
  230.     return NULL;
  231.  
  232.   ge->ge_node.ln_Type = ENT_GROUP;
  233.  
  234.   ge->ge_nmembers = nmembers;
  235.   ge->ge_tlen = txtlen;
  236.  
  237.   members = (UBYTE **)(ge + 1);
  238.   p = (UBYTE *)(members + nmembers);
  239.  
  240.   /* Copy name */
  241.   p = stpcopy(ge->ge_group->gr_name = p, name);
  242.   p = stpcopy(ge->ge_group->gr_passwd = p, pass);
  243.  
  244.   ge->ge_group->gr_gid = gid;
  245.   ge->ge_group->gr_mem = members;
  246.   
  247.   /* Copy the memberlist */
  248.   while (nmembers > 1) {
  249.     if (*memlist) {
  250.       nmembers--;
  251.       *members++ = p;
  252.       while (*p++ = *memlist++)
  253.     ;
  254.     } else {
  255.       memlist++;
  256.     }
  257.   }
  258.   *members = NULL;
  259.  
  260.   assert(p == ge->ge_group->gr_name + txtlen);
  261.  
  262.   return (struct Ent *)ge;
  263. }
  264.  
  265. /*
  266.  * Print out an group entry
  267.  */
  268. static int PrintGroup(BASE, BPTR file, struct Ent *e)
  269. {
  270.   struct GroupEnt *ge = (struct GroupEnt *)e;
  271.   UBYTE **member = ge->ge_group->gr_mem;
  272.   UBYTE *fmt = "%s";
  273.  
  274.   VFPrintf(file, "%s|%s|%ld|", (LONG*)ge->ge_group);
  275.   while (*member) {
  276.     FPrintf(file, fmt, *member++);
  277.     fmt = ",%s";
  278.   }
  279.   FPutC(file, '\n');
  280.  
  281.   return 0;
  282. }
  283.  
  284. /*
  285.  * Execute NI_MEMBERS command
  286.  */
  287. static void GetGroups(BASE, struct NetInfoReq *req, struct NetInfoMap *nim)
  288. {
  289.   int maxgroups = req->io_Length / sizeof(LONG);
  290.   LONG *groups = (LONG *)req->io_Data;
  291.   STRPTR uname = (STRPTR)req->io_Offset;
  292.   register int ngroups = 0;
  293.   register struct GroupEnt *ge;
  294.   register int i;
  295.   BYTE retval = 0;
  296.  
  297.   ge = (struct GroupEnt *)InternalSetEnts(nid, nim);
  298.  
  299.   while (ge = (struct GroupEnt *)GetNextEnt((struct Ent *)ge)) {
  300.     for (i = 0; ge->ge_group->gr_mem[i]; i++)
  301.       if (strcmp(ge->ge_group->gr_mem[i], uname) == 0) {
  302.     if (ngroups == maxgroups) {
  303.       retval = NIERR_TOOSMALL;
  304.       goto toomany;
  305.     }
  306.     groups[ngroups++] = ge->ge_group->gr_gid;
  307.       }
  308.   }
  309.  
  310.  toomany:
  311.   InternalEndEnts(nid, nim);
  312.  
  313.   req->io_Actual = ngroups * sizeof(LONG);
  314.   req->io_Error = retval;
  315.   TermIO(req);
  316. }
  317.