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