xref: /csrg-svn/lib/libc/gen/getpwent.c (revision 42624)
122095Smckusick /*
236215Sbostic  * Copyright (c) 1988 The Regents of the University of California.
336215Sbostic  * All rights reserved.
436215Sbostic  *
5*42624Sbostic  * %sccs.include.redist.c%
622095Smckusick  */
722095Smckusick 
826560Sdonn #if defined(LIBC_SCCS) && !defined(lint)
9*42624Sbostic static char sccsid[] = "@(#)getpwent.c	5.14 (Berkeley) 06/01/90";
1036215Sbostic #endif /* LIBC_SCCS and not lint */
1122095Smckusick 
1236215Sbostic #include <sys/types.h>
1336215Sbostic #include <sys/file.h>
142019Swnj #include <stdio.h>
152019Swnj #include <pwd.h>
1616416Sralph #include <ndbm.h>
172019Swnj 
1836215Sbostic static DBM *_pw_db;
1936215Sbostic static FILE *_pw_fp;
2036215Sbostic static struct passwd _pw_passwd;
2139174Sbostic static int _pw_getfirstkey, _pw_stayopen;
2241572Sedward static char _pw_flag, *_pw_file = _PATH_PASSWD, _pw_master;
232019Swnj 
2436456Sbostic #define	MAXLINELENGTH	1024
2536215Sbostic static char line[MAXLINELENGTH];
2617759Sserge 
2736855Sbostic struct passwd *
2836855Sbostic getpwent()
2936855Sbostic {
3036855Sbostic 
3141572Sedward 	if (!_pw_fp && !start_pw(1))
3236855Sbostic 		return((struct passwd *)NULL);
3341572Sedward 	if (!scanpw())
3441572Sedward 		return((struct passwd *)NULL);
3541572Sedward 	getpw();
3641572Sedward 	return(&_pw_passwd);
3736855Sbostic }
3836855Sbostic 
3936855Sbostic struct passwd *
4036855Sbostic getpwnam(nam)
4136855Sbostic 	char *nam;
4236855Sbostic {
4336855Sbostic 	int rval;
4436855Sbostic 
4541572Sedward 	if (!start_pw(0))
4636855Sbostic 		return((struct passwd *)NULL);
4736855Sbostic 	if (_pw_db) {
4836855Sbostic 		datum key;
4936855Sbostic 
5036855Sbostic 		key.dptr = nam;
5136855Sbostic 		key.dsize = strlen(nam);
5236855Sbostic 		rval = fetch_pw(key);
5336855Sbostic 	} else /* _pw_fp */
5437243Sbostic 		for (rval = 0; scanpw();)
5536855Sbostic 			if (!strcmp(nam, _pw_passwd.pw_name)) {
5636855Sbostic 				rval = 1;
5736855Sbostic 				break;
5836855Sbostic 			}
5936855Sbostic 	if (!_pw_stayopen)
6036855Sbostic 		endpwent();
6137243Sbostic 	if (rval)
6237243Sbostic 		getpw();
6336855Sbostic 	return(rval ? &_pw_passwd : (struct passwd *)NULL);
6436855Sbostic }
6536855Sbostic 
6636855Sbostic struct passwd *
6736855Sbostic getpwuid(uid)
6836855Sbostic 	int uid;
6936855Sbostic {
7036855Sbostic 	int rval;
7136855Sbostic 
7241572Sedward 	if (!start_pw(0))
7336855Sbostic 		return((struct passwd *)NULL);
7436855Sbostic 	if (_pw_db) {
7536855Sbostic 		datum key;
7636855Sbostic 
7736855Sbostic 		key.dptr = (char *)&uid;
7836855Sbostic 		key.dsize = sizeof(uid);
7936855Sbostic 		rval = fetch_pw(key);
8036855Sbostic 	} else /* _pw_fp */
8137243Sbostic 		for (rval = 0; scanpw();)
8236855Sbostic 			if (_pw_passwd.pw_uid == uid) {
8336855Sbostic 				rval = 1;
8436855Sbostic 				break;
8536855Sbostic 			}
8636855Sbostic 	if (!_pw_stayopen)
8736855Sbostic 		endpwent();
8837243Sbostic 	if (rval)
8937243Sbostic 		getpw();
9036855Sbostic 	return(rval ? &_pw_passwd : (struct passwd *)NULL);
9136855Sbostic }
9236855Sbostic 
9336215Sbostic static
9441572Sedward start_pw(want_fp)
9541572Sedward 	char want_fp;		/* open _pw_fp also */
962019Swnj {
9737196Sbostic 	char *p;
9837196Sbostic 
9936855Sbostic 	if (_pw_db) {
10039174Sbostic 		_pw_getfirstkey = 1;
10141572Sedward 		if (!want_fp)
10241572Sedward 			return(1);
10336855Sbostic 	}
10436855Sbostic 	if (_pw_fp) {
10536855Sbostic 		rewind(_pw_fp);
10636855Sbostic 		return(1);
10736855Sbostic 	}
10841572Sedward 	if (!_pw_db && (_pw_db = dbm_open(_pw_file, O_RDONLY, 0))) {
10939174Sbostic 		_pw_getfirstkey = 1;
11041572Sedward 		if (!want_fp)
11141572Sedward 			return(1);
11239174Sbostic 	}
11337196Sbostic 	/*
11437196Sbostic 	 * special case; if it's the official password file, look in
11537196Sbostic 	 * the master password file, otherwise, look in the file itself.
11637196Sbostic 	 */
11737196Sbostic 	p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD;
11841572Sedward 	if (_pw_fp = fopen(p, "r")) {
11941572Sedward 		_pw_master = 1;
12036855Sbostic 		return(1);
12141572Sedward 	}
12241572Sedward 	/*
12341572Sedward 	 * If we really want to set up _pw_fp, then try again
12441572Sedward 	 * with the old file.
12541572Sedward 	 */
12641572Sedward 	if (want_fp && p != _pw_file && (_pw_fp = fopen(_pw_file, "r"))) {
12741572Sedward 		_pw_master = 0;
12841572Sedward 		return(1);
12941572Sedward 	}
13036855Sbostic 	return(0);
13136855Sbostic }
13236855Sbostic 
13336855Sbostic setpwent()
13436855Sbostic {
13536855Sbostic 	return(setpassent(0));
13636855Sbostic }
13736855Sbostic 
13836855Sbostic setpassent(stayopen)
13936855Sbostic 	int stayopen;
14036855Sbostic {
14141572Sedward 	if (!start_pw(0))
14236855Sbostic 		return(0);
14336855Sbostic 	_pw_stayopen = stayopen;
14436855Sbostic 	return(1);
14536855Sbostic }
14636855Sbostic 
14736855Sbostic void
14836855Sbostic endpwent()
14936855Sbostic {
15036855Sbostic 	if (_pw_db) {
15136855Sbostic 		dbm_close(_pw_db);
15236855Sbostic 		_pw_db = (DBM *)NULL;
15341572Sedward 	}
15441572Sedward 	if (_pw_fp) {
15536855Sbostic 		(void)fclose(_pw_fp);
15636855Sbostic 		_pw_fp = (FILE *)NULL;
15736855Sbostic 	}
15836855Sbostic }
15936855Sbostic 
16036855Sbostic void
16136855Sbostic setpwfile(file)
16236855Sbostic 	char *file;
16336855Sbostic {
16436855Sbostic 	_pw_file = file;
16536855Sbostic }
16636855Sbostic 
16736855Sbostic static
16836855Sbostic scanpw()
16936855Sbostic {
17036215Sbostic 	register char *cp;
17136855Sbostic 	long atol();
17241756Smarc 	char *bp;
17336456Sbostic 	char *fgets(), *strsep(), *index();
17436215Sbostic 
17536215Sbostic 	for (;;) {
17636855Sbostic 		if (!(fgets(line, sizeof(line), _pw_fp)))
17736215Sbostic 			return(0);
17841756Smarc 		bp = line;
17936456Sbostic 		/* skip lines that are too big */
18036855Sbostic 		if (!index(line, '\n')) {
18136456Sbostic 			int ch;
18236456Sbostic 
18336456Sbostic 			while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
18436456Sbostic 				;
18536456Sbostic 			continue;
18636456Sbostic 		}
18741756Smarc 		_pw_passwd.pw_name = strsep(&bp, ":\n");
18841756Smarc 		_pw_passwd.pw_passwd = strsep(&bp, ":\n");
18941756Smarc 		if (!(cp = strsep(&bp, ":\n")))
19036215Sbostic 			continue;
19136215Sbostic 		_pw_passwd.pw_uid = atoi(cp);
19241756Smarc 		if (!(cp = strsep(&bp, ":\n")))
19336215Sbostic 			continue;
19436215Sbostic 		_pw_passwd.pw_gid = atoi(cp);
19541572Sedward 		if (_pw_master) {
19641756Smarc 			_pw_passwd.pw_class = strsep(&bp, ":\n");
19741756Smarc 			if (!(cp = strsep(&bp, ":\n")))
19841572Sedward 				continue;
19941572Sedward 			_pw_passwd.pw_change = atol(cp);
20041756Smarc 			if (!(cp = strsep(&bp, ":\n")))
20141572Sedward 				continue;
20241572Sedward 			_pw_passwd.pw_expire = atol(cp);
20341572Sedward 		}
20441756Smarc 		_pw_passwd.pw_gecos = strsep(&bp, ":\n");
20541756Smarc 		_pw_passwd.pw_dir = strsep(&bp, ":\n");
20641756Smarc 		_pw_passwd.pw_shell = strsep(&bp, ":\n");
20736855Sbostic 		if (!_pw_passwd.pw_shell)
20836855Sbostic 			continue;
20936855Sbostic 		return(1);
21036215Sbostic 	}
21136215Sbostic 	/* NOTREACHED */
2122019Swnj }
2132019Swnj 
21436215Sbostic static
21536855Sbostic fetch_pw(key)
21636215Sbostic 	datum key;
2172019Swnj {
21836855Sbostic 	register char *p, *t;
21936215Sbostic 
22036855Sbostic 	/*
22136855Sbostic 	 * the .dir file is LOCK_EX locked by programs that are
22236855Sbostic 	 * renaming the various password files.
22336855Sbostic 	 */
22436855Sbostic 	if (flock(dbm_dirfno(_pw_db), LOCK_SH))
22536215Sbostic 		return(0);
22636855Sbostic 	if (!key.dptr)
22739174Sbostic 		if (_pw_getfirstkey) {
22839174Sbostic 			_pw_getfirstkey = 0;
22936855Sbostic 			key = dbm_firstkey(_pw_db);
23036855Sbostic 		} else
23136855Sbostic 			key = dbm_nextkey(_pw_db);
23236855Sbostic 	if (key.dptr)
23336855Sbostic 		key = dbm_fetch(_pw_db, key);
23436215Sbostic 	(void)flock(dbm_dirfno(_pw_db), LOCK_UN);
23536855Sbostic 	if (!(p = key.dptr))
23636215Sbostic 		return(0);
23736855Sbostic 	t = line;
23836855Sbostic #define	EXPAND(e)	e = t; while (*t++ = *p++);
23936855Sbostic 	EXPAND(_pw_passwd.pw_name);
24036855Sbostic 	EXPAND(_pw_passwd.pw_passwd);
24136855Sbostic 	bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int));
24236855Sbostic 	p += sizeof(int);
24336855Sbostic 	bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int));
24436855Sbostic 	p += sizeof(int);
24536855Sbostic 	bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t));
24636855Sbostic 	p += sizeof(time_t);
24736855Sbostic 	EXPAND(_pw_passwd.pw_class);
24836855Sbostic 	EXPAND(_pw_passwd.pw_gecos);
24936855Sbostic 	EXPAND(_pw_passwd.pw_dir);
25036855Sbostic 	EXPAND(_pw_passwd.pw_shell);
25136855Sbostic 	bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t));
25236855Sbostic 	p += sizeof(time_t);
25336855Sbostic 	_pw_flag = *p;
25436215Sbostic 	return(1);
2552019Swnj }
2562019Swnj 
25738037Sbostic #define	_MAX_PASSWD_SIZE	50
25838037Sbostic static char pwbuf[_MAX_PASSWD_SIZE];
25938037Sbostic 
26036855Sbostic static
26136855Sbostic getpw()
2622019Swnj {
26336855Sbostic 	long pos, atol();
26437196Sbostic 	int fd, n;
26536855Sbostic 	char *p;
26638037Sbostic 	off_t lseek();
2672019Swnj 
26836868Sbostic 	if (geteuid())
26936868Sbostic 		return;
27037196Sbostic 	/*
27137196Sbostic 	 * special case; if it's the official password file, look in
27237196Sbostic 	 * the master password file, otherwise, look in the file itself.
27337196Sbostic 	 */
27437196Sbostic 	p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD;
27537196Sbostic 	if ((fd = open(p, O_RDONLY, 0)) < 0)
27637196Sbostic 		return;
27736855Sbostic 	pos = atol(_pw_passwd.pw_passwd);
27837196Sbostic 	if (lseek(fd, pos, L_SET) != pos)
27936855Sbostic 		goto bad;
28037196Sbostic 	if ((n = read(fd, pwbuf, sizeof(pwbuf) - 1)) < 0)
28136855Sbostic 		goto bad;
28236855Sbostic 	pwbuf[n] = '\0';
28336855Sbostic 	for (p = pwbuf; *p; ++p)
28436855Sbostic 		if (*p == ':') {
28536855Sbostic 			*p = '\0';
28636855Sbostic 			_pw_passwd.pw_passwd = pwbuf;
28736855Sbostic 			break;
28836855Sbostic 		}
28937196Sbostic bad:	(void)close(fd);
2902019Swnj }
291