xref: /csrg-svn/lib/libc/gen/getpwent.c (revision 36855)
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
15*36855Sbostic  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1622095Smckusick  */
1722095Smckusick 
1826560Sdonn #if defined(LIBC_SCCS) && !defined(lint)
19*36855Sbostic static char sccsid[] = "@(#)getpwent.c	5.5 (Berkeley) 02/22/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 
28*36855Sbostic #define static
2936215Sbostic static DBM *_pw_db;
3036215Sbostic static FILE *_pw_fp;
3136215Sbostic static struct passwd _pw_passwd;
32*36855Sbostic static int _pw_euid = -1, _pw_fd, _pw_rewind = 1, _pw_set, _pw_stayopen;
33*36855Sbostic static char _pw_flag, *_pw_file = _PATH_MASTERPASSWD;
342019Swnj 
3536456Sbostic #define	MAXLINELENGTH	1024
3636215Sbostic static char line[MAXLINELENGTH];
3717759Sserge 
38*36855Sbostic struct passwd *
39*36855Sbostic getpwent()
40*36855Sbostic {
41*36855Sbostic 	datum key;
42*36855Sbostic 	int rval;
43*36855Sbostic 
44*36855Sbostic 	if (!_pw_db && !_pw_fp && !start_pw())
45*36855Sbostic 		return((struct passwd *)NULL);
46*36855Sbostic 	do {
47*36855Sbostic 		if (_pw_db) {
48*36855Sbostic 			key.dptr = NULL;
49*36855Sbostic 			rval = fetch_pw(key);
50*36855Sbostic 		} else /* _pw_fp */
51*36855Sbostic 			rval = scanpw();
52*36855Sbostic 	} while (rval && _pw_flag != _PW_KEYBYNAME);
53*36855Sbostic 	if (_pw_euid == -1)
54*36855Sbostic 		_pw_euid = geteuid();
55*36855Sbostic 	if (!_pw_euid)
56*36855Sbostic 		getpw();
57*36855Sbostic 	return(rval ? &_pw_passwd : (struct passwd *)NULL);
58*36855Sbostic }
59*36855Sbostic 
60*36855Sbostic struct passwd *
61*36855Sbostic getpwnam(nam)
62*36855Sbostic 	char *nam;
63*36855Sbostic {
64*36855Sbostic 	int rval;
65*36855Sbostic 
66*36855Sbostic 	if (!start_pw())
67*36855Sbostic 		return((struct passwd *)NULL);
68*36855Sbostic 	if (_pw_db) {
69*36855Sbostic 		datum key;
70*36855Sbostic 
71*36855Sbostic 		key.dptr = nam;
72*36855Sbostic 		key.dsize = strlen(nam);
73*36855Sbostic 		rval = fetch_pw(key);
74*36855Sbostic 	} else /* _pw_fp */
75*36855Sbostic 		while (scanpw())
76*36855Sbostic 			if (!strcmp(nam, _pw_passwd.pw_name)) {
77*36855Sbostic 				rval = 1;
78*36855Sbostic 				break;
79*36855Sbostic 			}
80*36855Sbostic 	if (!_pw_stayopen)
81*36855Sbostic 		endpwent();
82*36855Sbostic 	if (_pw_euid == -1)
83*36855Sbostic 		_pw_euid = geteuid();
84*36855Sbostic 	if (!_pw_euid)
85*36855Sbostic 		getpw();
86*36855Sbostic 	return(rval ? &_pw_passwd : (struct passwd *)NULL);
87*36855Sbostic }
88*36855Sbostic 
89*36855Sbostic struct passwd *
90*36855Sbostic getpwuid(uid)
91*36855Sbostic 	int uid;
92*36855Sbostic {
93*36855Sbostic 	int rval;
94*36855Sbostic 
95*36855Sbostic 	if (!start_pw())
96*36855Sbostic 		return((struct passwd *)NULL);
97*36855Sbostic 	if (_pw_db) {
98*36855Sbostic 		datum key;
99*36855Sbostic 
100*36855Sbostic 		key.dptr = (char *)&uid;
101*36855Sbostic 		key.dsize = sizeof(uid);
102*36855Sbostic 		rval = fetch_pw(key);
103*36855Sbostic 	} else /* _pw_fp */
104*36855Sbostic 		while (scanpw())
105*36855Sbostic 			if (_pw_passwd.pw_uid == uid) {
106*36855Sbostic 				rval = 1;
107*36855Sbostic 				break;
108*36855Sbostic 			}
109*36855Sbostic 	if (!_pw_stayopen)
110*36855Sbostic 		endpwent();
111*36855Sbostic 	if (_pw_euid == -1)
112*36855Sbostic 		_pw_euid = geteuid();
113*36855Sbostic 	if (!_pw_euid)
114*36855Sbostic 		getpw();
115*36855Sbostic 	return(rval ? &_pw_passwd : (struct passwd *)NULL);
116*36855Sbostic }
117*36855Sbostic 
11836215Sbostic static
119*36855Sbostic start_pw()
1202019Swnj {
121*36855Sbostic 	if (_pw_db) {
122*36855Sbostic 		_pw_rewind = 1;
123*36855Sbostic 		return(1);
124*36855Sbostic 	}
125*36855Sbostic 	if (_pw_fp) {
126*36855Sbostic 		rewind(_pw_fp);
127*36855Sbostic 		return(1);
128*36855Sbostic 	}
129*36855Sbostic 	if (_pw_db = dbm_open(_pw_file, O_RDONLY, 0))
130*36855Sbostic 		return(1);
131*36855Sbostic 	if (_pw_fp = fopen(_pw_file, "r"))
132*36855Sbostic 		return(1);
133*36855Sbostic 	return(0);
134*36855Sbostic }
135*36855Sbostic 
136*36855Sbostic setpwent()
137*36855Sbostic {
138*36855Sbostic 	return(setpassent(0));
139*36855Sbostic }
140*36855Sbostic 
141*36855Sbostic setpassent(stayopen)
142*36855Sbostic 	int stayopen;
143*36855Sbostic {
144*36855Sbostic 	if (!start_pw())
145*36855Sbostic 		return(0);
146*36855Sbostic 	_pw_stayopen = stayopen;
147*36855Sbostic 	return(1);
148*36855Sbostic }
149*36855Sbostic 
150*36855Sbostic void
151*36855Sbostic endpwent()
152*36855Sbostic {
153*36855Sbostic 	if (_pw_db) {
154*36855Sbostic 		dbm_close(_pw_db);
155*36855Sbostic 		_pw_db = (DBM *)NULL;
156*36855Sbostic 	} else if (_pw_fp) {
157*36855Sbostic 		(void)fclose(_pw_fp);
158*36855Sbostic 		_pw_fp = (FILE *)NULL;
159*36855Sbostic 	}
160*36855Sbostic 	if (_pw_fd) {
161*36855Sbostic 		(void)close(_pw_fd);
162*36855Sbostic 		_pw_fd = NULL;
163*36855Sbostic 	}
164*36855Sbostic }
165*36855Sbostic 
166*36855Sbostic void
167*36855Sbostic setpwfile(file)
168*36855Sbostic 	char *file;
169*36855Sbostic {
170*36855Sbostic 	_pw_file = file;
171*36855Sbostic 	_pw_set = 1;
172*36855Sbostic }
173*36855Sbostic 
174*36855Sbostic static
175*36855Sbostic scanpw()
176*36855Sbostic {
17736215Sbostic 	register char *cp;
178*36855Sbostic 	long atol();
17936456Sbostic 	char *fgets(), *strsep(), *index();
18036215Sbostic 
18136215Sbostic 	for (;;) {
182*36855Sbostic 		if (!(fgets(line, sizeof(line), _pw_fp)))
18336215Sbostic 			return(0);
18436456Sbostic 		/* skip lines that are too big */
185*36855Sbostic 		if (!index(line, '\n')) {
18636456Sbostic 			int ch;
18736456Sbostic 
18836456Sbostic 			while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
18936456Sbostic 				;
19036456Sbostic 			continue;
19136456Sbostic 		}
192*36855Sbostic 		_pw_passwd.pw_name = strsep(line, ":\n");
19336215Sbostic 		_pw_passwd.pw_passwd = strsep((char *)NULL, ":\n");
19436215Sbostic 		if (!(cp = strsep((char *)NULL, ":\n")))
19536215Sbostic 			continue;
19636215Sbostic 		_pw_passwd.pw_uid = atoi(cp);
19736215Sbostic 		if (!(cp = strsep((char *)NULL, ":\n")))
19836215Sbostic 			continue;
19936215Sbostic 		_pw_passwd.pw_gid = atoi(cp);
200*36855Sbostic 		_pw_passwd.pw_class = strsep((char *)NULL, ":\n");
201*36855Sbostic 		if (!(cp = strsep((char *)NULL, ":\n")))
202*36855Sbostic 			continue;
203*36855Sbostic 		_pw_passwd.pw_change = atol(cp);
204*36855Sbostic 		if (!(cp = strsep((char *)NULL, ":\n")))
205*36855Sbostic 			continue;
206*36855Sbostic 		_pw_passwd.pw_expire = atol(cp);
20736215Sbostic 		_pw_passwd.pw_gecos = strsep((char *)NULL, ":\n");
20836215Sbostic 		_pw_passwd.pw_dir = strsep((char *)NULL, ":\n");
20936215Sbostic 		_pw_passwd.pw_shell = strsep((char *)NULL, ":\n");
210*36855Sbostic 		if (!_pw_passwd.pw_shell)
211*36855Sbostic 			continue;
212*36855Sbostic 		return(1);
21336215Sbostic 	}
21436215Sbostic 	/* NOTREACHED */
2152019Swnj }
2162019Swnj 
21736215Sbostic static
218*36855Sbostic fetch_pw(key)
21936215Sbostic 	datum key;
2202019Swnj {
221*36855Sbostic 	register char *p, *t;
22236215Sbostic 
223*36855Sbostic 	/*
224*36855Sbostic 	 * the .dir file is LOCK_EX locked by programs that are
225*36855Sbostic 	 * renaming the various password files.
226*36855Sbostic 	 */
227*36855Sbostic 	if (flock(dbm_dirfno(_pw_db), LOCK_SH))
22836215Sbostic 		return(0);
229*36855Sbostic 	if (!key.dptr)
230*36855Sbostic 		if (_pw_rewind) {
231*36855Sbostic 			_pw_rewind = 0;
232*36855Sbostic 			key = dbm_firstkey(_pw_db);
233*36855Sbostic 		} else
234*36855Sbostic 			key = dbm_nextkey(_pw_db);
235*36855Sbostic 	if (key.dptr)
236*36855Sbostic 		key = dbm_fetch(_pw_db, key);
23736215Sbostic 	(void)flock(dbm_dirfno(_pw_db), LOCK_UN);
238*36855Sbostic 	if (!(p = key.dptr))
23936215Sbostic 		return(0);
240*36855Sbostic 	t = line;
241*36855Sbostic #define	EXPAND(e)	e = t; while (*t++ = *p++);
242*36855Sbostic 	EXPAND(_pw_passwd.pw_name);
243*36855Sbostic 	EXPAND(_pw_passwd.pw_passwd);
244*36855Sbostic 	bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int));
245*36855Sbostic 	p += sizeof(int);
246*36855Sbostic 	bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int));
247*36855Sbostic 	p += sizeof(int);
248*36855Sbostic 	bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t));
249*36855Sbostic 	p += sizeof(time_t);
250*36855Sbostic 	EXPAND(_pw_passwd.pw_class);
251*36855Sbostic 	EXPAND(_pw_passwd.pw_gecos);
252*36855Sbostic 	EXPAND(_pw_passwd.pw_dir);
253*36855Sbostic 	EXPAND(_pw_passwd.pw_shell);
254*36855Sbostic 	bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t));
255*36855Sbostic 	p += sizeof(time_t);
256*36855Sbostic 	_pw_flag = *p;
25736215Sbostic 	return(1);
2582019Swnj }
2592019Swnj 
260*36855Sbostic static
261*36855Sbostic getpw()
2622019Swnj {
263*36855Sbostic 	static char pwbuf[50];
264*36855Sbostic 	long pos, atol();
265*36855Sbostic 	int n;
266*36855Sbostic 	char *p;
2672019Swnj 
268*36855Sbostic 	if (!_pw_fd && (_pw_fd = open(_pw_file, O_RDONLY, 0)) < 0)
269*36855Sbostic 		goto bad;
270*36855Sbostic 	pos = atol(_pw_passwd.pw_passwd);
271*36855Sbostic 	if (lseek(_pw_fd, pos, L_SET) != pos)
272*36855Sbostic 		goto bad;
273*36855Sbostic 	if ((n = read(_pw_fd, pwbuf, sizeof(pwbuf) - 1)) < 0)
274*36855Sbostic 		goto bad;
275*36855Sbostic 	pwbuf[n] = '\0';
276*36855Sbostic 	for (p = pwbuf; *p; ++p)
277*36855Sbostic 		if (*p == ':') {
278*36855Sbostic 			*p = '\0';
279*36855Sbostic 			_pw_passwd.pw_passwd = pwbuf;
280*36855Sbostic 			break;
281*36855Sbostic 		}
282*36855Sbostic 	if (!_pw_stayopen)
283*36855Sbostic bad:		(void)close(_pw_fd);
2842019Swnj }
285