getgrent.c revision 1.8 1 1.8 agc /* $NetBSD: getgrent.c,v 1.8 2003/10/13 15:36:33 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 *
44 1.8 agc * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
45 1.8 agc * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
46 1.8 agc * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
47 1.8 agc * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
48 1.8 agc * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
49 1.8 agc * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
50 1.8 agc * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
51 1.8 agc * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 1.1 gwr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 1.1 gwr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 1.1 gwr * SUCH DAMAGE.
55 1.1 gwr */
56 1.1 gwr
57 1.2 gwr /*
58 1.2 gwr * Copied from: lib/libc/gen/getgrent.c
59 1.6 elric * NetBSD: getgrent.c,v 1.46 2003/02/17 00:11:54 simonb Exp
60 1.2 gwr * and then gutted, leaving only /etc/group support.
61 1.2 gwr */
62 1.1 gwr
63 1.4 tsutsui #include <sys/cdefs.h>
64 1.4 tsutsui
65 1.4 tsutsui #ifdef __weak_alias
66 1.4 tsutsui #define endgrent _endgrent
67 1.4 tsutsui #define getgrent _getgrent
68 1.4 tsutsui #define getgrgid _getgrgid
69 1.4 tsutsui #define getgrnam _getgrnam
70 1.4 tsutsui #define setgrent _setgrent
71 1.4 tsutsui #define setgroupent _setgroupent
72 1.4 tsutsui
73 1.4 tsutsui __weak_alias(endgrent,_endgrent)
74 1.4 tsutsui __weak_alias(getgrent,_getgrent)
75 1.4 tsutsui __weak_alias(getgrgid,_getgrgid)
76 1.4 tsutsui __weak_alias(getgrnam,_getgrnam)
77 1.4 tsutsui __weak_alias(setgrent,_setgrent)
78 1.4 tsutsui __weak_alias(setgroupent,_setgroupent)
79 1.4 tsutsui #endif
80 1.1 gwr
81 1.5 lukem #include <sys/types.h>
82 1.5 lukem
83 1.5 lukem #include <grp.h>
84 1.5 lukem #include <limits.h>
85 1.5 lukem #include <stdio.h>
86 1.5 lukem #include <stdlib.h>
87 1.5 lukem #include <string.h>
88 1.5 lukem
89 1.6 elric struct group *_getgrent_user(const char *);
90 1.6 elric
91 1.5 lukem static FILE *_gr_fp;
92 1.5 lukem static struct group _gr_group;
93 1.6 elric static int _gr_stayopen;
94 1.5 lukem static int _gr_filesdone;
95 1.5 lukem
96 1.6 elric static int grscan(int, gid_t, const char *, const char *);
97 1.5 lukem static int grstart(void);
98 1.6 elric static int grmatchline(int, gid_t, const char *, const char *);
99 1.1 gwr
100 1.1 gwr #define MAXGRP 200
101 1.1 gwr #define MAXLINELENGTH 1024
102 1.6 elric
103 1.6 elric static __aconst char *members[MAXGRP];
104 1.5 lukem static char grline[MAXLINELENGTH];
105 1.1 gwr
106 1.1 gwr struct group *
107 1.5 lukem getgrent(void)
108 1.1 gwr {
109 1.6 elric
110 1.6 elric if ((!_gr_fp && !grstart()) || !grscan(0, 0, NULL, NULL))
111 1.6 elric return (NULL);
112 1.6 elric return &_gr_group;
113 1.6 elric }
114 1.6 elric
115 1.6 elric /*
116 1.6 elric * _getgrent_user() is designed only to be called by getgrouplist(3) and
117 1.6 elric * hence makes no guarantees about filling the entire structure that it
118 1.6 elric * returns. It may only fill in the group name and gid fields.
119 1.6 elric */
120 1.6 elric
121 1.6 elric struct group *
122 1.6 elric _getgrent_user(const char *user)
123 1.6 elric {
124 1.6 elric
125 1.6 elric if ((!_gr_fp && !grstart()) || !grscan(0, 0, NULL, user))
126 1.6 elric return (NULL);
127 1.6 elric return &_gr_group;
128 1.1 gwr }
129 1.1 gwr
130 1.1 gwr struct group *
131 1.5 lukem getgrnam(const char *name)
132 1.1 gwr {
133 1.1 gwr int rval;
134 1.1 gwr
135 1.5 lukem if (!grstart())
136 1.6 elric return NULL;
137 1.6 elric rval = grscan(1, 0, name, NULL);
138 1.1 gwr if (!_gr_stayopen)
139 1.1 gwr endgrent();
140 1.6 elric return (rval) ? &_gr_group : NULL;
141 1.1 gwr }
142 1.1 gwr
143 1.1 gwr struct group *
144 1.1 gwr getgrgid(gid_t gid)
145 1.1 gwr {
146 1.1 gwr int rval;
147 1.1 gwr
148 1.5 lukem if (!grstart())
149 1.6 elric return NULL;
150 1.6 elric rval = grscan(1, gid, NULL, NULL);
151 1.1 gwr if (!_gr_stayopen)
152 1.1 gwr endgrent();
153 1.6 elric return (rval) ? &_gr_group : NULL;
154 1.1 gwr }
155 1.1 gwr
156 1.1 gwr static int
157 1.5 lukem grstart(void)
158 1.1 gwr {
159 1.6 elric
160 1.5 lukem _gr_filesdone = 0;
161 1.1 gwr if (_gr_fp) {
162 1.1 gwr rewind(_gr_fp);
163 1.6 elric return 1;
164 1.1 gwr }
165 1.6 elric return (_gr_fp = fopen(_PATH_GROUP, "r")) ? 1 : 0;
166 1.1 gwr }
167 1.1 gwr
168 1.1 gwr void
169 1.5 lukem setgrent(void)
170 1.1 gwr {
171 1.6 elric
172 1.1 gwr (void) setgroupent(0);
173 1.1 gwr }
174 1.1 gwr
175 1.1 gwr int
176 1.5 lukem setgroupent(int stayopen)
177 1.1 gwr {
178 1.6 elric
179 1.5 lukem if (!grstart())
180 1.6 elric return 0;
181 1.1 gwr _gr_stayopen = stayopen;
182 1.6 elric return 1;
183 1.1 gwr }
184 1.1 gwr
185 1.1 gwr void
186 1.5 lukem endgrent(void)
187 1.1 gwr {
188 1.6 elric
189 1.5 lukem _gr_filesdone = 0;
190 1.1 gwr if (_gr_fp) {
191 1.1 gwr (void)fclose(_gr_fp);
192 1.1 gwr _gr_fp = NULL;
193 1.1 gwr }
194 1.1 gwr }
195 1.1 gwr
196 1.1 gwr static int
197 1.6 elric grscan(int search, gid_t gid, const char *name, const char *user)
198 1.1 gwr {
199 1.6 elric
200 1.5 lukem if (_gr_filesdone)
201 1.5 lukem return 0;
202 1.1 gwr for (;;) {
203 1.5 lukem if (!fgets(grline, sizeof(grline), _gr_fp)) {
204 1.5 lukem if (!search)
205 1.5 lukem _gr_filesdone = 1;
206 1.5 lukem return 0;
207 1.5 lukem }
208 1.1 gwr /* skip lines that are too big */
209 1.5 lukem if (!strchr(grline, '\n')) {
210 1.1 gwr int ch;
211 1.1 gwr
212 1.1 gwr while ((ch = getc(_gr_fp)) != '\n' && ch != EOF)
213 1.1 gwr ;
214 1.1 gwr continue;
215 1.1 gwr }
216 1.6 elric if (grmatchline(search, gid, name, user))
217 1.5 lukem return 1;
218 1.1 gwr }
219 1.1 gwr /* NOTREACHED */
220 1.5 lukem }
221 1.5 lukem
222 1.5 lukem static int
223 1.6 elric grmatchline(int search, gid_t gid, const char *name, const char *user)
224 1.5 lukem {
225 1.5 lukem unsigned long id;
226 1.6 elric __aconst char **m;
227 1.5 lukem char *cp, *bp, *ep;
228 1.5 lukem
229 1.5 lukem /* name may be NULL if search is nonzero */
230 1.5 lukem
231 1.5 lukem bp = grline;
232 1.5 lukem _gr_group.gr_name = strsep(&bp, ":\n");
233 1.5 lukem if (search && name && strcmp(_gr_group.gr_name, name))
234 1.5 lukem return 0;
235 1.5 lukem _gr_group.gr_passwd = strsep(&bp, ":\n");
236 1.5 lukem if (!(cp = strsep(&bp, ":\n")))
237 1.5 lukem return 0;
238 1.5 lukem id = strtoul(cp, &ep, 10);
239 1.5 lukem if (id > GID_MAX || *ep != '\0')
240 1.5 lukem return 0;
241 1.5 lukem _gr_group.gr_gid = (gid_t)id;
242 1.5 lukem if (search && name == NULL && _gr_group.gr_gid != gid)
243 1.5 lukem return 0;
244 1.5 lukem cp = NULL;
245 1.5 lukem if (bp == NULL)
246 1.5 lukem return 0;
247 1.5 lukem for (_gr_group.gr_mem = m = members;; bp++) {
248 1.5 lukem if (m == &members[MAXGRP - 1])
249 1.5 lukem break;
250 1.5 lukem if (*bp == ',') {
251 1.5 lukem if (cp) {
252 1.5 lukem *bp = '\0';
253 1.5 lukem *m++ = cp;
254 1.5 lukem cp = NULL;
255 1.5 lukem }
256 1.5 lukem } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') {
257 1.5 lukem if (cp) {
258 1.5 lukem *bp = '\0';
259 1.5 lukem *m++ = cp;
260 1.5 lukem }
261 1.5 lukem break;
262 1.5 lukem } else if (cp == NULL)
263 1.5 lukem cp = bp;
264 1.5 lukem }
265 1.5 lukem *m = NULL;
266 1.6 elric if (user) {
267 1.6 elric for (m = members; *m; m++)
268 1.6 elric if (!strcmp(user, *m))
269 1.6 elric return 1;
270 1.6 elric return 0;
271 1.6 elric }
272 1.5 lukem return 1;
273 1.1 gwr }
274