getpwent.c revision 1.5 1 /*
2 * Copyright (c) 1988 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #if defined(LIBC_SCCS) && !defined(lint)
35 static char sccsid[] = "@(#)getpwent.c 5.21 (Berkeley) 3/14/91";
36 #endif /* LIBC_SCCS and not lint */
37
38 #include <sys/param.h>
39 #include <fcntl.h>
40 #include <db.h>
41 #include <syslog.h>
42 #include <pwd.h>
43 #include <utmp.h>
44 #include <errno.h>
45 #include <unistd.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <limits.h>
49 #ifdef YP
50 #include <stdio.h>
51 #include <rpc/rpc.h>
52 #include <rpcsvc/yp_prot.h>
53 #include <rpcsvc/ypclnt.h>
54 #endif
55
56 static struct passwd _pw_passwd; /* password structure */
57 static DB *_pw_db; /* password database */
58 static int _pw_keynum; /* key counter */
59 static int _pw_stayopen; /* keep fd's open */
60 static int __hashpw(), __initdb();
61
62 #ifdef YP
63 static char *__ypcurrent, *__ypdomain;
64 static int __ypcurrentlen, __ypmode=0;
65 static char line[1024];
66
67 static int
68 __ypparse(pw, s)
69 struct passwd *pw;
70 char *s;
71 {
72 char *bp, *cp;
73
74 bp = s;
75 pw->pw_name = strsep(&bp, ":\n");
76 pw->pw_passwd = strsep(&bp, ":\n");
77 if (!(cp = strsep(&bp, ":\n")))
78 return 1;
79 pw->pw_uid = atoi(cp);
80 if (!(cp = strsep(&bp, ":\n")))
81 return 0;
82 pw->pw_gid = atoi(cp);
83 pw->pw_change = 0;
84 pw->pw_class = "";
85 pw->pw_gecos = strsep(&bp, ":\n");
86 pw->pw_dir = strsep(&bp, ":\n");
87 pw->pw_shell = strsep(&bp, ":\n");
88 pw->pw_expire = 0;
89 return 0;
90 }
91 #endif
92
93 struct passwd *
94 getpwent()
95 {
96 DBT key;
97 char bf[sizeof(_pw_keynum) + 1];
98 #ifdef YP
99 char *bp, *cp;
100 #endif
101
102 if (!_pw_db && !__initdb())
103 return((struct passwd *)NULL);
104
105 #ifdef YP
106 again:
107 if(__ypmode) {
108 char *key, *data;
109 int keylen, datalen;
110 int r;
111
112 if(!__ypdomain) {
113 if( _yp_check(&__ypdomain) == 0) {
114 __ypmode = 0;
115 goto again;
116 }
117 }
118 if(__ypcurrent) {
119 r = yp_next(__ypdomain, "passwd.byname",
120 __ypcurrent, __ypcurrentlen,
121 &key, &keylen, &data, &datalen);
122 free(__ypcurrent);
123 __ypcurrent = NULL;
124 /*printf("yp_next %d\n", r);*/
125 switch(r) {
126 case 0:
127 break;
128 default:
129 __ypcurrent = NULL;
130 __ypmode = 0;
131 free(data);
132 data = NULL;
133 goto again;
134 }
135 __ypcurrent = key;
136 __ypcurrentlen = keylen;
137 bcopy(data, line, datalen);
138 free(data);
139 data = NULL;
140 } else {
141 r = yp_first(__ypdomain, "passwd.byname",
142 &__ypcurrent, &__ypcurrentlen,
143 &data, &datalen);
144 /*printf("yp_first %d\n", r);*/
145 switch(r) {
146 case 0:
147 break;
148 default:
149 __ypmode = 0;
150 free(data);
151 goto again;
152 }
153 bcopy(data, line, datalen);
154 free(data);
155 data = NULL;
156 }
157 line[datalen] = '\0';
158 /*printf("line = %s\n", line);*/
159 bp = line;
160 goto parse;
161 }
162 #endif
163
164 ++_pw_keynum;
165 bf[0] = _PW_KEYBYNUM;
166 bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum));
167 key.data = (u_char *)bf;
168 key.size = sizeof(_pw_keynum) + 1;
169 if(__hashpw(&key)) {
170 #ifdef YP
171 if(strcmp(_pw_passwd.pw_name, "+") == 0) {
172 __ypmode = 1;
173 goto again;
174 }
175 #endif
176 return &_pw_passwd;
177 }
178 return (struct passwd *)NULL;
179
180 #ifdef YP
181 parse:
182 _pw_passwd.pw_name = strsep(&bp, ":\n");
183 _pw_passwd.pw_passwd = strsep(&bp, ":\n");
184 if (!(cp = strsep(&bp, ":\n")))
185 goto again;
186 _pw_passwd.pw_uid = atoi(cp);
187 if (!(cp = strsep(&bp, ":\n")))
188 goto again;
189 _pw_passwd.pw_gid = atoi(cp);
190 _pw_passwd.pw_change = 0;
191 _pw_passwd.pw_class = "";
192 _pw_passwd.pw_gecos = strsep(&bp, ":\n");
193 _pw_passwd.pw_dir = strsep(&bp, ":\n");
194 _pw_passwd.pw_shell = strsep(&bp, ":\n");
195 _pw_passwd.pw_expire = 0;
196 return &_pw_passwd;
197 #endif
198 }
199
200 struct passwd *
201 getpwnam(name)
202 const char *name;
203 {
204 DBT key;
205
206 #ifdef YP
207 char bf[sizeof(_pw_keynum) + 1];
208 int r;
209
210 if (!_pw_db && !__initdb())
211 return((struct passwd *)NULL);
212
213 for(_pw_keynum=1; _pw_keynum; _pw_keynum++) {
214 bf[0] = _PW_KEYBYNUM;
215 bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum));
216 key.data = (u_char *)bf;
217 key.size = sizeof(_pw_keynum) + 1;
218 if(__hashpw(&key) == 0)
219 break;
220 if(strcmp(_pw_passwd.pw_name, "+") == 0) {
221 if(!__ypdomain) {
222 if(_yp_check(&__ypdomain) == 0) {
223 continue;
224 }
225 }
226 if(__ypcurrent) {
227 free(__ypcurrent);
228 __ypcurrent = NULL;
229 }
230 r = yp_match(__ypdomain, "passwd.byname",
231 name, strlen(name),
232 &__ypcurrent, &__ypcurrentlen);
233 switch(r) {
234 case 0:
235 break;
236 default:
237 free(__ypcurrent);
238 __ypcurrent = NULL;
239 continue;
240 }
241 bcopy(__ypcurrent, line, __ypcurrentlen);
242 line[__ypcurrentlen] = '\0';
243 if(__ypparse(&_pw_passwd, line))
244 continue;
245 }
246 if( strcmp(_pw_passwd.pw_name, name) == 0) {
247 if (!_pw_stayopen) {
248 (void)(_pw_db->close)(_pw_db);
249 _pw_db = (DB *)NULL;
250 }
251 return &_pw_passwd;
252 }
253 continue;
254 }
255 if (!_pw_stayopen) {
256 (void)(_pw_db->close)(_pw_db);
257 _pw_db = (DB *)NULL;
258 }
259 return (struct passwd *)NULL;
260 #else
261 int len, rval;
262 char bf[UT_NAMESIZE + 1];
263
264 if (!_pw_db && !__initdb())
265 return((struct passwd *)NULL);
266
267 bf[0] = _PW_KEYBYNAME;
268 len = strlen(name);
269 bcopy(name, bf + 1, MIN(len, UT_NAMESIZE));
270 key.data = (u_char *)bf;
271 key.size = len + 1;
272 rval = __hashpw(&key);
273
274 if (!_pw_stayopen) {
275 (void)(_pw_db->close)(_pw_db);
276 _pw_db = (DB *)NULL;
277 }
278 return(rval ? &_pw_passwd : (struct passwd *)NULL);
279 #endif
280 }
281
282 struct passwd *
283 #ifdef __STDC__
284 getpwuid(uid_t uid)
285 #else
286 getpwuid(uid)
287 int uid;
288 #endif
289 {
290 DBT key;
291
292 #ifdef YP
293 char bf[sizeof(_pw_keynum) + 1], uidbuf[20];
294 int r;
295
296 if (!_pw_db && !__initdb())
297 return((struct passwd *)NULL);
298
299 for(_pw_keynum=1; _pw_keynum; _pw_keynum++) {
300 bf[0] = _PW_KEYBYNUM;
301 bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum));
302 key.data = (u_char *)bf;
303 key.size = sizeof(_pw_keynum) + 1;
304 if(__hashpw(&key) == 0)
305 break;
306 if(strcmp(_pw_passwd.pw_name, "+") == 0) {
307 if(!__ypdomain) {
308 if(_yp_check(&__ypdomain) == 0) {
309 continue;
310 }
311 }
312 if(__ypcurrent) {
313 free(__ypcurrent);
314 __ypcurrent = NULL;
315 }
316 sprintf(uidbuf, "%d", uid);
317 r = yp_match(__ypdomain, "passwd.byuid",
318 uidbuf, strlen(uidbuf),
319 &__ypcurrent, &__ypcurrentlen);
320 switch(r) {
321 case 0:
322 break;
323 default:
324 free(__ypcurrent);
325 __ypcurrent = NULL;
326 continue;
327 }
328 bcopy(__ypcurrent, line, __ypcurrentlen);
329 line[__ypcurrentlen] = '\0';
330 if(__ypparse(&_pw_passwd, line))
331 continue;
332 }
333 if( _pw_passwd.pw_uid == uid) {
334 if (!_pw_stayopen) {
335 (void)(_pw_db->close)(_pw_db);
336 _pw_db = (DB *)NULL;
337 }
338 return &_pw_passwd;
339 }
340 continue;
341 }
342 if (!_pw_stayopen) {
343 (void)(_pw_db->close)(_pw_db);
344 _pw_db = (DB *)NULL;
345 }
346 return (struct passwd *)NULL;
347 #else
348 int keyuid, rval;
349 char bf[sizeof(keyuid) + 1];
350
351 if (!_pw_db && !__initdb())
352 return((struct passwd *)NULL);
353
354 bf[0] = _PW_KEYBYUID;
355 keyuid = uid;
356 bcopy(&keyuid, bf + 1, sizeof(keyuid));
357 key.data = (u_char *)bf;
358 key.size = sizeof(keyuid) + 1;
359 rval = __hashpw(&key);
360
361 if (!_pw_stayopen) {
362 (void)(_pw_db->close)(_pw_db);
363 _pw_db = (DB *)NULL;
364 }
365 return(rval ? &_pw_passwd : (struct passwd *)NULL);
366 #endif
367 }
368
369 int
370 setpassent(stayopen)
371 int stayopen;
372 {
373 _pw_keynum = 0;
374 _pw_stayopen = stayopen;
375 return(1);
376 }
377
378 int
379 setpwent()
380 {
381 _pw_keynum = 0;
382 _pw_stayopen = 0;
383 #ifdef YP
384 __ypmode = 0;
385 if(__ypcurrent)
386 free(__ypcurrent);
387 __ypcurrent = NULL;
388 #endif
389 return(1);
390 }
391
392 void
393 endpwent()
394 {
395 _pw_keynum = 0;
396 if (_pw_db) {
397 (void)(_pw_db->close)(_pw_db);
398 _pw_db = (DB *)NULL;
399 }
400 #ifdef YP
401 __ypmode = 0;
402 if(__ypcurrent)
403 free(__ypcurrent);
404 __ypcurrent = NULL;
405 #endif
406 }
407
408 static int
409 __initdb()
410 {
411 static int warned;
412 char *p;
413
414 p = (geteuid()) ? _PATH_MP_DB : _PATH_SMP_DB;
415 _pw_db = dbopen(p, O_RDONLY, 0, DB_HASH, NULL);
416 if (_pw_db)
417 return(1);
418 if (!warned)
419 syslog(LOG_ERR, "%s: %m", p);
420 return(0);
421 }
422
423 static int
424 __hashpw(key)
425 DBT *key;
426 {
427 register char *p, *t;
428 static u_int max;
429 static char *line;
430 DBT data;
431
432 if ((_pw_db->get)(_pw_db, key, &data, 0))
433 return(0);
434 p = (char *)data.data;
435 if (data.size > max && !(line = realloc(line, max += 1024)))
436 return(0);
437
438 t = line;
439 #define EXPAND(e) e = t; while (*t++ = *p++);
440 EXPAND(_pw_passwd.pw_name);
441 EXPAND(_pw_passwd.pw_passwd);
442 bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int));
443 p += sizeof(int);
444 bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int));
445 p += sizeof(int);
446 bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t));
447 p += sizeof(time_t);
448 EXPAND(_pw_passwd.pw_class);
449 EXPAND(_pw_passwd.pw_gecos);
450 EXPAND(_pw_passwd.pw_dir);
451 EXPAND(_pw_passwd.pw_shell);
452 bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t));
453 p += sizeof(time_t);
454 return(1);
455 }
456