1 /* $NetBSD: getpwent.c,v 1.12 2011/01/12 23:34:00 joerg 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 getpwent_r _getpwent_r
44 #define getpwuid _getpwuid
45 #define getpwnam _getpwnam
46 #define setpwent _setpwent
47 #define setpassent _setpassent
48 #define getpwuid_r _getpwuid_r
49 #define getpwnam_r _getpwnam_r
50
51 __weak_alias(endpwent,_endpwent)
52 __weak_alias(setpwent,_setpwent)
53 __weak_alias(setpassent,_setpassent)
54
55 __weak_alias(getpwent,__getpwent50)
56 __weak_alias(getpwent_r,__getpwent_r50)
57 __weak_alias(getpwuid,__getpwuid50)
58 __weak_alias(getpwnam,__getpwnam50)
59 __weak_alias(getpwuid_r,__getpwuid_r50)
60 __weak_alias(getpwnam_r,__getpwnam_r50)
61 #endif
62
63 #include <sys/param.h>
64
65 #include <limits.h>
66 #include <pwd.h>
67 #include <stdlib.h>
68 #include <stdio.h>
69 #include <string.h>
70
71 static int pwstart(void);
72 static int pwscan(int, uid_t, const char *, struct passwd *,
73 char *, size_t);
74 static int pwmatchline(int, uid_t, const char *, struct passwd *,
75 char *);
76
77 static FILE *_pw_fp;
78 static struct passwd _pw_passwd; /* password structure */
79 static int _pw_stayopen; /* keep fd's open */
80 static int _pw_filesdone;
81
82 #define MAXLINELENGTH 1024
83
84 static char pwline[MAXLINELENGTH];
85
86 struct passwd *
getpwent(void)87 getpwent(void)
88 {
89
90 if ((!_pw_fp && !pwstart()) ||
91 !pwscan(0, 0, NULL, &_pw_passwd, pwline, sizeof(pwline)))
92 return (NULL);
93 return (&_pw_passwd);
94 }
95
96 int
getpwent_r(struct passwd * pwres,char * buf,size_t bufsiz,struct passwd ** pwd)97 getpwent_r(struct passwd *pwres, char *buf, size_t bufsiz,
98 struct passwd **pwd)
99 {
100 int rval;
101
102 if (!_pw_fp && !pwstart())
103 return 1;
104 rval = !pwscan(0, 0, NULL, pwres, buf, bufsiz);
105 if (rval)
106 *pwd = NULL;
107 else
108 *pwd = pwres;
109 return rval;
110 }
111
112 struct passwd *
getpwnam(const char * name)113 getpwnam(const char *name)
114 {
115 struct passwd *pwd;
116 return getpwnam_r(name, &_pw_passwd, pwline, sizeof(pwline),
117 &pwd) == 0 ? pwd : NULL;
118 }
119
120 int
getpwnam_r(const char * name,struct passwd * pwres,char * buf,size_t bufsiz,struct passwd ** pwd)121 getpwnam_r(const char *name, struct passwd *pwres, char *buf, size_t bufsiz,
122 struct passwd **pwd)
123 {
124 int rval;
125
126 if (!pwstart())
127 return 1;
128 rval = !pwscan(1, 0, name, pwres, buf, bufsiz);
129 if (!_pw_stayopen)
130 endpwent();
131 if (rval)
132 *pwd = NULL;
133 else
134 *pwd = pwres;
135 return rval;
136 }
137
138 struct passwd *
getpwuid(uid_t uid)139 getpwuid(uid_t uid)
140 {
141 struct passwd *pwd;
142 return getpwuid_r(uid, &_pw_passwd, pwline, sizeof(pwline),
143 &pwd) == 0 ? pwd : NULL;
144 }
145
146 int
getpwuid_r(uid_t uid,struct passwd * pwres,char * buf,size_t bufsiz,struct passwd ** pwd)147 getpwuid_r(uid_t uid, struct passwd *pwres, char *buf, size_t bufsiz,
148 struct passwd **pwd)
149 {
150 int rval;
151
152 if (!pwstart())
153 return 1;
154 rval = !pwscan(1, uid, NULL, pwres, buf, bufsiz);
155 if (!_pw_stayopen)
156 endpwent();
157 if (rval)
158 *pwd = NULL;
159 else
160 *pwd = pwres;
161 return rval;
162 }
163
164 void
setpwent(void)165 setpwent(void)
166 {
167
168 (void) setpassent(0);
169 }
170
171 int
setpassent(int stayopen)172 setpassent(int stayopen)
173 {
174
175 if (!pwstart())
176 return 0;
177 _pw_stayopen = stayopen;
178 return 1;
179 }
180
181 void
endpwent(void)182 endpwent(void)
183 {
184
185 _pw_filesdone = 0;
186 if (_pw_fp) {
187 (void)fclose(_pw_fp);
188 _pw_fp = NULL;
189 }
190 }
191
192 static int
pwstart(void)193 pwstart(void)
194 {
195
196 _pw_filesdone = 0;
197 if (_pw_fp) {
198 rewind(_pw_fp);
199 return 1;
200 }
201 return (_pw_fp = fopen(_PATH_MASTERPASSWD, "r")) ? 1 : 0;
202 }
203
204
205 static int
pwscan(int search,uid_t uid,const char * name,struct passwd * pwd,char * buf,size_t bufsiz)206 pwscan(int search, uid_t uid, const char *name, struct passwd *pwd, char *buf,
207 size_t bufsiz)
208 {
209
210 if (_pw_filesdone)
211 return 0;
212 for (;;) {
213 if (!fgets(buf, bufsiz, _pw_fp)) {
214 if (!search)
215 _pw_filesdone = 1;
216 return 0;
217 }
218 /* skip lines that are too big */
219 if (!strchr(buf, '\n')) {
220 int ch;
221
222 while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
223 ;
224 continue;
225 }
226 if (pwmatchline(search, uid, name, pwd, buf))
227 return 1;
228 }
229 /* NOTREACHED */
230 }
231
232 static int
pwmatchline(int search,uid_t uid,const char * name,struct passwd * pwd,char * buf)233 pwmatchline(int search, uid_t uid, const char *name, struct passwd *pwd,
234 char *buf)
235 {
236 unsigned long id;
237 char *cp, *bp, *ep;
238
239 /* name may be NULL if search is nonzero */
240
241 bp = buf;
242 memset(pwd, 0, sizeof(*pwd));
243 pwd->pw_name = strsep(&bp, ":\n"); /* name */
244 if (search && name && strcmp(pwd->pw_name, name))
245 return 0;
246
247 pwd->pw_passwd = strsep(&bp, ":\n"); /* passwd */
248
249 if (!(cp = strsep(&bp, ":\n"))) /* uid */
250 return 0;
251 id = strtoul(cp, &ep, 10);
252 if (id > UID_MAX || *ep != '\0')
253 return 0;
254 pwd->pw_uid = (uid_t)id;
255 if (search && name == NULL && pwd->pw_uid != uid)
256 return 0;
257
258 if (!(cp = strsep(&bp, ":\n"))) /* gid */
259 return 0;
260 id = strtoul(cp, &ep, 10);
261 if (id > GID_MAX || *ep != '\0')
262 return 0;
263 pwd->pw_gid = (gid_t)id;
264
265 if (!(pwd->pw_class = strsep(&bp, ":"))) /* class */
266 return 0;
267 if (!(ep = strsep(&bp, ":"))) /* change */
268 return 0;
269 if (!(ep = strsep(&bp, ":"))) /* expire */
270 return 0;
271
272 if (!(pwd->pw_gecos = strsep(&bp, ":\n"))) /* gecos */
273 return 0;
274 if (!(pwd->pw_dir = strsep(&bp, ":\n"))) /* directory */
275 return 0;
276 if (!(pwd->pw_shell = strsep(&bp, ":\n"))) /* shell */
277 return 0;
278
279 if (strchr(bp, ':') != NULL)
280 return 0;
281
282 return 1;
283 }
284