Change if(x)free(x); to free(x);
[oweals/busybox.git] / libpwdgrp / __getpwent.c
1 /*
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
21 #include "busybox.h" 
22
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <fcntl.h>
27 #include "pwd_.h"
28
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
37 struct 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 }