Print this page
*** NO COMMENTS ***

@@ -19,10 +19,11 @@
  * CDDL HEADER END
  */
 
 /*
  * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
  * For SUNWnskit - version 1.1
  */

@@ -35,13 +36,15 @@
 #include <pwd.h>
 #include <rpcsvc/ypclnt.h>
 #include "util.h"
 #include "table.h"
 #include "getgroup.h"
+#include "revnetgroup.h"
 
 #define MAXDOMAINLEN 256
-#define MAXGROUPLEN 1024
+#define MAXGROUPLEN  131072
+#define MAXKEYLEN    512
 
 /*
  * Reverse the netgroup file. A flag of "-u" means reverse by username,
  * one of "-h" means reverse by hostname. Each line in the output file
  * will begin with a key formed by concatenating the host or user name

@@ -56,153 +59,195 @@
  * Thus to find out all the groups that user "foo" of domain "bar" is in,
  * lookup the groups under  foo.bar, foo.*, *.bar and *.*.
  *
  */
 
-
-
-/* Stores a list of strings */
-typedef struct stringnode *stringlist;
-struct stringnode {
-    char *str;
-    stringlist next;
-};
-typedef struct stringnode stringnode;
-
-
-
-/* Stores a list of (name,list-of-groups) */
-typedef struct groupentrynode *groupentrylist;
-struct groupentrynode {
-    char *name;
-    stringlist groups;
-    groupentrylist next;
-};
-typedef struct groupentrynode groupentrynode;
-
-stringtable ngtable;
-
-static groupentrylist grouptable[TABLESIZE];
-
-static char *nextgroup(void);
-static void storegroup(char *group, struct grouplist *glist, int byuser);
-static void enter(char *name, char *group);
+static char *nextgroup(revhandle_t *, tablelist *);
+static void storegroup(char *group, revhandle_t *hdl);
+static void enter(char *name, char *group, revhandle_t *hdl);
 static void appendgroup(groupentrylist grlist, char *group);
 static groupentrylist newentry(char *name, char *group);
-static void loadtable(FILE *nf);
-static void dumptable(void);
+static void loadtable(FILE *nf, revhandle_t *hdl);
+static void dumptable(FILE *out, revhandle_t *hdl);
+static void free_table(revhandle_t *hdl);
 
 int
-main(argc, argv)
-    int argc;
-    char *argv[];
+revnetgroup_handle(FILE *fin, FILE *fout, boolean_t byuser)
 {
         char *group;
-        struct grouplist *glist;
-        int byuser;
+        revhandle_t hdl = {0};
+        tablelist walker = NULL;
 
-        loadtable(stdin);
-        if (argc == 2 && argv[1][0] == '-' &&
-                        (argv[1][1] == 'u' || argv[1][1] == 'h')) {
-                byuser = (argv[1][1] == 'u');
-        } else {
-                (void) fprintf(stderr,
-                                "usage: %s -h (by host), %s -u (by user)\n",
-                                argv[0], argv[0]);
-                exit(1);
-        }
+        hdl.rh_byuser = byuser;
+        loadtable(fin, &hdl);
 
-        while (group = nextgroup()) {
-                glist = my_getgroup(group);
-                storegroup(group, glist, byuser);
-        }
-        dumptable();
+        while (group = nextgroup(&hdl, &walker))
+                storegroup(group, &hdl);
 
+        dumptable(fout, &hdl);
+        free_table(&hdl);
         return (0);
 }
 
 /*
  *      Get the next netgroup from /etc/netgroup
  */
 static char *
-nextgroup(void)
+nextgroup(revhandle_t *hdl, tablelist *next)
 {
-        static int index = -1;
-        static tablelist cur = NULL;
-        char *group;
+        tablelist entry = *next;
+        uint_t i;
 
-        while (cur == NULL) {
-                if (++index == TABLESIZE) {
-                        return (NULL);
+        if (entry == NULL) {
+                for (i = hdl->rh_index; i < TABLESIZE; i++) {
+                        entry = hdl->ngtable[i];
+                        if (entry != NULL) {
+                                hdl->rh_index = i + 1;
+                                break;
                 }
-                cur = ngtable[index];
         }
-        group = cur->key;
-        cur = cur->next;
-        return (group);
+        }
+
+        if (entry == NULL) {
+                /* out of table */
+                hdl->rh_index = 0;
+                return (NULL);
+        }
+
+        *next = entry->next;
+        return (entry->key);
 }
 
 
+static void
+free_tablelist(tablelist e)
+{
+        tablelist next;
 
+        do {
+                next = e->next;
+
+                free(e->key);
+                free(e->datum);
+                free(e);
+        } while ((e = next) != NULL);
+}
+
+static void
+free_stringnode(stringnode *s)
+{
+        stringnode *next;
+
+        do {
+                next = s->s_next;
+
+                free(s);
+        } while ((s = next) != NULL);
+}
+
+static void
+free_groupentrylist(groupentrylist e)
+{
+        groupentrylist next;
+
+        do {
+                next = e->next;
+
+                free_stringnode(e->groups);
+                free(e->name);
+                free(e);
+        } while ((e = next) != NULL);
+}
+
+static void
+free_table(revhandle_t *hdl)
+{
+        int i;
+
+        /* ngtable */
+        for (i = 0; i < TABLESIZE; i++) {
+                tablelist e;
+
+                if ((e = hdl->ngtable[i]) == NULL)
+                        continue;
+
+                free_tablelist(e);
+                hdl->ngtable[i] = NULL;
+        }
+
+        /* grouptable */
+        for (i = 0; i < TABLESIZE; i++) {
+                groupentrylist e;
+
+                if ((e = hdl->grouptable[i]) == NULL)
+                        continue;
+
+                free_groupentrylist(e);
+                hdl->grouptable[i] = NULL;
+        }
+}
+
 /*
  * Dump out all of the stored info into a file
  */
 static void
-dumptable(void)
+dumptable(FILE *out, revhandle_t *hdl)
 {
         int i;
         groupentrylist entry;
-        stringlist groups;
+        stringnode *groups;
 
         for (i = 0; i < TABLESIZE; i++) {
-                if (entry = grouptable[i]) {
+                if (entry = hdl->grouptable[i]) {
                         while (entry) {
-                                fputs(entry->name, stdout);
-                                putc('\t', stdout);
+                                fputs(entry->name, out);
+                                putc('\t', out);
                                 for (groups = entry->groups; groups;
-                                                groups = groups->next) {
-                                        fputs(groups->str, stdout);
-                                        if (groups->next) {
-                                                putc(',', stdout);
+                                    groups = groups->s_next) {
+                                        fputs(groups->str, out);
+                                        if (groups->s_next) {
+                                                putc(',', out);
                                         }
                                 }
-                                putc('\n', stdout);
+                                putc('\n', out);
                                 entry = entry->next;
                         }
                 }
         }
 }
 
 
 
-
 /*
  *      Add a netgroup to a user's list of netgroups
  */
 static void
-storegroup(char *group, struct grouplist *glist, int byuser)
+storegroup(char *group, revhandle_t *hdl)
 {
-        char *name;     /* username or hostname */
-        char *domain;
-        char *key;
-        static char *universal = "*";
+        char key[MAXKEYLEN];
+        struct grouplist *glist;
 
-        for (; glist; glist = glist->gl_nxt) {
-                name = byuser ? glist->gl_name : glist->gl_machine;
+        doit(group, (struct list *)NULL, hdl);
+
+        for (glist = hdl->grouplist; glist; glist = glist->gl_nxt) {
+                const char *name;       /* username or hostname */
+                const char *domain;
+
+                name = hdl->rh_byuser ? glist->gl_name : glist->gl_machine;
                 if (!name) {
-                    name = universal;
+                        name = "*";
                 } else if (!isalnum(*name) && *name != '_') {
                     continue;
                 }
                 domain = glist->gl_domain;
                 if (!domain) {
-                    domain = universal;
+                        domain = "*";
                 }
-                key = malloc((unsigned) (strlen(name)+strlen(domain)+2));
-                (void) sprintf(key, "%s.%s", name, domain);
-                enter(key, group);
+                (void) snprintf(key, sizeof (key), "%s.%s", name, domain);
+                enter(key, group, hdl);
         }
+        freegrouplist(hdl);
 }
 
 
 
 static groupentrylist

@@ -214,44 +259,44 @@
 
         STRCPY(new->name, name);
 
         new->groups = MALLOC(stringnode);
         new->groups->str = group;
-        new->groups->next = NULL;
+        new->groups->s_next = NULL;
 
         new->next = NULL;
         return (new);
 }
 
 static void
 appendgroup(groupentrylist grlist, char *group)
 {
-        stringlist cur, prev;
+        stringnode *cur, *prev;
 
-        for (cur = grlist->groups; cur; prev = cur, cur = cur->next) {
+        for (cur = grlist->groups; cur; prev = cur, cur = cur->s_next) {
                 if (strcmp(group, cur->str) == 0) {
                     return;
                 }
         }
-        prev->next = MALLOC(stringnode);
-        cur = prev->next;
+        prev->s_next = MALLOC(stringnode);
+        cur = prev->s_next;
         cur->str = group;
-        cur->next = NULL;
+        cur->s_next = NULL;
 }
 
 static void
-enter(char *name, char *group)
+enter(char *name, char *group, revhandle_t *hdl)
 {
         int key;
         groupentrylist gel;
         groupentrylist gelprev;
 
         key = tablekey(name);
-        if (grouptable[key] == NULL) {
-                grouptable[key] = newentry(name, group);
+        if (hdl->grouptable[key] == NULL) {
+                hdl->grouptable[key] = newentry(name, group);
         } else {
-                gel = grouptable[key];
+                gel = hdl->grouptable[key];
                 while (gel && strcmp(gel->name, name)) {
                     gelprev = gel;
                     gel = gel->next;
                 }
                 if (gel) {

@@ -264,20 +309,25 @@
 
 /*
  * Load up a hash table with the info in /etc/netgroup
  */
 static void
-loadtable(FILE *nf)
+loadtable(FILE *nf, revhandle_t *hdl)
 {
-        char buf[MAXGROUPLEN];
+        char *buf;
         char *p;
         char *group;
         char *line;
 
+        buf = malloc(MAXGROUPLEN);
+        if (buf == NULL)
+                return;
+
         while (getaline(buf, MAXGROUPLEN, nf)) {
+                /* skip leading blanks */
                 for (p = buf; *p && isspace((int)*p); p++)
-                        ;       /* skip leading blanks */
+                        ;
                 for (; *p && *p != '#' && *p != ' ' && *p != '\t'; p++)
                         ;
                 if (*p == EOS || *p == '#')
                         continue;
                 *p++ = EOS;

@@ -288,8 +338,10 @@
                 if (*p == EOS || *p == '#')
                         continue;
 
                 STRCPY(group, buf);
                 STRCPY(line, p);
-                store(ngtable, group, line);
+                store(hdl->ngtable, group, line);
         }
+
+        free(buf);
 }