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
setnetgrent(group)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
getnetgrent(hostp,userp,domp)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
endnetgrent()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
innetgr(group,host,user,dom)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
parse_netgrp(group)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 *
read_for_group(group)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