xref: /csrg-svn/sbin/mountd/mountd.c (revision 38460)
1*38460Smckusick /*
2*38460Smckusick  * Copyright (c) 1989 The Regents of the University of California.
3*38460Smckusick  * All rights reserved.
4*38460Smckusick  *
5*38460Smckusick  * This code is derived from software contributed to Berkeley by
6*38460Smckusick  * Rick Macklem at The University of Guelph.
7*38460Smckusick  *
8*38460Smckusick  * Redistribution and use in source and binary forms are permitted
9*38460Smckusick  * provided that the above copyright notice and this paragraph are
10*38460Smckusick  * duplicated in all such forms and that any documentation,
11*38460Smckusick  * advertising materials, and other materials related to such
12*38460Smckusick  * distribution and use acknowledge that the software was developed
13*38460Smckusick  * by the University of California, Berkeley.  The name of the
14*38460Smckusick  * University may not be used to endorse or promote products derived
15*38460Smckusick  * from this software without specific prior written permission.
16*38460Smckusick  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17*38460Smckusick  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18*38460Smckusick  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19*38460Smckusick  */
20*38460Smckusick 
21*38460Smckusick #ifndef lint
22*38460Smckusick char copyright[] =
23*38460Smckusick "@(#) Copyright (c) 1989 Regents of the University of California.\n\
24*38460Smckusick  All rights reserved.\n";
25*38460Smckusick #endif not lint
26*38460Smckusick 
27*38460Smckusick #ifndef lint
28*38460Smckusick static char sccsid[] = "@(#)mountd.c	5.1 (Berkeley) 07/16/89";
29*38460Smckusick #endif not lint
30*38460Smckusick 
31*38460Smckusick #include <stdio.h>
32*38460Smckusick #include <strings.h>
33*38460Smckusick #include <syslog.h>
34*38460Smckusick #include <signal.h>
35*38460Smckusick #include <fcntl.h>
36*38460Smckusick #include <sys/param.h>
37*38460Smckusick #include <sys/types.h>
38*38460Smckusick #include <sys/ioctl.h>
39*38460Smckusick #include <sys/stat.h>
40*38460Smckusick #include <sys/dir.h>
41*38460Smckusick #include <sys/uio.h>
42*38460Smckusick #include <sys/namei.h>
43*38460Smckusick #include <sys/mount.h>
44*38460Smckusick #include <sys/socket.h>
45*38460Smckusick #include <sys/socketvar.h>
46*38460Smckusick #include <sys/errno.h>
47*38460Smckusick #include <netdb.h>
48*38460Smckusick #include <rpc/rpc.h>
49*38460Smckusick #include <rpc/pmap_clnt.h>
50*38460Smckusick #include <rpc/pmap_prot.h>
51*38460Smckusick #include <nfs/rpcv2.h>
52*38460Smckusick #include <nfs/nfsv2.h>
53*38460Smckusick 
54*38460Smckusick struct ufid {
55*38460Smckusick 	u_short	ufid_len;
56*38460Smckusick 	ino_t	ufid_ino;
57*38460Smckusick 	long	ufid_gen;
58*38460Smckusick };
59*38460Smckusick /*
60*38460Smckusick  * Structures for keeping the mount list and export list
61*38460Smckusick  */
62*38460Smckusick struct mountlist {
63*38460Smckusick 	struct mountlist *ml_next;
64*38460Smckusick 	struct mountlist *ml_prev;
65*38460Smckusick 	char	ml_host[RPCMNT_NAMELEN+1];
66*38460Smckusick 	char	ml_dirp[RPCMNT_PATHLEN+1];
67*38460Smckusick };
68*38460Smckusick 
69*38460Smckusick struct exportlist {
70*38460Smckusick 	struct exportlist *ex_next;
71*38460Smckusick 	struct exportlist *ex_prev;
72*38460Smckusick 	struct grouplist *ex_groups;
73*38460Smckusick 	int	ex_rootuid;
74*38460Smckusick 	int	ex_exflags;
75*38460Smckusick 	char	ex_dirp[RPCMNT_PATHLEN+1];
76*38460Smckusick };
77*38460Smckusick 
78*38460Smckusick struct grouplist {
79*38460Smckusick 	struct grouplist *gr_next;
80*38460Smckusick 	char	gr_name[RPCMNT_NAMELEN+1];
81*38460Smckusick };
82*38460Smckusick 
83*38460Smckusick /* Global defs */
84*38460Smckusick int xdr_fhs(), xdr_mlist(), xdr_dir(), xdr_explist();
85*38460Smckusick int mntsrv(), get_exportlist();
86*38460Smckusick struct exportlist exphead;
87*38460Smckusick struct mountlist mlhead;
88*38460Smckusick char exname[MAXPATHLEN];
89*38460Smckusick int def_rootuid = -2;
90*38460Smckusick extern int errno;
91*38460Smckusick #ifdef DEBUG
92*38460Smckusick int debug = 1;
93*38460Smckusick #else
94*38460Smckusick int debug = 0;
95*38460Smckusick #endif
96*38460Smckusick 
97*38460Smckusick /*
98*38460Smckusick  * Mountd server for NFS mount protocol as described in:
99*38460Smckusick  *  Networking on the Sun Workstation,
100*38460Smckusick  *  Part #800-1324-03 Rev. B
101*38460Smckusick  *  Network File System Protocol Specification Chap. 3
102*38460Smckusick  * The optional argument is the exports file name
103*38460Smckusick  * default: /etc/exports
104*38460Smckusick  */
105*38460Smckusick main(argc, argv)
106*38460Smckusick 	int argc;
107*38460Smckusick 	char *argv[];
108*38460Smckusick {
109*38460Smckusick 	SVCXPRT *transp;
110*38460Smckusick 
111*38460Smckusick 	if (debug == 0) {
112*38460Smckusick 		if (fork())
113*38460Smckusick 			exit(0);
114*38460Smckusick 		{ int s;
115*38460Smckusick 		for (s = 0; s < 10; s++)
116*38460Smckusick 			(void) close(s);
117*38460Smckusick 		}
118*38460Smckusick 		(void) open("/", O_RDONLY);
119*38460Smckusick 		(void) dup2(0, 1);
120*38460Smckusick 		(void) dup2(0, 2);
121*38460Smckusick 		{ int tt = open("/dev/tty", O_RDWR);
122*38460Smckusick 		  if (tt > 0) {
123*38460Smckusick 			ioctl(tt, TIOCNOTTY, (char *)0);
124*38460Smckusick 			close(tt);
125*38460Smckusick 		  }
126*38460Smckusick 		}
127*38460Smckusick 		(void) setpgrp(0, 0);
128*38460Smckusick 		signal(SIGTSTP, SIG_IGN);
129*38460Smckusick 		signal(SIGTTIN, SIG_IGN);
130*38460Smckusick 		signal(SIGTTOU, SIG_IGN);
131*38460Smckusick 		signal(SIGINT, SIG_IGN);
132*38460Smckusick 		signal(SIGQUIT, SIG_IGN);
133*38460Smckusick 		signal(SIGTERM, SIG_IGN);
134*38460Smckusick 	}
135*38460Smckusick 	openlog("mountd:", LOG_PID, LOG_DAEMON);
136*38460Smckusick 	mlhead.ml_next = mlhead.ml_prev = (struct mountlist *)0;
137*38460Smckusick 	exphead.ex_next = exphead.ex_prev = (struct exportlist *)0;
138*38460Smckusick 	if (argc == 2) {
139*38460Smckusick 		strncpy(exname, argv[1], MAXPATHLEN-1);
140*38460Smckusick 		exname[MAXPATHLEN-1] = '\0';
141*38460Smckusick 	} else
142*38460Smckusick 		strcpy(exname, "/etc/exports");
143*38460Smckusick 	get_exportlist();
144*38460Smckusick 	signal(SIGHUP, get_exportlist);
145*38460Smckusick 	if ((transp = svcudp_create(RPC_ANYSOCK)) == NULL) {
146*38460Smckusick 		syslog(LOG_ERR, "Can't create socket");
147*38460Smckusick 		exit(1);
148*38460Smckusick 	}
149*38460Smckusick 	pmap_unset(RPCPROG_MNT, RPCMNT_VER1);
150*38460Smckusick 	if (!svc_register(transp, RPCPROG_MNT, RPCMNT_VER1, mntsrv, IPPROTO_UDP)) {
151*38460Smckusick 		syslog(LOG_ERR, "Can't register mount");
152*38460Smckusick 		exit(1);
153*38460Smckusick 	}
154*38460Smckusick 	svc_run();
155*38460Smckusick 	syslog(LOG_ERR, "Mountd died");
156*38460Smckusick }
157*38460Smckusick 
158*38460Smckusick /*
159*38460Smckusick  * The mount rpc service
160*38460Smckusick  */
161*38460Smckusick mntsrv(rqstp, transp)
162*38460Smckusick 	register struct svc_req *rqstp;
163*38460Smckusick 	register SVCXPRT *transp;
164*38460Smckusick {
165*38460Smckusick 	register struct mountlist *mlp;
166*38460Smckusick 	register struct exportlist *ep;
167*38460Smckusick 	register struct grouplist *grp;
168*38460Smckusick 	struct mountlist *mlp2;
169*38460Smckusick 	nfsv2fh_t nfh;
170*38460Smckusick 	struct authunix_parms *ucr;
171*38460Smckusick 	struct stat stb;
172*38460Smckusick 	struct hostent *hp;
173*38460Smckusick 	struct sockaddr_in saddr;
174*38460Smckusick 	char dirpath[RPCMNT_PATHLEN+1];
175*38460Smckusick 	int ok = 0;
176*38460Smckusick 	int bad = ENOENT;
177*38460Smckusick 	int omask;
178*38460Smckusick 
179*38460Smckusick fprintf(stderr,"in mntsrv\n");
180*38460Smckusick 	if (rqstp->rq_proc == NULLPROC) {
181*38460Smckusick 		if (!svc_sendreply(transp, xdr_void, (caddr_t)0))
182*38460Smckusick 			syslog(LOG_ERR, "Can't send reply");
183*38460Smckusick 		return;
184*38460Smckusick 	}
185*38460Smckusick 
186*38460Smckusick 	/* Get authorization */
187*38460Smckusick 	switch (rqstp->rq_cred.oa_flavor) {
188*38460Smckusick 	case AUTH_UNIX:
189*38460Smckusick 		ucr = (struct authunix_parms *)rqstp->rq_clntcred;
190*38460Smckusick 		if (ucr->aup_uid == 0)
191*38460Smckusick 			break;
192*38460Smckusick 		/* Fall thru to */
193*38460Smckusick fprintf(stderr,"weak auth\n");
194*38460Smckusick 	case AUTH_NULL:
195*38460Smckusick 	default:
196*38460Smckusick 		svcerr_weakauth(transp);
197*38460Smckusick 		return;
198*38460Smckusick 	}
199*38460Smckusick 
200*38460Smckusick 	saddr.sin_family = AF_INET;
201*38460Smckusick 	saddr.sin_addr.s_addr = ntohl(transp->xp_raddr.sin_addr.s_addr);
202*38460Smckusick 	saddr.sin_port = 0;
203*38460Smckusick 	hp = gethostbyaddr((caddr_t)&saddr, transp->xp_addrlen, AF_INET);
204*38460Smckusick fprintf(stderr,"net_addr=0x%x\n",transp->xp_raddr.sin_addr.s_addr);
205*38460Smckusick fprintf(stderr,"aft gethost hp=0x%x\n",hp);
206*38460Smckusick 	switch (rqstp->rq_proc) {
207*38460Smckusick 	case RPCMNT_MOUNT:
208*38460Smckusick fprintf(stderr,"in mnt req\n");
209*38460Smckusick 		if (!svc_getargs(transp, xdr_dir, dirpath)) {
210*38460Smckusick 			svcerr_decode(transp);
211*38460Smckusick 			return;
212*38460Smckusick 		}
213*38460Smckusick 
214*38460Smckusick fprintf(stderr,"dirpath=%s\n",dirpath);
215*38460Smckusick 		/* If no hostname, return err */
216*38460Smckusick #ifdef notdef
217*38460Smckusick 		if (hp == NULL) {
218*38460Smckusick 			if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
219*38460Smckusick 				syslog(LOG_ERR, "Can't send reply");
220*38460Smckusick 			return;
221*38460Smckusick 		}
222*38460Smckusick 
223*38460Smckusick #endif
224*38460Smckusick 		/* Check to see if it's a valid dirpath */
225*38460Smckusick 		if (stat(dirpath, &stb) < 0 || (stb.st_mode&S_IFMT) !=
226*38460Smckusick 			S_IFDIR) {
227*38460Smckusick 			if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
228*38460Smckusick 				syslog(LOG_ERR, "Can't send reply");
229*38460Smckusick 			return;
230*38460Smckusick 		}
231*38460Smckusick 
232*38460Smckusick fprintf(stderr,"Look in exports list\n");
233*38460Smckusick 		/* Check in the exports list */
234*38460Smckusick 		omask = sigblock(sigmask(SIGHUP));
235*38460Smckusick 		ep = exphead.ex_next;
236*38460Smckusick 		while (ep != NULL) {
237*38460Smckusick 			if (!strcmp(ep->ex_dirp, dirpath)) {
238*38460Smckusick 				grp = ep->ex_groups;
239*38460Smckusick 				if (grp == NULL)
240*38460Smckusick 					break;
241*38460Smckusick 				while (grp != NULL) {
242*38460Smckusick 					if (!strcmp(grp->gr_name, hp->h_name))
243*38460Smckusick 						break;
244*38460Smckusick 					grp = grp->gr_next;
245*38460Smckusick 				}
246*38460Smckusick 				bad = EACCES;
247*38460Smckusick 				if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
248*38460Smckusick 					syslog(LOG_ERR, "Can't send reply");
249*38460Smckusick 				sigsetmask(omask);
250*38460Smckusick 				return;
251*38460Smckusick 			}
252*38460Smckusick 			ep = ep->ex_next;
253*38460Smckusick 		}
254*38460Smckusick 		sigsetmask(omask);
255*38460Smckusick 		if (ep == NULL) {
256*38460Smckusick 			bad = EACCES;
257*38460Smckusick 			if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
258*38460Smckusick 				syslog(LOG_ERR, "Can't send reply");
259*38460Smckusick 			return;
260*38460Smckusick 		}
261*38460Smckusick 
262*38460Smckusick fprintf(stderr,"get file handle\n");
263*38460Smckusick 		/* Get the file handle */
264*38460Smckusick 		bzero((caddr_t)&nfh, sizeof(nfh));
265*38460Smckusick 		if (getfh(dirpath, (fhandle_t *)&nfh) < 0) {
266*38460Smckusick 			bad = errno;
267*38460Smckusick 			if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
268*38460Smckusick 				syslog(LOG_ERR, "Can't send reply");
269*38460Smckusick 			return;
270*38460Smckusick 		}
271*38460Smckusick { struct ufid *ufp;
272*38460Smckusick ufp = (struct ufid *)&nfh.fh_generic;
273*38460Smckusick fprintf(stderr,"ftyp=%d fnum=%d\n",nfh.fh_generic.fh_fsid.val[1],
274*38460Smckusick nfh.fh_generic.fh_fsid.val[0]);
275*38460Smckusick fprintf(stderr,"fid num=%d gen=%d\n",ufp->ufid_ino,ufp->ufid_gen);
276*38460Smckusick }
277*38460Smckusick 		if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&nfh))
278*38460Smckusick 			syslog(LOG_ERR, "Can't send reply");
279*38460Smckusick 		mlp = (struct mountlist *)malloc(sizeof(struct mountlist));
280*38460Smckusick fprintf(stderr,"add to list\n");
281*38460Smckusick #ifdef notdef
282*38460Smckusick 		if (mlp != NULL) {
283*38460Smckusick 			strcpy(mlp->ml_host, hp->h_name);
284*38460Smckusick 			strcpy(mlp->ml_dirp, dirpath);
285*38460Smckusick 			mlp->ml_prev = &mlhead;
286*38460Smckusick 			mlp->ml_next = mlhead.ml_next;
287*38460Smckusick 			if (mlhead.ml_next != NULL)
288*38460Smckusick 				mlhead.ml_next->ml_prev = mlp;
289*38460Smckusick 			mlhead.ml_next = mlp;
290*38460Smckusick 		}
291*38460Smckusick #endif
292*38460Smckusick 		return;
293*38460Smckusick 	case RPCMNT_DUMP:
294*38460Smckusick 		if (!svc_sendreply(transp, xdr_mlist, (caddr_t)0))
295*38460Smckusick 			syslog(LOG_ERR, "Can't send reply");
296*38460Smckusick 		return;
297*38460Smckusick 	case RPCMNT_UMOUNT:
298*38460Smckusick 		if (!svc_getargs(transp, xdr_dir, dirpath)) {
299*38460Smckusick 			svcerr_decode(transp);
300*38460Smckusick 			return;
301*38460Smckusick 		}
302*38460Smckusick 		if (hp != NULL) {
303*38460Smckusick 			mlp = mlhead.ml_next;
304*38460Smckusick 			while (mlp != NULL) {
305*38460Smckusick 				if (!strcmp(mlp->ml_host, hp->h_name) &&
306*38460Smckusick 				    !strcmp(mlp->ml_dirp, dirpath)) {
307*38460Smckusick 					mlp->ml_prev->ml_next = mlp->ml_next;
308*38460Smckusick 					if (mlp->ml_next != NULL)
309*38460Smckusick 						mlp->ml_next->ml_prev =
310*38460Smckusick 						   mlp->ml_prev;
311*38460Smckusick 					free((caddr_t)mlp);
312*38460Smckusick 					break;
313*38460Smckusick 				}
314*38460Smckusick 				mlp = mlp->ml_next;
315*38460Smckusick 			}
316*38460Smckusick 		}
317*38460Smckusick 		if (!svc_sendreply(transp, xdr_void, (caddr_t)0))
318*38460Smckusick 			syslog(LOG_ERR, "Can't send reply");
319*38460Smckusick 		return;
320*38460Smckusick 	case RPCMNT_UMNTALL:
321*38460Smckusick 		if (hp != NULL) {
322*38460Smckusick 			mlp = mlhead.ml_next;
323*38460Smckusick 			while (mlp != NULL) {
324*38460Smckusick 				if (!strcmp(mlp->ml_host, hp->h_name)) {
325*38460Smckusick 					mlp2 = mlp;
326*38460Smckusick 					mlp->ml_prev->ml_next = mlp->ml_next;
327*38460Smckusick 					if (mlp->ml_next != NULL)
328*38460Smckusick 						mlp->ml_next->ml_prev =
329*38460Smckusick 						   mlp->ml_prev;
330*38460Smckusick 					mlp = mlp->ml_next;
331*38460Smckusick 					free((caddr_t)mlp2);
332*38460Smckusick 				} else
333*38460Smckusick 					mlp = mlp->ml_next;
334*38460Smckusick 			}
335*38460Smckusick 		}
336*38460Smckusick 		if (!svc_sendreply(transp, xdr_void, (caddr_t)0))
337*38460Smckusick 			syslog(LOG_ERR, "Can't send reply");
338*38460Smckusick 		return;
339*38460Smckusick 	case RPCMNT_EXPORT:
340*38460Smckusick 		if (!svc_sendreply(transp, xdr_explist, (caddr_t)0))
341*38460Smckusick 			syslog(LOG_ERR, "Can't send reply");
342*38460Smckusick 		return;
343*38460Smckusick 	default:
344*38460Smckusick 		svcerr_noproc(transp);
345*38460Smckusick 		return;
346*38460Smckusick 	}
347*38460Smckusick }
348*38460Smckusick 
349*38460Smckusick /*
350*38460Smckusick  * Xdr conversion for a dirpath string
351*38460Smckusick  */
352*38460Smckusick xdr_dir(xdrsp, dirp)
353*38460Smckusick 	XDR *xdrsp;
354*38460Smckusick 	char *dirp;
355*38460Smckusick {
356*38460Smckusick 	return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
357*38460Smckusick }
358*38460Smckusick 
359*38460Smckusick /*
360*38460Smckusick  * Xdr routine to generate fhstatus
361*38460Smckusick  */
362*38460Smckusick xdr_fhs(xdrsp, nfh)
363*38460Smckusick 	XDR *xdrsp;
364*38460Smckusick 	nfsv2fh_t *nfh;
365*38460Smckusick {
366*38460Smckusick 	int ok = 0;
367*38460Smckusick 
368*38460Smckusick 	if (!xdr_long(xdrsp, &ok))
369*38460Smckusick 		return (0);
370*38460Smckusick fprintf(stderr,"eo xdr_fhs\n");
371*38460Smckusick 	return (xdr_opaque(xdrsp, (caddr_t)nfh, NFSX_FH));
372*38460Smckusick }
373*38460Smckusick 
374*38460Smckusick xdr_mlist(xdrsp, cp)
375*38460Smckusick 	XDR *xdrsp;
376*38460Smckusick 	caddr_t cp;
377*38460Smckusick {
378*38460Smckusick 	register struct mountlist *mlp;
379*38460Smckusick 	int true = 1;
380*38460Smckusick 	int false = 0;
381*38460Smckusick 	char *strp;
382*38460Smckusick 
383*38460Smckusick 	mlp = mlhead.ml_next;
384*38460Smckusick 	while (mlp != NULL) {
385*38460Smckusick 		if (!xdr_bool(xdrsp, &true))
386*38460Smckusick 			return (0);
387*38460Smckusick 		strp = &mlp->ml_host[0];
388*38460Smckusick 		if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN))
389*38460Smckusick 			return (0);
390*38460Smckusick 		strp = &mlp->ml_dirp[0];
391*38460Smckusick 		if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))
392*38460Smckusick 			return (0);
393*38460Smckusick 		mlp = mlp->ml_next;
394*38460Smckusick 	}
395*38460Smckusick 	if (!xdr_bool(xdrsp, &false))
396*38460Smckusick 		return (0);
397*38460Smckusick 	return (1);
398*38460Smckusick }
399*38460Smckusick 
400*38460Smckusick /*
401*38460Smckusick  * Xdr conversion for export list
402*38460Smckusick  */
403*38460Smckusick xdr_explist(xdrsp, cp)
404*38460Smckusick 	XDR *xdrsp;
405*38460Smckusick 	caddr_t cp;
406*38460Smckusick {
407*38460Smckusick 	register struct exportlist *ep;
408*38460Smckusick 	register struct grouplist *grp;
409*38460Smckusick 	int true = 1;
410*38460Smckusick 	int false = 0;
411*38460Smckusick 	char *strp;
412*38460Smckusick 	int omask;
413*38460Smckusick 
414*38460Smckusick 	omask = sigblock(sigmask(SIGHUP));
415*38460Smckusick 	ep = exphead.ex_next;
416*38460Smckusick 	while (ep != NULL) {
417*38460Smckusick 		if (!xdr_bool(xdrsp, &true))
418*38460Smckusick 			goto errout;
419*38460Smckusick 		strp = &ep->ex_dirp[0];
420*38460Smckusick 		if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))
421*38460Smckusick 			goto errout;
422*38460Smckusick 		grp = ep->ex_groups;
423*38460Smckusick 		while (grp != NULL) {
424*38460Smckusick 			if (!xdr_bool(xdrsp, &true))
425*38460Smckusick 				goto errout;
426*38460Smckusick 			strp = &grp->gr_name[0];
427*38460Smckusick 			if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN))
428*38460Smckusick 				goto errout;
429*38460Smckusick 			grp = grp->gr_next;
430*38460Smckusick 		}
431*38460Smckusick 		if (!xdr_bool(xdrsp, &false))
432*38460Smckusick 			goto errout;
433*38460Smckusick 		ep = ep->ex_next;
434*38460Smckusick 	}
435*38460Smckusick 	sigsetmask(omask);
436*38460Smckusick 	if (!xdr_bool(xdrsp, &false))
437*38460Smckusick 		return (0);
438*38460Smckusick 	return (1);
439*38460Smckusick errout:
440*38460Smckusick 	sigsetmask(omask);
441*38460Smckusick 	return (0);
442*38460Smckusick }
443*38460Smckusick 
444*38460Smckusick #define LINESIZ	10240
445*38460Smckusick char line[LINESIZ];
446*38460Smckusick 
447*38460Smckusick /*
448*38460Smckusick  * Get the export list
449*38460Smckusick  */
450*38460Smckusick get_exportlist()
451*38460Smckusick {
452*38460Smckusick 	register struct exportlist *ep, *ep2;
453*38460Smckusick 	register struct grouplist *grp, *grp2;
454*38460Smckusick 	FILE *inf;
455*38460Smckusick 	char *cp, *endcp;
456*38460Smckusick 	int len;
457*38460Smckusick 	int rootuid, exflags;
458*38460Smckusick 
459*38460Smckusick 	/*
460*38460Smckusick 	 * First, get rid of the old list
461*38460Smckusick 	 */
462*38460Smckusick 	ep = exphead.ex_next;
463*38460Smckusick 	while (ep != NULL) {
464*38460Smckusick 		grp = ep->ex_groups;
465*38460Smckusick 		while (grp != NULL) {
466*38460Smckusick 			grp2 = grp;
467*38460Smckusick 			grp = grp->gr_next;
468*38460Smckusick 			free((caddr_t)grp2);
469*38460Smckusick 		}
470*38460Smckusick 		ep2 = ep;
471*38460Smckusick 		ep = ep->ex_next;
472*38460Smckusick 		free((caddr_t)ep2);
473*38460Smckusick 	}
474*38460Smckusick 
475*38460Smckusick 	/*
476*38460Smckusick 	 * Read in the exports file and build the list, calling
477*38460Smckusick 	 * exportfs() as we go along
478*38460Smckusick 	 */
479*38460Smckusick 	exphead.ex_next = exphead.ex_prev = (struct exportlist *)0;
480*38460Smckusick 	if ((inf = fopen(exname, "r")) == NULL) {
481*38460Smckusick 		syslog(LOG_ERR, "Can't open %s", exname);
482*38460Smckusick 		exit(2);
483*38460Smckusick 	}
484*38460Smckusick 	while (fgets(line, LINESIZ, inf)) {
485*38460Smckusick 		exflags = 0;
486*38460Smckusick 		rootuid = def_rootuid;
487*38460Smckusick 		cp = line;
488*38460Smckusick 		nextfield(&cp, &endcp);
489*38460Smckusick 		len = endcp-cp;
490*38460Smckusick 		if (len <= RPCMNT_PATHLEN && len > 0) {
491*38460Smckusick 			ep = (struct exportlist *)malloc(sizeof(*ep));
492*38460Smckusick 			ep->ex_next = ep->ex_prev = (struct exportlist *)0;
493*38460Smckusick 			ep->ex_groups = (struct grouplist *)0;
494*38460Smckusick 			bcopy(cp, ep->ex_dirp, len);
495*38460Smckusick 			ep->ex_dirp[len] = '\0';
496*38460Smckusick 		} else
497*38460Smckusick 			goto err;
498*38460Smckusick 		cp = endcp;
499*38460Smckusick 		nextfield(&cp, &endcp);
500*38460Smckusick 		len = endcp-cp;
501*38460Smckusick 		while (len > 0) {
502*38460Smckusick 			if (len <= RPCMNT_NAMELEN) {
503*38460Smckusick 				if (*cp == '-') {
504*38460Smckusick 					cp++;
505*38460Smckusick 					switch (*cp) {
506*38460Smckusick 					case 'o':
507*38460Smckusick 						exflags |= M_EXRDONLY;
508*38460Smckusick 						break;
509*38460Smckusick 					case 'r':
510*38460Smckusick 						if (*++cp == '=')
511*38460Smckusick 							rootuid = atoi(++cp);
512*38460Smckusick 						break;
513*38460Smckusick 					default:
514*38460Smckusick 						syslog(LOG_WARNING,
515*38460Smckusick 						  "Bad -%c option in %s",
516*38460Smckusick 						  *cp, exname);
517*38460Smckusick 						break;
518*38460Smckusick 					};
519*38460Smckusick 				} else {
520*38460Smckusick 					grp = (struct grouplist *)malloc(*grp);
521*38460Smckusick 					if (grp == NULL)
522*38460Smckusick 						goto err;
523*38460Smckusick 					bcopy(cp, grp->gr_name, len);
524*38460Smckusick 					grp->gr_name[len] = '\0';
525*38460Smckusick 					grp->gr_next = ep->ex_groups;
526*38460Smckusick 					ep->ex_groups = grp;
527*38460Smckusick 				}
528*38460Smckusick 			}
529*38460Smckusick 			cp = endcp;
530*38460Smckusick 			nextfield(&cp, &endcp);
531*38460Smckusick 			len = endcp-cp;
532*38460Smckusick 		}
533*38460Smckusick 		if (exportfs(ep->ex_dirp, rootuid, exflags) < 0) {
534*38460Smckusick 			syslog(LOG_WARNING, "Can't export %s", ep->ex_dirp);
535*38460Smckusick 			free((caddr_t)ep);
536*38460Smckusick 		} else {
537*38460Smckusick 			ep->ex_rootuid = rootuid;
538*38460Smckusick 			ep->ex_exflags = exflags;
539*38460Smckusick 			ep->ex_next = exphead.ex_next;
540*38460Smckusick 			ep->ex_prev = &exphead;
541*38460Smckusick 			if (ep->ex_next != NULL)
542*38460Smckusick 				ep->ex_next->ex_prev = ep;
543*38460Smckusick 			exphead.ex_next = ep;
544*38460Smckusick 		}
545*38460Smckusick 	}
546*38460Smckusick 	fclose(inf);
547*38460Smckusick 	return;
548*38460Smckusick err:
549*38460Smckusick 	syslog(LOG_ERR, "Bad /etc/exports, mountd Failed");
550*38460Smckusick 	exit(2);
551*38460Smckusick }
552*38460Smckusick 
553*38460Smckusick /*
554*38460Smckusick  * Parse out the next white space separated field
555*38460Smckusick  */
556*38460Smckusick nextfield(cp, endcp)
557*38460Smckusick 	char **cp;
558*38460Smckusick 	char **endcp;
559*38460Smckusick {
560*38460Smckusick 	register char *p;
561*38460Smckusick 
562*38460Smckusick 	p = *cp;
563*38460Smckusick 	while (*p == ' ' || *p == '\t')
564*38460Smckusick 		p++;
565*38460Smckusick 	if (*p == '\n' || *p == '\0') {
566*38460Smckusick 		*cp = *endcp = p;
567*38460Smckusick 		return;
568*38460Smckusick 	}
569*38460Smckusick 	*cp = p++;
570*38460Smckusick 	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
571*38460Smckusick 		p++;
572*38460Smckusick 	*endcp = p;
573*38460Smckusick }
574