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