]> git.saurik.com Git - apple/libinfo.git/blob - gen.subproj/getpwent.c
Libinfo-278.0.3.tar.gz
[apple/libinfo.git] / gen.subproj / getpwent.c
1 /*
2 * Copyright (c) 2007 Apple 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 * Directory Service 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 <netdb.h>
40 #include <netinet/in.h>
41 #include <arpa/inet.h>
42 #include <unistd.h>
43
44 #define forever for (;;)
45
46 #define _PWENT_ 0
47 #define _PWNAM_ 1
48 #define _PWUID_ 2
49
50 static struct passwd _pw = { 0 };
51 static FILE *_pfp = NULL;
52 static int _pwFileFormat = 1;
53
54 #define _HENT_ 0
55 #define _HNAM_ 1
56 #define _HADDR_ 2
57
58 static struct hostent _h = { 0 };
59 static FILE *_hfp = NULL;
60
61 /* Forward */
62 __private_extern__ void LI_files_setpwent();
63 __private_extern__ void LI_files_endhostent();
64
65 static void
66 freeList(char **l)
67 {
68 int i;
69
70 if (l == NULL) return;
71 for (i = 0; l[i] != NULL; i++)
72 {
73 if (l[i] != NULL) free(l[i]);
74 l[i] = NULL;
75 }
76 if (l != NULL) free(l);
77 }
78
79 static unsigned int
80 listLength(char **l)
81 {
82 int i;
83
84 if (l == NULL) return 0;
85 for (i = 0; l[i] != NULL; i++);
86 return i;
87 }
88
89 static char *
90 copyString(char *s)
91 {
92 int len;
93 char *t;
94
95 if (s == NULL) return NULL;
96
97 len = strlen(s) + 1;
98 t = malloc(len);
99 bcopy(s, t, len);
100 return t;
101 }
102
103
104 static char **
105 insertString(char *s, char **l, unsigned int x)
106 {
107 int i, len;
108
109 if (s == NULL) return l;
110 if (l == NULL)
111 {
112 l = (char **)malloc(2 * sizeof(char *));
113 l[0] = copyString(s);
114 l[1] = NULL;
115 return l;
116 }
117
118 for (i = 0; l[i] != NULL; i++);
119 len = i + 1; /* count the NULL on the end of the list too! */
120
121 l = (char **)realloc(l, (len + 1) * sizeof(char *));
122
123 if ((x >= (len - 1)) || (x == (unsigned int)-1))
124 {
125 l[len - 1] = copyString(s);
126 l[len] = NULL;
127 return l;
128 }
129
130 for (i = len; i > x; i--) l[i] = l[i - 1];
131 l[x] = copyString(s);
132 return l;
133 }
134
135 static char **
136 appendString(char *s, char **l)
137 {
138 return insertString(s, l, (unsigned int)-1);
139 }
140
141 static char **
142 tokenize(const char *data, const char *sep)
143 {
144 char **tokens = NULL;
145 const char *p;
146 int i, j, len;
147 char buf[4096];
148 int scanning;
149
150 if (data == NULL) return NULL;
151 if (sep == NULL)
152 {
153 tokens = appendString((char *)data, tokens);
154 return tokens;
155 }
156
157 len = strlen(sep);
158
159 p = data;
160
161 while (p[0] != '\0')
162 {
163 /* skip leading white space */
164 while ((p[0] == ' ') || (p[0] == '\t') || (p[0] == '\n')) p++;
165
166 /* check for end of line */
167 if (p[0] == '\0') break;
168
169 /* copy data */
170 i = 0;
171 scanning = 1;
172 for (j = 0; (j < len) && (scanning == 1); j++)
173 {
174 if (p[0] == sep[j] || (p[0] == '\0')) scanning = 0;
175 }
176
177 while (scanning == 1)
178 {
179 buf[i++] = p[0];
180 p++;
181 for (j = 0; (j < len) && (scanning == 1); j++)
182 {
183 if (p[0] == sep[j] || (p[0] == '\0')) scanning = 0;
184 }
185 }
186
187 /* back over trailing whitespace */
188 i--;
189 if (i > -1) { /* did we actually copy anything? */
190 while ((buf[i] == ' ') || (buf[i] == '\t') || (buf[i] == '\n')) i--;
191 }
192 buf[++i] = '\0';
193
194 tokens = appendString(buf, tokens);
195
196 /* check for end of line */
197 if (p[0] == '\0') break;
198
199 /* skip separator */
200 scanning = 1;
201 for (j = 0; (j < len) && (scanning == 1); j++)
202 {
203 if (p[0] == sep[j])
204 {
205 p++;
206 scanning = 0;
207 }
208 }
209
210 if ((scanning == 0) && p[0] == '\0')
211 {
212 /* line ended at a separator - add a null member */
213 tokens = appendString("", tokens);
214 return tokens;
215 }
216 }
217
218 return tokens;
219 }
220
221 static char *
222 getLine(FILE *fp)
223 {
224 char s[1024];
225 char *out;
226
227 s[0] = '\0';
228
229 fgets(s, 1024, fp);
230 if ((s == NULL) || (s[0] == '\0')) return NULL;
231
232 if (s[0] != '#') s[strlen(s) - 1] = '\0';
233
234 out = copyString(s);
235 return out;
236 }
237
238 /* USERS */
239
240 static void
241 LI_files_free_user()
242 {
243 if (_pw.pw_name != NULL) free(_pw.pw_name);
244 if (_pw.pw_passwd != NULL) free(_pw.pw_passwd);
245 if (_pw.pw_class != NULL) free(_pw.pw_class);
246 if (_pw.pw_gecos != NULL) free(_pw.pw_gecos);
247 if (_pw.pw_dir != NULL) free(_pw.pw_dir);
248 if (_pw.pw_shell != NULL) free(_pw.pw_shell);
249
250 _pw.pw_name = NULL;
251 _pw.pw_passwd = NULL;
252 _pw.pw_class = NULL;
253 _pw.pw_gecos = NULL;
254 _pw.pw_dir = NULL;
255 _pw.pw_shell = NULL;
256 }
257
258 static struct passwd *
259 LI_files_parse_user(char *data)
260 {
261 char **tokens;
262 int ntokens;
263
264 if (data == NULL) return NULL;
265
266 tokens = tokenize(data, ":");
267 ntokens = listLength(tokens);
268 if (( _pwFileFormat && (ntokens != 10)) ||
269 (!_pwFileFormat && (ntokens != 7)))
270 {
271 freeList(tokens);
272 return NULL;
273 }
274
275 LI_files_free_user();
276
277 _pw.pw_name = tokens[0];
278 _pw.pw_passwd = tokens[1];
279 _pw.pw_uid = atoi(tokens[2]);
280 free(tokens[2]);
281 _pw.pw_gid = atoi(tokens[3]);
282 free(tokens[3]);
283
284 if (_pwFileFormat)
285 {
286 _pw.pw_class = tokens[4];
287 _pw.pw_change = atoi(tokens[5]);
288 free(tokens[5]);
289 _pw.pw_expire = atoi(tokens[6]);
290 free(tokens[6]);
291 _pw.pw_gecos = tokens[7];
292 _pw.pw_dir = tokens[8];
293 _pw.pw_shell = tokens[9];
294 }
295 else
296 {
297 _pw.pw_class = copyString("");
298 _pw.pw_change = 0;
299 _pw.pw_expire = 0;
300 _pw.pw_gecos = tokens[4];
301 _pw.pw_dir = tokens[5];
302 _pw.pw_shell = tokens[6];
303 }
304
305 free(tokens);
306
307 return &_pw;
308 }
309
310 static struct passwd *
311 LI_files_getpw(const char *name, uid_t uid, int which)
312 {
313 char *line;
314 struct passwd *pw;
315
316 if (_pfp == NULL) LI_files_setpwent();
317 if (_pfp == NULL) return NULL;
318
319 if (which != _PWENT_) rewind(_pfp);
320
321 forever
322 {
323 line = getLine(_pfp);
324 if (line == NULL) break;
325
326 if (line[0] == '#')
327 {
328 free(line);
329 line = NULL;
330 continue;
331 }
332
333 pw = LI_files_parse_user(line);
334 free(line);
335 line = NULL;
336
337 if (pw == NULL) continue;
338
339 if (which == _PWENT_) return pw;
340
341 if (((which == _PWNAM_) && (!strcmp(name, pw->pw_name))) || ((which == _PWUID_) && (uid == pw->pw_uid)))
342 {
343 fclose(_pfp);
344 _pfp = NULL;
345 return pw;
346 }
347 }
348
349 fclose(_pfp);
350 _pfp = NULL;
351
352 return NULL;
353 }
354
355 /* "Public" */
356
357 __private_extern__ struct passwd *
358 LI_files_getpwent()
359 {
360 return LI_files_getpw(NULL, 0, _PWENT_);
361 }
362
363 __private_extern__ struct passwd *
364 LI_files_getpwnam(const char *name)
365 {
366 return LI_files_getpw(name, 0, _PWNAM_);
367 }
368
369 __private_extern__ struct passwd *
370 LI_files_getpwuid(uid_t uid)
371 {
372 return LI_files_getpw(NULL, uid, _PWUID_);
373 }
374
375 int
376 setpassent(int stayopen)
377 {
378 return 1;
379 }
380
381 __private_extern__ void
382 LI_files_setpwent()
383 {
384 if (_pfp == NULL)
385 {
386 char *pwFile;
387 if (geteuid() == 0)
388 {
389 pwFile = _PATH_MASTERPASSWD;
390 }
391 else
392 {
393 pwFile = _PATH_PASSWD;
394 _pwFileFormat = 0;
395 }
396
397 _pfp = fopen(pwFile, "r");
398 }
399 else rewind(_pfp);
400 }
401
402 __private_extern__ void
403 LI_files_endpwent()
404 {
405 if (_pfp != NULL)
406 {
407 fclose(_pfp);
408 _pfp = NULL;
409 }
410 }
411
412 /* HOSTS */
413
414 static void
415 LI_files_free_host()
416 {
417 int i;
418
419 if (_h.h_name != NULL) free(_h.h_name);
420
421 if (_h.h_aliases != NULL)
422 {
423 for (i = 0; _h.h_aliases[i] != NULL; i++) free(_h.h_aliases[i]);
424 free(_h.h_aliases);
425 }
426
427 if (_h.h_addr_list != NULL)
428 {
429 for (i = 0; _h.h_addr_list[i] != NULL; i++) free(_h.h_addr_list[i]);
430 free(_h.h_addr_list);
431 }
432
433 _h.h_name = NULL;
434 _h.h_aliases = NULL;
435 _h.h_addrtype = 0;
436 _h.h_length = 0;
437 _h.h_addr_list = NULL;
438 }
439
440 static struct hostent *
441 LI_files_parse_host(char *data)
442 {
443 char **tokens, *addrstr;
444 int i, ntokens, af;
445 struct in_addr a4;
446 struct in6_addr a6;
447
448 if (data == NULL) return NULL;
449
450 tokens = tokenize(data, " ");
451 ntokens = listLength(tokens);
452 if (ntokens < 2)
453 {
454 freeList(tokens);
455 return NULL;
456 }
457
458 LI_files_free_host();
459
460 af = AF_UNSPEC;
461 if (inet_pton(AF_INET, tokens[0], &a4) == 1) af = AF_INET;
462 else if (inet_pton(AF_INET6, tokens[0], &a6) == 1) af = AF_INET6;
463
464 if (af == AF_UNSPEC)
465 {
466 freeList(tokens);
467 return NULL;
468 }
469
470 addrstr = tokens[0];
471
472 _h.h_addrtype = af;
473 if (af == AF_INET)
474 {
475 _h.h_length = sizeof(struct in_addr);
476 _h.h_addr_list = (char **)calloc(2, sizeof(char *));
477 _h.h_addr_list[0] = (char *)calloc(1, _h.h_length);
478 memcpy(_h.h_addr_list[0], &a4, _h.h_length);
479 }
480 else
481 {
482 _h.h_length = sizeof(struct in6_addr);
483 _h.h_addr_list = (char **)calloc(2, sizeof(char *));
484 _h.h_addr_list[0] = (char *)calloc(1, _h.h_length);
485 memcpy(_h.h_addr_list[0], &a6, _h.h_length);
486 }
487
488 _h.h_name = tokens[1];
489
490 _h.h_aliases = (char **)calloc(ntokens - 1, sizeof(char *));
491 for (i = 2; i < ntokens; i++) _h.h_aliases[i-2] = tokens[i];
492
493 free(addrstr);
494 free(tokens);
495
496 return &_h;
497 }
498
499 static struct hostent *
500 LI_files_get_host(const char *name, const void *addr, int af, int which)
501 {
502 char *line;
503 struct hostent *h;
504 int i, got_host;
505
506 if ((which == _HADDR_) && (addr == NULL)) return NULL;
507
508 if (_hfp == NULL) _hfp = fopen(_PATH_HOSTS, "r");
509 if (_hfp == NULL) return NULL;
510
511 if (which != _HENT_) rewind(_hfp);
512
513 forever
514 {
515 line = getLine(_hfp);
516 if (line == NULL) break;
517
518 if (line[0] == '#')
519 {
520 free(line);
521 line = NULL;
522 continue;
523 }
524
525 h = LI_files_parse_host(line);
526 free(line);
527 line = NULL;
528
529 if (h == NULL) continue;
530
531 if (which == _HENT_) return h;
532
533 got_host = 0;
534
535 if ((which == _HNAM_) && (af == h->h_addrtype))
536 {
537 if (!strcmp(name, h->h_name)) got_host = 1;
538 else if (h->h_aliases != NULL)
539 {
540 for (i = 0; (h->h_aliases[i] != NULL) && (got_host == 0); i++)
541 if (!strcmp(name, h->h_aliases[i])) got_host = 1;
542 }
543 }
544
545 if ((which == _HADDR_) && (h->h_addrtype == af))
546 {
547 for (i = 0; (h->h_addr_list[i] != NULL) && (got_host == 0); i++)
548 if (memcmp(addr, h->h_addr_list[i], h->h_length) == 0) got_host = 1;
549 }
550
551 if (got_host == 1)
552 {
553 fclose(_hfp);
554 _hfp = NULL;
555 return h;
556 }
557 }
558
559 fclose(_hfp);
560 _hfp = NULL;
561
562 return NULL;
563 }
564
565 /* "Public" */
566
567 __private_extern__ struct hostent *
568 LI_files_gethostbyname(const char *name)
569 {
570 return LI_files_get_host(name, NULL, AF_INET, _HNAM_);
571 }
572
573 __private_extern__ struct hostent *
574 LI_files_gethostbyname2(const char *name, int af)
575 {
576 return LI_files_get_host(name, NULL, af, _HNAM_);
577 }
578
579 __private_extern__ struct hostent *
580 LI_files_gethostbyaddr(const void *addr, socklen_t len, int type)
581 {
582 if ((type == AF_INET) || (type == AF_INET6)) return LI_files_get_host(NULL, addr, type, _HADDR_);
583 return NULL;
584 }
585
586 __private_extern__ struct hostent *
587 LI_files_gethostent()
588 {
589 return LI_files_get_host(NULL, NULL, AF_UNSPEC, _HENT_);
590 }
591
592 __private_extern__ void
593 LI_files_sethostent(int stayopen)
594 {
595 }
596
597 __private_extern__ void
598 LI_files_endhostent()
599 {
600 if (_hfp != NULL)
601 {
602 fclose(_hfp);
603 _hfp = NULL;
604 }
605 }