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