xref: /csrg-svn/lib/libc/gen/getpwent.c (revision 41756)
122095Smckusick /*
236215Sbostic  * Copyright (c) 1988 The Regents of the University of California.
336215Sbostic  * All rights reserved.
436215Sbostic  *
536215Sbostic  * Redistribution and use in source and binary forms are permitted
636215Sbostic  * provided that the above copyright notice and this paragraph are
736215Sbostic  * duplicated in all such forms and that any documentation,
836215Sbostic  * advertising materials, and other materials related to such
936215Sbostic  * distribution and use acknowledge that the software was developed
1036215Sbostic  * by the University of California, Berkeley.  The name of the
1136215Sbostic  * University may not be used to endorse or promote products derived
1236215Sbostic  * from this software without specific prior written permission.
1336215Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1436215Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1536855Sbostic  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1622095Smckusick  */
1722095Smckusick 
1826560Sdonn #if defined(LIBC_SCCS) && !defined(lint)
19*41756Smarc static char sccsid[] = "@(#)getpwent.c	5.13 (Berkeley) 05/11/90";
2036215Sbostic #endif /* LIBC_SCCS and not lint */
2122095Smckusick 
2236215Sbostic #include <sys/types.h>
2336215Sbostic #include <sys/file.h>
242019Swnj #include <stdio.h>
252019Swnj #include <pwd.h>
2616416Sralph #include <ndbm.h>
272019Swnj 
2836215Sbostic static DBM *_pw_db;
2936215Sbostic static FILE *_pw_fp;
3036215Sbostic static struct passwd _pw_passwd;
3139174Sbostic static int _pw_getfirstkey, _pw_stayopen;
3241572Sedward static char _pw_flag, *_pw_file = _PATH_PASSWD, _pw_master;
332019Swnj 
3436456Sbostic #define	MAXLINELENGTH	1024
3536215Sbostic static char line[MAXLINELENGTH];
3617759Sserge 
3736855Sbostic struct passwd *
3836855Sbostic getpwent()
3936855Sbostic {
4036855Sbostic 
4141572Sedward 	if (!_pw_fp && !start_pw(1))
4236855Sbostic 		return((struct passwd *)NULL);
4341572Sedward 	if (!scanpw())
4441572Sedward 		return((struct passwd *)NULL);
4541572Sedward 	getpw();
4641572Sedward 	return(&_pw_passwd);
4736855Sbostic }
4836855Sbostic 
4936855Sbostic struct passwd *
5036855Sbostic getpwnam(nam)
5136855Sbostic 	char *nam;
5236855Sbostic {
5336855Sbostic 	int rval;
5436855Sbostic 
5541572Sedward 	if (!start_pw(0))
5636855Sbostic 		return((struct passwd *)NULL);
5736855Sbostic 	if (_pw_db) {
5836855Sbostic 		datum key;
5936855Sbostic 
6036855Sbostic 		key.dptr = nam;
6136855Sbostic 		key.dsize = strlen(nam);
6236855Sbostic 		rval = fetch_pw(key);
6336855Sbostic 	} else /* _pw_fp */
6437243Sbostic 		for (rval = 0; scanpw();)
6536855Sbostic 			if (!strcmp(nam, _pw_passwd.pw_name)) {
6636855Sbostic 				rval = 1;
6736855Sbostic 				break;
6836855Sbostic 			}
6936855Sbostic 	if (!_pw_stayopen)
7036855Sbostic 		endpwent();
7137243Sbostic 	if (rval)
7237243Sbostic 		getpw();
7336855Sbostic 	return(rval ? &_pw_passwd : (struct passwd *)NULL);
7436855Sbostic }
7536855Sbostic 
7636855Sbostic struct passwd *
7736855Sbostic getpwuid(uid)
7836855Sbostic 	int uid;
7936855Sbostic {
8036855Sbostic 	int rval;
8136855Sbostic 
8241572Sedward 	if (!start_pw(0))
8336855Sbostic 		return((struct passwd *)NULL);
8436855Sbostic 	if (_pw_db) {
8536855Sbostic 		datum key;
8636855Sbostic 
8736855Sbostic 		key.dptr = (char *)&uid;
8836855Sbostic 		key.dsize = sizeof(uid);
8936855Sbostic 		rval = fetch_pw(key);
9036855Sbostic 	} else /* _pw_fp */
9137243Sbostic 		for (rval = 0; scanpw();)
9236855Sbostic 			if (_pw_passwd.pw_uid == uid) {
9336855Sbostic 				rval = 1;
9436855Sbostic 				break;
9536855Sbostic 			}
9636855Sbostic 	if (!_pw_stayopen)
9736855Sbostic 		endpwent();
9837243Sbostic 	if (rval)
9937243Sbostic 		getpw();
10036855Sbostic 	return(rval ? &_pw_passwd : (struct passwd *)NULL);
10136855Sbostic }
10236855Sbostic 
10336215Sbostic static
10441572Sedward start_pw(want_fp)
10541572Sedward 	char want_fp;		/* open _pw_fp also */
1062019Swnj {
10737196Sbostic 	char *p;
10837196Sbostic 
10936855Sbostic 	if (_pw_db) {
11039174Sbostic 		_pw_getfirstkey = 1;
11141572Sedward 		if (!want_fp)
11241572Sedward 			return(1);
11336855Sbostic 	}
11436855Sbostic 	if (_pw_fp) {
11536855Sbostic 		rewind(_pw_fp);
11636855Sbostic 		return(1);
11736855Sbostic 	}
11841572Sedward 	if (!_pw_db && (_pw_db = dbm_open(_pw_file, O_RDONLY, 0))) {
11939174Sbostic 		_pw_getfirstkey = 1;
12041572Sedward 		if (!want_fp)
12141572Sedward 			return(1);
12239174Sbostic 	}
12337196Sbostic 	/*
12437196Sbostic 	 * special case; if it's the official password file, look in
12537196Sbostic 	 * the master password file, otherwise, look in the file itself.
12637196Sbostic 	 */
12737196Sbostic 	p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD;
12841572Sedward 	if (_pw_fp = fopen(p, "r")) {
12941572Sedward 		_pw_master = 1;
13036855Sbostic 		return(1);
13141572Sedward 	}
13241572Sedward 	/*
13341572Sedward 	 * If we really want to set up _pw_fp, then try again
13441572Sedward 	 * with the old file.
13541572Sedward 	 */
13641572Sedward 	if (want_fp && p != _pw_file && (_pw_fp = fopen(_pw_file, "r"))) {
13741572Sedward 		_pw_master = 0;
13841572Sedward 		return(1);
13941572Sedward 	}
14036855Sbostic 	return(0);
14136855Sbostic }
14236855Sbostic 
14336855Sbostic setpwent()
14436855Sbostic {
14536855Sbostic 	return(setpassent(0));
14636855Sbostic }
14736855Sbostic 
14836855Sbostic setpassent(stayopen)
14936855Sbostic 	int stayopen;
15036855Sbostic {
15141572Sedward 	if (!start_pw(0))
15236855Sbostic 		return(0);
15336855Sbostic 	_pw_stayopen = stayopen;
15436855Sbostic 	return(1);
15536855Sbostic }
15636855Sbostic 
15736855Sbostic void
15836855Sbostic endpwent()
15936855Sbostic {
16036855Sbostic 	if (_pw_db) {
16136855Sbostic 		dbm_close(_pw_db);
16236855Sbostic 		_pw_db = (DBM *)NULL;
16341572Sedward 	}
16441572Sedward 	if (_pw_fp) {
16536855Sbostic 		(void)fclose(_pw_fp);
16636855Sbostic 		_pw_fp = (FILE *)NULL;
16736855Sbostic 	}
16836855Sbostic }
16936855Sbostic 
17036855Sbostic void
17136855Sbostic setpwfile(file)
17236855Sbostic 	char *file;
17336855Sbostic {
17436855Sbostic 	_pw_file = file;
17536855Sbostic }
17636855Sbostic 
17736855Sbostic static
17836855Sbostic scanpw()
17936855Sbostic {
18036215Sbostic 	register char *cp;
18136855Sbostic 	long atol();
182*41756Smarc 	char *bp;
18336456Sbostic 	char *fgets(), *strsep(), *index();
18436215Sbostic 
18536215Sbostic 	for (;;) {
18636855Sbostic 		if (!(fgets(line, sizeof(line), _pw_fp)))
18736215Sbostic 			return(0);
188*41756Smarc 		bp = line;
18936456Sbostic 		/* skip lines that are too big */
19036855Sbostic 		if (!index(line, '\n')) {
19136456Sbostic 			int ch;
19236456Sbostic 
19336456Sbostic 			while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
19436456Sbostic 				;
19536456Sbostic 			continue;
19636456Sbostic 		}
197*41756Smarc 		_pw_passwd.pw_name = strsep(&bp, ":\n");
198*41756Smarc 		_pw_passwd.pw_passwd = strsep(&bp, ":\n");
199*41756Smarc 		if (!(cp = strsep(&bp, ":\n")))
20036215Sbostic 			continue;
20136215Sbostic 		_pw_passwd.pw_uid = atoi(cp);
202*41756Smarc 		if (!(cp = strsep(&bp, ":\n")))
20336215Sbostic 			continue;
20436215Sbostic 		_pw_passwd.pw_gid = atoi(cp);
20541572Sedward 		if (_pw_master) {
206*41756Smarc 			_pw_passwd.pw_class = strsep(&bp, ":\n");
207*41756Smarc 			if (!(cp = strsep(&bp, ":\n")))
20841572Sedward 				continue;
20941572Sedward 			_pw_passwd.pw_change = atol(cp);
210*41756Smarc 			if (!(cp = strsep(&bp, ":\n")))
21141572Sedward 				continue;
21241572Sedward 			_pw_passwd.pw_expire = atol(cp);
21341572Sedward 		}
214*41756Smarc 		_pw_passwd.pw_gecos = strsep(&bp, ":\n");
215*41756Smarc 		_pw_passwd.pw_dir = strsep(&bp, ":\n");
216*41756Smarc 		_pw_passwd.pw_shell = strsep(&bp, ":\n");
21736855Sbostic 		if (!_pw_passwd.pw_shell)
21836855Sbostic 			continue;
21936855Sbostic 		return(1);
22036215Sbostic 	}
22136215Sbostic 	/* NOTREACHED */
2222019Swnj }
2232019Swnj 
22436215Sbostic static
22536855Sbostic fetch_pw(key)
22636215Sbostic 	datum key;
2272019Swnj {
22836855Sbostic 	register char *p, *t;
22936215Sbostic 
23036855Sbostic 	/*
23136855Sbostic 	 * the .dir file is LOCK_EX locked by programs that are
23236855Sbostic 	 * renaming the various password files.
23336855Sbostic 	 */
23436855Sbostic 	if (flock(dbm_dirfno(_pw_db), LOCK_SH))
23536215Sbostic 		return(0);
23636855Sbostic 	if (!key.dptr)
23739174Sbostic 		if (_pw_getfirstkey) {
23839174Sbostic 			_pw_getfirstkey = 0;
23936855Sbostic 			key = dbm_firstkey(_pw_db);
24036855Sbostic 		} else
24136855Sbostic 			key = dbm_nextkey(_pw_db);
24236855Sbostic 	if (key.dptr)
24336855Sbostic 		key = dbm_fetch(_pw_db, key);
24436215Sbostic 	(void)flock(dbm_dirfno(_pw_db), LOCK_UN);
24536855Sbostic 	if (!(p = key.dptr))
24636215Sbostic 		return(0);
24736855Sbostic 	t = line;
24836855Sbostic #define	EXPAND(e)	e = t; while (*t++ = *p++);
24936855Sbostic 	EXPAND(_pw_passwd.pw_name);
25036855Sbostic 	EXPAND(_pw_passwd.pw_passwd);
25136855Sbostic 	bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int));
25236855Sbostic 	p += sizeof(int);
25336855Sbostic 	bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int));
25436855Sbostic 	p += sizeof(int);
25536855Sbostic 	bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t));
25636855Sbostic 	p += sizeof(time_t);
25736855Sbostic 	EXPAND(_pw_passwd.pw_class);
25836855Sbostic 	EXPAND(_pw_passwd.pw_gecos);
25936855Sbostic 	EXPAND(_pw_passwd.pw_dir);
26036855Sbostic 	EXPAND(_pw_passwd.pw_shell);
26136855Sbostic 	bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t));
26236855Sbostic 	p += sizeof(time_t);
26336855Sbostic 	_pw_flag = *p;
26436215Sbostic 	return(1);
2652019Swnj }
2662019Swnj 
26738037Sbostic #define	_MAX_PASSWD_SIZE	50
26838037Sbostic static char pwbuf[_MAX_PASSWD_SIZE];
26938037Sbostic 
27036855Sbostic static
27136855Sbostic getpw()
2722019Swnj {
27336855Sbostic 	long pos, atol();
27437196Sbostic 	int fd, n;
27536855Sbostic 	char *p;
27638037Sbostic 	off_t lseek();
2772019Swnj 
27836868Sbostic 	if (geteuid())
27936868Sbostic 		return;
28037196Sbostic 	/*
28137196Sbostic 	 * special case; if it's the official password file, look in
28237196Sbostic 	 * the master password file, otherwise, look in the file itself.
28337196Sbostic 	 */
28437196Sbostic 	p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD;
28537196Sbostic 	if ((fd = open(p, O_RDONLY, 0)) < 0)
28637196Sbostic 		return;
28736855Sbostic 	pos = atol(_pw_passwd.pw_passwd);
28837196Sbostic 	if (lseek(fd, pos, L_SET) != pos)
28936855Sbostic 		goto bad;
29037196Sbostic 	if ((n = read(fd, pwbuf, sizeof(pwbuf) - 1)) < 0)
29136855Sbostic 		goto bad;
29236855Sbostic 	pwbuf[n] = '\0';
29336855Sbostic 	for (p = pwbuf; *p; ++p)
29436855Sbostic 		if (*p == ':') {
29536855Sbostic 			*p = '\0';
29636855Sbostic 			_pw_passwd.pw_passwd = pwbuf;
29736855Sbostic 			break;
29836855Sbostic 		}
29937196Sbostic bad:	(void)close(fd);
3002019Swnj }
301