xref: /original-bsd/lib/libc/gen/getpwent.c (revision 00695d63)
1 /*
2  * Copyright (c) 1988, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #if defined(LIBC_SCCS) && !defined(lint)
9 static char sccsid[] = "@(#)getpwent.c	8.2 (Berkeley) 04/27/95";
10 #endif /* LIBC_SCCS and not lint */
11 
12 #include <sys/param.h>
13 #include <fcntl.h>
14 #include <db.h>
15 #include <syslog.h>
16 #include <pwd.h>
17 #include <utmp.h>
18 #include <errno.h>
19 #include <unistd.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <limits.h>
23 
24 /*
25  * The lookup techniques and data extraction code here must be kept
26  * in sync with that in `pwd_mkdb'.
27  */
28 
29 static struct passwd _pw_passwd;	/* password structure */
30 static DB *_pw_db;			/* password database */
31 static int _pw_keynum;			/* key counter */
32 static int _pw_stayopen;		/* keep fd's open */
33 static int __hashpw(), __initdb();
34 
35 struct passwd *
36 getpwent()
37 {
38 	DBT key;
39 	char bf[sizeof(_pw_keynum) + 1];
40 
41 	if (!_pw_db && !__initdb())
42 		return((struct passwd *)NULL);
43 
44 	++_pw_keynum;
45 	bf[0] = _PW_KEYBYNUM;
46 	bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum));
47 	key.data = (u_char *)bf;
48 	key.size = sizeof(_pw_keynum) + 1;
49 	return(__hashpw(&key) ? &_pw_passwd : (struct passwd *)NULL);
50 }
51 
52 struct passwd *
53 getpwnam(name)
54 	const char *name;
55 {
56 	DBT key;
57 	int len, rval;
58 	char bf[UT_NAMESIZE + 1];
59 
60 	if (!_pw_db && !__initdb())
61 		return((struct passwd *)NULL);
62 
63 	bf[0] = _PW_KEYBYNAME;
64 	len = strlen(name);
65 	bcopy(name, bf + 1, MIN(len, UT_NAMESIZE));
66 	key.data = (u_char *)bf;
67 	key.size = len + 1;
68 	rval = __hashpw(&key);
69 
70 	if (!_pw_stayopen) {
71 		(void)(_pw_db->close)(_pw_db);
72 		_pw_db = (DB *)NULL;
73 	}
74 	return(rval ? &_pw_passwd : (struct passwd *)NULL);
75 }
76 
77 struct passwd *
78 getpwuid(uid)
79 	uid_t uid;
80 {
81 	DBT key;
82 	int keyuid, rval;
83 	char bf[sizeof(keyuid) + 1];
84 
85 	if (!_pw_db && !__initdb())
86 		return((struct passwd *)NULL);
87 
88 	bf[0] = _PW_KEYBYUID;
89 	keyuid = uid;
90 	bcopy(&keyuid, bf + 1, sizeof(keyuid));
91 	key.data = (u_char *)bf;
92 	key.size = sizeof(keyuid) + 1;
93 	rval = __hashpw(&key);
94 
95 	if (!_pw_stayopen) {
96 		(void)(_pw_db->close)(_pw_db);
97 		_pw_db = (DB *)NULL;
98 	}
99 	return(rval ? &_pw_passwd : (struct passwd *)NULL);
100 }
101 
102 int
103 setpassent(stayopen)
104 	int stayopen;
105 {
106 	_pw_keynum = 0;
107 	_pw_stayopen = stayopen;
108 	return(1);
109 }
110 
111 int
112 setpwent()
113 {
114 	_pw_keynum = 0;
115 	_pw_stayopen = 0;
116 	return(1);
117 }
118 
119 void
120 endpwent()
121 {
122 	_pw_keynum = 0;
123 	if (_pw_db) {
124 		(void)(_pw_db->close)(_pw_db);
125 		_pw_db = (DB *)NULL;
126 	}
127 }
128 
129 static
130 __initdb()
131 {
132 	static int warned;
133 	char *p;
134 
135 	p = (geteuid()) ? _PATH_MP_DB : _PATH_SMP_DB;
136 	_pw_db = dbopen(p, O_RDONLY, 0, DB_HASH, NULL);
137 	if (_pw_db)
138 		return(1);
139 	if (!warned)
140 		syslog(LOG_ERR, "%s: %m", p);
141 	return(0);
142 }
143 
144 static
145 __hashpw(key)
146 	DBT *key;
147 {
148 	register char *p, *t;
149 	static u_int max;
150 	static char *line;
151 	DBT data;
152 
153 	if ((_pw_db->get)(_pw_db, key, &data, 0))
154 		return(0);
155 	p = (char *)data.data;
156 	if (data.size > max && !(line = realloc(line, max += 1024)))
157 		return(0);
158 
159 	/* THIS CODE MUST MATCH THAT IN pwd_mkdb. */
160 	t = line;
161 #define	EXPAND(e)	e = t; while (*t++ = *p++);
162 #define	SCALAR(v)	memmove(&(v), p, sizeof v); p += sizeof v
163 	EXPAND(_pw_passwd.pw_name);
164 	EXPAND(_pw_passwd.pw_passwd);
165 	SCALAR(_pw_passwd.pw_uid);
166 	SCALAR(_pw_passwd.pw_gid);
167 	SCALAR(_pw_passwd.pw_change);
168 	EXPAND(_pw_passwd.pw_class);
169 	EXPAND(_pw_passwd.pw_gecos);
170 	EXPAND(_pw_passwd.pw_dir);
171 	EXPAND(_pw_passwd.pw_shell);
172 	SCALAR(_pw_passwd.pw_expire);
173 	return(1);
174 }
175