xref: /netbsd-src/distrib/utils/libhack/getpwent.c (revision 8b0f9554ff8762542c4defc4f70e1eb76fb508fa)
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