]> git.saurik.com Git - apple/libinfo.git/blame - gen.subproj/getpwent.c
Libinfo-278.0.3.tar.gz
[apple/libinfo.git] / gen.subproj / getpwent.c
CommitLineData
03fb6eb0 1/*
b3dd680f 2 * Copyright (c) 2007 Apple Inc. All rights reserved.
03fb6eb0
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
ad21edcc
A
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.
03fb6eb0
A
13 *
14 * The Original Code and all software distributed under the License are
ad21edcc 15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
03fb6eb0
A
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
ad21edcc
A
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.
03fb6eb0
A
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
b3dd680f 29 * Directory Service does all flat file lookups when the system is multi-user.
03fb6eb0
A
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>
b3dd680f
A
39#include <netdb.h>
40#include <netinet/in.h>
41#include <arpa/inet.h>
a0865d63 42#include <unistd.h>
03fb6eb0
A
43
44#define forever for (;;)
45
46#define _PWENT_ 0
47#define _PWNAM_ 1
48#define _PWUID_ 2
49
50static struct passwd _pw = { 0 };
b3dd680f 51static FILE *_pfp = NULL;
a0865d63 52static int _pwFileFormat = 1;
03fb6eb0 53
b3dd680f
A
54#define _HENT_ 0
55#define _HNAM_ 1
56#define _HADDR_ 2
03fb6eb0 57
b3dd680f
A
58static struct hostent _h = { 0 };
59static FILE *_hfp = NULL;
60
61/* Forward */
62__private_extern__ void LI_files_setpwent();
63__private_extern__ void LI_files_endhostent();
03fb6eb0
A
64
65static void
66freeList(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
79static unsigned int
80listLength(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
89static char *
90copyString(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
104static char **
105insertString(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
135static char **
136appendString(char *s, char **l)
137{
138 return insertString(s, l, (unsigned int)-1);
139}
140
03fb6eb0
A
141static char **
142tokenize(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 }
b3dd680f 186
03fb6eb0
A
187 /* back over trailing whitespace */
188 i--;
ccd4a120
A
189 if (i > -1) { /* did we actually copy anything? */
190 while ((buf[i] == ' ') || (buf[i] == '\t') || (buf[i] == '\n')) i--;
191 }
03fb6eb0 192 buf[++i] = '\0';
b3dd680f 193
03fb6eb0
A
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 }
b3dd680f 217
03fb6eb0
A
218 return tokens;
219}
220
b3dd680f
A
221static char *
222getLine(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
240static void
241LI_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
258static struct passwd *
259LI_files_parse_user(char *data)
03fb6eb0
A
260{
261 char **tokens;
a0865d63 262 int ntokens;
03fb6eb0
A
263
264 if (data == NULL) return NULL;
265
266 tokens = tokenize(data, ":");
a0865d63
A
267 ntokens = listLength(tokens);
268 if (( _pwFileFormat && (ntokens != 10)) ||
b3dd680f 269 (!_pwFileFormat && (ntokens != 7)))
03fb6eb0
A
270 {
271 freeList(tokens);
272 return NULL;
273 }
274
b3dd680f 275 LI_files_free_user();
03fb6eb0
A
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]);
a0865d63
A
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 }
03fb6eb0
A
304
305 free(tokens);
306
307 return &_pw;
308}
309
b3dd680f
A
310static struct passwd *
311LI_files_getpw(const char *name, uid_t uid, int which)
03fb6eb0 312{
b3dd680f
A
313 char *line;
314 struct passwd *pw;
03fb6eb0 315
b3dd680f
A
316 if (_pfp == NULL) LI_files_setpwent();
317 if (_pfp == NULL) return NULL;
03fb6eb0 318
b3dd680f 319 if (which != _PWENT_) rewind(_pfp);
03fb6eb0 320
b3dd680f
A
321 forever
322 {
323 line = getLine(_pfp);
324 if (line == NULL) break;
03fb6eb0 325
b3dd680f
A
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 *
358LI_files_getpwent()
359{
360 return LI_files_getpw(NULL, 0, _PWENT_);
361}
362
363__private_extern__ struct passwd *
364LI_files_getpwnam(const char *name)
365{
366 return LI_files_getpw(name, 0, _PWNAM_);
367}
368
369__private_extern__ struct passwd *
370LI_files_getpwuid(uid_t uid)
371{
372 return LI_files_getpw(NULL, uid, _PWUID_);
03fb6eb0
A
373}
374
375int
376setpassent(int stayopen)
377{
b3dd680f 378 return 1;
03fb6eb0
A
379}
380
b3dd680f
A
381__private_extern__ void
382LI_files_setpwent()
03fb6eb0
A
383{
384 if (_pfp == NULL)
385 {
a0865d63
A
386 char *pwFile;
387 if (geteuid() == 0)
388 {
389 pwFile = _PATH_MASTERPASSWD;
390 }
391 else
392 {
393 pwFile = _PATH_PASSWD;
394 _pwFileFormat = 0;
395 }
b3dd680f 396
a0865d63 397 _pfp = fopen(pwFile, "r");
03fb6eb0
A
398 }
399 else rewind(_pfp);
03fb6eb0
A
400}
401
b3dd680f
A
402__private_extern__ void
403LI_files_endpwent()
03fb6eb0
A
404{
405 if (_pfp != NULL)
406 {
407 fclose(_pfp);
408 _pfp = NULL;
409 }
410}
411
b3dd680f
A
412/* HOSTS */
413
414static void
415LI_files_free_host()
03fb6eb0 416{
b3dd680f
A
417 int i;
418
419 if (_h.h_name != NULL) free(_h.h_name);
03fb6eb0 420
b3dd680f 421 if (_h.h_aliases != NULL)
03fb6eb0 422 {
b3dd680f
A
423 for (i = 0; _h.h_aliases[i] != NULL; i++) free(_h.h_aliases[i]);
424 free(_h.h_aliases);
03fb6eb0
A
425 }
426
b3dd680f
A
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
440static struct hostent *
441LI_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
499static struct hostent *
500LI_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
03fb6eb0
A
513 forever
514 {
b3dd680f 515 line = getLine(_hfp);
03fb6eb0
A
516 if (line == NULL) break;
517
518 if (line[0] == '#')
519 {
520 free(line);
521 line = NULL;
522 continue;
523 }
524
b3dd680f 525 h = LI_files_parse_host(line);
03fb6eb0
A
526 free(line);
527 line = NULL;
528
b3dd680f
A
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))
03fb6eb0 536 {
b3dd680f
A
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 }
03fb6eb0
A
543 }
544
b3dd680f 545 if ((which == _HADDR_) && (h->h_addrtype == af))
03fb6eb0 546 {
b3dd680f
A
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;
03fb6eb0
A
556 }
557 }
558
b3dd680f
A
559 fclose(_hfp);
560 _hfp = NULL;
561
562 return NULL;
563}
564
565/* "Public" */
566
567__private_extern__ struct hostent *
568LI_files_gethostbyname(const char *name)
569{
570 return LI_files_get_host(name, NULL, AF_INET, _HNAM_);
571}
572
573__private_extern__ struct hostent *
574LI_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 *
580LI_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_);
03fb6eb0
A
583 return NULL;
584}
585
b3dd680f
A
586__private_extern__ struct hostent *
587LI_files_gethostent()
03fb6eb0 588{
b3dd680f 589 return LI_files_get_host(NULL, NULL, AF_UNSPEC, _HENT_);
03fb6eb0
A
590}
591
b3dd680f
A
592__private_extern__ void
593LI_files_sethostent(int stayopen)
03fb6eb0 594{
03fb6eb0
A
595}
596
b3dd680f
A
597__private_extern__ void
598LI_files_endhostent()
03fb6eb0 599{
b3dd680f
A
600 if (_hfp != NULL)
601 {
602 fclose(_hfp);
603 _hfp = NULL;
604 }
03fb6eb0 605}