]>
Commit | Line | Data |
---|---|---|
03fb6eb0 A |
1 | /* |
2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
ad21edcc A |
6 | * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights |
7 | * Reserved. This file contains Original Code and/or Modifications of | |
8 | * Original Code as defined in and that are subject to the Apple Public | |
9 | * Source License Version 1.1 (the "License"). You may not use this file | |
10 | * except in compliance with the License. Please obtain a copy of the | |
11 | * License at http://www.apple.com/publicsource and read it before using | |
12 | * this file. | |
03fb6eb0 A |
13 | * |
14 | * The Original Code and all software distributed under the License are | |
ad21edcc | 15 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
03fb6eb0 A |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
ad21edcc A |
18 | * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the |
19 | * License for the specific language governing rights and limitations | |
20 | * under the License. | |
03fb6eb0 A |
21 | * |
22 | * @APPLE_LICENSE_HEADER_END@ | |
23 | */ | |
24 | /* | |
25 | * Copyright 1997 Apple Computer, Inc. (unpublished) | |
26 | * | |
27 | * /etc/passwd file access routines. | |
28 | * Just read from the /etc/passwd file and skip the dbm database, since | |
29 | * lookupd does all flat file lookups when the system is multi-user. | |
30 | * These routines are only used in single-user mode. | |
31 | * | |
32 | * 17 Apr 1997 file created - Marc Majka | |
33 | */ | |
34 | ||
35 | #include <stdio.h> | |
36 | #include <stdlib.h> | |
37 | #include <string.h> | |
38 | #include <pwd.h> | |
a0865d63 | 39 | #include <unistd.h> |
03fb6eb0 A |
40 | |
41 | #define forever for (;;) | |
42 | ||
43 | #define _PWENT_ 0 | |
44 | #define _PWNAM_ 1 | |
45 | #define _PWUID_ 2 | |
46 | ||
47 | static struct passwd _pw = { 0 }; | |
48 | static FILE *_pfp; | |
49 | static int _pwStayOpen; | |
a0865d63 | 50 | static int _pwFileFormat = 1; |
03fb6eb0 A |
51 | |
52 | static void | |
53 | free_pw() | |
54 | { | |
55 | if (_pw.pw_name != NULL) free(_pw.pw_name); | |
56 | if (_pw.pw_passwd != NULL) free(_pw.pw_passwd); | |
57 | if (_pw.pw_class != NULL) free(_pw.pw_class); | |
58 | if (_pw.pw_gecos != NULL) free(_pw.pw_gecos); | |
59 | if (_pw.pw_dir != NULL) free(_pw.pw_dir); | |
60 | if (_pw.pw_shell != NULL) free(_pw.pw_shell); | |
61 | ||
62 | _pw.pw_name = NULL; | |
63 | _pw.pw_passwd = NULL; | |
64 | _pw.pw_class = NULL; | |
65 | _pw.pw_gecos = NULL; | |
66 | _pw.pw_dir = NULL; | |
67 | _pw.pw_shell = NULL; | |
68 | } | |
69 | ||
70 | static void | |
71 | freeList(char **l) | |
72 | { | |
73 | int i; | |
74 | ||
75 | if (l == NULL) return; | |
76 | for (i = 0; l[i] != NULL; i++) | |
77 | { | |
78 | if (l[i] != NULL) free(l[i]); | |
79 | l[i] = NULL; | |
80 | } | |
81 | if (l != NULL) free(l); | |
82 | } | |
83 | ||
84 | static unsigned int | |
85 | listLength(char **l) | |
86 | { | |
87 | int i; | |
88 | ||
89 | if (l == NULL) return 0; | |
90 | for (i = 0; l[i] != NULL; i++); | |
91 | return i; | |
92 | } | |
93 | ||
94 | static char * | |
95 | copyString(char *s) | |
96 | { | |
97 | int len; | |
98 | char *t; | |
99 | ||
100 | if (s == NULL) return NULL; | |
101 | ||
102 | len = strlen(s) + 1; | |
103 | t = malloc(len); | |
104 | bcopy(s, t, len); | |
105 | return t; | |
106 | } | |
107 | ||
108 | ||
109 | static char ** | |
110 | insertString(char *s, char **l, unsigned int x) | |
111 | { | |
112 | int i, len; | |
113 | ||
114 | if (s == NULL) return l; | |
115 | if (l == NULL) | |
116 | { | |
117 | l = (char **)malloc(2 * sizeof(char *)); | |
118 | l[0] = copyString(s); | |
119 | l[1] = NULL; | |
120 | return l; | |
121 | } | |
122 | ||
123 | for (i = 0; l[i] != NULL; i++); | |
124 | len = i + 1; /* count the NULL on the end of the list too! */ | |
125 | ||
126 | l = (char **)realloc(l, (len + 1) * sizeof(char *)); | |
127 | ||
128 | if ((x >= (len - 1)) || (x == (unsigned int)-1)) | |
129 | { | |
130 | l[len - 1] = copyString(s); | |
131 | l[len] = NULL; | |
132 | return l; | |
133 | } | |
134 | ||
135 | for (i = len; i > x; i--) l[i] = l[i - 1]; | |
136 | l[x] = copyString(s); | |
137 | return l; | |
138 | } | |
139 | ||
140 | static char ** | |
141 | appendString(char *s, char **l) | |
142 | { | |
143 | return insertString(s, l, (unsigned int)-1); | |
144 | } | |
145 | ||
146 | ||
147 | static char ** | |
148 | tokenize(const char *data, const char *sep) | |
149 | { | |
150 | char **tokens = NULL; | |
151 | const char *p; | |
152 | int i, j, len; | |
153 | char buf[4096]; | |
154 | int scanning; | |
155 | ||
156 | if (data == NULL) return NULL; | |
157 | if (sep == NULL) | |
158 | { | |
159 | tokens = appendString((char *)data, tokens); | |
160 | return tokens; | |
161 | } | |
162 | ||
163 | len = strlen(sep); | |
164 | ||
165 | p = data; | |
166 | ||
167 | while (p[0] != '\0') | |
168 | { | |
169 | /* skip leading white space */ | |
170 | while ((p[0] == ' ') || (p[0] == '\t') || (p[0] == '\n')) p++; | |
171 | ||
172 | /* check for end of line */ | |
173 | if (p[0] == '\0') break; | |
174 | ||
175 | /* copy data */ | |
176 | i = 0; | |
177 | scanning = 1; | |
178 | for (j = 0; (j < len) && (scanning == 1); j++) | |
179 | { | |
180 | if (p[0] == sep[j] || (p[0] == '\0')) scanning = 0; | |
181 | } | |
182 | ||
183 | while (scanning == 1) | |
184 | { | |
185 | buf[i++] = p[0]; | |
186 | p++; | |
187 | for (j = 0; (j < len) && (scanning == 1); j++) | |
188 | { | |
189 | if (p[0] == sep[j] || (p[0] == '\0')) scanning = 0; | |
190 | } | |
191 | } | |
192 | ||
193 | /* back over trailing whitespace */ | |
194 | i--; | |
ccd4a120 A |
195 | if (i > -1) { /* did we actually copy anything? */ |
196 | while ((buf[i] == ' ') || (buf[i] == '\t') || (buf[i] == '\n')) i--; | |
197 | } | |
03fb6eb0 A |
198 | buf[++i] = '\0'; |
199 | ||
200 | tokens = appendString(buf, tokens); | |
201 | ||
202 | /* check for end of line */ | |
203 | if (p[0] == '\0') break; | |
204 | ||
205 | /* skip separator */ | |
206 | scanning = 1; | |
207 | for (j = 0; (j < len) && (scanning == 1); j++) | |
208 | { | |
209 | if (p[0] == sep[j]) | |
210 | { | |
211 | p++; | |
212 | scanning = 0; | |
213 | } | |
214 | } | |
215 | ||
216 | if ((scanning == 0) && p[0] == '\0') | |
217 | { | |
218 | /* line ended at a separator - add a null member */ | |
219 | tokens = appendString("", tokens); | |
220 | return tokens; | |
221 | } | |
222 | } | |
223 | return tokens; | |
224 | } | |
225 | ||
226 | struct passwd * | |
227 | parseUser(char *data) | |
228 | { | |
229 | char **tokens; | |
a0865d63 | 230 | int ntokens; |
03fb6eb0 A |
231 | |
232 | if (data == NULL) return NULL; | |
233 | ||
234 | tokens = tokenize(data, ":"); | |
a0865d63 A |
235 | ntokens = listLength(tokens); |
236 | if (( _pwFileFormat && (ntokens != 10)) || | |
237 | (!_pwFileFormat && (ntokens != 7))) | |
03fb6eb0 A |
238 | { |
239 | freeList(tokens); | |
240 | return NULL; | |
241 | } | |
242 | ||
243 | free_pw(); | |
244 | ||
245 | _pw.pw_name = tokens[0]; | |
246 | _pw.pw_passwd = tokens[1]; | |
247 | _pw.pw_uid = atoi(tokens[2]); | |
248 | free(tokens[2]); | |
249 | _pw.pw_gid = atoi(tokens[3]); | |
250 | free(tokens[3]); | |
a0865d63 A |
251 | |
252 | if (_pwFileFormat) | |
253 | { | |
254 | _pw.pw_class = tokens[4]; | |
255 | _pw.pw_change = atoi(tokens[5]); | |
256 | free(tokens[5]); | |
257 | _pw.pw_expire = atoi(tokens[6]); | |
258 | free(tokens[6]); | |
259 | _pw.pw_gecos = tokens[7]; | |
260 | _pw.pw_dir = tokens[8]; | |
261 | _pw.pw_shell = tokens[9]; | |
262 | } | |
263 | else | |
264 | { | |
265 | _pw.pw_class = copyString(""); | |
266 | _pw.pw_change = 0; | |
267 | _pw.pw_expire = 0; | |
268 | _pw.pw_gecos = tokens[4]; | |
269 | _pw.pw_dir = tokens[5]; | |
270 | _pw.pw_shell = tokens[6]; | |
271 | } | |
03fb6eb0 A |
272 | |
273 | free(tokens); | |
274 | ||
275 | return &_pw; | |
276 | } | |
277 | ||
278 | static char * | |
279 | getLine(FILE *fp) | |
280 | { | |
281 | char s[1024]; | |
282 | char *out; | |
283 | ||
284 | s[0] = '\0'; | |
285 | ||
286 | fgets(s, 1024, fp); | |
287 | if (s == NULL || s[0] == '\0') return NULL; | |
288 | ||
289 | if (s[0] != '#') s[strlen(s) - 1] = '\0'; | |
290 | ||
291 | out = copyString(s); | |
292 | return out; | |
293 | } | |
294 | ||
295 | int | |
296 | setpassent(int stayopen) | |
297 | { | |
298 | _pwStayOpen = stayopen; | |
299 | return(1); | |
300 | } | |
301 | ||
302 | int | |
303 | setpwent() | |
304 | { | |
305 | if (_pfp == NULL) | |
306 | { | |
a0865d63 A |
307 | char *pwFile; |
308 | if (geteuid() == 0) | |
309 | { | |
310 | pwFile = _PATH_MASTERPASSWD; | |
311 | } | |
312 | else | |
313 | { | |
314 | pwFile = _PATH_PASSWD; | |
315 | _pwFileFormat = 0; | |
316 | } | |
317 | _pfp = fopen(pwFile, "r"); | |
03fb6eb0 A |
318 | if (_pfp == NULL) |
319 | { | |
a0865d63 | 320 | perror(pwFile); |
03fb6eb0 A |
321 | return(0); |
322 | } | |
323 | } | |
324 | else rewind(_pfp); | |
325 | _pwStayOpen = 0; | |
326 | return(1); | |
327 | } | |
328 | ||
329 | void | |
330 | endpwent() | |
331 | { | |
332 | if (_pfp != NULL) | |
333 | { | |
334 | fclose(_pfp); | |
335 | _pfp = NULL; | |
336 | } | |
337 | } | |
338 | ||
339 | static struct passwd * | |
340 | getpw(const char *nam, uid_t uid, int which) | |
341 | { | |
342 | char *line; | |
343 | struct passwd *pw; | |
344 | ||
345 | if (which != 0) | |
346 | { | |
347 | if (setpwent() == 0) return NULL; | |
348 | } | |
349 | ||
350 | forever | |
351 | { | |
352 | line = getLine(_pfp); | |
353 | if (line == NULL) break; | |
354 | ||
355 | if (line[0] == '#') | |
356 | { | |
357 | free(line); | |
358 | line = NULL; | |
359 | continue; | |
360 | } | |
361 | ||
362 | pw = parseUser(line); | |
363 | free(line); | |
364 | line = NULL; | |
365 | ||
366 | if ((pw == NULL) || (which == _PWENT_)) | |
367 | { | |
368 | if (_pwStayOpen == 0) endpwent(); | |
369 | return pw; | |
370 | } | |
371 | ||
372 | if (((which == _PWNAM_) && (!strcmp(nam, pw->pw_name))) || | |
373 | ((which == _PWUID_) && (uid == pw->pw_uid))) | |
374 | { | |
375 | if (_pwStayOpen == 0) endpwent(); | |
376 | return pw; | |
377 | } | |
378 | } | |
379 | ||
380 | if (_pwStayOpen == 0) endpwent(); | |
381 | return NULL; | |
382 | } | |
383 | ||
384 | struct passwd * | |
385 | getpwent() | |
386 | { | |
387 | return getpw(NULL, 0, _PWENT_); | |
388 | } | |
389 | ||
390 | struct passwd * | |
391 | getpwnam(const char *nam) | |
392 | { | |
393 | return getpw(nam, 0, _PWNAM_); | |
394 | } | |
395 | ||
396 | struct passwd * | |
397 | getpwuid(uid_t uid) | |
398 | { | |
399 | return getpw(NULL, uid, _PWUID_); | |
400 | } |