xref: /csrg-svn/lib/libc/gen/getpwent.c (revision 37196)
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*37196Sbostic static char sccsid[] = "@(#)getpwent.c	5.8 (Berkeley) 03/16/89";
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;
31*37196Sbostic static int _pw_rewind = 1, _pw_stayopen;
32*37196Sbostic static char _pw_flag, *_pw_file = _PATH_PASSWD;
332019Swnj 
3436456Sbostic #define	MAXLINELENGTH	1024
3536215Sbostic static char line[MAXLINELENGTH];
3617759Sserge 
3736855Sbostic struct passwd *
3836855Sbostic getpwent()
3936855Sbostic {
4036855Sbostic 	datum key;
4136855Sbostic 	int rval;
4236855Sbostic 
4336855Sbostic 	if (!_pw_db && !_pw_fp && !start_pw())
4436855Sbostic 		return((struct passwd *)NULL);
4536855Sbostic 	do {
4636855Sbostic 		if (_pw_db) {
4736855Sbostic 			key.dptr = NULL;
4836855Sbostic 			rval = fetch_pw(key);
4936855Sbostic 		} else /* _pw_fp */
5036855Sbostic 			rval = scanpw();
5136855Sbostic 	} while (rval && _pw_flag != _PW_KEYBYNAME);
5236868Sbostic 	getpw();
5336855Sbostic 	return(rval ? &_pw_passwd : (struct passwd *)NULL);
5436855Sbostic }
5536855Sbostic 
5636855Sbostic struct passwd *
5736855Sbostic getpwnam(nam)
5836855Sbostic 	char *nam;
5936855Sbostic {
6036855Sbostic 	int rval;
6136855Sbostic 
6236855Sbostic 	if (!start_pw())
6336855Sbostic 		return((struct passwd *)NULL);
6436855Sbostic 	if (_pw_db) {
6536855Sbostic 		datum key;
6636855Sbostic 
6736855Sbostic 		key.dptr = nam;
6836855Sbostic 		key.dsize = strlen(nam);
6936855Sbostic 		rval = fetch_pw(key);
7036855Sbostic 	} else /* _pw_fp */
7136855Sbostic 		while (scanpw())
7236855Sbostic 			if (!strcmp(nam, _pw_passwd.pw_name)) {
7336855Sbostic 				rval = 1;
7436855Sbostic 				break;
7536855Sbostic 			}
7636855Sbostic 	if (!_pw_stayopen)
7736855Sbostic 		endpwent();
7836868Sbostic 	getpw();
7936855Sbostic 	return(rval ? &_pw_passwd : (struct passwd *)NULL);
8036855Sbostic }
8136855Sbostic 
8236855Sbostic struct passwd *
8336855Sbostic getpwuid(uid)
8436855Sbostic 	int uid;
8536855Sbostic {
8636855Sbostic 	int rval;
8736855Sbostic 
8836855Sbostic 	if (!start_pw())
8936855Sbostic 		return((struct passwd *)NULL);
9036855Sbostic 	if (_pw_db) {
9136855Sbostic 		datum key;
9236855Sbostic 
9336855Sbostic 		key.dptr = (char *)&uid;
9436855Sbostic 		key.dsize = sizeof(uid);
9536855Sbostic 		rval = fetch_pw(key);
9636855Sbostic 	} else /* _pw_fp */
9736855Sbostic 		while (scanpw())
9836855Sbostic 			if (_pw_passwd.pw_uid == uid) {
9936855Sbostic 				rval = 1;
10036855Sbostic 				break;
10136855Sbostic 			}
10236855Sbostic 	if (!_pw_stayopen)
10336855Sbostic 		endpwent();
10436868Sbostic 	getpw();
10536855Sbostic 	return(rval ? &_pw_passwd : (struct passwd *)NULL);
10636855Sbostic }
10736855Sbostic 
10836215Sbostic static
10936855Sbostic start_pw()
1102019Swnj {
111*37196Sbostic 	char *p;
112*37196Sbostic 
11336855Sbostic 	if (_pw_db) {
11436855Sbostic 		_pw_rewind = 1;
11536855Sbostic 		return(1);
11636855Sbostic 	}
11736855Sbostic 	if (_pw_fp) {
11836855Sbostic 		rewind(_pw_fp);
11936855Sbostic 		return(1);
12036855Sbostic 	}
12136855Sbostic 	if (_pw_db = dbm_open(_pw_file, O_RDONLY, 0))
12236855Sbostic 		return(1);
123*37196Sbostic 	/*
124*37196Sbostic 	 * special case; if it's the official password file, look in
125*37196Sbostic 	 * the master password file, otherwise, look in the file itself.
126*37196Sbostic 	 */
127*37196Sbostic 	p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD;
128*37196Sbostic 	if (_pw_fp = fopen(p, "r"))
12936855Sbostic 		return(1);
13036855Sbostic 	return(0);
13136855Sbostic }
13236855Sbostic 
13336855Sbostic setpwent()
13436855Sbostic {
13536855Sbostic 	return(setpassent(0));
13636855Sbostic }
13736855Sbostic 
13836855Sbostic setpassent(stayopen)
13936855Sbostic 	int stayopen;
14036855Sbostic {
14136855Sbostic 	if (!start_pw())
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;
15336855Sbostic 	} else if (_pw_fp) {
15436855Sbostic 		(void)fclose(_pw_fp);
15536855Sbostic 		_pw_fp = (FILE *)NULL;
15636855Sbostic 	}
15736855Sbostic }
15836855Sbostic 
15936855Sbostic void
16036855Sbostic setpwfile(file)
16136855Sbostic 	char *file;
16236855Sbostic {
16336855Sbostic 	_pw_file = file;
16436855Sbostic }
16536855Sbostic 
16636855Sbostic static
16736855Sbostic scanpw()
16836855Sbostic {
16936215Sbostic 	register char *cp;
17036855Sbostic 	long atol();
17136456Sbostic 	char *fgets(), *strsep(), *index();
17236215Sbostic 
17336215Sbostic 	for (;;) {
17436855Sbostic 		if (!(fgets(line, sizeof(line), _pw_fp)))
17536215Sbostic 			return(0);
17636456Sbostic 		/* skip lines that are too big */
17736855Sbostic 		if (!index(line, '\n')) {
17836456Sbostic 			int ch;
17936456Sbostic 
18036456Sbostic 			while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
18136456Sbostic 				;
18236456Sbostic 			continue;
18336456Sbostic 		}
18436855Sbostic 		_pw_passwd.pw_name = strsep(line, ":\n");
18536215Sbostic 		_pw_passwd.pw_passwd = strsep((char *)NULL, ":\n");
18636215Sbostic 		if (!(cp = strsep((char *)NULL, ":\n")))
18736215Sbostic 			continue;
18836215Sbostic 		_pw_passwd.pw_uid = atoi(cp);
18936215Sbostic 		if (!(cp = strsep((char *)NULL, ":\n")))
19036215Sbostic 			continue;
19136215Sbostic 		_pw_passwd.pw_gid = atoi(cp);
19236855Sbostic 		_pw_passwd.pw_class = strsep((char *)NULL, ":\n");
19336855Sbostic 		if (!(cp = strsep((char *)NULL, ":\n")))
19436855Sbostic 			continue;
19536855Sbostic 		_pw_passwd.pw_change = atol(cp);
19636855Sbostic 		if (!(cp = strsep((char *)NULL, ":\n")))
19736855Sbostic 			continue;
19836855Sbostic 		_pw_passwd.pw_expire = atol(cp);
19936215Sbostic 		_pw_passwd.pw_gecos = strsep((char *)NULL, ":\n");
20036215Sbostic 		_pw_passwd.pw_dir = strsep((char *)NULL, ":\n");
20136215Sbostic 		_pw_passwd.pw_shell = strsep((char *)NULL, ":\n");
20236855Sbostic 		if (!_pw_passwd.pw_shell)
20336855Sbostic 			continue;
20436855Sbostic 		return(1);
20536215Sbostic 	}
20636215Sbostic 	/* NOTREACHED */
2072019Swnj }
2082019Swnj 
20936215Sbostic static
21036855Sbostic fetch_pw(key)
21136215Sbostic 	datum key;
2122019Swnj {
21336855Sbostic 	register char *p, *t;
21436215Sbostic 
21536855Sbostic 	/*
21636855Sbostic 	 * the .dir file is LOCK_EX locked by programs that are
21736855Sbostic 	 * renaming the various password files.
21836855Sbostic 	 */
21936855Sbostic 	if (flock(dbm_dirfno(_pw_db), LOCK_SH))
22036215Sbostic 		return(0);
22136855Sbostic 	if (!key.dptr)
22236855Sbostic 		if (_pw_rewind) {
22336855Sbostic 			_pw_rewind = 0;
22436855Sbostic 			key = dbm_firstkey(_pw_db);
22536855Sbostic 		} else
22636855Sbostic 			key = dbm_nextkey(_pw_db);
22736855Sbostic 	if (key.dptr)
22836855Sbostic 		key = dbm_fetch(_pw_db, key);
22936215Sbostic 	(void)flock(dbm_dirfno(_pw_db), LOCK_UN);
23036855Sbostic 	if (!(p = key.dptr))
23136215Sbostic 		return(0);
23236855Sbostic 	t = line;
23336855Sbostic #define	EXPAND(e)	e = t; while (*t++ = *p++);
23436855Sbostic 	EXPAND(_pw_passwd.pw_name);
23536855Sbostic 	EXPAND(_pw_passwd.pw_passwd);
23636855Sbostic 	bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int));
23736855Sbostic 	p += sizeof(int);
23836855Sbostic 	bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int));
23936855Sbostic 	p += sizeof(int);
24036855Sbostic 	bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t));
24136855Sbostic 	p += sizeof(time_t);
24236855Sbostic 	EXPAND(_pw_passwd.pw_class);
24336855Sbostic 	EXPAND(_pw_passwd.pw_gecos);
24436855Sbostic 	EXPAND(_pw_passwd.pw_dir);
24536855Sbostic 	EXPAND(_pw_passwd.pw_shell);
24636855Sbostic 	bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t));
24736855Sbostic 	p += sizeof(time_t);
24836855Sbostic 	_pw_flag = *p;
24936215Sbostic 	return(1);
2502019Swnj }
2512019Swnj 
25236855Sbostic static
25336855Sbostic getpw()
2542019Swnj {
25536855Sbostic 	static char pwbuf[50];
25636868Sbostic 	off_t lseek();
25736855Sbostic 	long pos, atol();
258*37196Sbostic 	int fd, n;
25936855Sbostic 	char *p;
2602019Swnj 
26136868Sbostic 	if (geteuid())
26236868Sbostic 		return;
263*37196Sbostic 	/*
264*37196Sbostic 	 * special case; if it's the official password file, look in
265*37196Sbostic 	 * the master password file, otherwise, look in the file itself.
266*37196Sbostic 	 */
267*37196Sbostic 	p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD;
268*37196Sbostic 	if ((fd = open(p, O_RDONLY, 0)) < 0)
269*37196Sbostic 		return;
27036855Sbostic 	pos = atol(_pw_passwd.pw_passwd);
271*37196Sbostic 	if (lseek(fd, pos, L_SET) != pos)
27236855Sbostic 		goto bad;
273*37196Sbostic 	if ((n = read(fd, pwbuf, sizeof(pwbuf) - 1)) < 0)
27436855Sbostic 		goto bad;
27536855Sbostic 	pwbuf[n] = '\0';
27636855Sbostic 	for (p = pwbuf; *p; ++p)
27736855Sbostic 		if (*p == ':') {
27836855Sbostic 			*p = '\0';
27936855Sbostic 			_pw_passwd.pw_passwd = pwbuf;
28036855Sbostic 			break;
28136855Sbostic 		}
282*37196Sbostic bad:	(void)close(fd);
2832019Swnj }
284