getpwent.c revision 1.7 1 /* $NetBSD: getpwent.c,v 1.7 2003/08/07 09:27:57 agc Exp $ */
2
3 /*
4 * Copyright (c) 1987, 1988, 1989, 1993, 1994, 1995
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 /*
33 * Copied from: lib/libc/gen/getpwent.c
34 * NetBSD: getpwent.c,v 1.48 2000/10/03 03:22:26 enami Exp
35 * and then gutted, leaving only /etc/master.passwd support.
36 */
37
38 #include <sys/cdefs.h>
39
40 #ifdef __weak_alias
41 #define endpwent _endpwent
42 #define getpwent _getpwent
43 #define getpwuid _getpwuid
44 #define getpwnam _getpwnam
45 #define setpwent _setpwent
46 #define setpassent _setpassent
47
48 __weak_alias(endpwent,_endpwent)
49 __weak_alias(getpwent,_getpwent)
50 __weak_alias(getpwuid,_getpwuid)
51 __weak_alias(getpwnam,_getpwnam)
52 __weak_alias(setpwent,_setpwent)
53 __weak_alias(setpassent,_setpassent)
54 #endif
55
56 #include <sys/param.h>
57
58 #include <limits.h>
59 #include <pwd.h>
60 #include <stdlib.h>
61 #include <stdio.h>
62 #include <string.h>
63
64 static int pwstart(void);
65 static int pwscan(int, uid_t, const char *);
66 static int pwmatchline(int, uid_t, const char *);
67
68 static FILE *_pw_fp;
69 static struct passwd _pw_passwd; /* password structure */
70 static int _pw_stayopen; /* keep fd's open */
71 static int _pw_filesdone;
72
73 #define MAXLINELENGTH 1024
74
75 static char pwline[MAXLINELENGTH];
76
77 struct passwd *
78 getpwent(void)
79 {
80
81 if ((!_pw_fp && !pwstart()) || !pwscan(0, 0, NULL))
82 return (NULL);
83 return (&_pw_passwd);
84 }
85
86 struct passwd *
87 getpwnam(const char *name)
88 {
89 int rval;
90
91 if (!pwstart())
92 return NULL;
93 rval = pwscan(1, 0, name);
94 if (!_pw_stayopen)
95 endpwent();
96 return (rval) ? &_pw_passwd : NULL;
97 }
98
99 struct passwd *
100 getpwuid(uid_t uid)
101 {
102 int rval;
103
104 if (!pwstart())
105 return NULL;
106 rval = pwscan(1, uid, NULL);
107 if (!_pw_stayopen)
108 endpwent();
109 return (rval) ? &_pw_passwd : NULL;
110 }
111
112 void
113 setpwent(void)
114 {
115
116 (void) setpassent(0);
117 }
118
119 int
120 setpassent(int stayopen)
121 {
122
123 if (!pwstart())
124 return 0;
125 _pw_stayopen = stayopen;
126 return 1;
127 }
128
129 void
130 endpwent(void)
131 {
132
133 _pw_filesdone = 0;
134 if (_pw_fp) {
135 (void)fclose(_pw_fp);
136 _pw_fp = NULL;
137 }
138 }
139
140 static int
141 pwstart(void)
142 {
143
144 _pw_filesdone = 0;
145 if (_pw_fp) {
146 rewind(_pw_fp);
147 return 1;
148 }
149 return (_pw_fp = fopen(_PATH_MASTERPASSWD, "r")) ? 1 : 0;
150 }
151
152
153 static int
154 pwscan(int search, uid_t uid, const char *name)
155 {
156
157 if (_pw_filesdone)
158 return 0;
159 for (;;) {
160 if (!fgets(pwline, sizeof(pwline), _pw_fp)) {
161 if (!search)
162 _pw_filesdone = 1;
163 return 0;
164 }
165 /* skip lines that are too big */
166 if (!strchr(pwline, '\n')) {
167 int ch;
168
169 while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
170 ;
171 continue;
172 }
173 if (pwmatchline(search, uid, name))
174 return 1;
175 }
176 /* NOTREACHED */
177 }
178
179 static int
180 pwmatchline(int search, uid_t uid, const char *name)
181 {
182 unsigned long id;
183 char *cp, *bp, *ep;
184
185 /* name may be NULL if search is nonzero */
186
187 bp = pwline;
188 memset(&_pw_passwd, 0, sizeof(_pw_passwd));
189 _pw_passwd.pw_name = strsep(&bp, ":\n"); /* name */
190 if (search && name && strcmp(_pw_passwd.pw_name, name))
191 return 0;
192
193 _pw_passwd.pw_passwd = strsep(&bp, ":\n"); /* passwd */
194
195 if (!(cp = strsep(&bp, ":\n"))) /* uid */
196 return 0;
197 id = strtoul(cp, &ep, 10);
198 if (id > UID_MAX || *ep != '\0')
199 return 0;
200 _pw_passwd.pw_uid = (uid_t)id;
201 if (search && name == NULL && _pw_passwd.pw_uid != uid)
202 return 0;
203
204 if (!(cp = strsep(&bp, ":\n"))) /* gid */
205 return 0;
206 id = strtoul(cp, &ep, 10);
207 if (id > GID_MAX || *ep != '\0')
208 return 0;
209 _pw_passwd.pw_gid = (gid_t)id;
210
211 if (!(_pw_passwd.pw_class = strsep(&bp, ":"))) /* class */
212 return 0;
213 if (!(ep = strsep(&bp, ":"))) /* change */
214 return 0;
215 if (!(ep = strsep(&bp, ":"))) /* expire */
216 return 0;
217
218 if (!(_pw_passwd.pw_gecos = strsep(&bp, ":\n"))) /* gecos */
219 return 0;
220 if (!(_pw_passwd.pw_dir = strsep(&bp, ":\n"))) /* directory */
221 return 0;
222 if (!(_pw_passwd.pw_shell = strsep(&bp, ":\n"))) /* shell */
223 return 0;
224
225 if (strchr(bp, ':') != NULL)
226 return 0;
227
228 return 1;
229 }
230