Libinfo-89.tar.gz
[apple/libinfo.git] / gen.subproj / getpwent.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
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>
39 #include <unistd.h>
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;
50 static int _pwFileFormat = 1;
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--;
195 while ((buf[i] == ' ') || (buf[i] == '\t') || (buf[i] == '\n')) i--;
196 buf[++i] = '\0';
197
198 tokens = appendString(buf, tokens);
199
200 /* check for end of line */
201 if (p[0] == '\0') break;
202
203 /* skip separator */
204 scanning = 1;
205 for (j = 0; (j < len) && (scanning == 1); j++)
206 {
207 if (p[0] == sep[j])
208 {
209 p++;
210 scanning = 0;
211 }
212 }
213
214 if ((scanning == 0) && p[0] == '\0')
215 {
216 /* line ended at a separator - add a null member */
217 tokens = appendString("", tokens);
218 return tokens;
219 }
220 }
221 return tokens;
222 }
223
224 struct passwd *
225 parseUser(char *data)
226 {
227 char **tokens;
228 int ntokens;
229
230 if (data == NULL) return NULL;
231
232 tokens = tokenize(data, ":");
233 ntokens = listLength(tokens);
234 if (( _pwFileFormat && (ntokens != 10)) ||
235 (!_pwFileFormat && (ntokens != 7)))
236 {
237 freeList(tokens);
238 return NULL;
239 }
240
241 free_pw();
242
243 _pw.pw_name = tokens[0];
244 _pw.pw_passwd = tokens[1];
245 _pw.pw_uid = atoi(tokens[2]);
246 free(tokens[2]);
247 _pw.pw_gid = atoi(tokens[3]);
248 free(tokens[3]);
249
250 if (_pwFileFormat)
251 {
252 _pw.pw_class = tokens[4];
253 _pw.pw_change = atoi(tokens[5]);
254 free(tokens[5]);
255 _pw.pw_expire = atoi(tokens[6]);
256 free(tokens[6]);
257 _pw.pw_gecos = tokens[7];
258 _pw.pw_dir = tokens[8];
259 _pw.pw_shell = tokens[9];
260 }
261 else
262 {
263 _pw.pw_class = copyString("");
264 _pw.pw_change = 0;
265 _pw.pw_expire = 0;
266 _pw.pw_gecos = tokens[4];
267 _pw.pw_dir = tokens[5];
268 _pw.pw_shell = tokens[6];
269 }
270
271 free(tokens);
272
273 return &_pw;
274 }
275
276 static char *
277 getLine(FILE *fp)
278 {
279 char s[1024];
280 char *out;
281
282 s[0] = '\0';
283
284 fgets(s, 1024, fp);
285 if (s == NULL || s[0] == '\0') return NULL;
286
287 if (s[0] != '#') s[strlen(s) - 1] = '\0';
288
289 out = copyString(s);
290 return out;
291 }
292
293 int
294 setpassent(int stayopen)
295 {
296 _pwStayOpen = stayopen;
297 return(1);
298 }
299
300 int
301 setpwent()
302 {
303 if (_pfp == NULL)
304 {
305 char *pwFile;
306 if (geteuid() == 0)
307 {
308 pwFile = _PATH_MASTERPASSWD;
309 }
310 else
311 {
312 pwFile = _PATH_PASSWD;
313 _pwFileFormat = 0;
314 }
315 _pfp = fopen(pwFile, "r");
316 if (_pfp == NULL)
317 {
318 perror(pwFile);
319 return(0);
320 }
321 }
322 else rewind(_pfp);
323 _pwStayOpen = 0;
324 return(1);
325 }
326
327 void
328 endpwent()
329 {
330 if (_pfp != NULL)
331 {
332 fclose(_pfp);
333 _pfp = NULL;
334 }
335 }
336
337 static struct passwd *
338 getpw(const char *nam, uid_t uid, int which)
339 {
340 char *line;
341 struct passwd *pw;
342
343 if (which != 0)
344 {
345 if (setpwent() == 0) return NULL;
346 }
347
348 forever
349 {
350 line = getLine(_pfp);
351 if (line == NULL) break;
352
353 if (line[0] == '#')
354 {
355 free(line);
356 line = NULL;
357 continue;
358 }
359
360 pw = parseUser(line);
361 free(line);
362 line = NULL;
363
364 if ((pw == NULL) || (which == _PWENT_))
365 {
366 if (_pwStayOpen == 0) endpwent();
367 return pw;
368 }
369
370 if (((which == _PWNAM_) && (!strcmp(nam, pw->pw_name))) ||
371 ((which == _PWUID_) && (uid == pw->pw_uid)))
372 {
373 if (_pwStayOpen == 0) endpwent();
374 return pw;
375 }
376 }
377
378 if (_pwStayOpen == 0) endpwent();
379 return NULL;
380 }
381
382 struct passwd *
383 getpwent()
384 {
385 return getpw(NULL, 0, _PWENT_);
386 }
387
388 struct passwd *
389 getpwnam(const char *nam)
390 {
391 return getpw(nam, 0, _PWNAM_);
392 }
393
394 struct passwd *
395 getpwuid(uid_t uid)
396 {
397 return getpw(NULL, uid, _PWUID_);
398 }