xref: /original-bsd/lib/libc/gen/getnetgrent.c (revision 0842ddeb)
1 /*
2  * Copyright (c) 1992, 1993
3  *	The Regents of the University of California.  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	8.2 (Berkeley) 04/27/95";
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_str[3];	/* Field pointers, see below */
38 };
39 #define NG_HOST		0	/* Host name */
40 #define NG_USER		1	/* User name */
41 #define NG_DOM		2	/* and Domain name */
42 
43 static struct linelist	*linehead = (struct linelist *)0;
44 static struct netgrp	*nextgrp = (struct netgrp *)0;
45 static struct {
46 	struct netgrp	*gr;
47 	char		*grname;
48 } grouphead = {
49 	(struct netgrp *)0,
50 	(char *)0,
51 };
52 static FILE *netf = (FILE *)0;
53 static int parse_netgrp();
54 static struct linelist *read_for_group();
55 void setnetgrent(), endnetgrent();
56 int getnetgrent(), innetgr();
57 
58 #define	LINSIZ	1024	/* Length of netgroup file line */
59 
60 /*
61  * setnetgrent()
62  * Parse the netgroup file looking for the netgroup and build the list
63  * of netgrp structures. Let parse_netgrp() and read_for_group() do
64  * most of the work.
65  */
66 void
67 setnetgrent(group)
68 	char *group;
69 {
70 
71 	if (grouphead.gr == (struct netgrp *)0 ||
72 		strcmp(group, grouphead.grname)) {
73 		endnetgrent();
74 		if (netf = fopen(_PATH_NETGROUP, "r")) {
75 			if (parse_netgrp(group))
76 				endnetgrent();
77 			else {
78 				grouphead.grname = (char *)
79 					malloc(strlen(group) + 1);
80 				strcpy(grouphead.grname, group);
81 			}
82 			fclose(netf);
83 		}
84 	}
85 	nextgrp = grouphead.gr;
86 }
87 
88 /*
89  * Get the next netgroup off the list.
90  */
91 int
92 getnetgrent(hostp, userp, domp)
93 	char **hostp, **userp, **domp;
94 {
95 
96 	if (nextgrp) {
97 		*hostp = nextgrp->ng_str[NG_HOST];
98 		*userp = nextgrp->ng_str[NG_USER];
99 		*domp = nextgrp->ng_str[NG_DOM];
100 		nextgrp = nextgrp->ng_next;
101 		return (1);
102 	}
103 	return (0);
104 }
105 
106 /*
107  * endnetgrent() - cleanup
108  */
109 void
110 endnetgrent()
111 {
112 	register struct linelist *lp, *olp;
113 	register struct netgrp *gp, *ogp;
114 
115 	lp = linehead;
116 	while (lp) {
117 		olp = lp;
118 		lp = lp->l_next;
119 		free(olp->l_groupname);
120 		free(olp->l_line);
121 		free((char *)olp);
122 	}
123 	linehead = (struct linelist *)0;
124 	if (grouphead.grname) {
125 		free(grouphead.grname);
126 		grouphead.grname = (char *)0;
127 	}
128 	gp = grouphead.gr;
129 	while (gp) {
130 		ogp = gp;
131 		gp = gp->ng_next;
132 		if (ogp->ng_str[NG_HOST])
133 			free(ogp->ng_str[NG_HOST]);
134 		if (ogp->ng_str[NG_USER])
135 			free(ogp->ng_str[NG_USER]);
136 		if (ogp->ng_str[NG_DOM])
137 			free(ogp->ng_str[NG_DOM]);
138 		free((char *)ogp);
139 	}
140 	grouphead.gr = (struct netgrp *)0;
141 }
142 
143 /*
144  * Search for a match in a netgroup.
145  */
146 int
147 innetgr(group, host, user, dom)
148 	char *group, *host, *user, *dom;
149 {
150 	char *hst, *usr, *dm;
151 
152 	setnetgrent(group);
153 	while (getnetgrent(&hst, &usr, &dm))
154 		if ((host == (char *)0 || !strcmp(host, hst)) &&
155 		    (user == (char *)0 || !strcmp(user, usr)) &&
156 		    (dom == (char *)0 || !strcmp(dom, dm))) {
157 			endnetgrent();
158 			return (1);
159 		}
160 	endnetgrent();
161 	return (0);
162 }
163 
164 /*
165  * Parse the netgroup file setting up the linked lists.
166  */
167 static int
168 parse_netgrp(group)
169 	char *group;
170 {
171 	register char *spos, *epos;
172 	register int len, strpos;
173 	char *pos, *gpos;
174 	struct netgrp *grp;
175 	struct linelist *lp = linehead;
176 
177 	/*
178 	 * First, see if the line has already been read in.
179 	 */
180 	while (lp) {
181 		if (!strcmp(group, lp->l_groupname))
182 			break;
183 		lp = lp->l_next;
184 	}
185 	if (lp == (struct linelist *)0 &&
186 	    (lp = read_for_group(group)) == (struct linelist *)0)
187 		return (1);
188 	if (lp->l_parsed) {
189 		fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname);
190 		return (1);
191 	} else
192 		lp->l_parsed = 1;
193 	pos = lp->l_line;
194 	while (*pos != '\0') {
195 		if (*pos == '(') {
196 			grp = (struct netgrp *)malloc(sizeof (struct netgrp));
197 			bzero((char *)grp, sizeof (struct netgrp));
198 			grp->ng_next = grouphead.gr;
199 			grouphead.gr = grp;
200 			pos++;
201 			gpos = strsep(&pos, ")");
202 			for (strpos = 0; strpos < 3; strpos++) {
203 				if (spos = strsep(&gpos, ",")) {
204 					while (*spos == ' ' || *spos == '\t')
205 						spos++;
206 					if (epos = strpbrk(spos, " \t")) {
207 						*epos = '\0';
208 						len = epos - spos;
209 					} else
210 						len = strlen(spos);
211 					if (len > 0) {
212 						grp->ng_str[strpos] =  (char *)
213 							malloc(len + 1);
214 						bcopy(spos, grp->ng_str[strpos],
215 							len + 1);
216 					}
217 				} else
218 					goto errout;
219 			}
220 		} else {
221 			spos = strsep(&pos, ", \t");
222 			if (parse_netgrp(spos))
223 				return (1);
224 		}
225 		if (pos == NULL)
226 			break;
227 		while (*pos == ' ' || *pos == ',' || *pos == '\t')
228 			pos++;
229 	}
230 	return (0);
231 errout:
232 	fprintf(stderr, "Bad netgroup %s at ..%s\n", lp->l_groupname,
233 		spos);
234 	return (1);
235 }
236 
237 /*
238  * Read the netgroup file and save lines until the line for the netgroup
239  * is found. Return 1 if eof is encountered.
240  */
241 static struct linelist *
242 read_for_group(group)
243 	char *group;
244 {
245 	register char *pos, *spos, *linep, *olinep;
246 	register int len, olen;
247 	int cont;
248 	struct linelist *lp;
249 	char line[LINSIZ + 1];
250 
251 	while (fgets(line, LINSIZ, netf) != NULL) {
252 		pos = line;
253 		if (*pos == '#')
254 			continue;
255 		while (*pos == ' ' || *pos == '\t')
256 			pos++;
257 		spos = pos;
258 		while (*pos != ' ' && *pos != '\t' && *pos != '\n' &&
259 			*pos != '\0')
260 			pos++;
261 		len = pos - spos;
262 		while (*pos == ' ' || *pos == '\t')
263 			pos++;
264 		if (*pos != '\n' && *pos != '\0') {
265 			lp = (struct linelist *)malloc(sizeof (*lp));
266 			lp->l_parsed = 0;
267 			lp->l_groupname = (char *)malloc(len + 1);
268 			bcopy(spos, lp->l_groupname, len);
269 			*(lp->l_groupname + len) = '\0';
270 			len = strlen(pos);
271 			olen = 0;
272 
273 			/*
274 			 * Loop around handling line continuations.
275 			 */
276 			do {
277 				if (*(pos + len - 1) == '\n')
278 					len--;
279 				if (*(pos + len - 1) == '\\') {
280 					len--;
281 					cont = 1;
282 				} else
283 					cont = 0;
284 				if (len > 0) {
285 					linep = (char *)malloc(olen + len + 1);
286 					if (olen > 0) {
287 						bcopy(olinep, linep, olen);
288 						free(olinep);
289 					}
290 					bcopy(pos, linep + olen, len);
291 					olen += len;
292 					*(linep + olen) = '\0';
293 					olinep = linep;
294 				}
295 				if (cont) {
296 					if (fgets(line, LINSIZ, netf)) {
297 						pos = line;
298 						len = strlen(pos);
299 					} else
300 						cont = 0;
301 				}
302 			} while (cont);
303 			lp->l_line = linep;
304 			lp->l_next = linehead;
305 			linehead = lp;
306 
307 			/*
308 			 * If this is the one we wanted, we are done.
309 			 */
310 			if (!strcmp(lp->l_groupname, group))
311 				return (lp);
312 		}
313 	}
314 	return ((struct linelist *)0);
315 }
316