getnetgrent.c revision 1.1.1.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 1994/05/17 13:30:51 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 while (*pos == ' ' || *pos == ',' || *pos == '\t')
253 pos++;
254 }
255 return (0);
256 errout:
257 fprintf(stderr, "Bad netgroup %s at ..%s\n", lp->l_groupname,
258 spos);
259 return (1);
260 }
261
262 /*
263 * Read the netgroup file and save lines until the line for the netgroup
264 * is found. Return 1 if eof is encountered.
265 */
266 static struct linelist *
267 read_for_group(group)
268 char *group;
269 {
270 register char *pos, *spos, *linep, *olinep;
271 register int len, olen;
272 int cont;
273 struct linelist *lp;
274 char line[LINSIZ + 1];
275
276 while (fgets(line, LINSIZ, netf) != NULL) {
277 pos = line;
278 if (*pos == '#')
279 continue;
280 while (*pos == ' ' || *pos == '\t')
281 pos++;
282 spos = pos;
283 while (*pos != ' ' && *pos != '\t' && *pos != '\n' &&
284 *pos != '\0')
285 pos++;
286 len = pos - spos;
287 while (*pos == ' ' || *pos == '\t')
288 pos++;
289 if (*pos != '\n' && *pos != '\0') {
290 lp = (struct linelist *)malloc(sizeof (*lp));
291 lp->l_parsed = 0;
292 lp->l_groupname = (char *)malloc(len + 1);
293 bcopy(spos, lp->l_groupname, len);
294 *(lp->l_groupname + len) = '\0';
295 len = strlen(pos);
296 olen = 0;
297
298 /*
299 * Loop around handling line continuations.
300 */
301 do {
302 if (*(pos + len - 1) == '\n')
303 len--;
304 if (*(pos + len - 1) == '\\') {
305 len--;
306 cont = 1;
307 } else
308 cont = 0;
309 if (len > 0) {
310 linep = (char *)malloc(olen + len + 1);
311 if (olen > 0) {
312 bcopy(olinep, linep, olen);
313 free(olinep);
314 }
315 bcopy(pos, linep + olen, len);
316 olen += len;
317 *(linep + olen) = '\0';
318 olinep = linep;
319 }
320 if (cont) {
321 if (fgets(line, LINSIZ, netf)) {
322 pos = line;
323 len = strlen(pos);
324 } else
325 cont = 0;
326 }
327 } while (cont);
328 lp->l_line = linep;
329 lp->l_next = linehead;
330 linehead = lp;
331
332 /*
333 * If this is the one we wanted, we are done.
334 */
335 if (!strcmp(lp->l_groupname, group))
336 return (lp);
337 }
338 }
339 return ((struct linelist *)0);
340 }
341