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