getnetgrent.c revision 1.1.1.2 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 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37 #if defined(LIBC_SCCS) && !defined(lint)
38 static char sccsid[] = "@(#)getnetgrent.c 8.2 (Berkeley) 4/27/95";
39 #endif /* LIBC_SCCS and not lint */
40
41 #include <stdio.h>
42 #include <strings.h>
43
44 #define _PATH_NETGROUP "/etc/netgroup"
45
46 /*
47 * Static Variables and functions used by setnetgrent(), getnetgrent() and
48 * endnetgrent().
49 * There are two linked lists:
50 * - linelist is just used by setnetgrent() to parse the net group file via.
51 * parse_netgrp()
52 * - netgrp is the list of entries for the current netgroup
53 */
54 struct linelist {
55 struct linelist *l_next; /* Chain ptr. */
56 int l_parsed; /* Flag for cycles */
57 char *l_groupname; /* Name of netgroup */
58 char *l_line; /* Netgroup entrie(s) to be parsed */
59 };
60
61 struct netgrp {
62 struct netgrp *ng_next; /* Chain ptr */
63 char *ng_str[3]; /* Field pointers, see below */
64 };
65 #define NG_HOST 0 /* Host name */
66 #define NG_USER 1 /* User name */
67 #define NG_DOM 2 /* and Domain name */
68
69 static struct linelist *linehead = (struct linelist *)0;
70 static struct netgrp *nextgrp = (struct netgrp *)0;
71 static struct {
72 struct netgrp *gr;
73 char *grname;
74 } grouphead = {
75 (struct netgrp *)0,
76 (char *)0,
77 };
78 static FILE *netf = (FILE *)0;
79 static int parse_netgrp();
80 static struct linelist *read_for_group();
81 void setnetgrent(), endnetgrent();
82 int getnetgrent(), innetgr();
83
84 #define LINSIZ 1024 /* Length of netgroup file line */
85
86 /*
87 * setnetgrent()
88 * Parse the netgroup file looking for the netgroup and build the list
89 * of netgrp structures. Let parse_netgrp() and read_for_group() do
90 * most of the work.
91 */
92 void
93 setnetgrent(group)
94 char *group;
95 {
96
97 if (grouphead.gr == (struct netgrp *)0 ||
98 strcmp(group, grouphead.grname)) {
99 endnetgrent();
100 if (netf = fopen(_PATH_NETGROUP, "r")) {
101 if (parse_netgrp(group))
102 endnetgrent();
103 else {
104 grouphead.grname = (char *)
105 malloc(strlen(group) + 1);
106 strcpy(grouphead.grname, group);
107 }
108 fclose(netf);
109 }
110 }
111 nextgrp = grouphead.gr;
112 }
113
114 /*
115 * Get the next netgroup off the list.
116 */
117 int
118 getnetgrent(hostp, userp, domp)
119 char **hostp, **userp, **domp;
120 {
121
122 if (nextgrp) {
123 *hostp = nextgrp->ng_str[NG_HOST];
124 *userp = nextgrp->ng_str[NG_USER];
125 *domp = nextgrp->ng_str[NG_DOM];
126 nextgrp = nextgrp->ng_next;
127 return (1);
128 }
129 return (0);
130 }
131
132 /*
133 * endnetgrent() - cleanup
134 */
135 void
136 endnetgrent()
137 {
138 register struct linelist *lp, *olp;
139 register struct netgrp *gp, *ogp;
140
141 lp = linehead;
142 while (lp) {
143 olp = lp;
144 lp = lp->l_next;
145 free(olp->l_groupname);
146 free(olp->l_line);
147 free((char *)olp);
148 }
149 linehead = (struct linelist *)0;
150 if (grouphead.grname) {
151 free(grouphead.grname);
152 grouphead.grname = (char *)0;
153 }
154 gp = grouphead.gr;
155 while (gp) {
156 ogp = gp;
157 gp = gp->ng_next;
158 if (ogp->ng_str[NG_HOST])
159 free(ogp->ng_str[NG_HOST]);
160 if (ogp->ng_str[NG_USER])
161 free(ogp->ng_str[NG_USER]);
162 if (ogp->ng_str[NG_DOM])
163 free(ogp->ng_str[NG_DOM]);
164 free((char *)ogp);
165 }
166 grouphead.gr = (struct netgrp *)0;
167 }
168
169 /*
170 * Search for a match in a netgroup.
171 */
172 int
173 innetgr(group, host, user, dom)
174 char *group, *host, *user, *dom;
175 {
176 char *hst, *usr, *dm;
177
178 setnetgrent(group);
179 while (getnetgrent(&hst, &usr, &dm))
180 if ((host == (char *)0 || !strcmp(host, hst)) &&
181 (user == (char *)0 || !strcmp(user, usr)) &&
182 (dom == (char *)0 || !strcmp(dom, dm))) {
183 endnetgrent();
184 return (1);
185 }
186 endnetgrent();
187 return (0);
188 }
189
190 /*
191 * Parse the netgroup file setting up the linked lists.
192 */
193 static int
194 parse_netgrp(group)
195 char *group;
196 {
197 register char *spos, *epos;
198 register int len, strpos;
199 char *pos, *gpos;
200 struct netgrp *grp;
201 struct linelist *lp = linehead;
202
203 /*
204 * First, see if the line has already been read in.
205 */
206 while (lp) {
207 if (!strcmp(group, lp->l_groupname))
208 break;
209 lp = lp->l_next;
210 }
211 if (lp == (struct linelist *)0 &&
212 (lp = read_for_group(group)) == (struct linelist *)0)
213 return (1);
214 if (lp->l_parsed) {
215 fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname);
216 return (1);
217 } else
218 lp->l_parsed = 1;
219 pos = lp->l_line;
220 while (*pos != '\0') {
221 if (*pos == '(') {
222 grp = (struct netgrp *)malloc(sizeof (struct netgrp));
223 bzero((char *)grp, sizeof (struct netgrp));
224 grp->ng_next = grouphead.gr;
225 grouphead.gr = grp;
226 pos++;
227 gpos = strsep(&pos, ")");
228 for (strpos = 0; strpos < 3; strpos++) {
229 if (spos = strsep(&gpos, ",")) {
230 while (*spos == ' ' || *spos == '\t')
231 spos++;
232 if (epos = strpbrk(spos, " \t")) {
233 *epos = '\0';
234 len = epos - spos;
235 } else
236 len = strlen(spos);
237 if (len > 0) {
238 grp->ng_str[strpos] = (char *)
239 malloc(len + 1);
240 bcopy(spos, grp->ng_str[strpos],
241 len + 1);
242 }
243 } else
244 goto errout;
245 }
246 } else {
247 spos = strsep(&pos, ", \t");
248 if (parse_netgrp(spos))
249 return (1);
250 }
251 if (pos == NULL)
252 break;
253 while (*pos == ' ' || *pos == ',' || *pos == '\t')
254 pos++;
255 }
256 return (0);
257 errout:
258 fprintf(stderr, "Bad netgroup %s at ..%s\n", lp->l_groupname,
259 spos);
260 return (1);
261 }
262
263 /*
264 * Read the netgroup file and save lines until the line for the netgroup
265 * is found. Return 1 if eof is encountered.
266 */
267 static struct linelist *
268 read_for_group(group)
269 char *group;
270 {
271 register char *pos, *spos, *linep, *olinep;
272 register int len, olen;
273 int cont;
274 struct linelist *lp;
275 char line[LINSIZ + 1];
276
277 while (fgets(line, LINSIZ, netf) != NULL) {
278 pos = line;
279 if (*pos == '#')
280 continue;
281 while (*pos == ' ' || *pos == '\t')
282 pos++;
283 spos = pos;
284 while (*pos != ' ' && *pos != '\t' && *pos != '\n' &&
285 *pos != '\0')
286 pos++;
287 len = pos - spos;
288 while (*pos == ' ' || *pos == '\t')
289 pos++;
290 if (*pos != '\n' && *pos != '\0') {
291 lp = (struct linelist *)malloc(sizeof (*lp));
292 lp->l_parsed = 0;
293 lp->l_groupname = (char *)malloc(len + 1);
294 bcopy(spos, lp->l_groupname, len);
295 *(lp->l_groupname + len) = '\0';
296 len = strlen(pos);
297 olen = 0;
298
299 /*
300 * Loop around handling line continuations.
301 */
302 do {
303 if (*(pos + len - 1) == '\n')
304 len--;
305 if (*(pos + len - 1) == '\\') {
306 len--;
307 cont = 1;
308 } else
309 cont = 0;
310 if (len > 0) {
311 linep = (char *)malloc(olen + len + 1);
312 if (olen > 0) {
313 bcopy(olinep, linep, olen);
314 free(olinep);
315 }
316 bcopy(pos, linep + olen, len);
317 olen += len;
318 *(linep + olen) = '\0';
319 olinep = linep;
320 }
321 if (cont) {
322 if (fgets(line, LINSIZ, netf)) {
323 pos = line;
324 len = strlen(pos);
325 } else
326 cont = 0;
327 }
328 } while (cont);
329 lp->l_line = linep;
330 lp->l_next = linehead;
331 linehead = lp;
332
333 /*
334 * If this is the one we wanted, we are done.
335 */
336 if (!strcmp(lp->l_groupname, group))
337 return (lp);
338 }
339 }
340 return ((struct linelist *)0);
341 }
342