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 <stdlib.h>
22 #include <unistd.h>
23 #include <string.h>
24 #include <fcntl.h>
25 #include <pwd.h>
26 
27 #define PWD_BUFFER_SIZE 256
28 
29 /* This isn't as flash as my previous version -- it doesn't dynamically
30   scale down the gecos on too-long lines, but it also makes fewer syscalls,
31   so it's probably nicer.  Write me if you want the old version.  Maybe I
32   should include it as a build-time option... ?
33   -Nat <ndf@linux.mit.edu> */
34 
35 struct passwd *
__getpwent(int pwd_fd)36 __getpwent(int pwd_fd)
37 {
38   static char line_buff[PWD_BUFFER_SIZE];
39   static struct passwd passwd;
40   char * field_begin;
41   char * endptr;
42   char * gid_ptr;
43   char * uid_ptr;
44   int line_len;
45   int i;
46 
47   /* We use the restart label to handle malformatted lines */
48 restart:
49   /* Read the passwd line into the static buffer using a minimal of
50      syscalls. */
51   if ((line_len=read(pwd_fd, line_buff, PWD_BUFFER_SIZE))<=0)
52     return NULL;
53   field_begin=strchr(line_buff, '\n');
54   if (field_begin!=NULL)
55     lseek(pwd_fd, (long) (1+field_begin-(line_buff+line_len)), SEEK_CUR);
56   else /* The line is too long - skip it. :-\ */
57     {
58       do { if ((line_len=read(pwd_fd, line_buff, PWD_BUFFER_SIZE))<=0)
59 	return NULL;
60       } while (!(field_begin=strchr(line_buff, '\n')));
61       lseek(pwd_fd, (long) (field_begin-line_buff)-line_len+1, SEEK_CUR);
62       goto restart;
63     }
64   if (*line_buff=='#' || *line_buff==' ' || *line_buff=='\n' ||
65       *line_buff=='\t')
66       goto restart;
67   *field_begin='\0';
68 
69   /* We've read the line; now parse it. */
70   field_begin=line_buff;
71   for (i=0;i<7;i++)
72     {
73       switch(i)
74 	{
75 	case 0: passwd.pw_name=field_begin; break;
76 	case 1: passwd.pw_passwd=field_begin; break;
77 	case 2: uid_ptr=field_begin; break;
78 	case 3: gid_ptr=field_begin; break;
79 	case 4: passwd.pw_gecos=field_begin; break;
80 	case 5: passwd.pw_dir=field_begin; break;
81 	case 6: passwd.pw_shell=field_begin; break;
82 	}
83       if (i<6)
84 	{
85 	  field_begin=strchr(field_begin, ':');
86 	  if (field_begin==NULL) goto restart;
87 	  *field_begin++='\0';
88 	}
89     }
90   passwd.pw_gid=(gid_t) strtoul(gid_ptr, &endptr, 10);
91   if (*endptr!='\0') goto restart;
92 
93   passwd.pw_uid=(uid_t) strtoul(uid_ptr, &endptr, 10);
94   if (*endptr!='\0') goto restart;
95 
96   return &passwd;
97 }
98 
99 
100