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