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