getgrent.c revision 1.22 1 /* $NetBSD: getgrent.c,v 1.22 1998/02/26 03:01:12 perry Exp $ */
2
3 /*
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 * Portions Copyright (c) 1994, Jason Downs. All Rights Reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37 #include <sys/cdefs.h>
38 #if defined(LIBC_SCCS) && !defined(lint)
39 #if 0
40 static char sccsid[] = "@(#)getgrent.c 8.2 (Berkeley) 3/21/94";
41 #else
42 __RCSID("$NetBSD: getgrent.c,v 1.22 1998/02/26 03:01:12 perry Exp $");
43 #endif
44 #endif /* LIBC_SCCS and not lint */
45
46 #include "namespace.h"
47 #include <sys/types.h>
48 #include <limits.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <grp.h>
53 #ifdef YP
54 #include <rpc/rpc.h>
55 #include <rpcsvc/yp_prot.h>
56 #include <rpcsvc/ypclnt.h>
57 #endif
58
59 #ifdef __weak_alias
60 __weak_alias(endgrent,_endgrent);
61 __weak_alias(getgrent,_getgrent);
62 __weak_alias(getgrgid,_getgrgid);
63 __weak_alias(getgrnam,_getgrnam);
64 __weak_alias(setgrent,_setgrent);
65 __weak_alias(setgroupent,_setgroupent);
66 #endif
67
68 static FILE *_gr_fp;
69 static struct group _gr_group;
70 static int _gr_stayopen;
71 static int grscan __P((int, gid_t, const char *));
72 static int start_gr __P((void));
73
74 #define MAXGRP 200
75 static char *members[MAXGRP];
76 #define MAXLINELENGTH 1024
77 static char line[MAXLINELENGTH];
78
79 #ifdef YP
80 enum _ypmode { YPMODE_NONE, YPMODE_FULL, YPMODE_NAME };
81 static enum _ypmode __ypmode;
82 static char *__ypcurrent, *__ypdomain;
83 static int __ypcurrentlen;
84 #endif
85
86 struct group *
87 getgrent()
88 {
89 if ((!_gr_fp && !start_gr()) || !grscan(0, 0, NULL))
90 return(NULL);
91 return(&_gr_group);
92 }
93
94 struct group *
95 getgrnam(name)
96 const char *name;
97 {
98 int rval;
99
100 if (!start_gr())
101 return(NULL);
102 rval = grscan(1, 0, name);
103 if (!_gr_stayopen)
104 endgrent();
105 return(rval ? &_gr_group : NULL);
106 }
107
108 struct group *
109 #ifdef __STDC__
110 getgrgid(gid_t gid)
111 #else
112 getgrgid(gid)
113 gid_t gid;
114 #endif
115 {
116 int rval;
117
118 if (!start_gr())
119 return(NULL);
120 rval = grscan(1, gid, NULL);
121 if (!_gr_stayopen)
122 endgrent();
123 return(rval ? &_gr_group : NULL);
124 }
125
126 static int
127 start_gr()
128 {
129 if (_gr_fp) {
130 rewind(_gr_fp);
131 #ifdef YP
132 __ypmode = YPMODE_NONE;
133 if (__ypcurrent)
134 free(__ypcurrent);
135 __ypcurrent = NULL;
136 #endif
137 return(1);
138 }
139 return((_gr_fp = fopen(_PATH_GROUP, "r")) ? 1 : 0);
140 }
141
142 void
143 setgrent()
144 {
145 (void) setgroupent(0);
146 }
147
148 int
149 setgroupent(stayopen)
150 int stayopen;
151 {
152 if (!start_gr())
153 return(0);
154 _gr_stayopen = stayopen;
155 return(1);
156 }
157
158 void
159 endgrent()
160 {
161 if (_gr_fp) {
162 (void)fclose(_gr_fp);
163 _gr_fp = NULL;
164 #ifdef YP
165 __ypmode = YPMODE_NONE;
166 if (__ypcurrent)
167 free(__ypcurrent);
168 __ypcurrent = NULL;
169 #endif
170 }
171 }
172
173 static int
174 grscan(search, gid, name)
175 int search;
176 gid_t gid;
177 const char *name;
178 {
179 char *cp, **m;
180 char *bp, *ep;
181 unsigned long id;
182 #ifdef YP
183 char *key, *data;
184 int keylen, datalen;
185 int r;
186 char *grname = (char *)NULL;
187 #endif
188
189 for (;;) {
190 #ifdef YP
191 if (__ypmode != YPMODE_NONE) {
192
193 if (!__ypdomain) {
194 if (yp_get_default_domain(&__ypdomain)) {
195 __ypmode = YPMODE_NONE;
196 if (grname != (char *)NULL) {
197 free(grname);
198 grname = (char *)NULL;
199 }
200 continue;
201 }
202 }
203 switch(__ypmode) {
204 case YPMODE_FULL:
205 data = NULL;
206 if (__ypcurrent) {
207 key = NULL;
208 r = yp_next(__ypdomain, "group.byname",
209 __ypcurrent, __ypcurrentlen,
210 &key, &keylen, &data, &datalen);
211 free(__ypcurrent);
212 if (r != 0) {
213 __ypcurrent = NULL;
214 if (key)
215 free(key);
216 }
217 else {
218 __ypcurrent = key;
219 __ypcurrentlen = keylen;
220 }
221 } else {
222 r = yp_first(__ypdomain, "group.byname",
223 &__ypcurrent, &__ypcurrentlen,
224 &data, &datalen);
225 }
226 if (r != 0) {
227 __ypmode = YPMODE_NONE;
228 if (data)
229 free(data);
230 continue;
231 }
232 bcopy(data, line, (size_t)datalen);
233 free(data);
234 break;
235 case YPMODE_NAME:
236 if (grname != (char *)NULL) {
237 data = NULL;
238 r = yp_match(__ypdomain, "group.byname",
239 grname, (int)strlen(grname),
240 &data, &datalen);
241 __ypmode = YPMODE_NONE;
242 free(grname);
243 grname = (char *)NULL;
244 if (r != 0) {
245 if (data)
246 free(data);
247 continue;
248 }
249 bcopy(data, line, (size_t)datalen);
250 free(data);
251 } else {
252 /* YP not available? */
253 __ypmode = YPMODE_NONE;
254 continue;
255 }
256 break;
257 case YPMODE_NONE:
258 abort(); /* Cannot happen */
259 break;
260 }
261 line[datalen] = '\0';
262 bp = line;
263 goto parse;
264 }
265 #endif /* YP */
266 if (!fgets(line, sizeof(line), _gr_fp))
267 return(0);
268 bp = line;
269 /* skip lines that are too big */
270 if (!strchr(line, '\n')) {
271 int ch;
272
273 while ((ch = getc(_gr_fp)) != '\n' && ch != EOF)
274 ;
275 continue;
276 }
277 #ifdef YP
278 if (line[0] == '+') {
279 switch(line[1]) {
280 case ':':
281 case '\0':
282 case '\n':
283 if (_yp_check(NULL)) {
284 if (!search) {
285 __ypmode = YPMODE_FULL;
286 continue;
287 }
288 if (!__ypdomain &&
289 yp_get_default_domain(&__ypdomain))
290 continue;
291 data = NULL;
292 if (name) {
293 r = yp_match(__ypdomain,
294 "group.byname",
295 name,
296 (int)strlen(name),
297 &data, &datalen);
298 } else {
299 char buf[20];
300 snprintf(buf, sizeof(buf),
301 "%u", gid);
302 r = yp_match(__ypdomain,
303 "group.bygid",
304 buf,
305 (int)strlen(buf),
306 &data, &datalen);
307 }
308 if (r != 0) {
309 if (data)
310 free(data);
311 continue;
312 }
313 bcopy(data, line, (size_t)datalen);
314 free(data);
315 line[datalen] = '\0';
316 bp = line;
317 _gr_group.gr_name = strsep(&bp, ":\n");
318 _gr_group.gr_passwd =
319 strsep(&bp, ":\n");
320 if (!(cp = strsep(&bp, ":\n")))
321 continue;
322 if (name) {
323 id = strtoul(cp, &ep, 10);
324 if (id > GID_MAX || *ep != '\0')
325 continue;
326 _gr_group.gr_gid = (gid_t)id;
327 } else
328 _gr_group.gr_gid = gid;
329 goto found_it;
330 }
331 break;
332 default:
333 if (_yp_check(NULL)) {
334 char *tptr;
335
336 tptr = strsep(&bp, ":\n");
337 if (search && name &&
338 strcmp(tptr, name))
339 continue;
340 __ypmode = YPMODE_NAME;
341 grname = strdup(tptr + 1);
342 continue;
343 }
344 break;
345 }
346 }
347 parse:
348 #endif /* YP */
349 _gr_group.gr_name = strsep(&bp, ":\n");
350 if (search && name && strcmp(_gr_group.gr_name, name))
351 continue;
352 _gr_group.gr_passwd = strsep(&bp, ":\n");
353 if (!(cp = strsep(&bp, ":\n")))
354 continue;
355 id = strtoul(cp, &ep, 10);
356 if (id > GID_MAX || *ep != '\0')
357 continue;
358 _gr_group.gr_gid = (gid_t)id;
359 if (search && name == NULL && _gr_group.gr_gid != gid)
360 continue;
361 found_it:
362 cp = NULL;
363 if (bp == NULL)
364 continue;
365 for (m = _gr_group.gr_mem = members;; bp++) {
366 if (m == &members[MAXGRP - 1])
367 break;
368 if (*bp == ',') {
369 if (cp) {
370 *bp = '\0';
371 *m++ = cp;
372 cp = NULL;
373 }
374 } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') {
375 if (cp) {
376 *bp = '\0';
377 *m++ = cp;
378 }
379 break;
380 } else if (cp == NULL)
381 cp = bp;
382 }
383 *m = NULL;
384 return(1);
385 }
386 /* NOTREACHED */
387 }
388