]> git.saurik.com Git - apple/network_cmds.git/blame_incremental - revnetgroup.tproj/parse_netgroup.c
network_cmds-245.1.3.tar.gz
[apple/network_cmds.git] / revnetgroup.tproj / parse_netgroup.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23/* $OpenBSD: parse_netgroup.c,v 1.2 1997/08/18 03:11:35 millert Exp $ */
24/*
25 * Copyright (c) 1992, 1993
26 * The Regents of the University of California. All rights reserved.
27 *
28 * This code is derived from software contributed to Berkeley by
29 * Rick Macklem at The University of Guelph.
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3. All advertising materials mentioning features or use of this software
40 * must display the following acknowledgement:
41 * This product includes software developed by the University of
42 * California, Berkeley and its contributors.
43 * 4. Neither the name of the University nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * SUCH DAMAGE.
58 *
59 * $FreeBSD: parse_netgroup.c,v 1.5 1997/02/22 14:22:02 peter Exp $
60 */
61
62/*
63 * This is a specially hacked-up version of getnetgrent.c used to parse
64 * data from the stored hash table of netgroup info rather than from a
65 * file. It's used mainly for the parse_netgroup() function. All the YP
66 * stuff and file support has been stripped out since it isn't needed.
67 */
68
69#include <stdio.h>
70#include <string.h>
71#include <stdlib.h>
72#include <unistd.h>
73#include "hash.h"
74
75#ifndef lint
76static const char rcsid[] = "$OpenBSD: parse_netgroup.c,v 1.2 1997/08/18 03:11:35 millert Exp $";
77#endif
78
79/*
80 * Static Variables and functions used by setnetgrent(), getnetgrent() and
81 * __endnetgrent().
82 * There are two linked lists:
83 * - linelist is just used by setnetgrent() to parse the net group file via.
84 * parse_netgrp()
85 * - netgrp is the list of entries for the current netgroup
86 */
87struct linelist {
88 struct linelist *l_next; /* Chain ptr. */
89 int l_parsed; /* Flag for cycles */
90 char *l_groupname; /* Name of netgroup */
91 char *l_line; /* Netgroup entrie(s) to be parsed */
92};
93
94struct netgrp {
95 struct netgrp *ng_next; /* Chain ptr */
96 char *ng_str[3]; /* Field pointers, see below */
97};
98#define NG_HOST 0 /* Host name */
99#define NG_USER 1 /* User name */
100#define NG_DOM 2 /* and Domain name */
101
102static struct linelist *linehead = (struct linelist *)0;
103static struct netgrp *nextgrp = (struct netgrp *)0;
104static struct {
105 struct netgrp *gr;
106 char *grname;
107} grouphead = {
108 (struct netgrp *)0,
109 (char *)0,
110};
111static int parse_netgrp();
112static struct linelist *read_for_group();
113void __setnetgrent(), __endnetgrent();
114int __getnetgrent();
115extern struct group_entry *gtable[];
116
117/*
118 * setnetgrent()
119 * Parse the netgroup file looking for the netgroup and build the list
120 * of netgrp structures. Let parse_netgrp() and read_for_group() do
121 * most of the work.
122 */
123void
124__setnetgrent(group)
125 char *group;
126{
127 /* Sanity check */
128
129 if (group == NULL || !strlen(group))
130 return;
131
132 if (grouphead.gr == (struct netgrp *)0 ||
133 strcmp(group, grouphead.grname)) {
134 __endnetgrent();
135 if (parse_netgrp(group))
136 __endnetgrent();
137 else {
138 grouphead.grname = (char *)
139 malloc(strlen(group) + 1);
140 strcpy(grouphead.grname, group);
141 }
142 }
143 nextgrp = grouphead.gr;
144}
145
146/*
147 * Get the next netgroup off the list.
148 */
149int
150__getnetgrent(hostp, userp, domp)
151 char **hostp, **userp, **domp;
152{
153 if (nextgrp) {
154 *hostp = nextgrp->ng_str[NG_HOST];
155 *userp = nextgrp->ng_str[NG_USER];
156 *domp = nextgrp->ng_str[NG_DOM];
157 nextgrp = nextgrp->ng_next;
158 return (1);
159 }
160 return (0);
161}
162
163/*
164 * __endnetgrent() - cleanup
165 */
166void
167__endnetgrent()
168{
169 register struct linelist *lp, *olp;
170 register struct netgrp *gp, *ogp;
171
172 lp = linehead;
173 while (lp) {
174 olp = lp;
175 lp = lp->l_next;
176 free(olp->l_groupname);
177 free(olp->l_line);
178 free((char *)olp);
179 }
180 linehead = (struct linelist *)0;
181 if (grouphead.grname) {
182 free(grouphead.grname);
183 grouphead.grname = (char *)0;
184 }
185 gp = grouphead.gr;
186 while (gp) {
187 ogp = gp;
188 gp = gp->ng_next;
189 if (ogp->ng_str[NG_HOST])
190 free(ogp->ng_str[NG_HOST]);
191 if (ogp->ng_str[NG_USER])
192 free(ogp->ng_str[NG_USER]);
193 if (ogp->ng_str[NG_DOM])
194 free(ogp->ng_str[NG_DOM]);
195 free((char *)ogp);
196 }
197 grouphead.gr = (struct netgrp *)0;
198}
199
200/*
201 * Parse the netgroup file setting up the linked lists.
202 */
203static int
204parse_netgrp(group)
205 char *group;
206{
207 register char *spos, *epos;
208 register int len, strpos;
209#ifdef DEBUG
210 register int fields;
211#endif
212 char *pos, *gpos;
213 struct netgrp *grp;
214 struct linelist *lp = linehead;
215
216 /*
217 * First, see if the line has already been read in.
218 */
219 while (lp) {
220 if (!strcmp(group, lp->l_groupname))
221 break;
222 lp = lp->l_next;
223 }
224 if (lp == (struct linelist *)0 &&
225 (lp = read_for_group(group)) == (struct linelist *)0)
226 return (1);
227 if (lp->l_parsed) {
228#ifdef DEBUG
229 /*
230 * This error message is largely superflous since the
231 * code handles the error condition sucessfully, and
232 * spewing it out from inside libc can actually hose
233 * certain programs.
234 */
235 fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname);
236#endif
237 return (1);
238 } else
239 lp->l_parsed = 1;
240 pos = lp->l_line;
241 /* Watch for null pointer dereferences, dammit! */
242 while (pos != NULL && *pos != '\0') {
243 if (*pos == '(') {
244 grp = (struct netgrp *)malloc(sizeof (struct netgrp));
245 bzero((char *)grp, sizeof (struct netgrp));
246 grp->ng_next = grouphead.gr;
247 grouphead.gr = grp;
248 pos++;
249 gpos = strsep(&pos, ")");
250#ifdef DEBUG
251 fields = 0;
252#endif
253 for (strpos = 0; strpos < 3; strpos++) {
254 if ((spos = strsep(&gpos, ","))) {
255#ifdef DEBUG
256 fields++;
257#endif
258 while (*spos == ' ' || *spos == '\t')
259 spos++;
260 if ((epos = strpbrk(spos, " \t"))) {
261 *epos = '\0';
262 len = epos - spos;
263 } else
264 len = strlen(spos);
265 if (len > 0) {
266 grp->ng_str[strpos] = (char *)
267 malloc(len + 1);
268 bcopy(spos, grp->ng_str[strpos],
269 len + 1);
270 }
271 } else {
272 /*
273 * All other systems I've tested
274 * return NULL for empty netgroup
275 * fields. It's up to user programs
276 * to handle the NULLs appropriately.
277 */
278 grp->ng_str[strpos] = NULL;
279 }
280 }
281#ifdef DEBUG
282 /*
283 * Note: on other platforms, malformed netgroup
284 * entries are not normally flagged. While we
285 * can catch bad entries and report them, we should
286 * stay silent by default for compatibility's sake.
287 */
288 if (fields < 3)
289 fprintf(stderr, "Bad entry (%s%s%s%s%s) in netgroup \"%s\"\n",
290 grp->ng_str[NG_HOST] == NULL ? "" : grp->ng_str[NG_HOST],
291 grp->ng_str[NG_USER] == NULL ? "" : ",",
292 grp->ng_str[NG_USER] == NULL ? "" : grp->ng_str[NG_USER],
293 grp->ng_str[NG_DOM] == NULL ? "" : ",",
294 grp->ng_str[NG_DOM] == NULL ? "" : grp->ng_str[NG_DOM],
295 lp->l_groupname);
296#endif
297 } else {
298 spos = strsep(&pos, ", \t");
299 if (parse_netgrp(spos))
300 continue;
301 }
302 /* Watch for null pointer dereferences, dammit! */
303 if (pos != NULL)
304 while (*pos == ' ' || *pos == ',' || *pos == '\t')
305 pos++;
306 }
307 return (0);
308}
309
310/*
311 * Read the netgroup file and save lines until the line for the netgroup
312 * is found. Return 1 if eof is encountered.
313 */
314static struct linelist *
315read_for_group(group)
316 char *group;
317{
318 register char *pos, *spos, *linep = NULL, *olinep = NULL;
319 register int len, olen;
320 int cont;
321 struct linelist *lp;
322 char line[LINSIZ + 1];
323 char *data = NULL;
324
325 data = lookup (gtable, group);
326 sprintf(line, "%s %s", group, data);
327 pos = (char *)&line;
328#ifdef CANT_HAPPEN
329 if (*pos == '#')
330 continue;
331#endif
332 while (*pos == ' ' || *pos == '\t')
333 pos++;
334 spos = pos;
335 while (*pos != ' ' && *pos != '\t' && *pos != '\n' &&
336 *pos != '\0')
337 pos++;
338 len = pos - spos;
339 while (*pos == ' ' || *pos == '\t')
340 pos++;
341 if (*pos != '\n' && *pos != '\0') {
342 lp = (struct linelist *)malloc(sizeof (*lp));
343 lp->l_parsed = 0;
344 lp->l_groupname = (char *)malloc(len + 1);
345 bcopy(spos, lp->l_groupname, len);
346 *(lp->l_groupname + len) = '\0';
347 len = strlen(pos);
348 olen = 0;
349 /*
350 * Loop around handling line continuations.
351 */
352 do {
353 if (*(pos + len - 1) == '\n')
354 len--;
355 if (*(pos + len - 1) == '\\') {
356 len--;
357 cont = 1;
358 } else
359 cont = 0;
360 if (len > 0) {
361 linep = (char *)malloc(olen + len + 1);
362 if (olen > 0) {
363 bcopy(olinep, linep, olen);
364 free(olinep);
365 }
366 bcopy(pos, linep + olen, len);
367 olen += len;
368 *(linep + olen) = '\0';
369 olinep = linep;
370 }
371#ifdef CANT_HAPPEN
372 if (cont) {
373 if (fgets(line, LINSIZ, netf)) {
374 pos = line;
375 len = strlen(pos);
376 } else
377 cont = 0;
378 }
379#endif
380 } while (cont);
381 lp->l_line = linep;
382 lp->l_next = linehead;
383 linehead = lp;
384#ifdef CANT_HAPPEN
385 /*
386 * If this is the one we wanted, we are done.
387 */
388 if (!strcmp(lp->l_groupname, group))
389#endif
390 return (lp);
391 }
392 return ((struct linelist *)0);
393}