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