Libinfo-78.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
40 #define forever for (;;)
41
42 #define _PWENT_ 0
43 #define _PWNAM_ 1
44 #define _PWUID_ 2
45
46 static struct passwd _pw = { 0 };
47 static FILE *_pfp;
48 static int _pwStayOpen;
49
50 static void
51 free_pw()
52 {
53 if (_pw.pw_name != NULL) free(_pw.pw_name);
54 if (_pw.pw_passwd != NULL) free(_pw.pw_passwd);
55 if (_pw.pw_class != NULL) free(_pw.pw_class);
56 if (_pw.pw_gecos != NULL) free(_pw.pw_gecos);
57 if (_pw.pw_dir != NULL) free(_pw.pw_dir);
58 if (_pw.pw_shell != NULL) free(_pw.pw_shell);
59
60 _pw.pw_name = NULL;
61 _pw.pw_passwd = NULL;
62 _pw.pw_class = NULL;
63 _pw.pw_gecos = NULL;
64 _pw.pw_dir = NULL;
65 _pw.pw_shell = NULL;
66 }
67
68 static void
69 freeList(char **l)
70 {
71 int i;
72
73 if (l == NULL) return;
74 for (i = 0; l[i] != NULL; i++)
75 {
76 if (l[i] != NULL) free(l[i]);
77 l[i] = NULL;
78 }
79 if (l != NULL) free(l);
80 }
81
82 static unsigned int
83 listLength(char **l)
84 {
85 int i;
86
87 if (l == NULL) return 0;
88 for (i = 0; l[i] != NULL; i++);
89 return i;
90 }
91
92 static char *
93 copyString(char *s)
94 {
95 int len;
96 char *t;
97
98 if (s == NULL) return NULL;
99
100 len = strlen(s) + 1;
101 t = malloc(len);
102 bcopy(s, t, len);
103 return t;
104 }
105
106
107 static char **
108 insertString(char *s, char **l, unsigned int x)
109 {
110 int i, len;
111
112 if (s == NULL) return l;
113 if (l == NULL)
114 {
115 l = (char **)malloc(2 * sizeof(char *));
116 l[0] = copyString(s);
117 l[1] = NULL;
118 return l;
119 }
120
121 for (i = 0; l[i] != NULL; i++);
122 len = i + 1; /* count the NULL on the end of the list too! */
123
124 l = (char **)realloc(l, (len + 1) * sizeof(char *));
125
126 if ((x >= (len - 1)) || (x == (unsigned int)-1))
127 {
128 l[len - 1] = copyString(s);
129 l[len] = NULL;
130 return l;
131 }
132
133 for (i = len; i > x; i--) l[i] = l[i - 1];
134 l[x] = copyString(s);
135 return l;
136 }
137
138 static char **
139 appendString(char *s, char **l)
140 {
141 return insertString(s, l, (unsigned int)-1);
142 }
143
144
145 static char **
146 tokenize(const char *data, const char *sep)
147 {
148 char **tokens = NULL;
149 const char *p;
150 int i, j, len;
151 char buf[4096];
152 int scanning;
153
154 if (data == NULL) return NULL;
155 if (sep == NULL)
156 {
157 tokens = appendString((char *)data, tokens);
158 return tokens;
159 }
160
161 len = strlen(sep);
162
163 p = data;
164
165 while (p[0] != '\0')
166 {
167 /* skip leading white space */
168 while ((p[0] == ' ') || (p[0] == '\t') || (p[0] == '\n')) p++;
169
170 /* check for end of line */
171 if (p[0] == '\0') break;
172
173 /* copy data */
174 i = 0;
175 scanning = 1;
176 for (j = 0; (j < len) && (scanning == 1); j++)
177 {
178 if (p[0] == sep[j] || (p[0] == '\0')) scanning = 0;
179 }
180
181 while (scanning == 1)
182 {
183 buf[i++] = p[0];
184 p++;
185 for (j = 0; (j < len) && (scanning == 1); j++)
186 {
187 if (p[0] == sep[j] || (p[0] == '\0')) scanning = 0;
188 }
189 }
190
191 /* back over trailing whitespace */
192 i--;
193 while ((buf[i] == ' ') || (buf[i] == '\t') || (buf[i] == '\n')) i--;
194 buf[++i] = '\0';
195
196 tokens = appendString(buf, tokens);
197
198 /* check for end of line */
199 if (p[0] == '\0') break;
200
201 /* skip separator */
202 scanning = 1;
203 for (j = 0; (j < len) && (scanning == 1); j++)
204 {
205 if (p[0] == sep[j])
206 {
207 p++;
208 scanning = 0;
209 }
210 }
211
212 if ((scanning == 0) && p[0] == '\0')
213 {
214 /* line ended at a separator - add a null member */
215 tokens = appendString("", tokens);
216 return tokens;
217 }
218 }
219 return tokens;
220 }
221
222 struct passwd *
223 parseUser(char *data)
224 {
225 char **tokens;
226
227 if (data == NULL) return NULL;
228
229 tokens = tokenize(data, ":");
230 if (listLength(tokens) != 10)
231 {
232 freeList(tokens);
233 return NULL;
234 }
235
236 free_pw();
237
238 _pw.pw_name = tokens[0];
239 _pw.pw_passwd = tokens[1];
240 _pw.pw_uid = atoi(tokens[2]);
241 free(tokens[2]);
242 _pw.pw_gid = atoi(tokens[3]);
243 free(tokens[3]);
244 _pw.pw_class = tokens[4];
245 _pw.pw_change = atoi(tokens[5]);
246 free(tokens[5]);
247 _pw.pw_expire = atoi(tokens[6]);
248 free(tokens[6]);
249 _pw.pw_gecos = tokens[7];
250 _pw.pw_dir = tokens[8];
251 _pw.pw_shell = tokens[9];
252
253 free(tokens);
254
255 return &_pw;
256 }
257
258 static char *
259 getLine(FILE *fp)
260 {
261 char s[1024];
262 char *out;
263
264 s[0] = '\0';
265
266 fgets(s, 1024, fp);
267 if (s == NULL || s[0] == '\0') return NULL;
268
269 if (s[0] != '#') s[strlen(s) - 1] = '\0';
270
271 out = copyString(s);
272 return out;
273 }
274
275 int
276 setpassent(int stayopen)
277 {
278 _pwStayOpen = stayopen;
279 return(1);
280 }
281
282 int
283 setpwent()
284 {
285 if (_pfp == NULL)
286 {
287 _pfp = fopen(_PATH_MASTERPASSWD, "r");
288 if (_pfp == NULL)
289 {
290 perror(_PATH_MASTERPASSWD);
291 return(0);
292 }
293 }
294 else rewind(_pfp);
295 _pwStayOpen = 0;
296 return(1);
297 }
298
299 void
300 endpwent()
301 {
302 if (_pfp != NULL)
303 {
304 fclose(_pfp);
305 _pfp = NULL;
306 }
307 }
308
309 static struct passwd *
310 getpw(const char *nam, uid_t uid, int which)
311 {
312 char *line;
313 struct passwd *pw;
314
315 if (which != 0)
316 {
317 if (setpwent() == 0) return NULL;
318 }
319
320 forever
321 {
322 line = getLine(_pfp);
323 if (line == NULL) break;
324
325 if (line[0] == '#')
326 {
327 free(line);
328 line = NULL;
329 continue;
330 }
331
332 pw = parseUser(line);
333 free(line);
334 line = NULL;
335
336 if ((pw == NULL) || (which == _PWENT_))
337 {
338 if (_pwStayOpen == 0) endpwent();
339 return pw;
340 }
341
342 if (((which == _PWNAM_) && (!strcmp(nam, pw->pw_name))) ||
343 ((which == _PWUID_) && (uid == pw->pw_uid)))
344 {
345 if (_pwStayOpen == 0) endpwent();
346 return pw;
347 }
348 }
349
350 if (_pwStayOpen == 0) endpwent();
351 return NULL;
352 }
353
354 struct passwd *
355 getpwent()
356 {
357 return getpw(NULL, 0, _PWENT_);
358 }
359
360 struct passwd *
361 getpwnam(const char *nam)
362 {
363 return getpw(nam, 0, _PWNAM_);
364 }
365
366 struct passwd *
367 getpwuid(uid_t uid)
368 {
369 return getpw(NULL, uid, _PWUID_);
370 }