xref: /illumos-gate/usr/src/cmd/ypcmd/revnetgroup/revnetgroup.c (revision 23a1ccea6aac035f084a7a4cdc968687d1b02daf)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 /*
27  * For SUNWnskit - version 1.1
28  */
29 
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <stdio.h>
34 #include <ctype.h>
35 #include <pwd.h>
36 #include <rpcsvc/ypclnt.h>
37 #include "util.h"
38 #include "table.h"
39 #include "getgroup.h"
40 
41 #define	MAXDOMAINLEN 256
42 #define	MAXGROUPLEN 1024
43 
44 /*
45  * Reverse the netgroup file. A flag of "-u" means reverse by username,
46  * one of "-h" means reverse by hostname. Each line in the output file
47  * will begin with a key formed by concatenating the host or user name
48  * with the domain name. The key will be followed by a tab, then the
49  * comma-separated, newline-terminated list of groups to which the
50  * user or host belongs.
51  *
52  * Exception: Groups to which everyone belongs (universal groups) will
53  * not be included in the list.  The universal groups will be listed under
54  * the special name "*".
55  *
56  * Thus to find out all the groups that user "foo" of domain "bar" is in,
57  * lookup the groups under  foo.bar, foo.*, *.bar and *.*.
58  *
59  */
60 
61 
62 
63 /* Stores a list of strings */
64 typedef struct stringnode *stringlist;
65 struct stringnode {
66     char *str;
67     stringlist next;
68 };
69 typedef struct stringnode stringnode;
70 
71 
72 
73 /* Stores a list of (name,list-of-groups) */
74 typedef struct groupentrynode *groupentrylist;
75 struct groupentrynode {
76     char *name;
77     stringlist groups;
78     groupentrylist next;
79 };
80 typedef struct groupentrynode groupentrynode;
81 
82 stringtable ngtable;
83 
84 static groupentrylist grouptable[TABLESIZE];
85 
86 static char *nextgroup(void);
87 static void storegroup(char *group, struct grouplist *glist, int byuser);
88 static void enter(char *name, char *group);
89 static void appendgroup(groupentrylist grlist, char *group);
90 static groupentrylist newentry(char *name, char *group);
91 static void loadtable(FILE *nf);
92 static void dumptable(void);
93 
94 int
95 main(argc, argv)
96     int argc;
97     char *argv[];
98 {
99 	char *group;
100 	struct grouplist *glist;
101 	int byuser;
102 
103 	loadtable(stdin);
104 	if (argc == 2 && argv[1][0] == '-' &&
105 			(argv[1][1] == 'u' || argv[1][1] == 'h')) {
106 		byuser = (argv[1][1] == 'u');
107 	} else {
108 		(void) fprintf(stderr,
109 				"usage: %s -h (by host), %s -u (by user)\n",
110 				argv[0], argv[0]);
111 		exit(1);
112 	}
113 
114 	while (group = nextgroup()) {
115 		glist = my_getgroup(group);
116 		storegroup(group, glist, byuser);
117 	}
118 	dumptable();
119 
120 	return (0);
121 }
122 
123 /*
124  *	Get the next netgroup from /etc/netgroup
125  */
126 static char *
127 nextgroup(void)
128 {
129 	static int index = -1;
130 	static tablelist cur = NULL;
131 	char *group;
132 
133 	while (cur == NULL) {
134 		if (++index == TABLESIZE) {
135 			return (NULL);
136 		}
137 		cur = ngtable[index];
138 	}
139 	group = cur->key;
140 	cur = cur->next;
141 	return (group);
142 }
143 
144 
145 
146 /*
147  * Dump out all of the stored info into a file
148  */
149 static void
150 dumptable(void)
151 {
152 	int i;
153 	groupentrylist entry;
154 	stringlist groups;
155 
156 	for (i = 0; i < TABLESIZE; i++) {
157 		if (entry = grouptable[i]) {
158 			while (entry) {
159 				fputs(entry->name, stdout);
160 				putc('\t', stdout);
161 				for (groups = entry->groups; groups;
162 						groups = groups->next) {
163 					fputs(groups->str, stdout);
164 					if (groups->next) {
165 						putc(',', stdout);
166 					}
167 				}
168 				putc('\n', stdout);
169 				entry = entry->next;
170 			}
171 		}
172 	}
173 }
174 
175 
176 
177 
178 /*
179  *	Add a netgroup to a user's list of netgroups
180  */
181 static void
182 storegroup(char *group, struct grouplist *glist, int byuser)
183 {
184 	char *name;	/* username or hostname */
185 	char *domain;
186 	char *key;
187 	static char *universal = "*";
188 
189 	for (; glist; glist = glist->gl_nxt) {
190 		name = byuser ? glist->gl_name : glist->gl_machine;
191 		if (!name) {
192 		    name = universal;
193 		} else if (!isalnum(*name) && *name != '_') {
194 		    continue;
195 		}
196 		domain = glist->gl_domain;
197 		if (!domain) {
198 		    domain = universal;
199 		}
200 		key = malloc((unsigned) (strlen(name)+strlen(domain)+2));
201 		(void) sprintf(key, "%s.%s", name, domain);
202 		enter(key, group);
203 	}
204 }
205 
206 
207 
208 static groupentrylist
209 newentry(char *name, char *group)
210 {
211 	groupentrylist new;
212 
213 	new = MALLOC(groupentrynode);
214 
215 	STRCPY(new->name, name);
216 
217 	new->groups = MALLOC(stringnode);
218 	new->groups->str = group;
219 	new->groups->next = NULL;
220 
221 	new->next = NULL;
222 	return (new);
223 }
224 
225 static void
226 appendgroup(groupentrylist grlist, char *group)
227 {
228 	stringlist cur, prev;
229 
230 	for (cur = grlist->groups; cur; prev = cur, cur = cur->next) {
231 		if (strcmp(group, cur->str) == 0) {
232 		    return;
233 		}
234 	}
235 	prev->next = MALLOC(stringnode);
236 	cur = prev->next;
237 	cur->str = group;
238 	cur->next = NULL;
239 }
240 
241 static void
242 enter(char *name, char *group)
243 {
244 	int key;
245 	groupentrylist gel;
246 	groupentrylist gelprev;
247 
248 	key = tablekey(name);
249 	if (grouptable[key] == NULL) {
250 		grouptable[key] = newentry(name, group);
251 	} else {
252 		gel = grouptable[key];
253 		while (gel && strcmp(gel->name, name)) {
254 		    gelprev = gel;
255 		    gel = gel->next;
256 		}
257 		if (gel) {
258 		    appendgroup(gel, group);
259 		} else {
260 		    gelprev->next = newentry(name, group);
261 		}
262 	}
263 }
264 
265 /*
266  * Load up a hash table with the info in /etc/netgroup
267  */
268 static void
269 loadtable(FILE *nf)
270 {
271 	char buf[MAXGROUPLEN];
272 	char *p;
273 	char *group;
274 	char *line;
275 
276 	while (getaline(buf, MAXGROUPLEN, nf)) {
277 		for (p = buf; *p && isspace((int)*p); p++)
278 			;	/* skip leading blanks */
279 		for (; *p && *p != '#' && *p != ' ' && *p != '\t'; p++)
280 			;
281 		if (*p == EOS || *p == '#')
282 			continue;
283 		*p++ = EOS;
284 
285 		while (*p == ' ' || *p == '\t') {
286 			p++;
287 		}
288 		if (*p == EOS || *p == '#')
289 			continue;
290 
291 		STRCPY(group, buf);
292 		STRCPY(line, p);
293 		store(ngtable, group, line);
294 	}
295 }
296