lcl_ng.c revision 1.1.1.1.4.2 1 1.1.1.1.4.2 riz /* $NetBSD: lcl_ng.c,v 1.1.1.1.4.2 2011/01/06 21:42:18 riz Exp $ */
2 1.1.1.1.4.2 riz
3 1.1.1.1.4.2 riz /*
4 1.1.1.1.4.2 riz * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5 1.1.1.1.4.2 riz * Copyright (c) 1996-1999 by Internet Software Consortium.
6 1.1.1.1.4.2 riz *
7 1.1.1.1.4.2 riz * Permission to use, copy, modify, and distribute this software for any
8 1.1.1.1.4.2 riz * purpose with or without fee is hereby granted, provided that the above
9 1.1.1.1.4.2 riz * copyright notice and this permission notice appear in all copies.
10 1.1.1.1.4.2 riz *
11 1.1.1.1.4.2 riz * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12 1.1.1.1.4.2 riz * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 1.1.1.1.4.2 riz * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
14 1.1.1.1.4.2 riz * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 1.1.1.1.4.2 riz * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 1.1.1.1.4.2 riz * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17 1.1.1.1.4.2 riz * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 1.1.1.1.4.2 riz */
19 1.1.1.1.4.2 riz
20 1.1.1.1.4.2 riz #if !defined(LINT) && !defined(CODECENTER)
21 1.1.1.1.4.2 riz static const char rcsid[] = "Id: lcl_ng.c,v 1.3 2005/04/27 04:56:31 sra Exp";
22 1.1.1.1.4.2 riz #endif
23 1.1.1.1.4.2 riz
24 1.1.1.1.4.2 riz /* Imports */
25 1.1.1.1.4.2 riz
26 1.1.1.1.4.2 riz #include "port_before.h"
27 1.1.1.1.4.2 riz
28 1.1.1.1.4.2 riz #include <sys/types.h>
29 1.1.1.1.4.2 riz #include <netinet/in.h>
30 1.1.1.1.4.2 riz #include <arpa/nameser.h>
31 1.1.1.1.4.2 riz #include <resolv.h>
32 1.1.1.1.4.2 riz #include <errno.h>
33 1.1.1.1.4.2 riz #include <stdio.h>
34 1.1.1.1.4.2 riz #include <stdlib.h>
35 1.1.1.1.4.2 riz #include <string.h>
36 1.1.1.1.4.2 riz #include <unistd.h>
37 1.1.1.1.4.2 riz
38 1.1.1.1.4.2 riz #include <irs.h>
39 1.1.1.1.4.2 riz #include <isc/memcluster.h>
40 1.1.1.1.4.2 riz
41 1.1.1.1.4.2 riz #include "port_after.h"
42 1.1.1.1.4.2 riz
43 1.1.1.1.4.2 riz #include "irs_p.h"
44 1.1.1.1.4.2 riz #include "lcl_p.h"
45 1.1.1.1.4.2 riz
46 1.1.1.1.4.2 riz /* Definitions */
47 1.1.1.1.4.2 riz
48 1.1.1.1.4.2 riz #define NG_HOST 0 /*%< Host name */
49 1.1.1.1.4.2 riz #define NG_USER 1 /*%< User name */
50 1.1.1.1.4.2 riz #define NG_DOM 2 /*%< and Domain name */
51 1.1.1.1.4.2 riz #define LINSIZ 1024 /*%< Length of netgroup file line */
52 1.1.1.1.4.2 riz /*
53 1.1.1.1.4.2 riz * XXX Warning XXX
54 1.1.1.1.4.2 riz * This code is a hack-and-slash special. It realy needs to be
55 1.1.1.1.4.2 riz * rewritten with things like strdup, and realloc in mind.
56 1.1.1.1.4.2 riz * More reasonable data structures would not be a bad thing.
57 1.1.1.1.4.2 riz */
58 1.1.1.1.4.2 riz
59 1.1.1.1.4.2 riz /*%
60 1.1.1.1.4.2 riz * Static Variables and functions used by setnetgrent(), getnetgrent() and
61 1.1.1.1.4.2 riz * endnetgrent().
62 1.1.1.1.4.2 riz *
63 1.1.1.1.4.2 riz * There are two linked lists:
64 1.1.1.1.4.2 riz * \li linelist is just used by setnetgrent() to parse the net group file via.
65 1.1.1.1.4.2 riz * parse_netgrp()
66 1.1.1.1.4.2 riz * \li netgrp is the list of entries for the current netgroup
67 1.1.1.1.4.2 riz */
68 1.1.1.1.4.2 riz struct linelist {
69 1.1.1.1.4.2 riz struct linelist *l_next; /*%< Chain ptr. */
70 1.1.1.1.4.2 riz int l_parsed; /*%< Flag for cycles */
71 1.1.1.1.4.2 riz char * l_groupname; /*%< Name of netgroup */
72 1.1.1.1.4.2 riz char * l_line; /*%< Netgroup entrie(s) to be parsed */
73 1.1.1.1.4.2 riz };
74 1.1.1.1.4.2 riz
75 1.1.1.1.4.2 riz struct ng_old_struct {
76 1.1.1.1.4.2 riz struct ng_old_struct *ng_next; /*%< Chain ptr */
77 1.1.1.1.4.2 riz char * ng_str[3]; /*%< Field pointers, see below */
78 1.1.1.1.4.2 riz };
79 1.1.1.1.4.2 riz
80 1.1.1.1.4.2 riz struct pvt {
81 1.1.1.1.4.2 riz FILE *fp;
82 1.1.1.1.4.2 riz struct linelist *linehead;
83 1.1.1.1.4.2 riz struct ng_old_struct *nextgrp;
84 1.1.1.1.4.2 riz struct {
85 1.1.1.1.4.2 riz struct ng_old_struct *gr;
86 1.1.1.1.4.2 riz char *grname;
87 1.1.1.1.4.2 riz } grouphead;
88 1.1.1.1.4.2 riz };
89 1.1.1.1.4.2 riz
90 1.1.1.1.4.2 riz /* Forward */
91 1.1.1.1.4.2 riz
92 1.1.1.1.4.2 riz static void ng_rewind(struct irs_ng *, const char*);
93 1.1.1.1.4.2 riz static void ng_close(struct irs_ng *);
94 1.1.1.1.4.2 riz static int ng_next(struct irs_ng *, const char **,
95 1.1.1.1.4.2 riz const char **, const char **);
96 1.1.1.1.4.2 riz static int ng_test(struct irs_ng *, const char *,
97 1.1.1.1.4.2 riz const char *, const char *,
98 1.1.1.1.4.2 riz const char *);
99 1.1.1.1.4.2 riz static void ng_minimize(struct irs_ng *);
100 1.1.1.1.4.2 riz
101 1.1.1.1.4.2 riz static int parse_netgrp(struct irs_ng *, const char*);
102 1.1.1.1.4.2 riz static struct linelist *read_for_group(struct irs_ng *, const char *);
103 1.1.1.1.4.2 riz static void freelists(struct irs_ng *);
104 1.1.1.1.4.2 riz
105 1.1.1.1.4.2 riz /* Public */
106 1.1.1.1.4.2 riz
107 1.1.1.1.4.2 riz struct irs_ng *
108 1.1.1.1.4.2 riz irs_lcl_ng(struct irs_acc *this) {
109 1.1.1.1.4.2 riz struct irs_ng *ng;
110 1.1.1.1.4.2 riz struct pvt *pvt;
111 1.1.1.1.4.2 riz
112 1.1.1.1.4.2 riz UNUSED(this);
113 1.1.1.1.4.2 riz
114 1.1.1.1.4.2 riz if (!(ng = memget(sizeof *ng))) {
115 1.1.1.1.4.2 riz errno = ENOMEM;
116 1.1.1.1.4.2 riz return (NULL);
117 1.1.1.1.4.2 riz }
118 1.1.1.1.4.2 riz memset(ng, 0x5e, sizeof *ng);
119 1.1.1.1.4.2 riz if (!(pvt = memget(sizeof *pvt))) {
120 1.1.1.1.4.2 riz memput(ng, sizeof *ng);
121 1.1.1.1.4.2 riz errno = ENOMEM;
122 1.1.1.1.4.2 riz return (NULL);
123 1.1.1.1.4.2 riz }
124 1.1.1.1.4.2 riz memset(pvt, 0, sizeof *pvt);
125 1.1.1.1.4.2 riz ng->private = pvt;
126 1.1.1.1.4.2 riz ng->close = ng_close;
127 1.1.1.1.4.2 riz ng->next = ng_next;
128 1.1.1.1.4.2 riz ng->test = ng_test;
129 1.1.1.1.4.2 riz ng->rewind = ng_rewind;
130 1.1.1.1.4.2 riz ng->minimize = ng_minimize;
131 1.1.1.1.4.2 riz return (ng);
132 1.1.1.1.4.2 riz }
133 1.1.1.1.4.2 riz
134 1.1.1.1.4.2 riz /* Methods */
135 1.1.1.1.4.2 riz
136 1.1.1.1.4.2 riz static void
137 1.1.1.1.4.2 riz ng_close(struct irs_ng *this) {
138 1.1.1.1.4.2 riz struct pvt *pvt = (struct pvt *)this->private;
139 1.1.1.1.4.2 riz
140 1.1.1.1.4.2 riz if (pvt->fp != NULL)
141 1.1.1.1.4.2 riz fclose(pvt->fp);
142 1.1.1.1.4.2 riz freelists(this);
143 1.1.1.1.4.2 riz memput(pvt, sizeof *pvt);
144 1.1.1.1.4.2 riz memput(this, sizeof *this);
145 1.1.1.1.4.2 riz }
146 1.1.1.1.4.2 riz
147 1.1.1.1.4.2 riz /*%
148 1.1.1.1.4.2 riz * Parse the netgroup file looking for the netgroup and build the list
149 1.1.1.1.4.2 riz * of netgrp structures. Let parse_netgrp() and read_for_group() do
150 1.1.1.1.4.2 riz * most of the work.
151 1.1.1.1.4.2 riz */
152 1.1.1.1.4.2 riz static void
153 1.1.1.1.4.2 riz ng_rewind(struct irs_ng *this, const char *group) {
154 1.1.1.1.4.2 riz struct pvt *pvt = (struct pvt *)this->private;
155 1.1.1.1.4.2 riz
156 1.1.1.1.4.2 riz if (pvt->fp != NULL && fseek(pvt->fp, SEEK_CUR, 0L) == -1) {
157 1.1.1.1.4.2 riz fclose(pvt->fp);
158 1.1.1.1.4.2 riz pvt->fp = NULL;
159 1.1.1.1.4.2 riz }
160 1.1.1.1.4.2 riz
161 1.1.1.1.4.2 riz if (pvt->fp == NULL || pvt->grouphead.gr == NULL ||
162 1.1.1.1.4.2 riz strcmp(group, pvt->grouphead.grname)) {
163 1.1.1.1.4.2 riz freelists(this);
164 1.1.1.1.4.2 riz if (pvt->fp != NULL)
165 1.1.1.1.4.2 riz fclose(pvt->fp);
166 1.1.1.1.4.2 riz pvt->fp = fopen(_PATH_NETGROUP, "r");
167 1.1.1.1.4.2 riz if (pvt->fp != NULL) {
168 1.1.1.1.4.2 riz if (parse_netgrp(this, group))
169 1.1.1.1.4.2 riz freelists(this);
170 1.1.1.1.4.2 riz if (!(pvt->grouphead.grname = strdup(group)))
171 1.1.1.1.4.2 riz freelists(this);
172 1.1.1.1.4.2 riz fclose(pvt->fp);
173 1.1.1.1.4.2 riz pvt->fp = NULL;
174 1.1.1.1.4.2 riz }
175 1.1.1.1.4.2 riz }
176 1.1.1.1.4.2 riz pvt->nextgrp = pvt->grouphead.gr;
177 1.1.1.1.4.2 riz }
178 1.1.1.1.4.2 riz
179 1.1.1.1.4.2 riz /*%
180 1.1.1.1.4.2 riz * Get the next netgroup off the list.
181 1.1.1.1.4.2 riz */
182 1.1.1.1.4.2 riz static int
183 1.1.1.1.4.2 riz ng_next(struct irs_ng *this, const char **host, const char **user,
184 1.1.1.1.4.2 riz const char **domain)
185 1.1.1.1.4.2 riz {
186 1.1.1.1.4.2 riz struct pvt *pvt = (struct pvt *)this->private;
187 1.1.1.1.4.2 riz
188 1.1.1.1.4.2 riz if (pvt->nextgrp) {
189 1.1.1.1.4.2 riz *host = pvt->nextgrp->ng_str[NG_HOST];
190 1.1.1.1.4.2 riz *user = pvt->nextgrp->ng_str[NG_USER];
191 1.1.1.1.4.2 riz *domain = pvt->nextgrp->ng_str[NG_DOM];
192 1.1.1.1.4.2 riz pvt->nextgrp = pvt->nextgrp->ng_next;
193 1.1.1.1.4.2 riz return (1);
194 1.1.1.1.4.2 riz }
195 1.1.1.1.4.2 riz return (0);
196 1.1.1.1.4.2 riz }
197 1.1.1.1.4.2 riz
198 1.1.1.1.4.2 riz /*%
199 1.1.1.1.4.2 riz * Search for a match in a netgroup.
200 1.1.1.1.4.2 riz */
201 1.1.1.1.4.2 riz static int
202 1.1.1.1.4.2 riz ng_test(struct irs_ng *this, const char *name,
203 1.1.1.1.4.2 riz const char *host, const char *user, const char *domain)
204 1.1.1.1.4.2 riz {
205 1.1.1.1.4.2 riz const char *ng_host, *ng_user, *ng_domain;
206 1.1.1.1.4.2 riz
207 1.1.1.1.4.2 riz ng_rewind(this, name);
208 1.1.1.1.4.2 riz while (ng_next(this, &ng_host, &ng_user, &ng_domain))
209 1.1.1.1.4.2 riz if ((host == NULL || ng_host == NULL ||
210 1.1.1.1.4.2 riz !strcmp(host, ng_host)) &&
211 1.1.1.1.4.2 riz (user == NULL || ng_user == NULL ||
212 1.1.1.1.4.2 riz !strcmp(user, ng_user)) &&
213 1.1.1.1.4.2 riz (domain == NULL || ng_domain == NULL ||
214 1.1.1.1.4.2 riz !strcmp(domain, ng_domain))) {
215 1.1.1.1.4.2 riz freelists(this);
216 1.1.1.1.4.2 riz return (1);
217 1.1.1.1.4.2 riz }
218 1.1.1.1.4.2 riz freelists(this);
219 1.1.1.1.4.2 riz return (0);
220 1.1.1.1.4.2 riz }
221 1.1.1.1.4.2 riz
222 1.1.1.1.4.2 riz static void
223 1.1.1.1.4.2 riz ng_minimize(struct irs_ng *this) {
224 1.1.1.1.4.2 riz struct pvt *pvt = (struct pvt *)this->private;
225 1.1.1.1.4.2 riz
226 1.1.1.1.4.2 riz if (pvt->fp != NULL) {
227 1.1.1.1.4.2 riz (void)fclose(pvt->fp);
228 1.1.1.1.4.2 riz pvt->fp = NULL;
229 1.1.1.1.4.2 riz }
230 1.1.1.1.4.2 riz }
231 1.1.1.1.4.2 riz
232 1.1.1.1.4.2 riz /* Private */
233 1.1.1.1.4.2 riz
234 1.1.1.1.4.2 riz /*%
235 1.1.1.1.4.2 riz * endnetgrent() - cleanup
236 1.1.1.1.4.2 riz */
237 1.1.1.1.4.2 riz static void
238 1.1.1.1.4.2 riz freelists(struct irs_ng *this) {
239 1.1.1.1.4.2 riz struct pvt *pvt = (struct pvt *)this->private;
240 1.1.1.1.4.2 riz struct linelist *lp, *olp;
241 1.1.1.1.4.2 riz struct ng_old_struct *gp, *ogp;
242 1.1.1.1.4.2 riz
243 1.1.1.1.4.2 riz lp = pvt->linehead;
244 1.1.1.1.4.2 riz while (lp) {
245 1.1.1.1.4.2 riz olp = lp;
246 1.1.1.1.4.2 riz lp = lp->l_next;
247 1.1.1.1.4.2 riz free(olp->l_groupname);
248 1.1.1.1.4.2 riz free(olp->l_line);
249 1.1.1.1.4.2 riz free((char *)olp);
250 1.1.1.1.4.2 riz }
251 1.1.1.1.4.2 riz pvt->linehead = NULL;
252 1.1.1.1.4.2 riz if (pvt->grouphead.grname) {
253 1.1.1.1.4.2 riz free(pvt->grouphead.grname);
254 1.1.1.1.4.2 riz pvt->grouphead.grname = NULL;
255 1.1.1.1.4.2 riz }
256 1.1.1.1.4.2 riz gp = pvt->grouphead.gr;
257 1.1.1.1.4.2 riz while (gp) {
258 1.1.1.1.4.2 riz ogp = gp;
259 1.1.1.1.4.2 riz gp = gp->ng_next;
260 1.1.1.1.4.2 riz if (ogp->ng_str[NG_HOST])
261 1.1.1.1.4.2 riz free(ogp->ng_str[NG_HOST]);
262 1.1.1.1.4.2 riz if (ogp->ng_str[NG_USER])
263 1.1.1.1.4.2 riz free(ogp->ng_str[NG_USER]);
264 1.1.1.1.4.2 riz if (ogp->ng_str[NG_DOM])
265 1.1.1.1.4.2 riz free(ogp->ng_str[NG_DOM]);
266 1.1.1.1.4.2 riz free((char *)ogp);
267 1.1.1.1.4.2 riz }
268 1.1.1.1.4.2 riz pvt->grouphead.gr = NULL;
269 1.1.1.1.4.2 riz }
270 1.1.1.1.4.2 riz
271 1.1.1.1.4.2 riz /*%
272 1.1.1.1.4.2 riz * Parse the netgroup file setting up the linked lists.
273 1.1.1.1.4.2 riz */
274 1.1.1.1.4.2 riz static int
275 1.1.1.1.4.2 riz parse_netgrp(struct irs_ng *this, const char *group) {
276 1.1.1.1.4.2 riz struct pvt *pvt = (struct pvt *)this->private;
277 1.1.1.1.4.2 riz char *spos, *epos;
278 1.1.1.1.4.2 riz int len, strpos;
279 1.1.1.1.4.2 riz char *pos, *gpos;
280 1.1.1.1.4.2 riz struct ng_old_struct *grp;
281 1.1.1.1.4.2 riz struct linelist *lp = pvt->linehead;
282 1.1.1.1.4.2 riz
283 1.1.1.1.4.2 riz /*
284 1.1.1.1.4.2 riz * First, see if the line has already been read in.
285 1.1.1.1.4.2 riz */
286 1.1.1.1.4.2 riz while (lp) {
287 1.1.1.1.4.2 riz if (!strcmp(group, lp->l_groupname))
288 1.1.1.1.4.2 riz break;
289 1.1.1.1.4.2 riz lp = lp->l_next;
290 1.1.1.1.4.2 riz }
291 1.1.1.1.4.2 riz if (lp == NULL &&
292 1.1.1.1.4.2 riz (lp = read_for_group(this, group)) == NULL)
293 1.1.1.1.4.2 riz return (1);
294 1.1.1.1.4.2 riz if (lp->l_parsed) {
295 1.1.1.1.4.2 riz /*fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname);*/
296 1.1.1.1.4.2 riz return (1);
297 1.1.1.1.4.2 riz } else
298 1.1.1.1.4.2 riz lp->l_parsed = 1;
299 1.1.1.1.4.2 riz pos = lp->l_line;
300 1.1.1.1.4.2 riz while (*pos != '\0') {
301 1.1.1.1.4.2 riz if (*pos == '(') {
302 1.1.1.1.4.2 riz if (!(grp = malloc(sizeof (struct ng_old_struct)))) {
303 1.1.1.1.4.2 riz freelists(this);
304 1.1.1.1.4.2 riz errno = ENOMEM;
305 1.1.1.1.4.2 riz return (1);
306 1.1.1.1.4.2 riz }
307 1.1.1.1.4.2 riz memset(grp, 0, sizeof (struct ng_old_struct));
308 1.1.1.1.4.2 riz grp->ng_next = pvt->grouphead.gr;
309 1.1.1.1.4.2 riz pvt->grouphead.gr = grp;
310 1.1.1.1.4.2 riz pos++;
311 1.1.1.1.4.2 riz gpos = strsep(&pos, ")");
312 1.1.1.1.4.2 riz for (strpos = 0; strpos < 3; strpos++) {
313 1.1.1.1.4.2 riz if ((spos = strsep(&gpos, ","))) {
314 1.1.1.1.4.2 riz while (*spos == ' ' || *spos == '\t')
315 1.1.1.1.4.2 riz spos++;
316 1.1.1.1.4.2 riz if ((epos = strpbrk(spos, " \t"))) {
317 1.1.1.1.4.2 riz *epos = '\0';
318 1.1.1.1.4.2 riz len = epos - spos;
319 1.1.1.1.4.2 riz } else
320 1.1.1.1.4.2 riz len = strlen(spos);
321 1.1.1.1.4.2 riz if (len > 0) {
322 1.1.1.1.4.2 riz if(!(grp->ng_str[strpos]
323 1.1.1.1.4.2 riz = (char *)
324 1.1.1.1.4.2 riz malloc(len + 1))) {
325 1.1.1.1.4.2 riz freelists(this);
326 1.1.1.1.4.2 riz return (1);
327 1.1.1.1.4.2 riz }
328 1.1.1.1.4.2 riz memcpy(grp->ng_str[strpos],
329 1.1.1.1.4.2 riz spos,
330 1.1.1.1.4.2 riz len + 1);
331 1.1.1.1.4.2 riz }
332 1.1.1.1.4.2 riz } else
333 1.1.1.1.4.2 riz goto errout;
334 1.1.1.1.4.2 riz }
335 1.1.1.1.4.2 riz } else {
336 1.1.1.1.4.2 riz spos = strsep(&pos, ", \t");
337 1.1.1.1.4.2 riz if (spos != NULL && parse_netgrp(this, spos)) {
338 1.1.1.1.4.2 riz freelists(this);
339 1.1.1.1.4.2 riz return (1);
340 1.1.1.1.4.2 riz }
341 1.1.1.1.4.2 riz }
342 1.1.1.1.4.2 riz if (pos == NULL)
343 1.1.1.1.4.2 riz break;
344 1.1.1.1.4.2 riz while (*pos == ' ' || *pos == ',' || *pos == '\t')
345 1.1.1.1.4.2 riz pos++;
346 1.1.1.1.4.2 riz }
347 1.1.1.1.4.2 riz return (0);
348 1.1.1.1.4.2 riz errout:
349 1.1.1.1.4.2 riz /*fprintf(stderr, "Bad netgroup %s at ..%s\n", lp->l_groupname,
350 1.1.1.1.4.2 riz spos);*/
351 1.1.1.1.4.2 riz return (1);
352 1.1.1.1.4.2 riz }
353 1.1.1.1.4.2 riz
354 1.1.1.1.4.2 riz /*%
355 1.1.1.1.4.2 riz * Read the netgroup file and save lines until the line for the netgroup
356 1.1.1.1.4.2 riz * is found. Return 1 if eof is encountered.
357 1.1.1.1.4.2 riz */
358 1.1.1.1.4.2 riz static struct linelist *
359 1.1.1.1.4.2 riz read_for_group(struct irs_ng *this, const char *group) {
360 1.1.1.1.4.2 riz struct pvt *pvt = (struct pvt *)this->private;
361 1.1.1.1.4.2 riz char *pos, *spos, *linep = NULL, *olinep;
362 1.1.1.1.4.2 riz int len, olen, cont;
363 1.1.1.1.4.2 riz struct linelist *lp;
364 1.1.1.1.4.2 riz char line[LINSIZ + 1];
365 1.1.1.1.4.2 riz
366 1.1.1.1.4.2 riz while (fgets(line, LINSIZ, pvt->fp) != NULL) {
367 1.1.1.1.4.2 riz pos = line;
368 1.1.1.1.4.2 riz if (*pos == '#')
369 1.1.1.1.4.2 riz continue;
370 1.1.1.1.4.2 riz while (*pos == ' ' || *pos == '\t')
371 1.1.1.1.4.2 riz pos++;
372 1.1.1.1.4.2 riz spos = pos;
373 1.1.1.1.4.2 riz while (*pos != ' ' && *pos != '\t' && *pos != '\n' &&
374 1.1.1.1.4.2 riz *pos != '\0')
375 1.1.1.1.4.2 riz pos++;
376 1.1.1.1.4.2 riz len = pos - spos;
377 1.1.1.1.4.2 riz while (*pos == ' ' || *pos == '\t')
378 1.1.1.1.4.2 riz pos++;
379 1.1.1.1.4.2 riz if (*pos != '\n' && *pos != '\0') {
380 1.1.1.1.4.2 riz if (!(lp = malloc(sizeof (*lp)))) {
381 1.1.1.1.4.2 riz freelists(this);
382 1.1.1.1.4.2 riz return (NULL);
383 1.1.1.1.4.2 riz }
384 1.1.1.1.4.2 riz lp->l_parsed = 0;
385 1.1.1.1.4.2 riz if (!(lp->l_groupname = malloc(len + 1))) {
386 1.1.1.1.4.2 riz free(lp);
387 1.1.1.1.4.2 riz freelists(this);
388 1.1.1.1.4.2 riz return (NULL);
389 1.1.1.1.4.2 riz }
390 1.1.1.1.4.2 riz memcpy(lp->l_groupname, spos, len);
391 1.1.1.1.4.2 riz *(lp->l_groupname + len) = '\0';
392 1.1.1.1.4.2 riz len = strlen(pos);
393 1.1.1.1.4.2 riz olen = 0;
394 1.1.1.1.4.2 riz olinep = NULL;
395 1.1.1.1.4.2 riz
396 1.1.1.1.4.2 riz /*
397 1.1.1.1.4.2 riz * Loop around handling line continuations.
398 1.1.1.1.4.2 riz */
399 1.1.1.1.4.2 riz do {
400 1.1.1.1.4.2 riz if (*(pos + len - 1) == '\n')
401 1.1.1.1.4.2 riz len--;
402 1.1.1.1.4.2 riz if (*(pos + len - 1) == '\\') {
403 1.1.1.1.4.2 riz len--;
404 1.1.1.1.4.2 riz cont = 1;
405 1.1.1.1.4.2 riz } else
406 1.1.1.1.4.2 riz cont = 0;
407 1.1.1.1.4.2 riz if (len > 0) {
408 1.1.1.1.4.2 riz if (!(linep = malloc(olen + len + 1))){
409 1.1.1.1.4.2 riz if (olen > 0)
410 1.1.1.1.4.2 riz free(olinep);
411 1.1.1.1.4.2 riz free(lp->l_groupname);
412 1.1.1.1.4.2 riz free(lp);
413 1.1.1.1.4.2 riz freelists(this);
414 1.1.1.1.4.2 riz errno = ENOMEM;
415 1.1.1.1.4.2 riz return (NULL);
416 1.1.1.1.4.2 riz }
417 1.1.1.1.4.2 riz if (olen > 0) {
418 1.1.1.1.4.2 riz memcpy(linep, olinep, olen);
419 1.1.1.1.4.2 riz free(olinep);
420 1.1.1.1.4.2 riz }
421 1.1.1.1.4.2 riz memcpy(linep + olen, pos, len);
422 1.1.1.1.4.2 riz olen += len;
423 1.1.1.1.4.2 riz *(linep + olen) = '\0';
424 1.1.1.1.4.2 riz olinep = linep;
425 1.1.1.1.4.2 riz }
426 1.1.1.1.4.2 riz if (cont) {
427 1.1.1.1.4.2 riz if (fgets(line, LINSIZ, pvt->fp)) {
428 1.1.1.1.4.2 riz pos = line;
429 1.1.1.1.4.2 riz len = strlen(pos);
430 1.1.1.1.4.2 riz } else
431 1.1.1.1.4.2 riz cont = 0;
432 1.1.1.1.4.2 riz }
433 1.1.1.1.4.2 riz } while (cont);
434 1.1.1.1.4.2 riz lp->l_line = linep;
435 1.1.1.1.4.2 riz lp->l_next = pvt->linehead;
436 1.1.1.1.4.2 riz pvt->linehead = lp;
437 1.1.1.1.4.2 riz
438 1.1.1.1.4.2 riz /*
439 1.1.1.1.4.2 riz * If this is the one we wanted, we are done.
440 1.1.1.1.4.2 riz */
441 1.1.1.1.4.2 riz if (!strcmp(lp->l_groupname, group))
442 1.1.1.1.4.2 riz return (lp);
443 1.1.1.1.4.2 riz }
444 1.1.1.1.4.2 riz }
445 1.1.1.1.4.2 riz return (NULL);
446 1.1.1.1.4.2 riz }
447 1.1.1.1.4.2 riz
448 1.1.1.1.4.2 riz /*! \file */
449