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