--- old/usr/src/cmd/ypcmd/revnetgroup/revnetgroup.c	Tue Sep 11 18:26:17 2012
+++ new/usr/src/cmd/ypcmd/revnetgroup/revnetgroup.c	Tue Sep 11 18:26:16 2012
@@ -21,6 +21,7 @@
 
 /*
  * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -37,9 +38,11 @@
 #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,
@@ -58,65 +61,30 @@
  *
  */
 
-
-
-/* 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);
 }
 
@@ -124,48 +92,123 @@
  *	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;
 			}
 		}
@@ -174,33 +217,35 @@
 
 
 
-
 /*
  *	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;
+			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);
 }
 
 
@@ -216,7 +261,7 @@
 
 	new->groups = MALLOC(stringnode);
 	new->groups->str = group;
-	new->groups->next = NULL;
+	new->groups->s_next = NULL;
 
 	new->next = NULL;
 	return (new);
@@ -225,21 +270,21 @@
 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;
+			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;
@@ -246,18 +291,18 @@
 	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;
+			gelprev = gel;
+			gel = gel->next;
 		}
 		if (gel) {
-		    appendgroup(gel, group);
+			appendgroup(gel, group);
 		} else {
-		    gelprev->next = newentry(name, group);
+			gelprev->next = newentry(name, group);
 		}
 	}
 }
@@ -266,16 +311,21 @@
  * 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 == '#')
@@ -290,6 +340,8 @@
 
 		STRCPY(group, buf);
 		STRCPY(line, p);
-		store(ngtable, group, line);
+		store(hdl->ngtable, group, line);
 	}
+
+	free(buf);
 }
