1*52110e02Sthorpej /*	$NetBSD: bootparamd.c,v 1.7 1996/08/30 20:10:26 thorpej Exp $	*/
2*52110e02Sthorpej 
3ae99bc57Sderaadt /*
4ae99bc57Sderaadt  * This code is not copyright, and is placed in the public domain.
5ae99bc57Sderaadt  * Feel free to use and modify. Please send modifications and/or
6ae99bc57Sderaadt  * suggestions + bug fixes to Klas Heggemann <klas@nada.kth.se>
7ae99bc57Sderaadt  *
8ae99bc57Sderaadt  * Various small changes by Theo de Raadt <deraadt@fsa.ca>
90d8ec8d0Sderaadt  * Parser rewritten (adding YP support) by Roland McGrath <roland@frob.com>
10ae99bc57Sderaadt  */
11ae99bc57Sderaadt 
12ae99bc57Sderaadt #include <sys/types.h>
13ae99bc57Sderaadt #include <sys/ioctl.h>
14ae99bc57Sderaadt #include <sys/stat.h>
15ae99bc57Sderaadt #include <sys/socket.h>
16ae99bc57Sderaadt #include <rpc/rpc.h>
17ae99bc57Sderaadt #include <rpcsvc/bootparam_prot.h>
18ae99bc57Sderaadt #include <stdio.h>
19ae99bc57Sderaadt #include <netdb.h>
20ae99bc57Sderaadt #include <ctype.h>
21ae99bc57Sderaadt #include <syslog.h>
220d8ec8d0Sderaadt #include <string.h>
230d8ec8d0Sderaadt #include "pathnames.h"
24ae99bc57Sderaadt 
25ae99bc57Sderaadt #define MAXLEN 800
26ae99bc57Sderaadt 
27ae99bc57Sderaadt struct hostent *he;
28ae99bc57Sderaadt static char buffer[MAXLEN];
29ae99bc57Sderaadt static char hostname[MAX_MACHINE_NAME];
30ae99bc57Sderaadt static char askname[MAX_MACHINE_NAME];
31ae99bc57Sderaadt static char path[MAX_PATH_LEN];
32ae99bc57Sderaadt static char domain_name[MAX_MACHINE_NAME];
33ae99bc57Sderaadt 
34d8f00aa3Spk extern void bootparamprog_1 __P((struct svc_req *, SVCXPRT *));
35ae99bc57Sderaadt 
36d8f00aa3Spk int	_rpcsvcdirty = 0;
37d8f00aa3Spk int	_rpcpmstart = 0;
38ae99bc57Sderaadt int     debug = 0;
39ae99bc57Sderaadt int     dolog = 0;
40ae99bc57Sderaadt unsigned long route_addr, inet_addr();
41ae99bc57Sderaadt struct sockaddr_in my_addr;
42ae99bc57Sderaadt char   *progname;
430d8ec8d0Sderaadt char   *bootpfile = _PATH_BOOTPARAMS;
44ae99bc57Sderaadt 
45ae99bc57Sderaadt extern char *optarg;
46ae99bc57Sderaadt extern int optind;
47ae99bc57Sderaadt 
48ae99bc57Sderaadt void
49ae99bc57Sderaadt usage()
50ae99bc57Sderaadt {
51ae99bc57Sderaadt 	fprintf(stderr,
52ae99bc57Sderaadt 	    "usage: rpc.bootparamd [-d] [-s] [-r router] [-f bootparmsfile]\n");
53ae99bc57Sderaadt }
54ae99bc57Sderaadt 
55ae99bc57Sderaadt 
56ae99bc57Sderaadt /*
57ae99bc57Sderaadt  * ever familiar
58ae99bc57Sderaadt  */
59ae99bc57Sderaadt int
60ae99bc57Sderaadt main(argc, argv)
61ae99bc57Sderaadt 	int     argc;
62ae99bc57Sderaadt 	char  **argv;
63ae99bc57Sderaadt {
64ae99bc57Sderaadt 	SVCXPRT *transp;
65ae99bc57Sderaadt 	int     i, s, pid;
66ae99bc57Sderaadt 	char   *rindex();
67ae99bc57Sderaadt 	struct hostent *he;
68ae99bc57Sderaadt 	struct stat buf;
69ae99bc57Sderaadt 	char   *optstring;
70d907c076Smark 	int    c;
71ae99bc57Sderaadt 
72ae99bc57Sderaadt 	progname = rindex(argv[0], '/');
73ae99bc57Sderaadt 	if (progname)
74ae99bc57Sderaadt 		progname++;
75ae99bc57Sderaadt 	else
76ae99bc57Sderaadt 		progname = argv[0];
77ae99bc57Sderaadt 
78d907c076Smark 	while ((c = getopt(argc, argv, "dsr:f:")) != -1)
79ae99bc57Sderaadt 		switch (c) {
80ae99bc57Sderaadt 		case 'd':
81ae99bc57Sderaadt 			debug = 1;
82ae99bc57Sderaadt 			break;
83ae99bc57Sderaadt 		case 'r':
84ae99bc57Sderaadt 			if (isdigit(*optarg)) {
85ae99bc57Sderaadt 				route_addr = inet_addr(optarg);
86ae99bc57Sderaadt 				break;
87ae99bc57Sderaadt 			}
88ae99bc57Sderaadt 			he = gethostbyname(optarg);
89ae99bc57Sderaadt 			if (!he) {
90ae99bc57Sderaadt 				fprintf(stderr, "%s: No such host %s\n",
91ae99bc57Sderaadt 				    progname, optarg);
92ae99bc57Sderaadt 				usage();
93ae99bc57Sderaadt 				exit(1);
94ae99bc57Sderaadt 			}
95ae99bc57Sderaadt 			bcopy(he->h_addr, (char *) &route_addr, sizeof(route_addr));
96ae99bc57Sderaadt 			break;
97ae99bc57Sderaadt 		case 'f':
98ae99bc57Sderaadt 			bootpfile = optarg;
99ae99bc57Sderaadt 			break;
100ae99bc57Sderaadt 		case 's':
101ae99bc57Sderaadt 			dolog = 1;
102ae99bc57Sderaadt #ifndef LOG_DAEMON
103ae99bc57Sderaadt 			openlog(progname, 0, 0);
104ae99bc57Sderaadt #else
105ae99bc57Sderaadt 			openlog(progname, 0, LOG_DAEMON);
106ae99bc57Sderaadt 			setlogmask(LOG_UPTO(LOG_NOTICE));
107ae99bc57Sderaadt #endif
108ae99bc57Sderaadt 			break;
109ae99bc57Sderaadt 		default:
110ae99bc57Sderaadt 			usage();
111ae99bc57Sderaadt 			exit(1);
112ae99bc57Sderaadt 		}
113ae99bc57Sderaadt 
114ae99bc57Sderaadt 	if (stat(bootpfile, &buf)) {
115ae99bc57Sderaadt 		fprintf(stderr, "%s: ", progname);
116ae99bc57Sderaadt 		perror(bootpfile);
117ae99bc57Sderaadt 		exit(1);
118ae99bc57Sderaadt 	}
119ae99bc57Sderaadt 	if (!route_addr) {
120ae99bc57Sderaadt 		get_myaddress(&my_addr);
121ae99bc57Sderaadt 		bcopy(&my_addr.sin_addr.s_addr, &route_addr, sizeof(route_addr));
122ae99bc57Sderaadt 	}
123ae99bc57Sderaadt 	if (!debug)
124ae99bc57Sderaadt 		daemon();
125ae99bc57Sderaadt 
126ae99bc57Sderaadt 	(void) pmap_unset(BOOTPARAMPROG, BOOTPARAMVERS);
127ae99bc57Sderaadt 
128ae99bc57Sderaadt 	transp = svcudp_create(RPC_ANYSOCK);
129ae99bc57Sderaadt 	if (transp == NULL) {
130ae99bc57Sderaadt 		fprintf(stderr, "cannot create udp service.\n");
131ae99bc57Sderaadt 		exit(1);
132ae99bc57Sderaadt 	}
133ae99bc57Sderaadt 	if (!svc_register(transp, BOOTPARAMPROG, BOOTPARAMVERS,
134ae99bc57Sderaadt 		bootparamprog_1, IPPROTO_UDP)) {
135ae99bc57Sderaadt 		fprintf(stderr,
136ae99bc57Sderaadt 		    "bootparamd: unable to register BOOTPARAMPROG version %d, udp)\n",
137ae99bc57Sderaadt 		    BOOTPARAMVERS);
138ae99bc57Sderaadt 		exit(1);
139ae99bc57Sderaadt 	}
140ae99bc57Sderaadt 	svc_run();
141ae99bc57Sderaadt 	fprintf(stderr, "svc_run returned\n");
142ae99bc57Sderaadt 	exit(1);
143ae99bc57Sderaadt }
144ae99bc57Sderaadt 
145ae99bc57Sderaadt bp_whoami_res *
146d8f00aa3Spk bootparamproc_whoami_1_svc(whoami, rqstp)
147ae99bc57Sderaadt 	bp_whoami_arg *whoami;
148d8f00aa3Spk 	struct svc_req *rqstp;
149ae99bc57Sderaadt {
150ae99bc57Sderaadt 	long    haddr;
151ae99bc57Sderaadt 	static bp_whoami_res res;
1520d8ec8d0Sderaadt 
153ae99bc57Sderaadt 	if (debug)
154ae99bc57Sderaadt 		fprintf(stderr, "whoami got question for %d.%d.%d.%d\n",
155ae99bc57Sderaadt 		    255 & whoami->client_address.bp_address_u.ip_addr.net,
156ae99bc57Sderaadt 		    255 & whoami->client_address.bp_address_u.ip_addr.host,
157ae99bc57Sderaadt 		    255 & whoami->client_address.bp_address_u.ip_addr.lh,
158ae99bc57Sderaadt 		    255 & whoami->client_address.bp_address_u.ip_addr.impno);
159ae99bc57Sderaadt 	if (dolog)
160ae99bc57Sderaadt 		syslog(LOG_NOTICE, "whoami got question for %d.%d.%d.%d\n",
161ae99bc57Sderaadt 		    255 & whoami->client_address.bp_address_u.ip_addr.net,
162ae99bc57Sderaadt 		    255 & whoami->client_address.bp_address_u.ip_addr.host,
163ae99bc57Sderaadt 		    255 & whoami->client_address.bp_address_u.ip_addr.lh,
164ae99bc57Sderaadt 		    255 & whoami->client_address.bp_address_u.ip_addr.impno);
165ae99bc57Sderaadt 
166ae99bc57Sderaadt 	bcopy((char *) &whoami->client_address.bp_address_u.ip_addr, (char *) &haddr,
167ae99bc57Sderaadt 	    sizeof(haddr));
168ae99bc57Sderaadt 	he = gethostbyaddr((char *) &haddr, sizeof(haddr), AF_INET);
169ae99bc57Sderaadt 	if (!he)
170ae99bc57Sderaadt 		goto failed;
171ae99bc57Sderaadt 
172ae99bc57Sderaadt 	if (debug)
173ae99bc57Sderaadt 		fprintf(stderr, "This is host %s\n", he->h_name);
174ae99bc57Sderaadt 	if (dolog)
175ae99bc57Sderaadt 		syslog(LOG_NOTICE, "This is host %s\n", he->h_name);
176ae99bc57Sderaadt 
177ae99bc57Sderaadt 	strcpy(askname, he->h_name);
1780d8ec8d0Sderaadt 	if (!lookup_bootparam(askname, hostname, NULL, NULL, NULL)) {
179ae99bc57Sderaadt 		res.client_name = hostname;
180ae99bc57Sderaadt 		getdomainname(domain_name, MAX_MACHINE_NAME);
181ae99bc57Sderaadt 		res.domain_name = domain_name;
182ae99bc57Sderaadt 
183ae99bc57Sderaadt 		if (res.router_address.address_type != IP_ADDR_TYPE) {
184ae99bc57Sderaadt 			res.router_address.address_type = IP_ADDR_TYPE;
185ae99bc57Sderaadt 			bcopy(&route_addr, &res.router_address.bp_address_u.ip_addr, 4);
186ae99bc57Sderaadt 		}
187ae99bc57Sderaadt 		if (debug)
188ae99bc57Sderaadt 			fprintf(stderr, "Returning %s   %s    %d.%d.%d.%d\n",
189ae99bc57Sderaadt 			    res.client_name, res.domain_name,
190ae99bc57Sderaadt 			    255 & res.router_address.bp_address_u.ip_addr.net,
191ae99bc57Sderaadt 			    255 & res.router_address.bp_address_u.ip_addr.host,
192ae99bc57Sderaadt 			    255 & res.router_address.bp_address_u.ip_addr.lh,
193ae99bc57Sderaadt 			    255 & res.router_address.bp_address_u.ip_addr.impno);
194ae99bc57Sderaadt 		if (dolog)
195ae99bc57Sderaadt 			syslog(LOG_NOTICE, "Returning %s   %s    %d.%d.%d.%d\n",
196ae99bc57Sderaadt 			    res.client_name, res.domain_name,
197ae99bc57Sderaadt 			    255 & res.router_address.bp_address_u.ip_addr.net,
198ae99bc57Sderaadt 			    255 & res.router_address.bp_address_u.ip_addr.host,
199ae99bc57Sderaadt 			    255 & res.router_address.bp_address_u.ip_addr.lh,
200ae99bc57Sderaadt 			    255 & res.router_address.bp_address_u.ip_addr.impno);
201ae99bc57Sderaadt 
202ae99bc57Sderaadt 		return (&res);
203ae99bc57Sderaadt 	}
204ae99bc57Sderaadt failed:
205ae99bc57Sderaadt 	if (debug)
206ae99bc57Sderaadt 		fprintf(stderr, "whoami failed\n");
207ae99bc57Sderaadt 	if (dolog)
208ae99bc57Sderaadt 		syslog(LOG_NOTICE, "whoami failed\n");
209ae99bc57Sderaadt 	return (NULL);
210ae99bc57Sderaadt }
211ae99bc57Sderaadt 
212ae99bc57Sderaadt 
213ae99bc57Sderaadt bp_getfile_res *
214d8f00aa3Spk bootparamproc_getfile_1_svc(getfile, rqstp)
215ae99bc57Sderaadt 	bp_getfile_arg *getfile;
216d8f00aa3Spk 	struct svc_req *rqstp;
217ae99bc57Sderaadt {
218ae99bc57Sderaadt 	char   *where, *index();
219ae99bc57Sderaadt 	static bp_getfile_res res;
2200d8ec8d0Sderaadt 	int     err;
221ae99bc57Sderaadt 
222ae99bc57Sderaadt 	if (debug)
223ae99bc57Sderaadt 		fprintf(stderr, "getfile got question for \"%s\" and file \"%s\"\n",
224ae99bc57Sderaadt 		    getfile->client_name, getfile->file_id);
225ae99bc57Sderaadt 
226ae99bc57Sderaadt 	if (dolog)
227ae99bc57Sderaadt 		syslog(LOG_NOTICE, "getfile got question for \"%s\" and file \"%s\"\n",
228ae99bc57Sderaadt 		    getfile->client_name, getfile->file_id);
229ae99bc57Sderaadt 
230ae99bc57Sderaadt 	he = NULL;
231ae99bc57Sderaadt 	he = gethostbyname(getfile->client_name);
232ae99bc57Sderaadt 	if (!he)
233ae99bc57Sderaadt 		goto failed;
234ae99bc57Sderaadt 
235ae99bc57Sderaadt 	strcpy(askname, he->h_name);
2360d8ec8d0Sderaadt 	err = lookup_bootparam(askname, NULL, getfile->file_id,
2370d8ec8d0Sderaadt 	    &res.server_name, &res.server_path);
2380d8ec8d0Sderaadt 	if (err == 0) {
2390d8ec8d0Sderaadt 		he = gethostbyname(res.server_name);
240ae99bc57Sderaadt 		if (!he)
241ae99bc57Sderaadt 			goto failed;
242ae99bc57Sderaadt 		bcopy(he->h_addr, &res.server_address.bp_address_u.ip_addr, 4);
243ae99bc57Sderaadt 		res.server_address.address_type = IP_ADDR_TYPE;
2440d8ec8d0Sderaadt 	} else if (err == ENOENT && !strcmp(getfile->file_id, "dump")) {
2450d8ec8d0Sderaadt 		/* Special for dump, answer with null strings. */
246ae99bc57Sderaadt 		res.server_name[0] = '\0';
247ae99bc57Sderaadt 		res.server_path[0] = '\0';
248ae99bc57Sderaadt 		bzero(&res.server_address.bp_address_u.ip_addr, 4);
2490d8ec8d0Sderaadt 	} else {
2500d8ec8d0Sderaadt failed:
2510d8ec8d0Sderaadt 		if (debug)
2520d8ec8d0Sderaadt 			fprintf(stderr, "getfile failed for %s\n",
2530d8ec8d0Sderaadt 			    getfile->client_name);
2540d8ec8d0Sderaadt 		if (dolog)
2550d8ec8d0Sderaadt 			syslog(LOG_NOTICE,
2560d8ec8d0Sderaadt 			    "getfile failed for %s\n", getfile->client_name);
2570d8ec8d0Sderaadt 		return (NULL);
258ae99bc57Sderaadt 	}
2590d8ec8d0Sderaadt 
260ae99bc57Sderaadt 	if (debug)
261ae99bc57Sderaadt 		fprintf(stderr,
262ae99bc57Sderaadt 		    "returning server:%s path:%s address: %d.%d.%d.%d\n",
263ae99bc57Sderaadt 		    res.server_name, res.server_path,
264ae99bc57Sderaadt 		    255 & res.server_address.bp_address_u.ip_addr.net,
265ae99bc57Sderaadt 		    255 & res.server_address.bp_address_u.ip_addr.host,
266ae99bc57Sderaadt 		    255 & res.server_address.bp_address_u.ip_addr.lh,
267ae99bc57Sderaadt 		    255 & res.server_address.bp_address_u.ip_addr.impno);
268ae99bc57Sderaadt 	if (dolog)
269ae99bc57Sderaadt 		syslog(LOG_NOTICE,
270ae99bc57Sderaadt 		    "returning server:%s path:%s address: %d.%d.%d.%d\n",
271ae99bc57Sderaadt 		    res.server_name, res.server_path,
272ae99bc57Sderaadt 		    255 & res.server_address.bp_address_u.ip_addr.net,
273ae99bc57Sderaadt 		    255 & res.server_address.bp_address_u.ip_addr.host,
274ae99bc57Sderaadt 		    255 & res.server_address.bp_address_u.ip_addr.lh,
275ae99bc57Sderaadt 		    255 & res.server_address.bp_address_u.ip_addr.impno);
276ae99bc57Sderaadt 	return (&res);
277ae99bc57Sderaadt }
278ae99bc57Sderaadt 
279ae99bc57Sderaadt 
2800d8ec8d0Sderaadt int
2810d8ec8d0Sderaadt lookup_bootparam(client, client_canonical, id, server, path)
2820d8ec8d0Sderaadt 	char	*client;
2830d8ec8d0Sderaadt 	char	*client_canonical;
2840d8ec8d0Sderaadt 	char	*id;
2850d8ec8d0Sderaadt 	char	**server;
2860d8ec8d0Sderaadt 	char	**path;
287ae99bc57Sderaadt {
2880d8ec8d0Sderaadt 	FILE   *f = fopen(bootpfile, "r");
2890d8ec8d0Sderaadt #ifdef YP
2900d8ec8d0Sderaadt 	static char *ypbuf = NULL;
2910d8ec8d0Sderaadt 	static int ypbuflen = 0;
2920d8ec8d0Sderaadt #endif
2930d8ec8d0Sderaadt 	static char buf[BUFSIZ];
2940d8ec8d0Sderaadt 	char   *bp, *word;
2950d8ec8d0Sderaadt 	size_t  idlen = id == NULL ? 0 : strlen(id);
2960d8ec8d0Sderaadt 	int     contin = 0;
2970d8ec8d0Sderaadt 	int     found = 0;
298ae99bc57Sderaadt 
2990d8ec8d0Sderaadt 	if (f == NULL)
3000d8ec8d0Sderaadt 		return EINVAL;	/* ? */
301ae99bc57Sderaadt 
3020d8ec8d0Sderaadt 	while (fgets(buf, sizeof buf, f)) {
3030d8ec8d0Sderaadt 		int     wascontin = contin;
3040d8ec8d0Sderaadt 		contin = buf[strlen(buf) - 2] == '\\';
3050d8ec8d0Sderaadt 		bp = buf + strspn(buf, " \t\n");
306ae99bc57Sderaadt 
3070d8ec8d0Sderaadt 		switch (wascontin) {
3080d8ec8d0Sderaadt 		case -1:
3090d8ec8d0Sderaadt 			/* Continuation of uninteresting line */
3100d8ec8d0Sderaadt 			contin *= -1;
311ae99bc57Sderaadt 			continue;
3120d8ec8d0Sderaadt 		case 0:
3130d8ec8d0Sderaadt 			/* New line */
3140d8ec8d0Sderaadt 			contin *= -1;
3150d8ec8d0Sderaadt 			if (*bp == '#')
3160d8ec8d0Sderaadt 				continue;
3170d8ec8d0Sderaadt 			if ((word = strsep(&bp, " \t\n")) == NULL)
3180d8ec8d0Sderaadt 				continue;
3190d8ec8d0Sderaadt #ifdef YP
3200d8ec8d0Sderaadt 			/* A + in the file means try YP now */
3210d8ec8d0Sderaadt 			if (!strcmp(word, "+")) {
3220d8ec8d0Sderaadt 				char   *ypdom;
3230d8ec8d0Sderaadt 
3240d8ec8d0Sderaadt 				if (yp_get_default_domain(&ypdom) ||
3250d8ec8d0Sderaadt 				    yp_match(ypdom, "bootparams", client,
3260d8ec8d0Sderaadt 					strlen(client), &ypbuf, &ypbuflen))
3270d8ec8d0Sderaadt 					continue;
3280d8ec8d0Sderaadt 				bp = ypbuf;
3290d8ec8d0Sderaadt 				word = client;
3300d8ec8d0Sderaadt 				contin *= -1;
331ae99bc57Sderaadt 				break;
332ae99bc57Sderaadt 			}
3330d8ec8d0Sderaadt #endif
3340d8ec8d0Sderaadt 			/* See if this line's client is the one we are
3350d8ec8d0Sderaadt 			 * looking for */
3360d8ec8d0Sderaadt 			if (strcmp(word, client) != 0) {
337ae99bc57Sderaadt 				/*
3380d8ec8d0Sderaadt 				 * If it didn't match, try getting the
3390d8ec8d0Sderaadt 				 * canonical host name of the client
3400d8ec8d0Sderaadt 				 * on this line and comparing that to
3410d8ec8d0Sderaadt 				 * the client we are looking for
342ae99bc57Sderaadt 				 */
3430d8ec8d0Sderaadt 				struct hostent *hp = gethostbyname(word);
344031bfeccSderaadt 				if (hp == NULL || strcmp(hp->h_name, client))
3450d8ec8d0Sderaadt 					continue;
3460d8ec8d0Sderaadt 			}
3470d8ec8d0Sderaadt 			contin *= -1;
3480d8ec8d0Sderaadt 			break;
3490d8ec8d0Sderaadt 		case 1:
3500d8ec8d0Sderaadt 			/* Continued line we want to parse below */
3510d8ec8d0Sderaadt 			break;
3520d8ec8d0Sderaadt 		}
353ae99bc57Sderaadt 
3540d8ec8d0Sderaadt 		if (client_canonical)
3550d8ec8d0Sderaadt 			strncpy(client_canonical, word, MAX_MACHINE_NAME);
3560d8ec8d0Sderaadt 
3570d8ec8d0Sderaadt 		/* We have found a line for CLIENT */
358f392a261Sglass 		if (id == NULL) {
359f392a261Sglass 			(void) fclose(f);
3600d8ec8d0Sderaadt 			return 0;
361f392a261Sglass 		}
3620d8ec8d0Sderaadt 
3630d8ec8d0Sderaadt 		/* Look for a value for the parameter named by ID */
3640d8ec8d0Sderaadt 		while ((word = strsep(&bp, " \t\n")) != NULL) {
3650d8ec8d0Sderaadt 			if (!strncmp(word, id, idlen) && word[idlen] == '=') {
3660d8ec8d0Sderaadt 				/* We have found the entry we want */
3670d8ec8d0Sderaadt 				*server = &word[idlen + 1];
3680d8ec8d0Sderaadt 				*path = strchr(*server, ':');
3690d8ec8d0Sderaadt 				if (*path == NULL)
3700d8ec8d0Sderaadt 					/* Malformed entry */
3710d8ec8d0Sderaadt 					continue;
3720d8ec8d0Sderaadt 				*(*path)++ = '\0';
3730d8ec8d0Sderaadt 				(void) fclose(f);
3740d8ec8d0Sderaadt 				return 0;
375ae99bc57Sderaadt 			}
376ae99bc57Sderaadt 		}
3770d8ec8d0Sderaadt 
3780d8ec8d0Sderaadt 		found = 1;
379ae99bc57Sderaadt 	}
3800d8ec8d0Sderaadt 
3810d8ec8d0Sderaadt 	(void) fclose(f);
3820d8ec8d0Sderaadt 	return found ? ENOENT : EPERM;
383ae99bc57Sderaadt }
384