xref: /titanic_51/usr/src/lib/libbc/libc/gen/common/getgraent.c (revision 5d54f3d8999eac1762fe0a8c7177d20f1f201fae)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 1990 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <grp.h>
31 #include <grpadj.h>
32 #include <rpcsvc/ypclnt.h>
33 #include <string.h>
34 #include <malloc.h>
35 
36 extern void rewind();
37 extern long strtol();
38 extern int fclose();
39 
40 void	setgraent(void);
41 void	endgraent(void);
42 
43 static struct gradata {
44 	char	*domain;
45 	FILE	*grfa;
46 	char	*yp;
47 	int	yplen;
48 	char	*oldyp;
49 	int	oldyplen;
50 	struct list {
51 		char *name;
52 		struct list *nxt;
53 	} *minuslist;			/* list of - items */
54 	struct	group_adjunct interpgra;
55 	char	interpline[BUFSIZ+1];
56 	struct	group_adjunct *sv;
57 } *gradata, *_gradata(void);
58 
59 static char *GROUPADJ = "/etc/security/group.adjunct";
60 
61 static struct group_adjunct	*interpret(char *, int);
62 static struct group_adjunct	*interpretwithsave(char *, int,
63     struct group_adjunct *);
64 static struct group_adjunct	*save(struct group_adjunct *);
65 static struct group_adjunct	*getnamefromyellow(char *,
66     struct group_adjunct *);
67 static int	onminuslist(struct group_adjunct *);
68 static int	matchname(char [], struct group_adjunct **, char *);
69 static void	freeminuslist(void);
70 static void	getnextfromyellow(void);
71 static void	getfirstfromyellow(void);
72 static void	addtominuslist(char *);
73 
74 
75 static struct gradata *
76 _gradata(void)
77 {
78 	struct gradata *g = gradata;
79 
80 	if (g == 0) {
81 		g = (struct gradata *)calloc(1, sizeof (struct gradata));
82 		gradata = g;
83 	}
84 	return (g);
85 }
86 
87 struct group_adjunct *
88 getgranam(char *name)
89 {
90 	struct gradata *g = _gradata();
91 	struct group_adjunct *gra;
92 	char line[BUFSIZ+1];
93 
94 	setgraent();
95 	if (g == 0)
96 		return (0);
97 	if (!g->grfa)
98 		return (NULL);
99 	while (fgets(line, BUFSIZ, g->grfa) != NULL) {
100 		if ((gra = interpret(line, strlen(line))) == NULL)
101 			continue;
102 		if (matchname(line, &gra, name)) {
103 			endgraent();
104 			return (gra);
105 		}
106 	}
107 	endgraent();
108 	return (NULL);
109 }
110 
111 void
112 setgraent(void)
113 {
114 	struct gradata *g = _gradata();
115 
116 	if (g == NULL)
117 		return;
118 	if (g->domain == NULL)
119 		(void) yp_get_default_domain(&g->domain);
120 	if (!g->grfa)
121 		g->grfa = fopen(GROUPADJ, "r");
122 	else
123 		rewind(g->grfa);
124 	if (g->yp)
125 		free(g->yp);
126 	g->yp = NULL;
127 	freeminuslist();
128 }
129 
130 void
131 endgraent(void)
132 {
133 	struct gradata *g = _gradata();
134 
135 	if (g == 0)
136 		return;
137 	if (g->grfa) {
138 		(void) fclose(g->grfa);
139 		g->grfa = NULL;
140 	}
141 	if (g->yp)
142 		free(g->yp);
143 	g->yp = NULL;
144 	freeminuslist();
145 }
146 
147 struct group_adjunct *
148 fgetgraent(FILE *f)
149 {
150 	char line1[BUFSIZ+1];
151 
152 	if(fgets(line1, BUFSIZ, f) == NULL)
153 		return (NULL);
154 	return (interpret(line1, strlen(line1)));
155 }
156 
157 static char *
158 grskip(char *p, int c)
159 {
160 	while(*p && *p != c && *p != '\n') ++p;
161 	if (*p == '\n')
162 		*p = '\0';
163 	else if (*p != '\0')
164 		*p++ = '\0';
165 	return (p);
166 }
167 
168 struct group_adjunct *
169 getgraent(void)
170 {
171 	struct gradata *g = _gradata();
172 	char line1[BUFSIZ+1];
173 	static struct group_adjunct *savegra;
174 	struct group_adjunct *gra;
175 
176 	if (g == 0)
177 		return (0);
178 	if (g->domain == NULL) {
179 		(void) yp_get_default_domain(&g->domain);
180 	}
181 	if(!g->grfa && !(g->grfa = fopen(GROUPADJ, "r")))
182 		return (NULL);
183   again:
184 	if (g->yp) {
185 		gra = interpretwithsave(g->yp, g->yplen, savegra);
186 		free(g->yp);
187 		if (gra == NULL)
188 			return (NULL);
189 		getnextfromyellow();
190 		if (onminuslist(gra))
191 			goto again;
192 		else
193 			return (gra);
194 	}
195 	else if (fgets(line1, BUFSIZ, g->grfa) == NULL)
196 		return (NULL);
197 	if ((gra = interpret(line1, strlen(line1))) == NULL)
198 		return (NULL);
199 	switch(line1[0]) {
200 		case '+':
201 			if (strcmp(gra->gra_name, "+") == 0) {
202 				getfirstfromyellow();
203 				savegra = save(gra);
204 				goto again;
205 			}
206 			/*
207 			 * else look up this entry in NIS
208 			 */
209 			savegra = save(gra);
210 			gra = getnamefromyellow(gra->gra_name+1, savegra);
211 			if (gra == NULL)
212 				goto again;
213 			else if (onminuslist(gra))
214 				goto again;
215 			else
216 				return (gra);
217 			break;
218 		case '-':
219 			addtominuslist(gra->gra_name+1);
220 			goto again;
221 			break;
222 		default:
223 			if (onminuslist(gra))
224 				goto again;
225 			return (gra);
226 			break;
227 	}
228 	/* NOTREACHED */
229 }
230 
231 static struct group_adjunct *
232 interpret(char *val, int len)
233 {
234 	struct gradata *g = _gradata();
235 	char *p;
236 
237 	if (g == 0)
238 		return (0);
239 	strncpy(g->interpline, val, len);
240 	p = g->interpline;
241 	g->interpline[len] = '\n';
242 	g->interpline[len+1] = 0;
243 	g->interpgra.gra_name = p;
244 	p = grskip(p,':');
245         if (strcmp(g->interpgra.gra_name, "+") == 0) {
246                 /* we are going to the NIS - fix the
247                  * rest of the struct as much as is needed
248                  */
249                 g->interpgra.gra_passwd = "";
250 		return (&g->interpgra);
251         }
252 	g->interpgra.gra_passwd = p;
253         while(*p && *p != '\n') p++;
254         *p = '\0';
255 	return (&g->interpgra);
256 }
257 
258 static void
259 freeminuslist(void)
260 {
261 	struct gradata *g = _gradata();
262 	struct list *ls;
263 
264 	if (g == 0)
265 		return;
266 	for (ls = g->minuslist; ls != NULL; ls = ls->nxt) {
267 		free(ls->name);
268 		free(ls);
269 	}
270 	g->minuslist = NULL;
271 }
272 
273 static struct group_adjunct *
274 interpretwithsave(char *val, int len, struct group_adjunct *savegra)
275 {
276 	struct gradata *g = _gradata();
277 	struct group_adjunct *gra;
278 
279 	if (g == 0)
280 		return (0);
281 	if ((gra = interpret(val, len)) == NULL)
282 		return (NULL);
283 	if (savegra->gra_passwd && *savegra->gra_passwd)
284 		gra->gra_passwd =  savegra->gra_passwd;
285 	return (gra);
286 }
287 
288 static int
289 onminuslist(struct group_adjunct *gra)
290 {
291 	struct gradata *g = _gradata();
292 	struct list *ls;
293 	char *nm;
294 
295 	if (g == 0)
296 		return (0);
297 	nm = gra->gra_name;
298 	for (ls = g->minuslist; ls != NULL; ls = ls->nxt)
299 		if (strcmp(ls->name, nm) == 0)
300 			return (1);
301 	return (0);
302 }
303 
304 static void
305 getnextfromyellow(void)
306 {
307 	struct gradata *g = _gradata();
308 	int reason;
309 	char *key = NULL;
310 	int keylen;
311 
312 	if (g == 0)
313 		return;
314 	if (reason = yp_next(g->domain, "group.adjunct.byname",
315 	    g->oldyp, g->oldyplen, &key, &keylen,
316 	    &g->yp, &g->yplen)) {
317 #ifdef DEBUG
318 fprintf(stderr, "reason yp_next failed is %d\n", reason);
319 #endif
320 		g->yp = NULL;
321 	}
322 	if (g->oldyp)
323 		free(g->oldyp);
324 	g->oldyp = key;
325 	g->oldyplen = keylen;
326 }
327 
328 static void
329 getfirstfromyellow(void)
330 {
331 	struct gradata *g = _gradata();
332 	int reason;
333 	char *key = NULL;
334 	int keylen;
335 
336 	if (g == 0)
337 		return;
338 	if (reason =  yp_first(g->domain, "group.adjunct.byname",
339 	    &key, &keylen, &g->yp, &g->yplen)) {
340 #ifdef DEBUG
341 fprintf(stderr, "reason yp_first failed is %d\n", reason);
342 #endif
343 		g->yp = NULL;
344 	}
345 	if (g->oldyp)
346 		free(g->oldyp);
347 	g->oldyp = key;
348 	g->oldyplen = keylen;
349 }
350 
351 static struct group_adjunct *
352 getnamefromyellow(char *name, struct group_adjunct *savegra)
353 {
354 	struct gradata *g = _gradata();
355 	struct group_adjunct *gra;
356 	int reason;
357 	char *val;
358 	int vallen;
359 
360 	if (g == 0)
361 		return (NULL);
362 	if (reason = yp_match(g->domain, "group.adjunct.byname",
363 	    name, strlen(name), &val, &vallen)) {
364 #ifdef DEBUG
365 fprintf(stderr, "reason yp_next failed is %d\n", reason);
366 #endif
367 		return (NULL);
368 	}
369 	else {
370 		gra = interpret(val, vallen);
371 		free(val);
372 		if (gra == NULL)
373 			return (NULL);
374 		if (savegra->gra_passwd && *savegra->gra_passwd)
375 			gra->gra_passwd =  savegra->gra_passwd;
376 		return (gra);
377 	}
378 }
379 
380 static void
381 addtominuslist(char *name)
382 {
383 	struct gradata *g = _gradata();
384 	struct list *ls;
385 	char *buf;
386 
387 	if (g == 0)
388 		return;
389 	ls = (struct list *)malloc(sizeof(struct list));
390 	buf = (char *)malloc(strlen(name) + 1);
391 	(void) strcpy(buf, name);
392 	ls->name = buf;
393 	ls->nxt = g->minuslist;
394 	g->minuslist = ls;
395 }
396 
397 /*
398  * save away psswd field, which is the only
399  * one which can be specified in a local + entry to override the
400  * value in the NIS
401  */
402 static struct group_adjunct *
403 save(struct group_adjunct *gra)
404 {
405 	struct gradata *g = _gradata();
406 
407 	if (g == 0)
408 		return (0);
409 	/*
410 	 * free up stuff from last time around
411 	 */
412 	if (g->sv) {
413 		free(g->sv->gra_passwd);
414 		free(g->sv);
415 	}
416 	g->sv = (struct group_adjunct *)calloc(1, sizeof(struct group_adjunct));
417 	g->sv->gra_passwd = (char *)malloc(strlen(gra->gra_passwd) + 1);
418 	(void) strcpy(g->sv->gra_passwd, gra->gra_passwd);
419 	return (g->sv);
420 }
421 
422 static int
423 matchname(char line1[], struct group_adjunct **grap, char *name)
424 {
425 	struct group_adjunct *savegra;
426 	struct group_adjunct *gra = *grap;
427 
428 	switch (line1[0]) {
429 		case '+':
430 			if (strcmp(gra->gra_name, "+") == 0) {
431 				savegra = save(gra);
432 				gra = getnamefromyellow(name, savegra);
433 				if (gra) {
434 					*grap = gra;
435 					return (1);
436 				}
437 				else
438 					return (0);
439 			}
440 			if (strcmp(gra->gra_name+1, name) == 0) {
441 				savegra = save(gra);
442 				gra = getnamefromyellow(gra->gra_name+1, savegra);
443 				if (gra) {
444 					*grap = gra;
445 					return (1);
446 				}
447 				else
448 					return (0);
449 			}
450 			break;
451 		case '-':
452 			if (strcmp(gra->gra_name+1, name) == 0) {
453 				*grap = NULL;
454 				return (1);
455 			}
456 			break;
457 		default:
458 			if (strcmp(gra->gra_name, name) == 0)
459 				return (1);
460 	}
461 	return (0);
462 }
463