getgrent.c revision 1.7 1 /* $NetBSD: getgrent.c,v 1.7 2003/08/07 09:27:57 agc Exp $ */
2
3 /*
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 /*
33 * Portions Copyright (c) 1994, Jason Downs. All Rights Reserved.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 * 3. All advertising materials mentioning features or use of this software
44 * must display the following acknowledgement:
45 * This product includes software developed by the University of
46 * California, Berkeley and its contributors.
47 * 4. Neither the name of the University nor the names of its contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
50 *
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * SUCH DAMAGE.
62 */
63
64 /*
65 * Copied from: lib/libc/gen/getgrent.c
66 * NetBSD: getgrent.c,v 1.46 2003/02/17 00:11:54 simonb Exp
67 * and then gutted, leaving only /etc/group support.
68 */
69
70 #include <sys/cdefs.h>
71
72 #ifdef __weak_alias
73 #define endgrent _endgrent
74 #define getgrent _getgrent
75 #define getgrgid _getgrgid
76 #define getgrnam _getgrnam
77 #define setgrent _setgrent
78 #define setgroupent _setgroupent
79
80 __weak_alias(endgrent,_endgrent)
81 __weak_alias(getgrent,_getgrent)
82 __weak_alias(getgrgid,_getgrgid)
83 __weak_alias(getgrnam,_getgrnam)
84 __weak_alias(setgrent,_setgrent)
85 __weak_alias(setgroupent,_setgroupent)
86 #endif
87
88 #include <sys/types.h>
89
90 #include <grp.h>
91 #include <limits.h>
92 #include <stdio.h>
93 #include <stdlib.h>
94 #include <string.h>
95
96 struct group *_getgrent_user(const char *);
97
98 static FILE *_gr_fp;
99 static struct group _gr_group;
100 static int _gr_stayopen;
101 static int _gr_filesdone;
102
103 static int grscan(int, gid_t, const char *, const char *);
104 static int grstart(void);
105 static int grmatchline(int, gid_t, const char *, const char *);
106
107 #define MAXGRP 200
108 #define MAXLINELENGTH 1024
109
110 static __aconst char *members[MAXGRP];
111 static char grline[MAXLINELENGTH];
112
113 struct group *
114 getgrent(void)
115 {
116
117 if ((!_gr_fp && !grstart()) || !grscan(0, 0, NULL, NULL))
118 return (NULL);
119 return &_gr_group;
120 }
121
122 /*
123 * _getgrent_user() is designed only to be called by getgrouplist(3) and
124 * hence makes no guarantees about filling the entire structure that it
125 * returns. It may only fill in the group name and gid fields.
126 */
127
128 struct group *
129 _getgrent_user(const char *user)
130 {
131
132 if ((!_gr_fp && !grstart()) || !grscan(0, 0, NULL, user))
133 return (NULL);
134 return &_gr_group;
135 }
136
137 struct group *
138 getgrnam(const char *name)
139 {
140 int rval;
141
142 if (!grstart())
143 return NULL;
144 rval = grscan(1, 0, name, NULL);
145 if (!_gr_stayopen)
146 endgrent();
147 return (rval) ? &_gr_group : NULL;
148 }
149
150 struct group *
151 getgrgid(gid_t gid)
152 {
153 int rval;
154
155 if (!grstart())
156 return NULL;
157 rval = grscan(1, gid, NULL, NULL);
158 if (!_gr_stayopen)
159 endgrent();
160 return (rval) ? &_gr_group : NULL;
161 }
162
163 static int
164 grstart(void)
165 {
166
167 _gr_filesdone = 0;
168 if (_gr_fp) {
169 rewind(_gr_fp);
170 return 1;
171 }
172 return (_gr_fp = fopen(_PATH_GROUP, "r")) ? 1 : 0;
173 }
174
175 void
176 setgrent(void)
177 {
178
179 (void) setgroupent(0);
180 }
181
182 int
183 setgroupent(int stayopen)
184 {
185
186 if (!grstart())
187 return 0;
188 _gr_stayopen = stayopen;
189 return 1;
190 }
191
192 void
193 endgrent(void)
194 {
195
196 _gr_filesdone = 0;
197 if (_gr_fp) {
198 (void)fclose(_gr_fp);
199 _gr_fp = NULL;
200 }
201 }
202
203 static int
204 grscan(int search, gid_t gid, const char *name, const char *user)
205 {
206
207 if (_gr_filesdone)
208 return 0;
209 for (;;) {
210 if (!fgets(grline, sizeof(grline), _gr_fp)) {
211 if (!search)
212 _gr_filesdone = 1;
213 return 0;
214 }
215 /* skip lines that are too big */
216 if (!strchr(grline, '\n')) {
217 int ch;
218
219 while ((ch = getc(_gr_fp)) != '\n' && ch != EOF)
220 ;
221 continue;
222 }
223 if (grmatchline(search, gid, name, user))
224 return 1;
225 }
226 /* NOTREACHED */
227 }
228
229 static int
230 grmatchline(int search, gid_t gid, const char *name, const char *user)
231 {
232 unsigned long id;
233 __aconst char **m;
234 char *cp, *bp, *ep;
235
236 /* name may be NULL if search is nonzero */
237
238 bp = grline;
239 _gr_group.gr_name = strsep(&bp, ":\n");
240 if (search && name && strcmp(_gr_group.gr_name, name))
241 return 0;
242 _gr_group.gr_passwd = strsep(&bp, ":\n");
243 if (!(cp = strsep(&bp, ":\n")))
244 return 0;
245 id = strtoul(cp, &ep, 10);
246 if (id > GID_MAX || *ep != '\0')
247 return 0;
248 _gr_group.gr_gid = (gid_t)id;
249 if (search && name == NULL && _gr_group.gr_gid != gid)
250 return 0;
251 cp = NULL;
252 if (bp == NULL)
253 return 0;
254 for (_gr_group.gr_mem = m = members;; bp++) {
255 if (m == &members[MAXGRP - 1])
256 break;
257 if (*bp == ',') {
258 if (cp) {
259 *bp = '\0';
260 *m++ = cp;
261 cp = NULL;
262 }
263 } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') {
264 if (cp) {
265 *bp = '\0';
266 *m++ = cp;
267 }
268 break;
269 } else if (cp == NULL)
270 cp = bp;
271 }
272 *m = NULL;
273 if (user) {
274 for (m = members; *m; m++)
275 if (!strcmp(user, *m))
276 return 1;
277 return 0;
278 }
279 return 1;
280 }
281