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