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