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 *
getpwent()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 *
getpwnam(name)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 *
getpwuid(uid)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
setpassent(stayopen)103 setpassent(stayopen)
104 int stayopen;
105 {
106 _pw_keynum = 0;
107 _pw_stayopen = stayopen;
108 return(1);
109 }
110
111 int
setpwent()112 setpwent()
113 {
114 _pw_keynum = 0;
115 _pw_stayopen = 0;
116 return(1);
117 }
118
119 void
endpwent()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
__initdb()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
__hashpw(key)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