Commit | Line | Data |
---|---|---|
b8f253e8 | 1 | /* |
196b72db KB |
2 | * Copyright (c) 1988 The Regents of the University of California. |
3 | * All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms are permitted | |
6 | * provided that the above copyright notice and this paragraph are | |
7 | * duplicated in all such forms and that any documentation, | |
8 | * advertising materials, and other materials related to such | |
9 | * distribution and use acknowledge that the software was developed | |
10 | * by the University of California, Berkeley. The name of the | |
11 | * University may not be used to endorse or promote products derived | |
12 | * from this software without specific prior written permission. | |
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
96efcec2 | 15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
b8f253e8 KM |
16 | */ |
17 | ||
2ce81398 | 18 | #if defined(LIBC_SCCS) && !defined(lint) |
f63a642f | 19 | static char sccsid[] = "@(#)getpwent.c 5.11 (Berkeley) %G%"; |
196b72db | 20 | #endif /* LIBC_SCCS and not lint */ |
b8f253e8 | 21 | |
196b72db KB |
22 | #include <sys/types.h> |
23 | #include <sys/file.h> | |
a4b07b23 BJ |
24 | #include <stdio.h> |
25 | #include <pwd.h> | |
499a4b51 | 26 | #include <ndbm.h> |
a4b07b23 | 27 | |
196b72db KB |
28 | static DBM *_pw_db; |
29 | static FILE *_pw_fp; | |
30 | static struct passwd _pw_passwd; | |
f63a642f | 31 | static int _pw_getfirstkey, _pw_stayopen; |
33306bfc | 32 | static char _pw_flag, *_pw_file = _PATH_PASSWD; |
cc8dd839 | 33 | |
352c409f | 34 | #define MAXLINELENGTH 1024 |
196b72db | 35 | static char line[MAXLINELENGTH]; |
a4b07b23 | 36 | |
96efcec2 KB |
37 | struct passwd * |
38 | getpwent() | |
39 | { | |
40 | datum key; | |
41 | int rval; | |
42 | ||
43 | if (!_pw_db && !_pw_fp && !start_pw()) | |
44 | return((struct passwd *)NULL); | |
45 | do { | |
46 | if (_pw_db) { | |
47 | key.dptr = NULL; | |
48 | rval = fetch_pw(key); | |
49 | } else /* _pw_fp */ | |
50 | rval = scanpw(); | |
51 | } while (rval && _pw_flag != _PW_KEYBYNAME); | |
cc84a39f KB |
52 | if (rval) |
53 | getpw(); | |
96efcec2 KB |
54 | return(rval ? &_pw_passwd : (struct passwd *)NULL); |
55 | } | |
56 | ||
57 | struct passwd * | |
58 | getpwnam(nam) | |
59 | char *nam; | |
60 | { | |
61 | int rval; | |
62 | ||
63 | if (!start_pw()) | |
64 | return((struct passwd *)NULL); | |
65 | if (_pw_db) { | |
66 | datum key; | |
67 | ||
68 | key.dptr = nam; | |
69 | key.dsize = strlen(nam); | |
70 | rval = fetch_pw(key); | |
71 | } else /* _pw_fp */ | |
cc84a39f | 72 | for (rval = 0; scanpw();) |
96efcec2 KB |
73 | if (!strcmp(nam, _pw_passwd.pw_name)) { |
74 | rval = 1; | |
75 | break; | |
76 | } | |
77 | if (!_pw_stayopen) | |
78 | endpwent(); | |
cc84a39f KB |
79 | if (rval) |
80 | getpw(); | |
96efcec2 KB |
81 | return(rval ? &_pw_passwd : (struct passwd *)NULL); |
82 | } | |
83 | ||
84 | struct passwd * | |
85 | getpwuid(uid) | |
86 | int uid; | |
87 | { | |
88 | int rval; | |
89 | ||
90 | if (!start_pw()) | |
91 | return((struct passwd *)NULL); | |
92 | if (_pw_db) { | |
93 | datum key; | |
94 | ||
95 | key.dptr = (char *)&uid; | |
96 | key.dsize = sizeof(uid); | |
97 | rval = fetch_pw(key); | |
98 | } else /* _pw_fp */ | |
cc84a39f | 99 | for (rval = 0; scanpw();) |
96efcec2 KB |
100 | if (_pw_passwd.pw_uid == uid) { |
101 | rval = 1; | |
102 | break; | |
103 | } | |
104 | if (!_pw_stayopen) | |
105 | endpwent(); | |
cc84a39f KB |
106 | if (rval) |
107 | getpw(); | |
96efcec2 KB |
108 | return(rval ? &_pw_passwd : (struct passwd *)NULL); |
109 | } | |
110 | ||
196b72db | 111 | static |
96efcec2 KB |
112 | start_pw() |
113 | { | |
33306bfc KB |
114 | char *p; |
115 | ||
96efcec2 | 116 | if (_pw_db) { |
f63a642f | 117 | _pw_getfirstkey = 1; |
96efcec2 KB |
118 | return(1); |
119 | } | |
120 | if (_pw_fp) { | |
121 | rewind(_pw_fp); | |
122 | return(1); | |
123 | } | |
f63a642f KB |
124 | if (_pw_db = dbm_open(_pw_file, O_RDONLY, 0)) { |
125 | _pw_getfirstkey = 1; | |
96efcec2 | 126 | return(1); |
f63a642f | 127 | } |
33306bfc KB |
128 | /* |
129 | * special case; if it's the official password file, look in | |
130 | * the master password file, otherwise, look in the file itself. | |
131 | */ | |
132 | p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD; | |
133 | if (_pw_fp = fopen(p, "r")) | |
96efcec2 KB |
134 | return(1); |
135 | return(0); | |
136 | } | |
137 | ||
138 | setpwent() | |
139 | { | |
140 | return(setpassent(0)); | |
141 | } | |
142 | ||
143 | setpassent(stayopen) | |
144 | int stayopen; | |
145 | { | |
146 | if (!start_pw()) | |
147 | return(0); | |
148 | _pw_stayopen = stayopen; | |
149 | return(1); | |
150 | } | |
151 | ||
152 | void | |
153 | endpwent() | |
154 | { | |
155 | if (_pw_db) { | |
156 | dbm_close(_pw_db); | |
157 | _pw_db = (DBM *)NULL; | |
158 | } else if (_pw_fp) { | |
159 | (void)fclose(_pw_fp); | |
160 | _pw_fp = (FILE *)NULL; | |
161 | } | |
96efcec2 KB |
162 | } |
163 | ||
164 | void | |
165 | setpwfile(file) | |
166 | char *file; | |
167 | { | |
168 | _pw_file = file; | |
96efcec2 KB |
169 | } |
170 | ||
171 | static | |
172 | scanpw() | |
a4b07b23 | 173 | { |
196b72db | 174 | register char *cp; |
96efcec2 | 175 | long atol(); |
352c409f | 176 | char *fgets(), *strsep(), *index(); |
196b72db KB |
177 | |
178 | for (;;) { | |
96efcec2 | 179 | if (!(fgets(line, sizeof(line), _pw_fp))) |
196b72db | 180 | return(0); |
352c409f | 181 | /* skip lines that are too big */ |
96efcec2 | 182 | if (!index(line, '\n')) { |
352c409f KB |
183 | int ch; |
184 | ||
185 | while ((ch = getc(_pw_fp)) != '\n' && ch != EOF) | |
186 | ; | |
187 | continue; | |
188 | } | |
96efcec2 | 189 | _pw_passwd.pw_name = strsep(line, ":\n"); |
196b72db KB |
190 | _pw_passwd.pw_passwd = strsep((char *)NULL, ":\n"); |
191 | if (!(cp = strsep((char *)NULL, ":\n"))) | |
192 | continue; | |
193 | _pw_passwd.pw_uid = atoi(cp); | |
194 | if (!(cp = strsep((char *)NULL, ":\n"))) | |
195 | continue; | |
196 | _pw_passwd.pw_gid = atoi(cp); | |
96efcec2 KB |
197 | _pw_passwd.pw_class = strsep((char *)NULL, ":\n"); |
198 | if (!(cp = strsep((char *)NULL, ":\n"))) | |
199 | continue; | |
200 | _pw_passwd.pw_change = atol(cp); | |
201 | if (!(cp = strsep((char *)NULL, ":\n"))) | |
202 | continue; | |
203 | _pw_passwd.pw_expire = atol(cp); | |
196b72db KB |
204 | _pw_passwd.pw_gecos = strsep((char *)NULL, ":\n"); |
205 | _pw_passwd.pw_dir = strsep((char *)NULL, ":\n"); | |
206 | _pw_passwd.pw_shell = strsep((char *)NULL, ":\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 | } |