Libinfo-173.1.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 if (i > -1) { /* did we actually copy anything? */
196 while ((buf[i] == ' ') || (buf[i] == '\t') || (buf[i] == '\n')) i--;
197 }
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;
230 int ntokens;
231
232 if (data == NULL) return NULL;
233
234 tokens = tokenize(data, ":");
235 ntokens = listLength(tokens);
236 if (( _pwFileFormat && (ntokens != 10)) ||
237 (!_pwFileFormat && (ntokens != 7)))
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]);
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 }
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 {
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");
318 if (_pfp == NULL)
319 {
320 perror(pwFile);
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 }