1*b7dcf10eScgd /*	$NetBSD: bootparamd.c,v 1.9 1996/10/14 19:28:09 cgd Exp $	*/
252110e02Sthorpej 
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>
23*b7dcf10eScgd #include <arpa/inet.h>
240d8ec8d0Sderaadt #include "pathnames.h"
25ae99bc57Sderaadt 
26ae99bc57Sderaadt #define MAXLEN 800
27ae99bc57Sderaadt 
28ae99bc57Sderaadt static char hostname[MAX_MACHINE_NAME];
29ae99bc57Sderaadt static char askname[MAX_MACHINE_NAME];
30ae99bc57Sderaadt static char domain_name[MAX_MACHINE_NAME];
31ae99bc57Sderaadt 
32d8f00aa3Spk extern void bootparamprog_1 __P((struct svc_req *, SVCXPRT *));
33ae99bc57Sderaadt 
34d8f00aa3Spk int	_rpcsvcdirty = 0;
35d8f00aa3Spk int	_rpcpmstart = 0;
36ae99bc57Sderaadt int     debug = 0;
37ae99bc57Sderaadt int     dolog = 0;
38ae99bc57Sderaadt unsigned long route_addr, inet_addr();
39ae99bc57Sderaadt struct sockaddr_in my_addr;
40ae99bc57Sderaadt char   *progname;
410d8ec8d0Sderaadt char   *bootpfile = _PATH_BOOTPARAMS;
42ae99bc57Sderaadt 
43ae99bc57Sderaadt extern char *optarg;
44ae99bc57Sderaadt extern int optind;
45ae99bc57Sderaadt 
46ae99bc57Sderaadt void
47ae99bc57Sderaadt usage()
48ae99bc57Sderaadt {
49ae99bc57Sderaadt 	fprintf(stderr,
50ae99bc57Sderaadt 	    "usage: rpc.bootparamd [-d] [-s] [-r router] [-f bootparmsfile]\n");
51ae99bc57Sderaadt }
52ae99bc57Sderaadt 
53ae99bc57Sderaadt 
54ae99bc57Sderaadt /*
55ae99bc57Sderaadt  * ever familiar
56ae99bc57Sderaadt  */
57ae99bc57Sderaadt int
58ae99bc57Sderaadt main(argc, argv)
59ae99bc57Sderaadt 	int     argc;
60ae99bc57Sderaadt 	char  **argv;
61ae99bc57Sderaadt {
62ae99bc57Sderaadt 	SVCXPRT *transp;
63ae99bc57Sderaadt 	struct hostent *he;
64ae99bc57Sderaadt 	struct stat buf;
65d907c076Smark 	int    c;
66ae99bc57Sderaadt 
67ae99bc57Sderaadt 	progname = rindex(argv[0], '/');
68ae99bc57Sderaadt 	if (progname)
69ae99bc57Sderaadt 		progname++;
70ae99bc57Sderaadt 	else
71ae99bc57Sderaadt 		progname = argv[0];
72ae99bc57Sderaadt 
73d907c076Smark 	while ((c = getopt(argc, argv, "dsr:f:")) != -1)
74ae99bc57Sderaadt 		switch (c) {
75ae99bc57Sderaadt 		case 'd':
76ae99bc57Sderaadt 			debug = 1;
77ae99bc57Sderaadt 			break;
78ae99bc57Sderaadt 		case 'r':
79ae99bc57Sderaadt 			if (isdigit(*optarg)) {
80ae99bc57Sderaadt 				route_addr = inet_addr(optarg);
81ae99bc57Sderaadt 				break;
82ae99bc57Sderaadt 			}
83ae99bc57Sderaadt 			he = gethostbyname(optarg);
84ae99bc57Sderaadt 			if (!he) {
85ae99bc57Sderaadt 				fprintf(stderr, "%s: No such host %s\n",
86ae99bc57Sderaadt 				    progname, optarg);
87ae99bc57Sderaadt 				usage();
88ae99bc57Sderaadt 				exit(1);
89ae99bc57Sderaadt 			}
90ae99bc57Sderaadt 			bcopy(he->h_addr, (char *) &route_addr, sizeof(route_addr));
91ae99bc57Sderaadt 			break;
92ae99bc57Sderaadt 		case 'f':
93ae99bc57Sderaadt 			bootpfile = optarg;
94ae99bc57Sderaadt 			break;
95ae99bc57Sderaadt 		case 's':
96ae99bc57Sderaadt 			dolog = 1;
97ae99bc57Sderaadt #ifndef LOG_DAEMON
98ae99bc57Sderaadt 			openlog(progname, 0, 0);
99ae99bc57Sderaadt #else
100ae99bc57Sderaadt 			openlog(progname, 0, LOG_DAEMON);
101ae99bc57Sderaadt 			setlogmask(LOG_UPTO(LOG_NOTICE));
102ae99bc57Sderaadt #endif
103ae99bc57Sderaadt 			break;
104ae99bc57Sderaadt 		default:
105ae99bc57Sderaadt 			usage();
106ae99bc57Sderaadt 			exit(1);
107ae99bc57Sderaadt 		}
108ae99bc57Sderaadt 
109ae99bc57Sderaadt 	if (stat(bootpfile, &buf)) {
110ae99bc57Sderaadt 		fprintf(stderr, "%s: ", progname);
111ae99bc57Sderaadt 		perror(bootpfile);
112ae99bc57Sderaadt 		exit(1);
113ae99bc57Sderaadt 	}
114ae99bc57Sderaadt 	if (!route_addr) {
115ae99bc57Sderaadt 		get_myaddress(&my_addr);
116ae99bc57Sderaadt 		bcopy(&my_addr.sin_addr.s_addr, &route_addr, sizeof(route_addr));
117ae99bc57Sderaadt 	}
118ae99bc57Sderaadt 	if (!debug)
119ae99bc57Sderaadt 		daemon();
120ae99bc57Sderaadt 
121ae99bc57Sderaadt 	(void) pmap_unset(BOOTPARAMPROG, BOOTPARAMVERS);
122ae99bc57Sderaadt 
123ae99bc57Sderaadt 	transp = svcudp_create(RPC_ANYSOCK);
124ae99bc57Sderaadt 	if (transp == NULL) {
125ae99bc57Sderaadt 		fprintf(stderr, "cannot create udp service.\n");
126ae99bc57Sderaadt 		exit(1);
127ae99bc57Sderaadt 	}
128ae99bc57Sderaadt 	if (!svc_register(transp, BOOTPARAMPROG, BOOTPARAMVERS,
129ae99bc57Sderaadt 		bootparamprog_1, IPPROTO_UDP)) {
130ae99bc57Sderaadt 		fprintf(stderr,
131ae99bc57Sderaadt 		    "bootparamd: unable to register BOOTPARAMPROG version %d, udp)\n",
132ae99bc57Sderaadt 		    BOOTPARAMVERS);
133ae99bc57Sderaadt 		exit(1);
134ae99bc57Sderaadt 	}
135ae99bc57Sderaadt 	svc_run();
136ae99bc57Sderaadt 	fprintf(stderr, "svc_run returned\n");
137ae99bc57Sderaadt 	exit(1);
138ae99bc57Sderaadt }
139ae99bc57Sderaadt 
140ae99bc57Sderaadt bp_whoami_res *
141d8f00aa3Spk bootparamproc_whoami_1_svc(whoami, rqstp)
142ae99bc57Sderaadt 	bp_whoami_arg *whoami;
143d8f00aa3Spk 	struct svc_req *rqstp;
144ae99bc57Sderaadt {
145ae99bc57Sderaadt 	static bp_whoami_res res;
146*b7dcf10eScgd 	struct hostent *he;
147*b7dcf10eScgd 	struct in_addr inaddr;
148*b7dcf10eScgd 	long    haddr;
1490d8ec8d0Sderaadt 
150ae99bc57Sderaadt 	if (debug)
151ae99bc57Sderaadt 		fprintf(stderr, "whoami got question for %d.%d.%d.%d\n",
152ae99bc57Sderaadt 		    255 & whoami->client_address.bp_address_u.ip_addr.net,
153ae99bc57Sderaadt 		    255 & whoami->client_address.bp_address_u.ip_addr.host,
154ae99bc57Sderaadt 		    255 & whoami->client_address.bp_address_u.ip_addr.lh,
155ae99bc57Sderaadt 		    255 & whoami->client_address.bp_address_u.ip_addr.impno);
156ae99bc57Sderaadt 	if (dolog)
157ae99bc57Sderaadt 		syslog(LOG_NOTICE, "whoami got question for %d.%d.%d.%d\n",
158ae99bc57Sderaadt 		    255 & whoami->client_address.bp_address_u.ip_addr.net,
159ae99bc57Sderaadt 		    255 & whoami->client_address.bp_address_u.ip_addr.host,
160ae99bc57Sderaadt 		    255 & whoami->client_address.bp_address_u.ip_addr.lh,
161ae99bc57Sderaadt 		    255 & whoami->client_address.bp_address_u.ip_addr.impno);
162ae99bc57Sderaadt 
163ae99bc57Sderaadt 	bcopy((char *) &whoami->client_address.bp_address_u.ip_addr, (char *) &haddr,
164ae99bc57Sderaadt 	    sizeof(haddr));
165ae99bc57Sderaadt 	he = gethostbyaddr((char *) &haddr, sizeof(haddr), AF_INET);
166*b7dcf10eScgd 	if (he)
167*b7dcf10eScgd 		strcpy(askname, he->h_name);
168*b7dcf10eScgd 	else {
169*b7dcf10eScgd 		inaddr.s_addr = haddr;
170*b7dcf10eScgd 		strcpy(askname, inet_ntoa(inaddr));
171*b7dcf10eScgd 	}
172ae99bc57Sderaadt 
173ae99bc57Sderaadt 	if (debug)
174*b7dcf10eScgd 		fprintf(stderr, "This is host %s\n", askname);
175ae99bc57Sderaadt 	if (dolog)
176*b7dcf10eScgd 		syslog(LOG_NOTICE, "This is host %s\n", askname);
177ae99bc57Sderaadt 
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 	if (debug)
205ae99bc57Sderaadt 		fprintf(stderr, "whoami failed\n");
206ae99bc57Sderaadt 	if (dolog)
207ae99bc57Sderaadt 		syslog(LOG_NOTICE, "whoami failed\n");
208ae99bc57Sderaadt 	return (NULL);
209ae99bc57Sderaadt }
210ae99bc57Sderaadt 
211ae99bc57Sderaadt 
212ae99bc57Sderaadt bp_getfile_res *
213d8f00aa3Spk bootparamproc_getfile_1_svc(getfile, rqstp)
214ae99bc57Sderaadt 	bp_getfile_arg *getfile;
215d8f00aa3Spk 	struct svc_req *rqstp;
216ae99bc57Sderaadt {
217ae99bc57Sderaadt 	static bp_getfile_res res;
218*b7dcf10eScgd 	struct hostent *he;
2190d8ec8d0Sderaadt 	int     err;
220ae99bc57Sderaadt 
221ae99bc57Sderaadt 	if (debug)
222ae99bc57Sderaadt 		fprintf(stderr, "getfile got question for \"%s\" and file \"%s\"\n",
223ae99bc57Sderaadt 		    getfile->client_name, getfile->file_id);
224ae99bc57Sderaadt 
225ae99bc57Sderaadt 	if (dolog)
226ae99bc57Sderaadt 		syslog(LOG_NOTICE, "getfile got question for \"%s\" and file \"%s\"\n",
227ae99bc57Sderaadt 		    getfile->client_name, getfile->file_id);
228ae99bc57Sderaadt 
229ae99bc57Sderaadt 	he = NULL;
230ae99bc57Sderaadt 	he = gethostbyname(getfile->client_name);
231ae99bc57Sderaadt 	if (!he)
232ae99bc57Sderaadt 		goto failed;
233ae99bc57Sderaadt 
234ae99bc57Sderaadt 	strcpy(askname, he->h_name);
2350d8ec8d0Sderaadt 	err = lookup_bootparam(askname, NULL, getfile->file_id,
2360d8ec8d0Sderaadt 	    &res.server_name, &res.server_path);
2370d8ec8d0Sderaadt 	if (err == 0) {
2380d8ec8d0Sderaadt 		he = gethostbyname(res.server_name);
239ae99bc57Sderaadt 		if (!he)
240ae99bc57Sderaadt 			goto failed;
241ae99bc57Sderaadt 		bcopy(he->h_addr, &res.server_address.bp_address_u.ip_addr, 4);
242ae99bc57Sderaadt 		res.server_address.address_type = IP_ADDR_TYPE;
2430d8ec8d0Sderaadt 	} else if (err == ENOENT && !strcmp(getfile->file_id, "dump")) {
2440d8ec8d0Sderaadt 		/* Special for dump, answer with null strings. */
245ae99bc57Sderaadt 		res.server_name[0] = '\0';
246ae99bc57Sderaadt 		res.server_path[0] = '\0';
247ae99bc57Sderaadt 		bzero(&res.server_address.bp_address_u.ip_addr, 4);
2480d8ec8d0Sderaadt 	} else {
2490d8ec8d0Sderaadt failed:
2500d8ec8d0Sderaadt 		if (debug)
2510d8ec8d0Sderaadt 			fprintf(stderr, "getfile failed for %s\n",
2520d8ec8d0Sderaadt 			    getfile->client_name);
2530d8ec8d0Sderaadt 		if (dolog)
2540d8ec8d0Sderaadt 			syslog(LOG_NOTICE,
2550d8ec8d0Sderaadt 			    "getfile failed for %s\n", getfile->client_name);
2560d8ec8d0Sderaadt 		return (NULL);
257ae99bc57Sderaadt 	}
2580d8ec8d0Sderaadt 
259ae99bc57Sderaadt 	if (debug)
260ae99bc57Sderaadt 		fprintf(stderr,
261ae99bc57Sderaadt 		    "returning server:%s path:%s address: %d.%d.%d.%d\n",
262ae99bc57Sderaadt 		    res.server_name, res.server_path,
263ae99bc57Sderaadt 		    255 & res.server_address.bp_address_u.ip_addr.net,
264ae99bc57Sderaadt 		    255 & res.server_address.bp_address_u.ip_addr.host,
265ae99bc57Sderaadt 		    255 & res.server_address.bp_address_u.ip_addr.lh,
266ae99bc57Sderaadt 		    255 & res.server_address.bp_address_u.ip_addr.impno);
267ae99bc57Sderaadt 	if (dolog)
268ae99bc57Sderaadt 		syslog(LOG_NOTICE,
269ae99bc57Sderaadt 		    "returning server:%s path:%s address: %d.%d.%d.%d\n",
270ae99bc57Sderaadt 		    res.server_name, res.server_path,
271ae99bc57Sderaadt 		    255 & res.server_address.bp_address_u.ip_addr.net,
272ae99bc57Sderaadt 		    255 & res.server_address.bp_address_u.ip_addr.host,
273ae99bc57Sderaadt 		    255 & res.server_address.bp_address_u.ip_addr.lh,
274ae99bc57Sderaadt 		    255 & res.server_address.bp_address_u.ip_addr.impno);
275ae99bc57Sderaadt 	return (&res);
276ae99bc57Sderaadt }
277ae99bc57Sderaadt 
278ae99bc57Sderaadt 
2790d8ec8d0Sderaadt int
2800d8ec8d0Sderaadt lookup_bootparam(client, client_canonical, id, server, path)
2810d8ec8d0Sderaadt 	char	*client;
2820d8ec8d0Sderaadt 	char	*client_canonical;
2830d8ec8d0Sderaadt 	char	*id;
2840d8ec8d0Sderaadt 	char	**server;
2850d8ec8d0Sderaadt 	char	**path;
286ae99bc57Sderaadt {
2870d8ec8d0Sderaadt 	FILE   *f = fopen(bootpfile, "r");
2880d8ec8d0Sderaadt #ifdef YP
2890d8ec8d0Sderaadt 	static char *ypbuf = NULL;
2900d8ec8d0Sderaadt 	static int ypbuflen = 0;
2910d8ec8d0Sderaadt #endif
2920d8ec8d0Sderaadt 	static char buf[BUFSIZ];
2930d8ec8d0Sderaadt 	char   *bp, *word;
2940d8ec8d0Sderaadt 	size_t  idlen = id == NULL ? 0 : strlen(id);
2950d8ec8d0Sderaadt 	int     contin = 0;
2960d8ec8d0Sderaadt 	int     found = 0;
297ae99bc57Sderaadt 
2980d8ec8d0Sderaadt 	if (f == NULL)
2990d8ec8d0Sderaadt 		return EINVAL;	/* ? */
300ae99bc57Sderaadt 
3010d8ec8d0Sderaadt 	while (fgets(buf, sizeof buf, f)) {
3020d8ec8d0Sderaadt 		int     wascontin = contin;
3030d8ec8d0Sderaadt 		contin = buf[strlen(buf) - 2] == '\\';
3040d8ec8d0Sderaadt 		bp = buf + strspn(buf, " \t\n");
305ae99bc57Sderaadt 
3060d8ec8d0Sderaadt 		switch (wascontin) {
3070d8ec8d0Sderaadt 		case -1:
3080d8ec8d0Sderaadt 			/* Continuation of uninteresting line */
3090d8ec8d0Sderaadt 			contin *= -1;
310ae99bc57Sderaadt 			continue;
3110d8ec8d0Sderaadt 		case 0:
3120d8ec8d0Sderaadt 			/* New line */
3130d8ec8d0Sderaadt 			contin *= -1;
3140d8ec8d0Sderaadt 			if (*bp == '#')
3150d8ec8d0Sderaadt 				continue;
3160d8ec8d0Sderaadt 			if ((word = strsep(&bp, " \t\n")) == NULL)
3170d8ec8d0Sderaadt 				continue;
3180d8ec8d0Sderaadt #ifdef YP
3190d8ec8d0Sderaadt 			/* A + in the file means try YP now */
3200d8ec8d0Sderaadt 			if (!strcmp(word, "+")) {
3210d8ec8d0Sderaadt 				char   *ypdom;
3220d8ec8d0Sderaadt 
3230d8ec8d0Sderaadt 				if (yp_get_default_domain(&ypdom) ||
3240d8ec8d0Sderaadt 				    yp_match(ypdom, "bootparams", client,
3250d8ec8d0Sderaadt 					strlen(client), &ypbuf, &ypbuflen))
3260d8ec8d0Sderaadt 					continue;
3270d8ec8d0Sderaadt 				bp = ypbuf;
3280d8ec8d0Sderaadt 				word = client;
3290d8ec8d0Sderaadt 				contin *= -1;
330ae99bc57Sderaadt 				break;
331ae99bc57Sderaadt 			}
3320d8ec8d0Sderaadt #endif
3330d8ec8d0Sderaadt 			/* See if this line's client is the one we are
3340d8ec8d0Sderaadt 			 * looking for */
335010a229cScgd 			if (strcasecmp(word, client) != 0) {
336ae99bc57Sderaadt 				/*
3370d8ec8d0Sderaadt 				 * If it didn't match, try getting the
3380d8ec8d0Sderaadt 				 * canonical host name of the client
3390d8ec8d0Sderaadt 				 * on this line and comparing that to
3400d8ec8d0Sderaadt 				 * the client we are looking for
341ae99bc57Sderaadt 				 */
3420d8ec8d0Sderaadt 				struct hostent *hp = gethostbyname(word);
343010a229cScgd 				if (hp == NULL ||
344010a229cScgd 				    strcasecmp(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