xref: /csrg-svn/lib/libc/gen/getnetgrent.c (revision 53149)
1*53149Smckusick /*
2*53149Smckusick  * Copyright (c) 1992 The Regents of the University of California.
3*53149Smckusick  * All rights reserved.
4*53149Smckusick  *
5*53149Smckusick  * This code is derived from software contributed to Berkeley by
6*53149Smckusick  * Rick Macklem at The University of Guelph.
7*53149Smckusick  *
8*53149Smckusick  * %sccs.include.redist.c%
9*53149Smckusick  */
10*53149Smckusick 
11*53149Smckusick #if defined(LIBC_SCCS) && !defined(lint)
12*53149Smckusick static char sccsid[] = "@(#)getnetgrent.c	5.1 (Berkeley) 04/09/92";
13*53149Smckusick #endif /* LIBC_SCCS and not lint */
14*53149Smckusick 
15*53149Smckusick #include <stdio.h>
16*53149Smckusick #include <strings.h>
17*53149Smckusick 
18*53149Smckusick #define _PATH_NETGROUP "/etc/netgroup"
19*53149Smckusick 
20*53149Smckusick /*
21*53149Smckusick  * Static Variables and functions used by setnetgrent(), getnetgrent() and
22*53149Smckusick  * endnetgrent().
23*53149Smckusick  * There are two linked lists:
24*53149Smckusick  * - linelist is just used by setnetgrent() to parse the net group file via.
25*53149Smckusick  *   parse_netgrp()
26*53149Smckusick  * - netgrp is the list of entries for the current netgroup
27*53149Smckusick  */
28*53149Smckusick struct linelist {
29*53149Smckusick 	struct linelist	*l_next;	/* Chain ptr. */
30*53149Smckusick 	int		l_parsed;	/* Flag for cycles */
31*53149Smckusick 	char		*l_groupname;	/* Name of netgroup */
32*53149Smckusick 	char		*l_line;	/* Netgroup entrie(s) to be parsed */
33*53149Smckusick };
34*53149Smckusick 
35*53149Smckusick struct netgrp {
36*53149Smckusick 	struct netgrp	*ng_next;	/* Chain ptr */
37*53149Smckusick 	char		*ng_host;	/* Host name */
38*53149Smckusick 	char		*ng_user;	/* User name */
39*53149Smckusick 	char		*ng_dom;	/* and Domain name */
40*53149Smckusick };
41*53149Smckusick 
42*53149Smckusick static struct linelist	*linehead = (struct linelist *)0;
43*53149Smckusick static struct netgrp	*nextgrp = (struct netgrp *)0;
44*53149Smckusick static struct {
45*53149Smckusick 	struct netgrp	*gr;
46*53149Smckusick 	char		*grname;
47*53149Smckusick } grouphead = {
48*53149Smckusick 	(struct netgrp *)0,
49*53149Smckusick 	(char *)0,
50*53149Smckusick };
51*53149Smckusick static FILE *netf = (FILE *)0;
52*53149Smckusick static int parse_netgrp();
53*53149Smckusick static struct linelist *read_for_group();
54*53149Smckusick void setnetgrent(), endnetgrent();
55*53149Smckusick int getnetgrent(), innetgr();
56*53149Smckusick 
57*53149Smckusick #define	LINSIZ	1024	/* Length of netgroup file line */
58*53149Smckusick 
59*53149Smckusick /*
60*53149Smckusick  * setnetgrent()
61*53149Smckusick  * Parse the netgroup file looking for the netgroup and build the list
62*53149Smckusick  * of netgrp structures. Let parse_netgrp() and read_for_group() do
63*53149Smckusick  * most of the work.
64*53149Smckusick  */
65*53149Smckusick void
66*53149Smckusick setnetgrent(group)
67*53149Smckusick 	char *group;
68*53149Smckusick {
69*53149Smckusick 
70*53149Smckusick 	if (grouphead.gr == (struct netgrp *)0 ||
71*53149Smckusick 		strcmp(group, grouphead.grname)) {
72*53149Smckusick 		endnetgrent();
73*53149Smckusick 		if (netf = fopen(_PATH_NETGROUP, "r")) {
74*53149Smckusick 			if (parse_netgrp(group))
75*53149Smckusick 				endnetgrent();
76*53149Smckusick 			else {
77*53149Smckusick 				grouphead.grname = (char *)
78*53149Smckusick 					malloc(strlen(group) + 1);
79*53149Smckusick 				strcpy(grouphead.grname, group);
80*53149Smckusick 			}
81*53149Smckusick 			fclose(netf);
82*53149Smckusick 		}
83*53149Smckusick 	}
84*53149Smckusick 	nextgrp = grouphead.gr;
85*53149Smckusick }
86*53149Smckusick 
87*53149Smckusick /*
88*53149Smckusick  * Get the next netgroup off the list.
89*53149Smckusick  */
90*53149Smckusick int
91*53149Smckusick getnetgrent(hostp, userp, domp)
92*53149Smckusick 	char **hostp, **userp, **domp;
93*53149Smckusick {
94*53149Smckusick 
95*53149Smckusick 	if (nextgrp) {
96*53149Smckusick 		*hostp = nextgrp->ng_host;
97*53149Smckusick 		*userp = nextgrp->ng_user;
98*53149Smckusick 		*domp = nextgrp->ng_dom;
99*53149Smckusick 		nextgrp = nextgrp->ng_next;
100*53149Smckusick 		return (1);
101*53149Smckusick 	}
102*53149Smckusick 	return (0);
103*53149Smckusick }
104*53149Smckusick 
105*53149Smckusick /*
106*53149Smckusick  * endnetgrent() - cleanup
107*53149Smckusick  */
108*53149Smckusick void
109*53149Smckusick endnetgrent()
110*53149Smckusick {
111*53149Smckusick 	register struct linelist *lp, *olp;
112*53149Smckusick 	register struct netgrp *gp, *ogp;
113*53149Smckusick 
114*53149Smckusick 	lp = linehead;
115*53149Smckusick 	while (lp) {
116*53149Smckusick 		olp = lp;
117*53149Smckusick 		lp = lp->l_next;
118*53149Smckusick 		free(olp->l_groupname);
119*53149Smckusick 		free(olp->l_line);
120*53149Smckusick 		free((char *)olp);
121*53149Smckusick 	}
122*53149Smckusick 	linehead = (struct linelist *)0;
123*53149Smckusick 	if (grouphead.grname) {
124*53149Smckusick 		free(grouphead.grname);
125*53149Smckusick 		grouphead.grname = (char *)0;
126*53149Smckusick 	}
127*53149Smckusick 	gp = grouphead.gr;
128*53149Smckusick 	while (gp) {
129*53149Smckusick 		ogp = gp;
130*53149Smckusick 		gp = gp->ng_next;
131*53149Smckusick 		if (ogp->ng_host)
132*53149Smckusick 			free(ogp->ng_host);
133*53149Smckusick 		if (ogp->ng_user)
134*53149Smckusick 			free(ogp->ng_user);
135*53149Smckusick 		if (ogp->ng_dom)
136*53149Smckusick 			free(ogp->ng_dom);
137*53149Smckusick 		free((char *)ogp);
138*53149Smckusick 	}
139*53149Smckusick 	grouphead.gr = (struct netgrp *)0;
140*53149Smckusick }
141*53149Smckusick 
142*53149Smckusick /*
143*53149Smckusick  * Search for a match in a netgroup.
144*53149Smckusick  */
145*53149Smckusick int
146*53149Smckusick innetgr(group, host, user, dom)
147*53149Smckusick 	char *group, *host, *user, *dom;
148*53149Smckusick {
149*53149Smckusick 	char *hst, *usr, *dm;
150*53149Smckusick 
151*53149Smckusick 	setnetgrent(group);
152*53149Smckusick 	while (getnetgrent(&hst, &usr, &dm))
153*53149Smckusick 		if ((host == (char *)0 || !strcmp(host, hst)) &&
154*53149Smckusick 		    (user == (char *)0 || !strcmp(user, usr)) &&
155*53149Smckusick 		    (dom == (char *)0 || !strcmp(dom, dm))) {
156*53149Smckusick 			endnetgrent();
157*53149Smckusick 			return (1);
158*53149Smckusick 		}
159*53149Smckusick 	endnetgrent();
160*53149Smckusick 	return (0);
161*53149Smckusick }
162*53149Smckusick 
163*53149Smckusick /*
164*53149Smckusick  * Parse the netgroup file setting up the linked lists.
165*53149Smckusick  */
166*53149Smckusick static int
167*53149Smckusick parse_netgrp(group)
168*53149Smckusick 	char *group;
169*53149Smckusick {
170*53149Smckusick 	register char *pos, *spos;
171*53149Smckusick 	register int len;
172*53149Smckusick 	struct netgrp *grp;
173*53149Smckusick 	struct linelist *lp = linehead;
174*53149Smckusick 
175*53149Smckusick 	/*
176*53149Smckusick 	 * First, see if the line has already been read in.
177*53149Smckusick 	 */
178*53149Smckusick 	while (lp) {
179*53149Smckusick 		if (!strcmp(group, lp->l_groupname))
180*53149Smckusick 			break;
181*53149Smckusick 		lp = lp->l_next;
182*53149Smckusick 	}
183*53149Smckusick 	if (lp == (struct linelist *)0 &&
184*53149Smckusick 	    (lp = read_for_group(group)) == (struct linelist *)0)
185*53149Smckusick 		return (1);
186*53149Smckusick 	if (lp->l_parsed) {
187*53149Smckusick 		fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname);
188*53149Smckusick 		return (1);
189*53149Smckusick 	} else
190*53149Smckusick 		lp->l_parsed = 1;
191*53149Smckusick 	pos = lp->l_line;
192*53149Smckusick 	while (*pos != '\0') {
193*53149Smckusick 		if (*pos == '(') {
194*53149Smckusick 			grp = (struct netgrp *)malloc(sizeof (struct netgrp));
195*53149Smckusick 			bzero((char *)grp, sizeof (struct netgrp));
196*53149Smckusick 			grp->ng_next = grouphead.gr;
197*53149Smckusick 			grouphead.gr = grp;
198*53149Smckusick 			spos = ++pos;
199*53149Smckusick 			while (*pos != ',' && *pos != '\0')
200*53149Smckusick 				pos++;
201*53149Smckusick 			if (*pos == '\0')
202*53149Smckusick 				goto errout;
203*53149Smckusick 			len = pos - spos;
204*53149Smckusick 			if (len > 0) {
205*53149Smckusick 				grp->ng_host = (char *)malloc(len + 1);
206*53149Smckusick 				bcopy(spos, grp->ng_host, len);
207*53149Smckusick 				*(grp->ng_host + len) = '\0';
208*53149Smckusick 			}
209*53149Smckusick 			spos = ++pos;
210*53149Smckusick 			while (*pos != ',' && *pos != '\0')
211*53149Smckusick 				pos++;
212*53149Smckusick 			if (*pos == '\0')
213*53149Smckusick 				goto errout;
214*53149Smckusick 			len = pos - spos;
215*53149Smckusick 			if (len > 0) {
216*53149Smckusick 				grp->ng_user = (char *)malloc(len + 1);
217*53149Smckusick 				bcopy(spos, grp->ng_user, len);
218*53149Smckusick 				*(grp->ng_user + len) = '\0';
219*53149Smckusick 			}
220*53149Smckusick 			spos = ++pos;
221*53149Smckusick 			while (*pos != ')' && *pos != '\0')
222*53149Smckusick 				pos++;
223*53149Smckusick 			if (*pos == '\0')
224*53149Smckusick 				goto errout;
225*53149Smckusick 			len = pos - spos;
226*53149Smckusick 			if (len > 0) {
227*53149Smckusick 				grp->ng_dom = (char *)malloc(len + 1);
228*53149Smckusick 				bcopy(spos, grp->ng_dom, len);
229*53149Smckusick 				*(grp->ng_dom + len) = '\0';
230*53149Smckusick 			}
231*53149Smckusick 			if (*++pos != '\0' &&
232*53149Smckusick 				(*pos != ',' || *++pos == ',' || *pos == '\0'))
233*53149Smckusick 				goto errout;
234*53149Smckusick 		} else {
235*53149Smckusick 			spos = pos;
236*53149Smckusick 			while (*pos != ',' && *pos != '\0')
237*53149Smckusick 				pos++;
238*53149Smckusick 			if (*pos == ',')
239*53149Smckusick 				*pos++ = '\0';
240*53149Smckusick 			if (parse_netgrp(spos))
241*53149Smckusick 				return (1);
242*53149Smckusick 		}
243*53149Smckusick 	}
244*53149Smckusick 	return (0);
245*53149Smckusick errout:
246*53149Smckusick 	fprintf(stderr, "Bad netgroup %s at ..%s\n", lp->l_groupname,
247*53149Smckusick 		spos);
248*53149Smckusick 	return (1);
249*53149Smckusick }
250*53149Smckusick 
251*53149Smckusick /*
252*53149Smckusick  * Read the netgroup file and save lines until the line for the netgroup
253*53149Smckusick  * is found. Return 1 if eof is encountered.
254*53149Smckusick  */
255*53149Smckusick static struct linelist *
256*53149Smckusick read_for_group(group)
257*53149Smckusick 	char *group;
258*53149Smckusick {
259*53149Smckusick 	register char *pos, *spos;
260*53149Smckusick 	register int len;
261*53149Smckusick 	struct linelist *lp;
262*53149Smckusick 	char line[LINSIZ + 1];
263*53149Smckusick 
264*53149Smckusick 	while (fgets(line, LINSIZ, netf) != NULL) {
265*53149Smckusick 		pos = line;
266*53149Smckusick 		while (*pos == ' ' || *pos == '\t')
267*53149Smckusick 			pos++;
268*53149Smckusick 		spos = pos;
269*53149Smckusick 		while (*pos != ' ' && *pos != '\t' && *pos != '\n' &&
270*53149Smckusick 			*pos != '\0')
271*53149Smckusick 			pos++;
272*53149Smckusick 		len = pos - spos;
273*53149Smckusick 		while (*pos == ' ' || *pos == '\t')
274*53149Smckusick 			pos++;
275*53149Smckusick 		if (*pos != '\n' && *pos != '\0') {
276*53149Smckusick 			lp = (struct linelist *)malloc(sizeof (*lp));
277*53149Smckusick 			lp->l_parsed = 0;
278*53149Smckusick 			lp->l_groupname = (char *)malloc(len + 1);
279*53149Smckusick 			bcopy(spos, lp->l_groupname, len);
280*53149Smckusick 			*(lp->l_groupname + len) = '\0';
281*53149Smckusick 			spos = lp->l_line = (char *)malloc(LINSIZ);
282*53149Smckusick 			while (*pos != '\n' && *pos != '\0') {
283*53149Smckusick 				if (*pos != ' ' && *pos != '\t')
284*53149Smckusick 					*spos++ = *pos++;
285*53149Smckusick 				else
286*53149Smckusick 					pos++;
287*53149Smckusick 			}
288*53149Smckusick 			*spos = '\0';
289*53149Smckusick 			lp->l_next = linehead;
290*53149Smckusick 			linehead = lp;
291*53149Smckusick 
292*53149Smckusick 			/*
293*53149Smckusick 			 * If this is the one we wanted, we are done.
294*53149Smckusick 			 */
295*53149Smckusick 			if (!strcmp(lp->l_groupname, group))
296*53149Smckusick 				return (lp);
297*53149Smckusick 		}
298*53149Smckusick 	}
299*53149Smckusick 	return ((struct linelist *)0);
300*53149Smckusick }
301