Commit | Line | Data |
---|---|---|
b8f253e8 | 1 | /* |
196b72db KB |
2 | * Copyright (c) 1988 The Regents of the University of California. |
3 | * All rights reserved. | |
4 | * | |
269a7923 | 5 | * %sccs.include.redist.c% |
b8f253e8 KM |
6 | */ |
7 | ||
2ce81398 | 8 | #if defined(LIBC_SCCS) && !defined(lint) |
269a7923 | 9 | static char sccsid[] = "@(#)getpwent.c 5.14 (Berkeley) %G%"; |
196b72db | 10 | #endif /* LIBC_SCCS and not lint */ |
b8f253e8 | 11 | |
196b72db KB |
12 | #include <sys/types.h> |
13 | #include <sys/file.h> | |
a4b07b23 BJ |
14 | #include <stdio.h> |
15 | #include <pwd.h> | |
499a4b51 | 16 | #include <ndbm.h> |
a4b07b23 | 17 | |
196b72db KB |
18 | static DBM *_pw_db; |
19 | static FILE *_pw_fp; | |
20 | static struct passwd _pw_passwd; | |
f63a642f | 21 | static int _pw_getfirstkey, _pw_stayopen; |
94aa68ce | 22 | static char _pw_flag, *_pw_file = _PATH_PASSWD, _pw_master; |
cc8dd839 | 23 | |
352c409f | 24 | #define MAXLINELENGTH 1024 |
196b72db | 25 | static char line[MAXLINELENGTH]; |
a4b07b23 | 26 | |
96efcec2 KB |
27 | struct passwd * |
28 | getpwent() | |
29 | { | |
96efcec2 | 30 | |
94aa68ce | 31 | if (!_pw_fp && !start_pw(1)) |
96efcec2 | 32 | return((struct passwd *)NULL); |
94aa68ce EW |
33 | if (!scanpw()) |
34 | return((struct passwd *)NULL); | |
35 | getpw(); | |
36 | return(&_pw_passwd); | |
96efcec2 KB |
37 | } |
38 | ||
39 | struct passwd * | |
40 | getpwnam(nam) | |
41 | char *nam; | |
42 | { | |
43 | int rval; | |
44 | ||
94aa68ce | 45 | if (!start_pw(0)) |
96efcec2 KB |
46 | return((struct passwd *)NULL); |
47 | if (_pw_db) { | |
48 | datum key; | |
49 | ||
50 | key.dptr = nam; | |
51 | key.dsize = strlen(nam); | |
52 | rval = fetch_pw(key); | |
53 | } else /* _pw_fp */ | |
cc84a39f | 54 | for (rval = 0; scanpw();) |
96efcec2 KB |
55 | if (!strcmp(nam, _pw_passwd.pw_name)) { |
56 | rval = 1; | |
57 | break; | |
58 | } | |
59 | if (!_pw_stayopen) | |
60 | endpwent(); | |
cc84a39f KB |
61 | if (rval) |
62 | getpw(); | |
96efcec2 KB |
63 | return(rval ? &_pw_passwd : (struct passwd *)NULL); |
64 | } | |
65 | ||
66 | struct passwd * | |
67 | getpwuid(uid) | |
68 | int uid; | |
69 | { | |
70 | int rval; | |
71 | ||
94aa68ce | 72 | if (!start_pw(0)) |
96efcec2 KB |
73 | return((struct passwd *)NULL); |
74 | if (_pw_db) { | |
75 | datum key; | |
76 | ||
77 | key.dptr = (char *)&uid; | |
78 | key.dsize = sizeof(uid); | |
79 | rval = fetch_pw(key); | |
80 | } else /* _pw_fp */ | |
cc84a39f | 81 | for (rval = 0; scanpw();) |
96efcec2 KB |
82 | if (_pw_passwd.pw_uid == uid) { |
83 | rval = 1; | |
84 | break; | |
85 | } | |
86 | if (!_pw_stayopen) | |
87 | endpwent(); | |
cc84a39f KB |
88 | if (rval) |
89 | getpw(); | |
96efcec2 KB |
90 | return(rval ? &_pw_passwd : (struct passwd *)NULL); |
91 | } | |
92 | ||
196b72db | 93 | static |
94aa68ce EW |
94 | start_pw(want_fp) |
95 | char want_fp; /* open _pw_fp also */ | |
96efcec2 | 96 | { |
33306bfc KB |
97 | char *p; |
98 | ||
96efcec2 | 99 | if (_pw_db) { |
f63a642f | 100 | _pw_getfirstkey = 1; |
94aa68ce EW |
101 | if (!want_fp) |
102 | return(1); | |
96efcec2 KB |
103 | } |
104 | if (_pw_fp) { | |
105 | rewind(_pw_fp); | |
106 | return(1); | |
107 | } | |
94aa68ce | 108 | if (!_pw_db && (_pw_db = dbm_open(_pw_file, O_RDONLY, 0))) { |
f63a642f | 109 | _pw_getfirstkey = 1; |
94aa68ce EW |
110 | if (!want_fp) |
111 | return(1); | |
f63a642f | 112 | } |
33306bfc KB |
113 | /* |
114 | * special case; if it's the official password file, look in | |
115 | * the master password file, otherwise, look in the file itself. | |
116 | */ | |
117 | p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD; | |
94aa68ce EW |
118 | if (_pw_fp = fopen(p, "r")) { |
119 | _pw_master = 1; | |
120 | return(1); | |
121 | } | |
122 | /* | |
123 | * If we really want to set up _pw_fp, then try again | |
124 | * with the old file. | |
125 | */ | |
126 | if (want_fp && p != _pw_file && (_pw_fp = fopen(_pw_file, "r"))) { | |
127 | _pw_master = 0; | |
96efcec2 | 128 | return(1); |
94aa68ce | 129 | } |
96efcec2 KB |
130 | return(0); |
131 | } | |
132 | ||
133 | setpwent() | |
134 | { | |
135 | return(setpassent(0)); | |
136 | } | |
137 | ||
138 | setpassent(stayopen) | |
139 | int stayopen; | |
140 | { | |
94aa68ce | 141 | if (!start_pw(0)) |
96efcec2 KB |
142 | return(0); |
143 | _pw_stayopen = stayopen; | |
144 | return(1); | |
145 | } | |
146 | ||
147 | void | |
148 | endpwent() | |
149 | { | |
150 | if (_pw_db) { | |
151 | dbm_close(_pw_db); | |
152 | _pw_db = (DBM *)NULL; | |
94aa68ce EW |
153 | } |
154 | if (_pw_fp) { | |
96efcec2 KB |
155 | (void)fclose(_pw_fp); |
156 | _pw_fp = (FILE *)NULL; | |
157 | } | |
96efcec2 KB |
158 | } |
159 | ||
160 | void | |
161 | setpwfile(file) | |
162 | char *file; | |
163 | { | |
164 | _pw_file = file; | |
96efcec2 KB |
165 | } |
166 | ||
167 | static | |
168 | scanpw() | |
a4b07b23 | 169 | { |
196b72db | 170 | register char *cp; |
96efcec2 | 171 | long atol(); |
0f38f0b7 | 172 | char *bp; |
352c409f | 173 | char *fgets(), *strsep(), *index(); |
196b72db KB |
174 | |
175 | for (;;) { | |
96efcec2 | 176 | if (!(fgets(line, sizeof(line), _pw_fp))) |
196b72db | 177 | return(0); |
0f38f0b7 | 178 | bp = line; |
352c409f | 179 | /* skip lines that are too big */ |
96efcec2 | 180 | if (!index(line, '\n')) { |
352c409f KB |
181 | int ch; |
182 | ||
183 | while ((ch = getc(_pw_fp)) != '\n' && ch != EOF) | |
184 | ; | |
185 | continue; | |
186 | } | |
0f38f0b7 MT |
187 | _pw_passwd.pw_name = strsep(&bp, ":\n"); |
188 | _pw_passwd.pw_passwd = strsep(&bp, ":\n"); | |
189 | if (!(cp = strsep(&bp, ":\n"))) | |
196b72db KB |
190 | continue; |
191 | _pw_passwd.pw_uid = atoi(cp); | |
0f38f0b7 | 192 | if (!(cp = strsep(&bp, ":\n"))) |
196b72db KB |
193 | continue; |
194 | _pw_passwd.pw_gid = atoi(cp); | |
94aa68ce | 195 | if (_pw_master) { |
0f38f0b7 MT |
196 | _pw_passwd.pw_class = strsep(&bp, ":\n"); |
197 | if (!(cp = strsep(&bp, ":\n"))) | |
94aa68ce EW |
198 | continue; |
199 | _pw_passwd.pw_change = atol(cp); | |
0f38f0b7 | 200 | if (!(cp = strsep(&bp, ":\n"))) |
94aa68ce EW |
201 | continue; |
202 | _pw_passwd.pw_expire = atol(cp); | |
203 | } | |
0f38f0b7 MT |
204 | _pw_passwd.pw_gecos = strsep(&bp, ":\n"); |
205 | _pw_passwd.pw_dir = strsep(&bp, ":\n"); | |
206 | _pw_passwd.pw_shell = strsep(&bp, ":\n"); | |
96efcec2 KB |
207 | if (!_pw_passwd.pw_shell) |
208 | continue; | |
209 | return(1); | |
196b72db KB |
210 | } |
211 | /* NOTREACHED */ | |
a4b07b23 BJ |
212 | } |
213 | ||
196b72db | 214 | static |
96efcec2 | 215 | fetch_pw(key) |
196b72db | 216 | datum key; |
a4b07b23 | 217 | { |
96efcec2 | 218 | register char *p, *t; |
196b72db | 219 | |
96efcec2 KB |
220 | /* |
221 | * the .dir file is LOCK_EX locked by programs that are | |
222 | * renaming the various password files. | |
223 | */ | |
224 | if (flock(dbm_dirfno(_pw_db), LOCK_SH)) | |
196b72db | 225 | return(0); |
96efcec2 | 226 | if (!key.dptr) |
f63a642f KB |
227 | if (_pw_getfirstkey) { |
228 | _pw_getfirstkey = 0; | |
96efcec2 KB |
229 | key = dbm_firstkey(_pw_db); |
230 | } else | |
231 | key = dbm_nextkey(_pw_db); | |
232 | if (key.dptr) | |
233 | key = dbm_fetch(_pw_db, key); | |
196b72db | 234 | (void)flock(dbm_dirfno(_pw_db), LOCK_UN); |
96efcec2 | 235 | if (!(p = key.dptr)) |
196b72db | 236 | return(0); |
96efcec2 KB |
237 | t = line; |
238 | #define EXPAND(e) e = t; while (*t++ = *p++); | |
239 | EXPAND(_pw_passwd.pw_name); | |
240 | EXPAND(_pw_passwd.pw_passwd); | |
241 | bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int)); | |
242 | p += sizeof(int); | |
243 | bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int)); | |
244 | p += sizeof(int); | |
245 | bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t)); | |
246 | p += sizeof(time_t); | |
247 | EXPAND(_pw_passwd.pw_class); | |
248 | EXPAND(_pw_passwd.pw_gecos); | |
249 | EXPAND(_pw_passwd.pw_dir); | |
250 | EXPAND(_pw_passwd.pw_shell); | |
251 | bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t)); | |
252 | p += sizeof(time_t); | |
253 | _pw_flag = *p; | |
196b72db | 254 | return(1); |
a4b07b23 BJ |
255 | } |
256 | ||
3b8a62fc KB |
257 | #define _MAX_PASSWD_SIZE 50 |
258 | static char pwbuf[_MAX_PASSWD_SIZE]; | |
259 | ||
96efcec2 KB |
260 | static |
261 | getpw() | |
196b72db | 262 | { |
96efcec2 | 263 | long pos, atol(); |
33306bfc | 264 | int fd, n; |
96efcec2 | 265 | char *p; |
3b8a62fc | 266 | off_t lseek(); |
196b72db | 267 | |
972b418a KB |
268 | if (geteuid()) |
269 | return; | |
33306bfc KB |
270 | /* |
271 | * special case; if it's the official password file, look in | |
272 | * the master password file, otherwise, look in the file itself. | |
273 | */ | |
274 | p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD; | |
275 | if ((fd = open(p, O_RDONLY, 0)) < 0) | |
276 | return; | |
96efcec2 | 277 | pos = atol(_pw_passwd.pw_passwd); |
33306bfc | 278 | if (lseek(fd, pos, L_SET) != pos) |
96efcec2 | 279 | goto bad; |
33306bfc | 280 | if ((n = read(fd, pwbuf, sizeof(pwbuf) - 1)) < 0) |
96efcec2 KB |
281 | goto bad; |
282 | pwbuf[n] = '\0'; | |
283 | for (p = pwbuf; *p; ++p) | |
284 | if (*p == ':') { | |
285 | *p = '\0'; | |
286 | _pw_passwd.pw_passwd = pwbuf; | |
287 | break; | |
288 | } | |
33306bfc | 289 | bad: (void)close(fd); |
02d7fd83 | 290 | } |