Home | History | Annotate | Line # | Download | only in gen
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