blob: 1b38c27efc6e5a89f3e7713d372f9e0858e9cb7b [file] [log] [blame]
Robert Griebl1fca5582002-06-04 20:45:46 +00001/*
2 * __getpwent.c - This file is part of the libc-8086/pwd package for ELKS,
3 * Copyright (C) 1995, 1996 Nat Friedman <ndf@linux.mit.edu>.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 */
20
Robert Griebl1fca5582002-06-04 20:45:46 +000021#include <stdlib.h>
22#include <unistd.h>
23#include <string.h>
24#include <fcntl.h>
Glenn L McGrath4e05b9b2002-12-07 23:14:40 +000025
Eric Andersen887ca792002-07-03 23:19:26 +000026#include "pwd_.h"
Glenn L McGrath4e05b9b2002-12-07 23:14:40 +000027#include "busybox.h"
Robert Griebl1fca5582002-06-04 20:45:46 +000028
29#define PWD_BUFFER_SIZE 256
30
31/* This isn't as flash as my previous version -- it doesn't dynamically
32 scale down the gecos on too-long lines, but it also makes fewer syscalls,
33 so it's probably nicer. Write me if you want the old version. Maybe I
34 should include it as a build-time option... ?
35 -Nat <ndf@linux.mit.edu> */
36
37struct passwd *__getpwent(int pwd_fd)
38{
39 static char line_buff[PWD_BUFFER_SIZE];
40 static struct passwd passwd;
41 char *field_begin;
42 char *endptr;
43 char *gid_ptr=NULL;
44 char *uid_ptr=NULL;
45 int line_len;
46 int i;
47
48 /* We use the restart label to handle malformatted lines */
49 restart:
50 /* Read the passwd line into the static buffer using a minimal of
51 syscalls. */
52 if ((line_len = read(pwd_fd, line_buff, PWD_BUFFER_SIZE)) <= 0)
53 return NULL;
54 field_begin = strchr(line_buff, '\n');
55 if (field_begin != NULL)
56 lseek(pwd_fd, (long) (1 + field_begin - (line_buff + line_len)),
57 SEEK_CUR);
58 else { /* The line is too long - skip it. :-\ */
59
60 do {
61 if ((line_len = read(pwd_fd, line_buff, PWD_BUFFER_SIZE)) <= 0)
62 return NULL;
63 } while (!(field_begin = strchr(line_buff, '\n')));
64 lseek(pwd_fd, (long) (field_begin - line_buff) - line_len + 1,
65 SEEK_CUR);
66 goto restart;
67 }
68 if (*line_buff == '#' || *line_buff == ' ' || *line_buff == '\n' ||
69 *line_buff == '\t')
70 goto restart;
71 *field_begin = '\0';
72
73 /* We've read the line; now parse it. */
74 field_begin = line_buff;
75 for (i = 0; i < 7; i++) {
76 switch (i) {
77 case 0:
78 passwd.pw_name = field_begin;
79 break;
80 case 1:
81 passwd.pw_passwd = field_begin;
82 break;
83 case 2:
84 uid_ptr = field_begin;
85 break;
86 case 3:
87 gid_ptr = field_begin;
88 break;
89 case 4:
90 passwd.pw_gecos = field_begin;
91 break;
92 case 5:
93 passwd.pw_dir = field_begin;
94 break;
95 case 6:
96 passwd.pw_shell = field_begin;
97 break;
98 }
99 if (i < 6) {
100 field_begin = strchr(field_begin, ':');
101 if (field_begin == NULL)
102 goto restart;
103 *field_begin++ = '\0';
104 }
105 }
106 passwd.pw_gid = (gid_t) strtoul(gid_ptr, &endptr, 10);
107 if (*endptr != '\0')
108 goto restart;
109
110 passwd.pw_uid = (uid_t) strtoul(uid_ptr, &endptr, 10);
111 if (*endptr != '\0')
112 goto restart;
113
114 return &passwd;
115}