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