xref: /dflybsd-src/usr.sbin/mtree/getid.c (revision 27a796753626c4fca2de1d161fddbac6d6930ecc)
1*a43287ccSSascha Wildner /*	$NetBSD: getid.c,v 1.10 2014/10/27 21:46:45 christos Exp $	*/
2*a43287ccSSascha Wildner /*	from: NetBSD: getpwent.c,v 1.48 2000/10/03 03:22:26 enami Exp */
3*a43287ccSSascha Wildner /*	from: NetBSD: getgrent.c,v 1.41 2002/01/12 23:51:30 lukem Exp */
4*a43287ccSSascha Wildner 
5*a43287ccSSascha Wildner /*
6*a43287ccSSascha Wildner  * Copyright (c) 1987, 1988, 1989, 1993, 1994, 1995
7*a43287ccSSascha Wildner  *	The Regents of the University of California.  All rights reserved.
8*a43287ccSSascha Wildner  *
9*a43287ccSSascha Wildner  * Redistribution and use in source and binary forms, with or without
10*a43287ccSSascha Wildner  * modification, are permitted provided that the following conditions
11*a43287ccSSascha Wildner  * are met:
12*a43287ccSSascha Wildner  * 1. Redistributions of source code must retain the above copyright
13*a43287ccSSascha Wildner  *    notice, this list of conditions and the following disclaimer.
14*a43287ccSSascha Wildner  * 2. Redistributions in binary form must reproduce the above copyright
15*a43287ccSSascha Wildner  *    notice, this list of conditions and the following disclaimer in the
16*a43287ccSSascha Wildner  *    documentation and/or other materials provided with the distribution.
17*a43287ccSSascha Wildner  * 3. Neither the name of the University nor the names of its contributors
18*a43287ccSSascha Wildner  *    may be used to endorse or promote products derived from this software
19*a43287ccSSascha Wildner  *    without specific prior written permission.
20*a43287ccSSascha Wildner  *
21*a43287ccSSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22*a43287ccSSascha Wildner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23*a43287ccSSascha Wildner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24*a43287ccSSascha Wildner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25*a43287ccSSascha Wildner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26*a43287ccSSascha Wildner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27*a43287ccSSascha Wildner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28*a43287ccSSascha Wildner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29*a43287ccSSascha Wildner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30*a43287ccSSascha Wildner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*a43287ccSSascha Wildner  * SUCH DAMAGE.
32*a43287ccSSascha Wildner  */
33*a43287ccSSascha Wildner 
34*a43287ccSSascha Wildner /*-
35*a43287ccSSascha Wildner  * Copyright (c) 2002 The NetBSD Foundation, Inc.
36*a43287ccSSascha Wildner  * All rights reserved.
37*a43287ccSSascha Wildner  *
38*a43287ccSSascha Wildner  * This code is derived from software contributed to The NetBSD Foundation
39*a43287ccSSascha Wildner  * by Luke Mewburn of Wasabi Systems.
40*a43287ccSSascha Wildner  *
41*a43287ccSSascha Wildner  * Redistribution and use in source and binary forms, with or without
42*a43287ccSSascha Wildner  * modification, are permitted provided that the following conditions
43*a43287ccSSascha Wildner  * are met:
44*a43287ccSSascha Wildner  * 1. Redistributions of source code must retain the above copyright
45*a43287ccSSascha Wildner  *    notice, this list of conditions and the following disclaimer.
46*a43287ccSSascha Wildner  * 2. Redistributions in binary form must reproduce the above copyright
47*a43287ccSSascha Wildner  *    notice, this list of conditions and the following disclaimer in the
48*a43287ccSSascha Wildner  *    documentation and/or other materials provided with the distribution.
49*a43287ccSSascha Wildner  *
50*a43287ccSSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
51*a43287ccSSascha Wildner  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
52*a43287ccSSascha Wildner  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53*a43287ccSSascha Wildner  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
54*a43287ccSSascha Wildner  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
55*a43287ccSSascha Wildner  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
56*a43287ccSSascha Wildner  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
57*a43287ccSSascha Wildner  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
58*a43287ccSSascha Wildner  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
59*a43287ccSSascha Wildner  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
60*a43287ccSSascha Wildner  * POSSIBILITY OF SUCH DAMAGE.
61*a43287ccSSascha Wildner  */
62*a43287ccSSascha Wildner 
63*a43287ccSSascha Wildner #include <sys/param.h>
64*a43287ccSSascha Wildner 
65*a43287ccSSascha Wildner #include <grp.h>
66*a43287ccSSascha Wildner #include <limits.h>
67*a43287ccSSascha Wildner #include <pwd.h>
68*a43287ccSSascha Wildner #include <stdlib.h>
69*a43287ccSSascha Wildner #include <stdio.h>
70*a43287ccSSascha Wildner #include <string.h>
71*a43287ccSSascha Wildner #include <time.h>
72*a43287ccSSascha Wildner #include <unistd.h>
73*a43287ccSSascha Wildner 
74*a43287ccSSascha Wildner #include "extern.h"
75*a43287ccSSascha Wildner 
76*a43287ccSSascha Wildner static	struct group *	gi_getgrnam(const char *);
77*a43287ccSSascha Wildner static	struct group *	gi_getgrgid(gid_t);
78*a43287ccSSascha Wildner static	int		gi_setgroupent(int);
79*a43287ccSSascha Wildner static	void		gi_endgrent(void);
80*a43287ccSSascha Wildner static	int		grstart(void);
81*a43287ccSSascha Wildner static	int		grscan(int, gid_t, const char *);
82*a43287ccSSascha Wildner static	int		grmatchline(int, gid_t, const char *);
83*a43287ccSSascha Wildner 
84*a43287ccSSascha Wildner static	struct passwd *	gi_getpwnam(const char *);
85*a43287ccSSascha Wildner static	struct passwd *	gi_getpwuid(uid_t);
86*a43287ccSSascha Wildner static	int		gi_setpassent(int);
87*a43287ccSSascha Wildner static	void		gi_endpwent(void);
88*a43287ccSSascha Wildner static	int		pwstart(void);
89*a43287ccSSascha Wildner static	int		pwscan(int, uid_t, const char *);
90*a43287ccSSascha Wildner static	int		pwmatchline(int, uid_t, const char *);
91*a43287ccSSascha Wildner 
92*a43287ccSSascha Wildner #define	MAXGRP		200
93*a43287ccSSascha Wildner #define	MAXLINELENGTH	1024
94*a43287ccSSascha Wildner 
95*a43287ccSSascha Wildner static	FILE		*_gr_fp;
96*a43287ccSSascha Wildner static	struct group	_gr_group;
97*a43287ccSSascha Wildner static	int		_gr_stayopen;
98*a43287ccSSascha Wildner static	int		_gr_filesdone;
99*a43287ccSSascha Wildner static	FILE		*_pw_fp;
100*a43287ccSSascha Wildner static	struct passwd	_pw_passwd;	/* password structure */
101*a43287ccSSascha Wildner static	int		_pw_stayopen;	/* keep fd's open */
102*a43287ccSSascha Wildner static	int		_pw_filesdone;
103*a43287ccSSascha Wildner 
104*a43287ccSSascha Wildner static	char		grfile[MAXPATHLEN];
105*a43287ccSSascha Wildner static	char		pwfile[MAXPATHLEN];
106*a43287ccSSascha Wildner 
107*a43287ccSSascha Wildner static	char		*members[MAXGRP];
108*a43287ccSSascha Wildner static	char		grline[MAXLINELENGTH];
109*a43287ccSSascha Wildner static	char		pwline[MAXLINELENGTH];
110*a43287ccSSascha Wildner 
111*a43287ccSSascha Wildner int
setup_getid(const char * dir)112*a43287ccSSascha Wildner setup_getid(const char *dir)
113*a43287ccSSascha Wildner {
114*a43287ccSSascha Wildner 	if (dir == NULL)
115*a43287ccSSascha Wildner 		return (0);
116*a43287ccSSascha Wildner 
117*a43287ccSSascha Wildner 				/* close existing databases */
118*a43287ccSSascha Wildner 	gi_endgrent();
119*a43287ccSSascha Wildner 	gi_endpwent();
120*a43287ccSSascha Wildner 
121*a43287ccSSascha Wildner 				/* build paths to new databases */
122*a43287ccSSascha Wildner 	snprintf(grfile, sizeof(grfile), "%s/group", dir);
123*a43287ccSSascha Wildner 	snprintf(pwfile, sizeof(pwfile), "%s/master.passwd", dir);
124*a43287ccSSascha Wildner 
125*a43287ccSSascha Wildner 				/* try to open new databases */
126*a43287ccSSascha Wildner 	if (!grstart() || !pwstart())
127*a43287ccSSascha Wildner 		return (0);
128*a43287ccSSascha Wildner 
129*a43287ccSSascha Wildner 				/* switch pwcache(3) lookup functions */
130*a43287ccSSascha Wildner 	if (pwcache_groupdb(gi_setgroupent, gi_endgrent,
131*a43287ccSSascha Wildner 			    gi_getgrnam, gi_getgrgid) == -1
132*a43287ccSSascha Wildner 	    || pwcache_userdb(gi_setpassent, gi_endpwent,
133*a43287ccSSascha Wildner 			    gi_getpwnam, gi_getpwuid) == -1)
134*a43287ccSSascha Wildner 		return (0);
135*a43287ccSSascha Wildner 
136*a43287ccSSascha Wildner 	return (1);
137*a43287ccSSascha Wildner }
138*a43287ccSSascha Wildner 
139*a43287ccSSascha Wildner 
140*a43287ccSSascha Wildner /*
141*a43287ccSSascha Wildner  * group lookup functions
142*a43287ccSSascha Wildner  */
143*a43287ccSSascha Wildner 
144*a43287ccSSascha Wildner static struct group *
gi_getgrnam(const char * name)145*a43287ccSSascha Wildner gi_getgrnam(const char *name)
146*a43287ccSSascha Wildner {
147*a43287ccSSascha Wildner 	int rval;
148*a43287ccSSascha Wildner 
149*a43287ccSSascha Wildner 	if (!grstart())
150*a43287ccSSascha Wildner 		return NULL;
151*a43287ccSSascha Wildner 	rval = grscan(1, 0, name);
152*a43287ccSSascha Wildner 	if (!_gr_stayopen)
153*a43287ccSSascha Wildner 		endgrent();
154*a43287ccSSascha Wildner 	return (rval) ? &_gr_group : NULL;
155*a43287ccSSascha Wildner }
156*a43287ccSSascha Wildner 
157*a43287ccSSascha Wildner static struct group *
gi_getgrgid(gid_t gid)158*a43287ccSSascha Wildner gi_getgrgid(gid_t gid)
159*a43287ccSSascha Wildner {
160*a43287ccSSascha Wildner 	int rval;
161*a43287ccSSascha Wildner 
162*a43287ccSSascha Wildner 	if (!grstart())
163*a43287ccSSascha Wildner 		return NULL;
164*a43287ccSSascha Wildner 	rval = grscan(1, gid, NULL);
165*a43287ccSSascha Wildner 	if (!_gr_stayopen)
166*a43287ccSSascha Wildner 		endgrent();
167*a43287ccSSascha Wildner 	return (rval) ? &_gr_group : NULL;
168*a43287ccSSascha Wildner }
169*a43287ccSSascha Wildner 
170*a43287ccSSascha Wildner static int
gi_setgroupent(int stayopen)171*a43287ccSSascha Wildner gi_setgroupent(int stayopen)
172*a43287ccSSascha Wildner {
173*a43287ccSSascha Wildner 
174*a43287ccSSascha Wildner 	if (!grstart())
175*a43287ccSSascha Wildner 		return 0;
176*a43287ccSSascha Wildner 	_gr_stayopen = stayopen;
177*a43287ccSSascha Wildner 	return 1;
178*a43287ccSSascha Wildner }
179*a43287ccSSascha Wildner 
180*a43287ccSSascha Wildner static void
gi_endgrent(void)181*a43287ccSSascha Wildner gi_endgrent(void)
182*a43287ccSSascha Wildner {
183*a43287ccSSascha Wildner 
184*a43287ccSSascha Wildner 	_gr_filesdone = 0;
185*a43287ccSSascha Wildner 	if (_gr_fp) {
186*a43287ccSSascha Wildner 		(void)fclose(_gr_fp);
187*a43287ccSSascha Wildner 		_gr_fp = NULL;
188*a43287ccSSascha Wildner 	}
189*a43287ccSSascha Wildner }
190*a43287ccSSascha Wildner 
191*a43287ccSSascha Wildner static int
grstart(void)192*a43287ccSSascha Wildner grstart(void)
193*a43287ccSSascha Wildner {
194*a43287ccSSascha Wildner 
195*a43287ccSSascha Wildner 	_gr_filesdone = 0;
196*a43287ccSSascha Wildner 	if (_gr_fp) {
197*a43287ccSSascha Wildner 		rewind(_gr_fp);
198*a43287ccSSascha Wildner 		return 1;
199*a43287ccSSascha Wildner 	}
200*a43287ccSSascha Wildner 	if (grfile[0] == '\0')			/* sanity check */
201*a43287ccSSascha Wildner 		return 0;
202*a43287ccSSascha Wildner 
203*a43287ccSSascha Wildner 	_gr_fp = fopen(grfile, "r");
204*a43287ccSSascha Wildner 	if (_gr_fp != NULL)
205*a43287ccSSascha Wildner 		return 1;
206*a43287ccSSascha Wildner 	warn("Can't open `%s'", grfile);
207*a43287ccSSascha Wildner 	return 0;
208*a43287ccSSascha Wildner }
209*a43287ccSSascha Wildner 
210*a43287ccSSascha Wildner 
211*a43287ccSSascha Wildner static int
grscan(int search,gid_t gid,const char * name)212*a43287ccSSascha Wildner grscan(int search, gid_t gid, const char *name)
213*a43287ccSSascha Wildner {
214*a43287ccSSascha Wildner 
215*a43287ccSSascha Wildner 	if (_gr_filesdone)
216*a43287ccSSascha Wildner 		return 0;
217*a43287ccSSascha Wildner 	for (;;) {
218*a43287ccSSascha Wildner 		if (!fgets(grline, sizeof(grline), _gr_fp)) {
219*a43287ccSSascha Wildner 			if (!search)
220*a43287ccSSascha Wildner 				_gr_filesdone = 1;
221*a43287ccSSascha Wildner 			return 0;
222*a43287ccSSascha Wildner 		}
223*a43287ccSSascha Wildner 		/* skip lines that are too big */
224*a43287ccSSascha Wildner 		if (!strchr(grline, '\n')) {
225*a43287ccSSascha Wildner 			int ch;
226*a43287ccSSascha Wildner 
227*a43287ccSSascha Wildner 			while ((ch = getc(_gr_fp)) != '\n' && ch != EOF)
228*a43287ccSSascha Wildner 				;
229*a43287ccSSascha Wildner 			continue;
230*a43287ccSSascha Wildner 		}
231*a43287ccSSascha Wildner 		/* skip comments */
232*a43287ccSSascha Wildner 		if (grline[0] == '#')
233*a43287ccSSascha Wildner 			continue;
234*a43287ccSSascha Wildner 		if (grmatchline(search, gid, name))
235*a43287ccSSascha Wildner 			return 1;
236*a43287ccSSascha Wildner 	}
237*a43287ccSSascha Wildner 	/* NOTREACHED */
238*a43287ccSSascha Wildner }
239*a43287ccSSascha Wildner 
240*a43287ccSSascha Wildner static int
grmatchline(int search,gid_t gid,const char * name)241*a43287ccSSascha Wildner grmatchline(int search, gid_t gid, const char *name)
242*a43287ccSSascha Wildner {
243*a43287ccSSascha Wildner 	unsigned long	id;
244*a43287ccSSascha Wildner 	char		**m;
245*a43287ccSSascha Wildner 	char		*cp, *bp, *ep;
246*a43287ccSSascha Wildner 
247*a43287ccSSascha Wildner 	/* name may be NULL if search is nonzero */
248*a43287ccSSascha Wildner 
249*a43287ccSSascha Wildner 	bp = grline;
250*a43287ccSSascha Wildner 	memset(&_gr_group, 0, sizeof(_gr_group));
251*a43287ccSSascha Wildner 	_gr_group.gr_name = strsep(&bp, ":\n");
252*a43287ccSSascha Wildner 	if (search && name && strcmp(_gr_group.gr_name, name))
253*a43287ccSSascha Wildner 		return 0;
254*a43287ccSSascha Wildner 	_gr_group.gr_passwd = strsep(&bp, ":\n");
255*a43287ccSSascha Wildner 	if (!(cp = strsep(&bp, ":\n")))
256*a43287ccSSascha Wildner 		return 0;
257*a43287ccSSascha Wildner 	id = strtoul(cp, &ep, 10);
258*a43287ccSSascha Wildner 	if (id > GID_MAX || *ep != '\0')
259*a43287ccSSascha Wildner 		return 0;
260*a43287ccSSascha Wildner 	_gr_group.gr_gid = (gid_t)id;
261*a43287ccSSascha Wildner 	if (search && name == NULL && _gr_group.gr_gid != gid)
262*a43287ccSSascha Wildner 		return 0;
263*a43287ccSSascha Wildner 	cp = NULL;
264*a43287ccSSascha Wildner 	if (bp == NULL)
265*a43287ccSSascha Wildner 		return 0;
266*a43287ccSSascha Wildner 	for (_gr_group.gr_mem = m = members;; bp++) {
267*a43287ccSSascha Wildner 		if (m == &members[MAXGRP - 1])
268*a43287ccSSascha Wildner 			break;
269*a43287ccSSascha Wildner 		if (*bp == ',') {
270*a43287ccSSascha Wildner 			if (cp) {
271*a43287ccSSascha Wildner 				*bp = '\0';
272*a43287ccSSascha Wildner 				*m++ = cp;
273*a43287ccSSascha Wildner 				cp = NULL;
274*a43287ccSSascha Wildner 			}
275*a43287ccSSascha Wildner 		} else if (*bp == '\0' || *bp == '\n' || *bp == ' ') {
276*a43287ccSSascha Wildner 			if (cp) {
277*a43287ccSSascha Wildner 				*bp = '\0';
278*a43287ccSSascha Wildner 				*m++ = cp;
279*a43287ccSSascha Wildner 			}
280*a43287ccSSascha Wildner 			break;
281*a43287ccSSascha Wildner 		} else if (cp == NULL)
282*a43287ccSSascha Wildner 			cp = bp;
283*a43287ccSSascha Wildner 	}
284*a43287ccSSascha Wildner 	*m = NULL;
285*a43287ccSSascha Wildner 	return 1;
286*a43287ccSSascha Wildner }
287*a43287ccSSascha Wildner 
288*a43287ccSSascha Wildner 
289*a43287ccSSascha Wildner /*
290*a43287ccSSascha Wildner  * user lookup functions
291*a43287ccSSascha Wildner  */
292*a43287ccSSascha Wildner 
293*a43287ccSSascha Wildner static struct passwd *
gi_getpwnam(const char * name)294*a43287ccSSascha Wildner gi_getpwnam(const char *name)
295*a43287ccSSascha Wildner {
296*a43287ccSSascha Wildner 	int rval;
297*a43287ccSSascha Wildner 
298*a43287ccSSascha Wildner 	if (!pwstart())
299*a43287ccSSascha Wildner 		return NULL;
300*a43287ccSSascha Wildner 	rval = pwscan(1, 0, name);
301*a43287ccSSascha Wildner 	if (!_pw_stayopen)
302*a43287ccSSascha Wildner 		endpwent();
303*a43287ccSSascha Wildner 	return (rval) ? &_pw_passwd : NULL;
304*a43287ccSSascha Wildner }
305*a43287ccSSascha Wildner 
306*a43287ccSSascha Wildner static struct passwd *
gi_getpwuid(uid_t uid)307*a43287ccSSascha Wildner gi_getpwuid(uid_t uid)
308*a43287ccSSascha Wildner {
309*a43287ccSSascha Wildner 	int rval;
310*a43287ccSSascha Wildner 
311*a43287ccSSascha Wildner 	if (!pwstart())
312*a43287ccSSascha Wildner 		return NULL;
313*a43287ccSSascha Wildner 	rval = pwscan(1, uid, NULL);
314*a43287ccSSascha Wildner 	if (!_pw_stayopen)
315*a43287ccSSascha Wildner 		endpwent();
316*a43287ccSSascha Wildner 	return (rval) ? &_pw_passwd : NULL;
317*a43287ccSSascha Wildner }
318*a43287ccSSascha Wildner 
319*a43287ccSSascha Wildner static int
gi_setpassent(int stayopen)320*a43287ccSSascha Wildner gi_setpassent(int stayopen)
321*a43287ccSSascha Wildner {
322*a43287ccSSascha Wildner 
323*a43287ccSSascha Wildner 	if (!pwstart())
324*a43287ccSSascha Wildner 		return 0;
325*a43287ccSSascha Wildner 	_pw_stayopen = stayopen;
326*a43287ccSSascha Wildner 	return 1;
327*a43287ccSSascha Wildner }
328*a43287ccSSascha Wildner 
329*a43287ccSSascha Wildner static void
gi_endpwent(void)330*a43287ccSSascha Wildner gi_endpwent(void)
331*a43287ccSSascha Wildner {
332*a43287ccSSascha Wildner 
333*a43287ccSSascha Wildner 	_pw_filesdone = 0;
334*a43287ccSSascha Wildner 	if (_pw_fp) {
335*a43287ccSSascha Wildner 		(void)fclose(_pw_fp);
336*a43287ccSSascha Wildner 		_pw_fp = NULL;
337*a43287ccSSascha Wildner 	}
338*a43287ccSSascha Wildner }
339*a43287ccSSascha Wildner 
340*a43287ccSSascha Wildner static int
pwstart(void)341*a43287ccSSascha Wildner pwstart(void)
342*a43287ccSSascha Wildner {
343*a43287ccSSascha Wildner 
344*a43287ccSSascha Wildner 	_pw_filesdone = 0;
345*a43287ccSSascha Wildner 	if (_pw_fp) {
346*a43287ccSSascha Wildner 		rewind(_pw_fp);
347*a43287ccSSascha Wildner 		return 1;
348*a43287ccSSascha Wildner 	}
349*a43287ccSSascha Wildner 	if (pwfile[0] == '\0')			/* sanity check */
350*a43287ccSSascha Wildner 		return 0;
351*a43287ccSSascha Wildner 	_pw_fp = fopen(pwfile, "r");
352*a43287ccSSascha Wildner 	if (_pw_fp != NULL)
353*a43287ccSSascha Wildner 		return 1;
354*a43287ccSSascha Wildner 	warn("Can't open `%s'", pwfile);
355*a43287ccSSascha Wildner 	return 0;
356*a43287ccSSascha Wildner }
357*a43287ccSSascha Wildner 
358*a43287ccSSascha Wildner 
359*a43287ccSSascha Wildner static int
pwscan(int search,uid_t uid,const char * name)360*a43287ccSSascha Wildner pwscan(int search, uid_t uid, const char *name)
361*a43287ccSSascha Wildner {
362*a43287ccSSascha Wildner 
363*a43287ccSSascha Wildner 	if (_pw_filesdone)
364*a43287ccSSascha Wildner 		return 0;
365*a43287ccSSascha Wildner 	for (;;) {
366*a43287ccSSascha Wildner 		if (!fgets(pwline, sizeof(pwline), _pw_fp)) {
367*a43287ccSSascha Wildner 			if (!search)
368*a43287ccSSascha Wildner 				_pw_filesdone = 1;
369*a43287ccSSascha Wildner 			return 0;
370*a43287ccSSascha Wildner 		}
371*a43287ccSSascha Wildner 		/* skip lines that are too big */
372*a43287ccSSascha Wildner 		if (!strchr(pwline, '\n')) {
373*a43287ccSSascha Wildner 			int ch;
374*a43287ccSSascha Wildner 
375*a43287ccSSascha Wildner 			while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
376*a43287ccSSascha Wildner 				;
377*a43287ccSSascha Wildner 			continue;
378*a43287ccSSascha Wildner 		}
379*a43287ccSSascha Wildner 		/* skip comments */
380*a43287ccSSascha Wildner 		if (pwline[0] == '#')
381*a43287ccSSascha Wildner 			continue;
382*a43287ccSSascha Wildner 		if (pwmatchline(search, uid, name))
383*a43287ccSSascha Wildner 			return 1;
384*a43287ccSSascha Wildner 	}
385*a43287ccSSascha Wildner 	/* NOTREACHED */
386*a43287ccSSascha Wildner }
387*a43287ccSSascha Wildner 
388*a43287ccSSascha Wildner static int
pwmatchline(int search,uid_t uid,const char * name)389*a43287ccSSascha Wildner pwmatchline(int search, uid_t uid, const char *name)
390*a43287ccSSascha Wildner {
391*a43287ccSSascha Wildner 	unsigned long	id;
392*a43287ccSSascha Wildner 	char		*cp, *bp, *ep;
393*a43287ccSSascha Wildner 
394*a43287ccSSascha Wildner 	/* name may be NULL if search is nonzero */
395*a43287ccSSascha Wildner 
396*a43287ccSSascha Wildner 	bp = pwline;
397*a43287ccSSascha Wildner 	memset(&_pw_passwd, 0, sizeof(_pw_passwd));
398*a43287ccSSascha Wildner 	_pw_passwd.pw_name = strsep(&bp, ":\n");		/* name */
399*a43287ccSSascha Wildner 	if (search && name && strcmp(_pw_passwd.pw_name, name))
400*a43287ccSSascha Wildner 		return 0;
401*a43287ccSSascha Wildner 
402*a43287ccSSascha Wildner 	_pw_passwd.pw_passwd = strsep(&bp, ":\n");		/* passwd */
403*a43287ccSSascha Wildner 
404*a43287ccSSascha Wildner 	if (!(cp = strsep(&bp, ":\n")))				/* uid */
405*a43287ccSSascha Wildner 		return 0;
406*a43287ccSSascha Wildner 	id = strtoul(cp, &ep, 10);
407*a43287ccSSascha Wildner 	if (id > UID_MAX || *ep != '\0')
408*a43287ccSSascha Wildner 		return 0;
409*a43287ccSSascha Wildner 	_pw_passwd.pw_uid = (uid_t)id;
410*a43287ccSSascha Wildner 	if (search && name == NULL && _pw_passwd.pw_uid != uid)
411*a43287ccSSascha Wildner 		return 0;
412*a43287ccSSascha Wildner 
413*a43287ccSSascha Wildner 	if (!(cp = strsep(&bp, ":\n")))				/* gid */
414*a43287ccSSascha Wildner 		return 0;
415*a43287ccSSascha Wildner 	id = strtoul(cp, &ep, 10);
416*a43287ccSSascha Wildner 	if (id > GID_MAX || *ep != '\0')
417*a43287ccSSascha Wildner 		return 0;
418*a43287ccSSascha Wildner 	_pw_passwd.pw_gid = (gid_t)id;
419*a43287ccSSascha Wildner 
420*a43287ccSSascha Wildner 	if (!(ep = strsep(&bp, ":")))				/* class */
421*a43287ccSSascha Wildner 		return 0;
422*a43287ccSSascha Wildner 	if (!(ep = strsep(&bp, ":")))				/* change */
423*a43287ccSSascha Wildner 		return 0;
424*a43287ccSSascha Wildner 	if (!(ep = strsep(&bp, ":")))				/* expire */
425*a43287ccSSascha Wildner 		return 0;
426*a43287ccSSascha Wildner 
427*a43287ccSSascha Wildner 	if (!(_pw_passwd.pw_gecos = strsep(&bp, ":\n")))	/* gecos */
428*a43287ccSSascha Wildner 		return 0;
429*a43287ccSSascha Wildner 	if (!(_pw_passwd.pw_dir = strsep(&bp, ":\n")))		/* directory */
430*a43287ccSSascha Wildner 		return 0;
431*a43287ccSSascha Wildner 	if (!(_pw_passwd.pw_shell = strsep(&bp, ":\n")))	/* shell */
432*a43287ccSSascha Wildner 		return 0;
433*a43287ccSSascha Wildner 
434*a43287ccSSascha Wildner 	if (strchr(bp, ':') != NULL)
435*a43287ccSSascha Wildner 		return 0;
436*a43287ccSSascha Wildner 
437*a43287ccSSascha Wildner 	return 1;
438*a43287ccSSascha Wildner }
439*a43287ccSSascha Wildner 
440