Home | History | Annotate | Line # | Download | only in gen
getpwent.c revision 1.7
      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 = "from: @(#)getpwent.c	5.21 (Berkeley) 3/14/91";*/
     36 static char *rcsid = "$Id: getpwent.c,v 1.7 1993/08/26 00:44:42 jtc Exp $";
     37 #endif /* LIBC_SCCS and not lint */
     38 
     39 #include <sys/param.h>
     40 #include <fcntl.h>
     41 #include <db.h>
     42 #include <syslog.h>
     43 #include <pwd.h>
     44 #include <utmp.h>
     45 #include <errno.h>
     46 #include <unistd.h>
     47 #include <stdlib.h>
     48 #include <string.h>
     49 #include <limits.h>
     50 #ifdef YP
     51 #include <stdio.h>
     52 #include <rpc/rpc.h>
     53 #include <rpcsvc/yp_prot.h>
     54 #include <rpcsvc/ypclnt.h>
     55 #endif
     56 
     57 static struct passwd _pw_passwd;	/* password structure */
     58 static DB *_pw_db;			/* password database */
     59 static int _pw_keynum;			/* key counter */
     60 static int _pw_stayopen;		/* keep fd's open */
     61 static int __hashpw(), __initdb();
     62 
     63 #ifdef YP
     64 static char     *__ypcurrent, *__ypdomain;
     65 static int      __ypcurrentlen, __ypmode=0;
     66 static char	line[1024];
     67 
     68 static int
     69 __ypparse(pw, s)
     70 struct passwd *pw;
     71 char *s;
     72 {
     73 	char *bp, *cp;
     74 
     75 	bp = s;
     76 	pw->pw_name = strsep(&bp, ":\n");
     77 	pw->pw_passwd = strsep(&bp, ":\n");
     78 	if (!(cp = strsep(&bp, ":\n")))
     79 		return 1;
     80 	pw->pw_uid = atoi(cp);
     81 	if (!(cp = strsep(&bp, ":\n")))
     82 		return 0;
     83 	pw->pw_gid = atoi(cp);
     84 	pw->pw_change = 0;
     85 	pw->pw_class = "";
     86 	pw->pw_gecos = strsep(&bp, ":\n");
     87 	pw->pw_dir = strsep(&bp, ":\n");
     88 	pw->pw_shell = strsep(&bp, ":\n");
     89 	pw->pw_expire = 0;
     90 	return 0;
     91 }
     92 #endif
     93 
     94 struct passwd *
     95 getpwent()
     96 {
     97 	DBT key;
     98 	char bf[sizeof(_pw_keynum) + 1];
     99 #ifdef YP
    100 	char *bp, *cp;
    101 #endif
    102 
    103 	if (!_pw_db && !__initdb())
    104 		return((struct passwd *)NULL);
    105 
    106 #ifdef YP
    107 again:
    108 	if(__ypmode) {
    109 		char *key, *data;
    110 		int keylen, datalen;
    111 		int r;
    112 
    113 		if(!__ypdomain) {
    114 			if( _yp_check(&__ypdomain) == 0) {
    115 				__ypmode = 0;
    116 				goto again;
    117 			}
    118 		}
    119 		if(__ypcurrent) {
    120 			r = yp_next(__ypdomain, "passwd.byname",
    121 				__ypcurrent, __ypcurrentlen,
    122 				&key, &keylen, &data, &datalen);
    123 			free(__ypcurrent);
    124 			__ypcurrent = NULL;
    125 			/*printf("yp_next %d\n", r);*/
    126 			switch(r) {
    127 			case 0:
    128 				break;
    129 			default:
    130 				__ypcurrent = NULL;
    131 				__ypmode = 0;
    132 				free(data);
    133 				data = NULL;
    134 				goto again;
    135 			}
    136 			__ypcurrent = key;
    137 			__ypcurrentlen = keylen;
    138 			bcopy(data, line, datalen);
    139 			free(data);
    140 			data = NULL;
    141 		} else {
    142 			r = yp_first(__ypdomain, "passwd.byname",
    143 				&__ypcurrent, &__ypcurrentlen,
    144 				&data, &datalen);
    145 			/*printf("yp_first %d\n", r);*/
    146 			switch(r) {
    147 			case 0:
    148 				break;
    149 			default:
    150 				__ypmode = 0;
    151 				free(data);
    152 				goto again;
    153 			}
    154 			bcopy(data, line, datalen);
    155 			free(data);
    156 			data = NULL;
    157 		}
    158 		line[datalen] = '\0';
    159 		/*printf("line = %s\n", line);*/
    160 		bp = line;
    161 		goto parse;
    162 	}
    163 #endif
    164 
    165 	++_pw_keynum;
    166 	bf[0] = _PW_KEYBYNUM;
    167 	bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum));
    168 	key.data = (u_char *)bf;
    169 	key.size = sizeof(_pw_keynum) + 1;
    170 	if(__hashpw(&key)) {
    171 #ifdef YP
    172 		if(strcmp(_pw_passwd.pw_name, "+") == 0) {
    173 			__ypmode = 1;
    174 			goto again;
    175 		}
    176 #endif
    177 		return &_pw_passwd;
    178 	}
    179 	return (struct passwd *)NULL;
    180 
    181 #ifdef YP
    182 parse:
    183 	_pw_passwd.pw_name = strsep(&bp, ":\n");
    184 	_pw_passwd.pw_passwd = strsep(&bp, ":\n");
    185 	if (!(cp = strsep(&bp, ":\n")))
    186 		goto again;
    187 	_pw_passwd.pw_uid = atoi(cp);
    188 	if (!(cp = strsep(&bp, ":\n")))
    189 		goto again;
    190 	_pw_passwd.pw_gid = atoi(cp);
    191 	_pw_passwd.pw_change = 0;
    192 	_pw_passwd.pw_class = "";
    193 	_pw_passwd.pw_gecos = strsep(&bp, ":\n");
    194 	_pw_passwd.pw_dir = strsep(&bp, ":\n");
    195 	_pw_passwd.pw_shell = strsep(&bp, ":\n");
    196 	_pw_passwd.pw_expire = 0;
    197 	return &_pw_passwd;
    198 #endif
    199 }
    200 
    201 struct passwd *
    202 getpwnam(name)
    203 	const char *name;
    204 {
    205 	DBT key;
    206 
    207 #ifdef YP
    208 	char bf[sizeof(_pw_keynum) + 1];
    209 	int r;
    210 
    211 	if (!_pw_db && !__initdb())
    212 		return((struct passwd *)NULL);
    213 
    214 	for(_pw_keynum=1; _pw_keynum; _pw_keynum++) {
    215 		bf[0] = _PW_KEYBYNUM;
    216 		bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum));
    217 		key.data = (u_char *)bf;
    218 		key.size = sizeof(_pw_keynum) + 1;
    219 		if(__hashpw(&key) == 0)
    220 			break;
    221 		if(strcmp(_pw_passwd.pw_name, "+") == 0) {
    222 			if(!__ypdomain) {
    223 				if(_yp_check(&__ypdomain) == 0) {
    224 					continue;
    225 				}
    226 			}
    227 			if(__ypcurrent) {
    228 				free(__ypcurrent);
    229 				__ypcurrent = NULL;
    230 			}
    231 			r = yp_match(__ypdomain, "passwd.byname",
    232 				name, strlen(name),
    233 				&__ypcurrent, &__ypcurrentlen);
    234 			switch(r) {
    235 			case 0:
    236 				break;
    237 			default:
    238 				free(__ypcurrent);
    239 				__ypcurrent = NULL;
    240 				continue;
    241 			}
    242 			bcopy(__ypcurrent, line, __ypcurrentlen);
    243 			line[__ypcurrentlen] = '\0';
    244 			if(__ypparse(&_pw_passwd, line))
    245 				continue;
    246 		}
    247 		if( strcmp(_pw_passwd.pw_name, name) == 0) {
    248 			if (!_pw_stayopen) {
    249 				(void)(_pw_db->close)(_pw_db);
    250 				_pw_db = (DB *)NULL;
    251 			}
    252 			return &_pw_passwd;
    253 		}
    254 		continue;
    255 	}
    256 	if (!_pw_stayopen) {
    257 		(void)(_pw_db->close)(_pw_db);
    258 		_pw_db = (DB *)NULL;
    259 	}
    260 	return (struct passwd *)NULL;
    261 #else
    262 	int len, rval;
    263 	char bf[UT_NAMESIZE + 1];
    264 
    265 	if (!_pw_db && !__initdb())
    266 		return((struct passwd *)NULL);
    267 
    268 	bf[0] = _PW_KEYBYNAME;
    269 	len = strlen(name);
    270 	bcopy(name, bf + 1, MIN(len, UT_NAMESIZE));
    271 	key.data = (u_char *)bf;
    272 	key.size = len + 1;
    273 	rval = __hashpw(&key);
    274 
    275 	if (!_pw_stayopen) {
    276 		(void)(_pw_db->close)(_pw_db);
    277 		_pw_db = (DB *)NULL;
    278 	}
    279 	return(rval ? &_pw_passwd : (struct passwd *)NULL);
    280 #endif
    281 }
    282 
    283 struct passwd *
    284 #ifdef __STDC__
    285 getpwuid(uid_t uid)
    286 #else
    287 getpwuid(uid)
    288 	int uid;
    289 #endif
    290 {
    291 	DBT key;
    292 
    293 #ifdef YP
    294 	char bf[sizeof(_pw_keynum) + 1], uidbuf[20];
    295 	int r;
    296 
    297 	if (!_pw_db && !__initdb())
    298 		return((struct passwd *)NULL);
    299 
    300 	for(_pw_keynum=1; _pw_keynum; _pw_keynum++) {
    301 		bf[0] = _PW_KEYBYNUM;
    302 		bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum));
    303 		key.data = (u_char *)bf;
    304 		key.size = sizeof(_pw_keynum) + 1;
    305 		if(__hashpw(&key) == 0)
    306 			break;
    307 		if(strcmp(_pw_passwd.pw_name, "+") == 0) {
    308 			if(!__ypdomain) {
    309 				if(_yp_check(&__ypdomain) == 0) {
    310 					continue;
    311 				}
    312 			}
    313 			if(__ypcurrent) {
    314 				free(__ypcurrent);
    315 				__ypcurrent = NULL;
    316 			}
    317 			sprintf(uidbuf, "%d", uid);
    318 			r = yp_match(__ypdomain, "passwd.byuid",
    319 				uidbuf, strlen(uidbuf),
    320 				&__ypcurrent, &__ypcurrentlen);
    321 			switch(r) {
    322 			case 0:
    323 				break;
    324 			default:
    325 				free(__ypcurrent);
    326 				__ypcurrent = NULL;
    327 				continue;
    328 			}
    329 			bcopy(__ypcurrent, line, __ypcurrentlen);
    330 			line[__ypcurrentlen] = '\0';
    331 			if(__ypparse(&_pw_passwd, line))
    332 				continue;
    333 		}
    334 		if( _pw_passwd.pw_uid == uid) {
    335 			if (!_pw_stayopen) {
    336 				(void)(_pw_db->close)(_pw_db);
    337 				_pw_db = (DB *)NULL;
    338 			}
    339 			return &_pw_passwd;
    340 		}
    341 		continue;
    342 	}
    343 	if (!_pw_stayopen) {
    344 		(void)(_pw_db->close)(_pw_db);
    345 		_pw_db = (DB *)NULL;
    346 	}
    347 	return (struct passwd *)NULL;
    348 #else
    349 	int keyuid, rval;
    350 	char bf[sizeof(keyuid) + 1];
    351 
    352 	if (!_pw_db && !__initdb())
    353 		return((struct passwd *)NULL);
    354 
    355 	bf[0] = _PW_KEYBYUID;
    356 	keyuid = uid;
    357 	bcopy(&keyuid, bf + 1, sizeof(keyuid));
    358 	key.data = (u_char *)bf;
    359 	key.size = sizeof(keyuid) + 1;
    360 	rval = __hashpw(&key);
    361 
    362 	if (!_pw_stayopen) {
    363 		(void)(_pw_db->close)(_pw_db);
    364 		_pw_db = (DB *)NULL;
    365 	}
    366 	return(rval ? &_pw_passwd : (struct passwd *)NULL);
    367 #endif
    368 }
    369 
    370 int
    371 setpassent(stayopen)
    372 	int stayopen;
    373 {
    374 	_pw_keynum = 0;
    375 	_pw_stayopen = stayopen;
    376 	return(1);
    377 }
    378 
    379 int
    380 setpwent()
    381 {
    382 	_pw_keynum = 0;
    383 	_pw_stayopen = 0;
    384 #ifdef YP
    385 	__ypmode = 0;
    386 	if(__ypcurrent)
    387 		free(__ypcurrent);
    388 	__ypcurrent = NULL;
    389 #endif
    390 	return(1);
    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 	return(0);
    422 }
    423 
    424 static int
    425 __hashpw(key)
    426 	DBT *key;
    427 {
    428 	register char *p, *t;
    429 	static u_int max;
    430 	static char *line;
    431 	DBT data;
    432 
    433 	if ((_pw_db->get)(_pw_db, key, &data, 0))
    434 		return(0);
    435 	p = (char *)data.data;
    436 	if (data.size > max && !(line = realloc(line, max += 1024)))
    437 		return(0);
    438 
    439 	t = line;
    440 #define	EXPAND(e)	e = t; while (*t++ = *p++);
    441 	EXPAND(_pw_passwd.pw_name);
    442 	EXPAND(_pw_passwd.pw_passwd);
    443 	bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int));
    444 	p += sizeof(int);
    445 	bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int));
    446 	p += sizeof(int);
    447 	bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t));
    448 	p += sizeof(time_t);
    449 	EXPAND(_pw_passwd.pw_class);
    450 	EXPAND(_pw_passwd.pw_gecos);
    451 	EXPAND(_pw_passwd.pw_dir);
    452 	EXPAND(_pw_passwd.pw_shell);
    453 	bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t));
    454 	p += sizeof(time_t);
    455 	return(1);
    456 }
    457