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