xref: /csrg-svn/sbin/mountd/mountd.c (revision 51667)
138460Smckusick /*
238460Smckusick  * Copyright (c) 1989 The Regents of the University of California.
338460Smckusick  * All rights reserved.
438460Smckusick  *
538460Smckusick  * This code is derived from software contributed to Berkeley by
6*51667Smckusick  * Herb Hasler and Rick Macklem at The University of Guelph.
738460Smckusick  *
842703Sbostic  * %sccs.include.redist.c%
938460Smckusick  */
1038460Smckusick 
1138460Smckusick #ifndef lint
1238460Smckusick char copyright[] =
1338460Smckusick "@(#) Copyright (c) 1989 Regents of the University of California.\n\
1438460Smckusick  All rights reserved.\n";
1538460Smckusick #endif not lint
1638460Smckusick 
1738460Smckusick #ifndef lint
18*51667Smckusick static char sccsid[] = "@(#)mountd.c	5.15 (Berkeley) 11/12/91";
1938460Smckusick #endif not lint
2038460Smckusick 
21*51667Smckusick #include <pwd.h>
22*51667Smckusick #include <grp.h>
23*51667Smckusick #include <unistd.h>
24*51667Smckusick #include <stdlib.h>
25*51667Smckusick #include <fcntl.h>
2638460Smckusick #include <sys/param.h>
2738460Smckusick #include <sys/ioctl.h>
2838460Smckusick #include <sys/stat.h>
2939681Smckusick #include <sys/file.h>
30*51667Smckusick #include <sys/ucred.h>
3138460Smckusick #include <sys/mount.h>
3238460Smckusick #include <sys/socket.h>
3338460Smckusick #include <sys/errno.h>
3442038Sbostic #include <sys/signal.h>
3542038Sbostic #include <stdio.h>
3642038Sbostic #include <string.h>
3742038Sbostic #include <syslog.h>
3838460Smckusick #include <netdb.h>
3938460Smckusick #include <rpc/rpc.h>
4038460Smckusick #include <rpc/pmap_clnt.h>
4138460Smckusick #include <rpc/pmap_prot.h>
42*51667Smckusick #ifdef ISO
43*51667Smckusick #include <netiso/iso.h>
44*51667Smckusick #endif
4538460Smckusick #include <nfs/rpcv2.h>
4638460Smckusick #include <nfs/nfsv2.h>
4739681Smckusick #include "pathnames.h"
4838460Smckusick 
49*51667Smckusick #define DEF_NAME "default"
50*51667Smckusick 
51*51667Smckusick #define MNT_HOST   0
52*51667Smckusick #define MNT_GROUP  1
53*51667Smckusick #define	MNT_ISO    2
54*51667Smckusick 
55*51667Smckusick struct namelist {
56*51667Smckusick 	char name[RPCMNT_NAMELEN+1];
57*51667Smckusick 	struct namelist *next;
5838460Smckusick };
59*51667Smckusick struct namegrp {
60*51667Smckusick 	char gname[RPCMNT_NAMELEN+1];
61*51667Smckusick 	struct namegrp *next;
62*51667Smckusick 	struct namelist *names;
63*51667Smckusick };
6438460Smckusick /*
6538460Smckusick  * Structures for keeping the mount list and export list
6638460Smckusick  */
6738460Smckusick struct mountlist {
6844015Smckusick 	struct mountlist *ml_next;
6938460Smckusick 	char	ml_host[RPCMNT_NAMELEN+1];
7038460Smckusick 	char	ml_dirp[RPCMNT_PATHLEN+1];
7138460Smckusick };
7238460Smckusick 
7338460Smckusick struct exportlist {
7438460Smckusick 	struct exportlist *ex_next;
7538460Smckusick 	struct exportlist *ex_prev;
7638460Smckusick 	struct grouplist *ex_groups;
77*51667Smckusick 	int	ex_defset;
7838460Smckusick 	char	ex_dirp[RPCMNT_PATHLEN+1];
7938460Smckusick };
8038460Smckusick 
81*51667Smckusick union grouptypes {
82*51667Smckusick 	struct hostent *gt_hostent;
83*51667Smckusick 	struct groupnames *gt_grpname;
84*51667Smckusick #ifdef ISO
85*51667Smckusick 	struct sockaddr_iso *gt_isoaddr;
86*51667Smckusick #endif
87*51667Smckusick };
88*51667Smckusick 
8938460Smckusick struct grouplist {
90*51667Smckusick 	int type;
91*51667Smckusick 	int exflags;
92*51667Smckusick 	struct ucred anoncr;
93*51667Smckusick 	union grouptypes gr_ptr;
9438460Smckusick 	struct grouplist *gr_next;
9538460Smckusick };
9638460Smckusick 
97*51667Smckusick struct al_mnt {
98*51667Smckusick 	struct al_mnt *al_next;
99*51667Smckusick 	fsid_t	al_mnted;
100*51667Smckusick };
101*51667Smckusick 
102*51667Smckusick struct groupnames {
103*51667Smckusick 	char gn_name[RPCMNT_NAMELEN+1];
104*51667Smckusick 	struct grouplist *gn_glist;
105*51667Smckusick 	struct groupnames *gn_next;
106*51667Smckusick };
107*51667Smckusick 
10838460Smckusick /* Global defs */
10946709Sbostic int mntsrv(), umntall_each(), xdr_fhs(), xdr_mlist(), xdr_dir(), xdr_explist();
110*51667Smckusick void get_exportlist(), send_umntall(), nextfield(), do_opt();
111*51667Smckusick void get_mountlist(), add_mlist(), del_mlist(), free_exp(), free_grp();
112*51667Smckusick void get_group(), get_host(), do_group();
113*51667Smckusick char *realpath();
114*51667Smckusick #ifdef ISO
115*51667Smckusick struct iso_addr *iso_addr();
116*51667Smckusick #endif
11738460Smckusick struct exportlist exphead;
11844015Smckusick struct mountlist *mlhead;
119*51667Smckusick struct groupnames *grpnames;
12038460Smckusick char exname[MAXPATHLEN];
121*51667Smckusick struct ucred def_anon = {
122*51667Smckusick 	(u_short) 1,
123*51667Smckusick 	(uid_t) -2,
124*51667Smckusick 	1,
125*51667Smckusick 	(gid_t) -2,
126*51667Smckusick };
12744015Smckusick int root_only = 1;
12838460Smckusick extern int errno;
129*51667Smckusick struct al_mnt *al_head = (struct al_mnt *)0;
13038460Smckusick #ifdef DEBUG
13138460Smckusick int debug = 1;
13238460Smckusick #else
13338460Smckusick int debug = 0;
13438460Smckusick #endif
13538460Smckusick 
13638460Smckusick /*
13738460Smckusick  * Mountd server for NFS mount protocol as described in:
13839681Smckusick  * NFS: Network File System Protocol Specification, RFC1094, Appendix A
13944015Smckusick  * The optional arguments are the exports file name
14039681Smckusick  * default: _PATH_EXPORTS
14144015Smckusick  * and "-n" to allow nonroot mount.
14238460Smckusick  */
14338460Smckusick main(argc, argv)
14438460Smckusick 	int argc;
14544015Smckusick 	char **argv;
14638460Smckusick {
14738460Smckusick 	SVCXPRT *transp;
14844015Smckusick 	int c;
14944015Smckusick 	extern int optind;
15044015Smckusick 	extern char *optarg;
15138460Smckusick 
15244015Smckusick 	while ((c = getopt(argc, argv, "n")) != EOF)
15344015Smckusick 		switch (c) {
15444015Smckusick 		case 'n':
15544015Smckusick 			root_only = 0;
15644015Smckusick 			break;
15744015Smckusick 		default:
15844015Smckusick 			fprintf(stderr, "Usage: mountd [-n] [export_file]\n");
15944015Smckusick 			exit(1);
16044015Smckusick 		};
16144015Smckusick 	argc -= optind;
16244015Smckusick 	argv += optind;
163*51667Smckusick 	grpnames = (struct groupnames *)0;
16444015Smckusick 	exphead.ex_next = exphead.ex_prev = (struct exportlist *)0;
16544015Smckusick 	mlhead = (struct mountlist *)0;
16644015Smckusick 	if (argc == 1) {
16744015Smckusick 		strncpy(exname, *argv, MAXPATHLEN-1);
16844015Smckusick 		exname[MAXPATHLEN-1] = '\0';
16944015Smckusick 	} else
17044015Smckusick 		strcpy(exname, _PATH_EXPORTS);
17144338Smckusick 	openlog("mountd:", LOG_PID, LOG_DAEMON);
172*51667Smckusick 	if (debug)
173*51667Smckusick 		fprintf(stderr,"Getting export list.\n");
17444015Smckusick 	get_exportlist();
175*51667Smckusick 	if (debug)
176*51667Smckusick 		fprintf(stderr,"Getting mount list.\n");
17744015Smckusick 	get_mountlist();
178*51667Smckusick 	if (debug)
179*51667Smckusick 		fprintf(stderr,"Here we go.\n");
18038460Smckusick 	if (debug == 0) {
18144690Skarels 		daemon(0, 0);
18238460Smckusick 		signal(SIGINT, SIG_IGN);
18338460Smckusick 		signal(SIGQUIT, SIG_IGN);
18438460Smckusick 	}
18538460Smckusick 	signal(SIGHUP, get_exportlist);
18644015Smckusick 	signal(SIGTERM, send_umntall);
18740494Smckusick 	{ FILE *pidfile = fopen(_PATH_MOUNTDPID, "w");
18840494Smckusick 	  if (pidfile != NULL) {
18940494Smckusick 		fprintf(pidfile, "%d\n", getpid());
19040494Smckusick 		fclose(pidfile);
19140494Smckusick 	  }
19240494Smckusick 	}
19338460Smckusick 	if ((transp = svcudp_create(RPC_ANYSOCK)) == NULL) {
19438460Smckusick 		syslog(LOG_ERR, "Can't create socket");
19538460Smckusick 		exit(1);
19638460Smckusick 	}
19738460Smckusick 	pmap_unset(RPCPROG_MNT, RPCMNT_VER1);
198*51667Smckusick 	if (!svc_register(transp, RPCPROG_MNT, RPCMNT_VER1, mntsrv,
199*51667Smckusick 	    IPPROTO_UDP)) {
20038460Smckusick 		syslog(LOG_ERR, "Can't register mount");
20138460Smckusick 		exit(1);
20238460Smckusick 	}
20338460Smckusick 	svc_run();
20438460Smckusick 	syslog(LOG_ERR, "Mountd died");
20544690Skarels 	exit(1);
20638460Smckusick }
20738460Smckusick 
20838460Smckusick /*
20938460Smckusick  * The mount rpc service
21038460Smckusick  */
21138460Smckusick mntsrv(rqstp, transp)
21238460Smckusick 	register struct svc_req *rqstp;
21338460Smckusick 	register SVCXPRT *transp;
21438460Smckusick {
21539681Smckusick 	register struct grouplist *grp;
21639681Smckusick 	register u_long **addrp;
21738460Smckusick 	register struct exportlist *ep;
21838460Smckusick 	nfsv2fh_t nfh;
21938460Smckusick 	struct authunix_parms *ucr;
22038460Smckusick 	struct stat stb;
22138460Smckusick 	struct hostent *hp;
22239681Smckusick 	u_long saddr;
223*51667Smckusick 	char rpcpath[RPCMNT_PATHLEN+1], dirpath[MAXPATHLEN];
22438460Smckusick 	int bad = ENOENT;
225*51667Smckusick 	int found, matched;
22638460Smckusick 	int omask;
22739681Smckusick 	uid_t uid = -2;
22838460Smckusick 
22938460Smckusick 	/* Get authorization */
23038460Smckusick 	switch (rqstp->rq_cred.oa_flavor) {
23138460Smckusick 	case AUTH_UNIX:
23238460Smckusick 		ucr = (struct authunix_parms *)rqstp->rq_clntcred;
23339681Smckusick 		uid = ucr->aup_uid;
23439681Smckusick 		break;
23538460Smckusick 	case AUTH_NULL:
23638460Smckusick 	default:
23739681Smckusick 		break;
23838460Smckusick 	}
23938460Smckusick 
24039681Smckusick 	saddr = transp->xp_raddr.sin_addr.s_addr;
24139681Smckusick 	hp = (struct hostent *)0;
24238460Smckusick 	switch (rqstp->rq_proc) {
24339681Smckusick 	case NULLPROC:
24439681Smckusick 		if (!svc_sendreply(transp, xdr_void, (caddr_t)0))
24539681Smckusick 			syslog(LOG_ERR, "Can't send reply");
24639681Smckusick 		return;
24738460Smckusick 	case RPCMNT_MOUNT:
248*51667Smckusick 		if ((uid != 0 && root_only) || uid == -2) {
24939681Smckusick 			svcerr_weakauth(transp);
25039681Smckusick 			return;
25139681Smckusick 		}
252*51667Smckusick 		if (!svc_getargs(transp, xdr_dir, rpcpath)) {
25338460Smckusick 			svcerr_decode(transp);
25438460Smckusick 			return;
25538460Smckusick 		}
25638460Smckusick 
257*51667Smckusick 		/*
258*51667Smckusick 		 * Get the real pathname and make sure it is a directory
259*51667Smckusick 		 * that exists.
260*51667Smckusick 		 */
261*51667Smckusick 		if (realpath(rpcpath, dirpath) == 0 || stat(dirpath, &stb) < 0
262*51667Smckusick 			|| (stb.st_mode&S_IFMT) != S_IFDIR) {
263*51667Smckusick 			chdir("/");	/* Just in case realpath doesn't */
264*51667Smckusick 			if (debug)
265*51667Smckusick 				fprintf(stderr,"stat failed on %s\n",dirpath);
26638460Smckusick 			if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
26738460Smckusick 				syslog(LOG_ERR, "Can't send reply");
26838460Smckusick 			return;
26938460Smckusick 		}
27038460Smckusick 
27138460Smckusick 		/* Check in the exports list */
27238460Smckusick 		omask = sigblock(sigmask(SIGHUP));
27338460Smckusick 		ep = exphead.ex_next;
274*51667Smckusick 		found = FALSE;
275*51667Smckusick 		matched = FALSE;
276*51667Smckusick 		while (ep != NULL && !found && !matched) {
277*51667Smckusick 			struct grouplist *tgrp;
278*51667Smckusick 			if (debug)
279*51667Smckusick 			    fprintf(stderr,"dirp=[%s]\n",ep->ex_dirp);
28038460Smckusick 			if (!strcmp(ep->ex_dirp, dirpath)) {
281*51667Smckusick 			    if (ep->ex_defset)
282*51667Smckusick 				grp = (struct grouplist *)0;
283*51667Smckusick 			    else
28438460Smckusick 				grp = ep->ex_groups;
285*51667Smckusick 			    if (grp == NULL) {
286*51667Smckusick 				if (debug)
287*51667Smckusick 				    fprintf(stderr,"grp is null\n");
288*51667Smckusick 				found = TRUE;
289*51667Smckusick 			    }
290*51667Smckusick 			    while (grp && !found) {
291*51667Smckusick 				matched = TRUE;
292*51667Smckusick 				if (debug)
293*51667Smckusick 				    fprintf(stderr,"type = [%d]\n",grp->type);
294*51667Smckusick 				if (grp->type == MNT_GROUP) {
295*51667Smckusick 				    tgrp = grp->gr_ptr.gt_grpname->gn_glist;
296*51667Smckusick 				    if (tgrp)
297*51667Smckusick 					addrp = (u_long **)
298*51667Smckusick 					   tgrp->gr_ptr.gt_hostent->h_addr_list;
299*51667Smckusick 				    while(tgrp && !found) {
300*51667Smckusick 					if (debug)
301*51667Smckusick 					    fprintf(stderr, "cmp [%d] [%d]\n",
302*51667Smckusick 						**addrp,saddr);
303*51667Smckusick 					if (**addrp == saddr) {
304*51667Smckusick 					    found = TRUE;
305*51667Smckusick 					    hp = tgrp->gr_ptr.gt_hostent;
306*51667Smckusick 					    break;
307*51667Smckusick 					}
308*51667Smckusick 					if (*++addrp == NULL) {
309*51667Smckusick 					    tgrp = tgrp->gr_next;
310*51667Smckusick 					    if (tgrp == NULL)
31138460Smckusick 						break;
312*51667Smckusick 					    addrp = (u_long **)tgrp->
313*51667Smckusick 						gr_ptr.gt_hostent->h_addr_list;
314*51667Smckusick 					}
315*51667Smckusick 				    }
316*51667Smckusick 				} else if (grp->type == MNT_HOST) {
317*51667Smckusick 				    addrp = (u_long **)
318*51667Smckusick 					grp->gr_ptr.gt_hostent->h_addr_list;
319*51667Smckusick 				    while (*addrp) {
320*51667Smckusick 					if (debug)
321*51667Smckusick 					    fprintf(stderr, "cmp [%d] [%d]\n",
322*51667Smckusick 						**addrp,saddr);
323*51667Smckusick 					if (**addrp == saddr) {
324*51667Smckusick 					    found = TRUE;
325*51667Smckusick 					    hp = grp->gr_ptr.gt_hostent;
326*51667Smckusick 					    break;
327*51667Smckusick 					}
328*51667Smckusick 					addrp++;
329*51667Smckusick 				    }
33038460Smckusick 				}
331*51667Smckusick 				grp = grp->gr_next;
332*51667Smckusick 			    }
33338460Smckusick 			}
33438460Smckusick 			ep = ep->ex_next;
33538460Smckusick 		}
336*51667Smckusick 		if (!found) {
33738460Smckusick 			bad = EACCES;
33838460Smckusick 			if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
33938460Smckusick 				syslog(LOG_ERR, "Can't send reply");
340*51667Smckusick 			sigsetmask(omask);
34138460Smckusick 			return;
342*51667Smckusick 		} else {
343*51667Smckusick 			/* Get the file handle */
344*51667Smckusick 			bzero((caddr_t)&nfh, sizeof(nfh));
345*51667Smckusick 			if (getfh(dirpath, (fhandle_t *)&nfh) < 0) {
346*51667Smckusick 				bad = errno;
347*51667Smckusick 				fprintf(stderr,
348*51667Smckusick 				    "Couldn't get file handle for %s.\n",
349*51667Smckusick 				    dirpath);
350*51667Smckusick 				if (!svc_sendreply(transp, xdr_long,
351*51667Smckusick 				    (caddr_t)&bad))
352*51667Smckusick 					syslog(LOG_ERR, "Can't send reply");
353*51667Smckusick 				sigsetmask(omask);
354*51667Smckusick 				return;
355*51667Smckusick 			}
356*51667Smckusick 			if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&nfh))
35738460Smckusick 				syslog(LOG_ERR, "Can't send reply");
358*51667Smckusick 			if (hp == NULL)
359*51667Smckusick 				hp = gethostbyaddr((caddr_t)&saddr,
360*51667Smckusick 				    sizeof(saddr), AF_INET);
361*51667Smckusick 			if (hp)
362*51667Smckusick 				add_mlist(hp->h_name, dirpath);
363*51667Smckusick 			else
364*51667Smckusick 				add_mlist(inet_ntoa(transp->xp_raddr.sin_addr),
365*51667Smckusick 					dirpath);
366*51667Smckusick 			if (debug)
367*51667Smckusick 				fprintf(stderr,"Mount successfull.\n");
36838460Smckusick 		}
369*51667Smckusick 		sigsetmask(omask);
37038460Smckusick 		return;
37138460Smckusick 	case RPCMNT_DUMP:
37238460Smckusick 		if (!svc_sendreply(transp, xdr_mlist, (caddr_t)0))
37338460Smckusick 			syslog(LOG_ERR, "Can't send reply");
37438460Smckusick 		return;
37538460Smckusick 	case RPCMNT_UMOUNT:
376*51667Smckusick 		if ((uid != 0 && root_only) || uid == -2) {
37739681Smckusick 			svcerr_weakauth(transp);
37839681Smckusick 			return;
37939681Smckusick 		}
38038460Smckusick 		if (!svc_getargs(transp, xdr_dir, dirpath)) {
38138460Smckusick 			svcerr_decode(transp);
38238460Smckusick 			return;
38338460Smckusick 		}
38438460Smckusick 		if (!svc_sendreply(transp, xdr_void, (caddr_t)0))
38538460Smckusick 			syslog(LOG_ERR, "Can't send reply");
38644015Smckusick 		hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET);
38744015Smckusick 		if (hp)
38844015Smckusick 			del_mlist(hp->h_name, dirpath);
389*51667Smckusick 		del_mlist(inet_ntoa(transp->xp_raddr.sin_addr), dirpath);
39038460Smckusick 		return;
39138460Smckusick 	case RPCMNT_UMNTALL:
392*51667Smckusick 		if ((uid != 0 && root_only) || uid == -2) {
39339681Smckusick 			svcerr_weakauth(transp);
39439681Smckusick 			return;
39539681Smckusick 		}
39638460Smckusick 		if (!svc_sendreply(transp, xdr_void, (caddr_t)0))
39738460Smckusick 			syslog(LOG_ERR, "Can't send reply");
39844015Smckusick 		hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET);
39944015Smckusick 		if (hp)
40044015Smckusick 			del_mlist(hp->h_name, (char *)0);
401*51667Smckusick 		del_mlist(inet_ntoa(transp->xp_raddr.sin_addr), (char *)0);
40238460Smckusick 		return;
40338460Smckusick 	case RPCMNT_EXPORT:
40438460Smckusick 		if (!svc_sendreply(transp, xdr_explist, (caddr_t)0))
40538460Smckusick 			syslog(LOG_ERR, "Can't send reply");
40638460Smckusick 		return;
40738460Smckusick 	default:
40838460Smckusick 		svcerr_noproc(transp);
40938460Smckusick 		return;
41038460Smckusick 	}
41138460Smckusick }
41238460Smckusick 
41338460Smckusick /*
41438460Smckusick  * Xdr conversion for a dirpath string
41538460Smckusick  */
41638460Smckusick xdr_dir(xdrsp, dirp)
41738460Smckusick 	XDR *xdrsp;
41838460Smckusick 	char *dirp;
41938460Smckusick {
42038460Smckusick 	return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
42138460Smckusick }
42238460Smckusick 
42338460Smckusick /*
42438460Smckusick  * Xdr routine to generate fhstatus
42538460Smckusick  */
42638460Smckusick xdr_fhs(xdrsp, nfh)
42738460Smckusick 	XDR *xdrsp;
42838460Smckusick 	nfsv2fh_t *nfh;
42938460Smckusick {
43038460Smckusick 	int ok = 0;
43138460Smckusick 
43238460Smckusick 	if (!xdr_long(xdrsp, &ok))
43338460Smckusick 		return (0);
43438460Smckusick 	return (xdr_opaque(xdrsp, (caddr_t)nfh, NFSX_FH));
43538460Smckusick }
43638460Smckusick 
43738460Smckusick xdr_mlist(xdrsp, cp)
43838460Smckusick 	XDR *xdrsp;
43938460Smckusick 	caddr_t cp;
44038460Smckusick {
44144015Smckusick 	register struct mountlist *mlp;
44238460Smckusick 	int true = 1;
44338460Smckusick 	int false = 0;
44438460Smckusick 	char *strp;
44538460Smckusick 
44644015Smckusick 	mlp = mlhead;
44744015Smckusick 	while (mlp) {
44844015Smckusick 		if (!xdr_bool(xdrsp, &true))
44944015Smckusick 			return (0);
45044015Smckusick 		strp = &mlp->ml_host[0];
45144015Smckusick 		if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN))
45244015Smckusick 			return (0);
45344015Smckusick 		strp = &mlp->ml_dirp[0];
45444015Smckusick 		if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))
45544015Smckusick 			return (0);
45644015Smckusick 		mlp = mlp->ml_next;
45738460Smckusick 	}
45838460Smckusick 	if (!xdr_bool(xdrsp, &false))
45938460Smckusick 		return (0);
46038460Smckusick 	return (1);
46138460Smckusick }
46238460Smckusick 
46338460Smckusick /*
46438460Smckusick  * Xdr conversion for export list
46538460Smckusick  */
46638460Smckusick xdr_explist(xdrsp, cp)
46738460Smckusick 	XDR *xdrsp;
46838460Smckusick 	caddr_t cp;
46938460Smckusick {
47038460Smckusick 	register struct exportlist *ep;
471*51667Smckusick 	register struct grouplist *grp, *tgrp;
47238460Smckusick 	int true = 1;
47338460Smckusick 	int false = 0;
47438460Smckusick 	char *strp;
47538460Smckusick 	int omask;
47638460Smckusick 
47738460Smckusick 	omask = sigblock(sigmask(SIGHUP));
47838460Smckusick 	ep = exphead.ex_next;
47938460Smckusick 	while (ep != NULL) {
48038460Smckusick 		if (!xdr_bool(xdrsp, &true))
48138460Smckusick 			goto errout;
48238460Smckusick 		strp = &ep->ex_dirp[0];
48338460Smckusick 		if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))
48438460Smckusick 			goto errout;
48538460Smckusick 		grp = ep->ex_groups;
48638460Smckusick 		while (grp != NULL) {
487*51667Smckusick 			if (grp->type == MNT_GROUP) {
488*51667Smckusick 				tgrp = grp->gr_ptr.gt_grpname->gn_glist;
489*51667Smckusick 				while (tgrp) {
490*51667Smckusick 					if (!xdr_bool(xdrsp, &true))
491*51667Smckusick 						goto errout;
492*51667Smckusick 					strp = tgrp->gr_ptr.gt_hostent->h_name;
493*51667Smckusick 					if (!xdr_string(xdrsp, &strp,
494*51667Smckusick 					    RPCMNT_NAMELEN))
495*51667Smckusick 						goto errout;
496*51667Smckusick 					tgrp = tgrp->gr_next;
497*51667Smckusick 				}
498*51667Smckusick 			} else if (grp->type == MNT_HOST) {
499*51667Smckusick 				if (!xdr_bool(xdrsp, &true))
500*51667Smckusick 					goto errout;
501*51667Smckusick 				strp = grp->gr_ptr.gt_hostent->h_name;
502*51667Smckusick 				if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN))
503*51667Smckusick 					goto errout;
504*51667Smckusick 			}
50538460Smckusick 			grp = grp->gr_next;
50638460Smckusick 		}
50738460Smckusick 		if (!xdr_bool(xdrsp, &false))
50838460Smckusick 			goto errout;
50938460Smckusick 		ep = ep->ex_next;
51038460Smckusick 	}
51138460Smckusick 	sigsetmask(omask);
51238460Smckusick 	if (!xdr_bool(xdrsp, &false))
51338460Smckusick 		return (0);
51438460Smckusick 	return (1);
51538460Smckusick errout:
51638460Smckusick 	sigsetmask(omask);
51738460Smckusick 	return (0);
51838460Smckusick }
51938460Smckusick 
52038460Smckusick #define LINESIZ	10240
52138460Smckusick char line[LINESIZ];
52238460Smckusick 
52338460Smckusick /*
52438460Smckusick  * Get the export list
52538460Smckusick  */
52646709Sbostic void
52738460Smckusick get_exportlist()
52838460Smckusick {
529*51667Smckusick 	struct grouplist *grp, *tgrp;
530*51667Smckusick 	struct al_mnt *al_mp, *t_almp;
53138460Smckusick 	register struct exportlist *ep, *ep2;
532*51667Smckusick 	struct groupnames *t_gn, *t_gn2;
533*51667Smckusick 	struct ucred anoncr;
53438460Smckusick 	FILE *inf;
53538460Smckusick 	char *cp, *endcp;
53639681Smckusick 	char savedc;
537*51667Smckusick 	int len, dirplen, def_set;
538*51667Smckusick 	int exflags;
53938460Smckusick 
54038460Smckusick 	/*
54138460Smckusick 	 * First, get rid of the old list
54238460Smckusick 	 */
54338460Smckusick 	ep = exphead.ex_next;
54438460Smckusick 	while (ep != NULL) {
54538460Smckusick 		ep2 = ep;
54638460Smckusick 		ep = ep->ex_next;
54744015Smckusick 		free_exp(ep2);
54838460Smckusick 	}
549*51667Smckusick 	exphead.ex_next = exphead.ex_prev = (struct exportlist *)0;
55038460Smckusick 
551*51667Smckusick 	t_gn = grpnames;
552*51667Smckusick 	while(t_gn != NULL) {
553*51667Smckusick 		t_gn2 = t_gn;
554*51667Smckusick 		t_gn = t_gn->gn_next;
555*51667Smckusick 		free_grp(t_gn2);
556*51667Smckusick 	}
557*51667Smckusick 	grpnames = (struct groupnames *)0;
558*51667Smckusick 
559*51667Smckusick 	al_mp = al_head;
560*51667Smckusick 	while (al_mp) {
561*51667Smckusick 		t_almp = al_mp;
562*51667Smckusick 		al_mp = al_mp->al_next;
563*51667Smckusick 		free((caddr_t)t_almp);
564*51667Smckusick 	}
565*51667Smckusick 	al_head = (struct al_mnt *)0;
566*51667Smckusick 
56738460Smckusick 	/*
56838460Smckusick 	 * Read in the exports file and build the list, calling
569*51667Smckusick 	 * mount() as we go along to push the export rules into the kernel.
57038460Smckusick 	 */
57138460Smckusick 	if ((inf = fopen(exname, "r")) == NULL) {
57238460Smckusick 		syslog(LOG_ERR, "Can't open %s", exname);
57338460Smckusick 		exit(2);
57438460Smckusick 	}
57538460Smckusick 	while (fgets(line, LINESIZ, inf)) {
576*51667Smckusick 		def_set = TRUE;
577*51667Smckusick 		if (debug)
578*51667Smckusick 			fprintf(stderr,"Got line %s\n",line);
57938460Smckusick 		cp = line;
58038460Smckusick 		nextfield(&cp, &endcp);
581*51667Smckusick 		if (*cp == '#')
582*51667Smckusick 			goto nextline;
583*51667Smckusick 		if (*cp != '/') {
584*51667Smckusick 			/* create group listing of names */
585*51667Smckusick 			get_group(cp, ep);
586*51667Smckusick 			goto nextline;
58745271Smckusick 		}
588*51667Smckusick 		exflags = MNT_EXPORTED;
589*51667Smckusick 		anoncr = def_anon;
59044015Smckusick 
59144015Smckusick 		/*
59244015Smckusick 		 * Create new exports list entry
59344015Smckusick 		 */
59438460Smckusick 		len = endcp-cp;
59538460Smckusick 		if (len <= RPCMNT_PATHLEN && len > 0) {
596*51667Smckusick 			/*
597*51667Smckusick 			 * See if this directory is already in the list.
598*51667Smckusick 			 */
599*51667Smckusick 			ep = exphead.ex_next;
600*51667Smckusick 			while (ep) {
601*51667Smckusick 				if (!strcmp(ep->ex_dirp, cp))
602*51667Smckusick 					break;
603*51667Smckusick 				ep = ep->ex_next;
604*51667Smckusick 			}
605*51667Smckusick 			if (ep == (struct exportlist *)0) {
606*51667Smckusick 				ep = (struct exportlist *)malloc(sizeof(*ep));
607*51667Smckusick 				if (ep == NULL)
608*51667Smckusick 					goto err;
609*51667Smckusick 				ep->ex_next = (struct exportlist *)0;
610*51667Smckusick 				ep->ex_prev = (struct exportlist *)0;
611*51667Smckusick 				ep->ex_groups = (struct grouplist *)0;
612*51667Smckusick 				ep->ex_defset = FALSE;
613*51667Smckusick 				bcopy(cp, ep->ex_dirp, len);
614*51667Smckusick 				ep->ex_dirp[len] = '\0';
615*51667Smckusick 			}
61644015Smckusick 			dirplen = len;
617*51667Smckusick 			if (debug)
618*51667Smckusick 				fprintf(stderr, "Making new ep. [%s]\n",
619*51667Smckusick 				    ep->ex_dirp);
62045271Smckusick 		} else {
621*51667Smckusick 			syslog(LOG_ERR, "Bad Exports File line: %s\n", line);
622*51667Smckusick 			goto nextline;
62345271Smckusick 		}
62438460Smckusick 		cp = endcp;
62538460Smckusick 		nextfield(&cp, &endcp);
62638460Smckusick 		len = endcp-cp;
62738460Smckusick 		while (len > 0) {
62839681Smckusick 			savedc = *endcp;
62939681Smckusick 			*endcp = '\0';
63045271Smckusick 			if (len > RPCMNT_NAMELEN)
63145271Smckusick 				goto more;
63245271Smckusick 			if (*cp == '-') {
633*51667Smckusick 				do_opt(cp + 1, ep, &exflags, &anoncr);
634*51667Smckusick 				exflags |= MNT_EXPORTED;
635*51667Smckusick 				def_set = TRUE;
636*51667Smckusick 				if (debug)
637*51667Smckusick 					fprintf(stderr, "got r=%d, ex=%d\n",
638*51667Smckusick 					    anoncr.cr_uid,exflags);
63945271Smckusick 				goto more;
640*51667Smckusick 			} else {
641*51667Smckusick 				def_set = FALSE;
642*51667Smckusick 				if (*cp == '$') {
643*51667Smckusick 					do_group(cp + 1, endcp, &grp);
644*51667Smckusick 					grp->type = MNT_GROUP;
645*51667Smckusick 				} else {
646*51667Smckusick 					get_host(cp, endcp, ep, &grp);
64738460Smckusick 				}
648*51667Smckusick 				if (grp != NULL) {
649*51667Smckusick 					grp->exflags = exflags;
650*51667Smckusick 					grp->anoncr = anoncr;
651*51667Smckusick 					grp->gr_next = ep->ex_groups;
652*51667Smckusick 					ep->ex_groups = grp;
653*51667Smckusick 				}
65438460Smckusick 			}
65545271Smckusick 		more:
65638460Smckusick 			cp = endcp;
65739681Smckusick 			*cp = savedc;
65838460Smckusick 			nextfield(&cp, &endcp);
65945271Smckusick 			len = endcp - cp;
66038460Smckusick 		}
661*51667Smckusick 		if (def_set == TRUE) {
662*51667Smckusick 		    if (ep->ex_defset == TRUE)
663*51667Smckusick 			syslog(LOG_ERR, "Default specified again dir:%s\n",
664*51667Smckusick 				ep->ex_dirp);
665*51667Smckusick 		    else {
666*51667Smckusick 			struct hostent *hpe;
667*51667Smckusick 
668*51667Smckusick 			ep->ex_defset = TRUE;
669*51667Smckusick 			if (debug)
670*51667Smckusick 				fprintf(stderr,"Adding a default entry\n");
671*51667Smckusick 			/* add a default group and make the grp list NULL */
672*51667Smckusick 			hpe = (struct hostent *)malloc(sizeof(struct hostent));
673*51667Smckusick 			if (hpe == NULL) {
674*51667Smckusick 				syslog(LOG_ERR,"No more memory: mountd Failed");
675*51667Smckusick 				exit(2);
676*51667Smckusick 			}
677*51667Smckusick 			tgrp = (struct grouplist *)
678*51667Smckusick 			    malloc(sizeof(struct grouplist));
679*51667Smckusick 			if (tgrp == NULL) {
680*51667Smckusick 				syslog(LOG_ERR,"No more memory: mountd Failed");
681*51667Smckusick 				exit(2);
682*51667Smckusick 			}
683*51667Smckusick 			tgrp->anoncr = anoncr;
684*51667Smckusick 			tgrp->exflags = exflags;
685*51667Smckusick 			hpe->h_name = (char *)malloc(sizeof(DEF_NAME)+1);
686*51667Smckusick 			if (hpe->h_name == NULL) {
687*51667Smckusick 				syslog(LOG_ERR,"No more memory: mountd Failed");
688*51667Smckusick 				exit(2);
689*51667Smckusick 			}
690*51667Smckusick 			strcpy(hpe->h_name,DEF_NAME);
691*51667Smckusick 			hpe->h_addrtype = AF_INET;
692*51667Smckusick 			hpe->h_length = sizeof (u_long);
693*51667Smckusick 			hpe->h_addr_list = INADDR_ANY;
694*51667Smckusick 			tgrp->gr_ptr.gt_hostent = hpe;
695*51667Smckusick 			tgrp->gr_next = ep->ex_groups;
696*51667Smckusick 			ep->ex_groups = tgrp;
697*51667Smckusick 		    }
698*51667Smckusick 		}
699*51667Smckusick 		grp = ep->ex_groups;
700*51667Smckusick 		while (grp != NULL) {
701*51667Smckusick 			exflags = grp->exflags;
702*51667Smckusick 			anoncr = grp->anoncr;
703*51667Smckusick 			if (grp->type == MNT_GROUP) {
704*51667Smckusick 				tgrp = grp->gr_ptr.gt_grpname->gn_glist;
705*51667Smckusick 				while(tgrp != NULL) {
706*51667Smckusick 					if (do_mount(ep, tgrp, exflags, &anoncr,
707*51667Smckusick 					    dirplen) == FALSE)
708*51667Smckusick 						goto nextline;
709*51667Smckusick 					tgrp = tgrp->gr_next;
710*51667Smckusick 				}
711*51667Smckusick 			} else {
712*51667Smckusick 				if (do_mount(ep, grp, exflags, &anoncr, dirplen)
713*51667Smckusick 				    == FALSE)
714*51667Smckusick 					goto nextline;
715*51667Smckusick 			}
716*51667Smckusick 			grp = grp->gr_next;
717*51667Smckusick 		}
718*51667Smckusick 		if (cp)
719*51667Smckusick 			*cp = savedc;
720*51667Smckusick 		if (ep->ex_prev == (struct exportlist *)0) {
721*51667Smckusick 			ep->ex_next = exphead.ex_next;
722*51667Smckusick 			ep->ex_prev = &exphead;
723*51667Smckusick 			if (ep->ex_next != NULL)
724*51667Smckusick 				ep->ex_next->ex_prev = ep;
725*51667Smckusick 			exphead.ex_next = ep;
726*51667Smckusick 		}
727*51667Smckusick nextline:
728*51667Smckusick 		;
729*51667Smckusick 	}
730*51667Smckusick 	fclose(inf);
731*51667Smckusick 	return;
732*51667Smckusick err:
733*51667Smckusick 	syslog(LOG_ERR, "No more memory: mountd Failed");
734*51667Smckusick 	exit(2);
735*51667Smckusick }
736*51667Smckusick 
737*51667Smckusick do_mount(ep, grp, exflags, anoncrp, dirplen)
738*51667Smckusick 	struct exportlist *ep;
739*51667Smckusick 	struct grouplist *grp;
740*51667Smckusick 	int exflags, dirplen;
741*51667Smckusick 	struct ucred *anoncrp;
742*51667Smckusick {
743*51667Smckusick 	int done, found;
744*51667Smckusick 	register u_long **addrp;
745*51667Smckusick 	struct sockaddr_in sin;
746*51667Smckusick 	struct statfs stfsbuf;
747*51667Smckusick 	struct ufs_args args, targs;
748*51667Smckusick 	struct al_mnt *al_mp;
749*51667Smckusick 	char *cp, savedc;
750*51667Smckusick 
751*51667Smckusick 	args.fspec = 0;
752*51667Smckusick 	args.exflags = exflags;
753*51667Smckusick 	args.anon = *anoncrp;
754*51667Smckusick 	sin.sin_family = AF_INET;
755*51667Smckusick 	sin.sin_port = 0;
756*51667Smckusick 	sin.sin_len = sizeof(sin);
757*51667Smckusick 	if (grp->type == MNT_HOST)
758*51667Smckusick 		addrp = (u_long **)grp->gr_ptr.gt_hostent->h_addr_list;
759*51667Smckusick 	done = FALSE;
760*51667Smckusick 	while(!done) {
761*51667Smckusick 		if (grp->type == MNT_HOST) {
762*51667Smckusick 			if (!strcmp(grp->gr_ptr.gt_hostent->h_name, DEF_NAME))
763*51667Smckusick 				sin.sin_addr.s_addr = INADDR_ANY;
764*51667Smckusick 			else
765*51667Smckusick 				sin.sin_addr.s_addr = **addrp;
766*51667Smckusick 			args.saddr = (struct sockaddr *)&sin;
767*51667Smckusick 			args.slen = sizeof(sin);
768*51667Smckusick #ifdef ISO
769*51667Smckusick 		} else if (grp->type == MNT_ISO) {
770*51667Smckusick 			args.saddr = (struct sockaddr *)grp->gr_ptr.gt_isoaddr;
771*51667Smckusick 			args.slen = sizeof (struct sockaddr_iso);
772*51667Smckusick #endif	/* ISO */
773*51667Smckusick 		} else {
774*51667Smckusick 			syslog(LOG_ERR, "Bad grouptype");
775*51667Smckusick 			free_exp(ep);
776*51667Smckusick 			return (FALSE);
777*51667Smckusick 		}
778*51667Smckusick 		if (statfs(ep->ex_dirp, &stfsbuf) < 0) {
779*51667Smckusick 			if (debug) {
780*51667Smckusick 				fprintf(stderr,"statfs failed.\n");
781*51667Smckusick 			}
782*51667Smckusick 			syslog(LOG_ERR, "Invalid path: %s", ep->ex_dirp);
783*51667Smckusick 			free_exp(ep);
784*51667Smckusick 			return(FALSE);
785*51667Smckusick 		}
786*51667Smckusick 		found = FALSE;
787*51667Smckusick 		for (al_mp = al_head; al_mp && !found; al_mp = al_mp->al_next)
788*51667Smckusick 			if (al_mp->al_mnted.val[0] == stfsbuf.f_fsid.val[0] &&
789*51667Smckusick 			    al_mp->al_mnted.val[1] == stfsbuf.f_fsid.val[1])
790*51667Smckusick 				found = TRUE;
791*51667Smckusick 		if (!found) {
792*51667Smckusick 			/* first time for fs, so must send a MNT_DELEXPORT
793*51667Smckusick 			 * to clear the old export list held in the kernel
794*51667Smckusick 			 * for this fs.
795*51667Smckusick 			 */
796*51667Smckusick 			al_mp = (struct al_mnt *)malloc(sizeof (struct al_mnt));
797*51667Smckusick 			al_mp->al_mnted = stfsbuf.f_fsid;
798*51667Smckusick 			al_mp->al_next = al_head;
799*51667Smckusick 			al_head = al_mp;
800*51667Smckusick 			targs.fspec = 0;
801*51667Smckusick 			targs.exflags = MNT_DELEXPORT;
80244015Smckusick 			cp = (char *)0;
803*51667Smckusick 			while (mount(MOUNT_UFS, ep->ex_dirp,
804*51667Smckusick 			       stfsbuf.f_flags | MNT_UPDATE, &targs) < 0) {
805*51667Smckusick 				if (debug) {
806*51667Smckusick 					fprintf(stderr,
807*51667Smckusick 					    "tried [%s][%d]\n",
808*51667Smckusick 					    ep->ex_dirp,errno);
809*51667Smckusick 				}
81044015Smckusick 				if (cp == NULL)
81144015Smckusick 					cp = ep->ex_dirp + dirplen - 1;
81244015Smckusick 				else
81344015Smckusick 					*cp = savedc;
814*51667Smckusick 				cp--;
81544015Smckusick 				/* back up over the last component */
81644015Smckusick 				while (*cp == '/' && cp > ep->ex_dirp)
81744015Smckusick 					cp--;
81844015Smckusick 				while (*(cp - 1) != '/' && cp > ep->ex_dirp)
81944015Smckusick 					cp--;
82044015Smckusick 				if (cp == ep->ex_dirp) {
821*51667Smckusick 					if (debug) {
822*51667Smckusick 						fprintf(stderr,"mnt unsucc\n");
823*51667Smckusick 					}
824*51667Smckusick 					syslog(LOG_ERR,
825*51667Smckusick 					    "Can't export %s", ep->ex_dirp);
82644015Smckusick 					free_exp(ep);
827*51667Smckusick 					return(FALSE);
82844015Smckusick 				}
82944015Smckusick 				savedc = *cp;
83044015Smckusick 				*cp = '\0';
83144015Smckusick 			}
832*51667Smckusick 			if (cp != NULL) {
83344015Smckusick 				*cp = savedc;
834*51667Smckusick 			}
83538460Smckusick 		}
836*51667Smckusick 		cp = (char *)0;
837*51667Smckusick 		while (mount(MOUNT_UFS, ep->ex_dirp,
838*51667Smckusick 		       stfsbuf.f_flags | MNT_UPDATE, &args) < 0) {
839*51667Smckusick 			if (errno == EPERM) {
840*51667Smckusick 				syslog(LOG_ERR,
841*51667Smckusick 				     "Can't change attributes for %s.\n",
842*51667Smckusick 				     ep->ex_dirp);
843*51667Smckusick 				if (cp != NULL)
844*51667Smckusick 					*cp = savedc;
845*51667Smckusick 				break;
846*51667Smckusick 			}
847*51667Smckusick 			if (cp == NULL)
848*51667Smckusick 				cp = ep->ex_dirp + dirplen - 1;
849*51667Smckusick 			else
850*51667Smckusick 				*cp = savedc;
851*51667Smckusick 			cp--;
852*51667Smckusick 			/* back up over the last component */
853*51667Smckusick 			while (*cp == '/' && cp > ep->ex_dirp)
854*51667Smckusick 				cp--;
855*51667Smckusick 			while (*(cp - 1) != '/' && cp > ep->ex_dirp)
856*51667Smckusick 				cp--;
857*51667Smckusick 			if (cp == ep->ex_dirp) {
858*51667Smckusick 				if (debug) {
859*51667Smckusick 					fprintf(stderr,"mnt unsucc\n");
860*51667Smckusick 				}
861*51667Smckusick 				syslog(LOG_ERR, "Can't export %s", ep->ex_dirp);
862*51667Smckusick 				free_exp(ep);
863*51667Smckusick 				return(FALSE);
864*51667Smckusick 			}
865*51667Smckusick 			savedc = *cp;
866*51667Smckusick 			*cp = '\0';
867*51667Smckusick 		}
868*51667Smckusick 		if (addrp == NULL)
869*51667Smckusick 			done = TRUE;
870*51667Smckusick 		else {
871*51667Smckusick 			++addrp;
872*51667Smckusick 			if (*addrp == NULL)
873*51667Smckusick 				done = TRUE;
874*51667Smckusick 		}
875*51667Smckusick 		if (cp != NULL)
876*51667Smckusick 			*cp = savedc;
87738460Smckusick 	}
878*51667Smckusick 	return(TRUE);
87938460Smckusick }
88038460Smckusick 
881*51667Smckusick 
88238460Smckusick /*
88338460Smckusick  * Parse out the next white space separated field
88438460Smckusick  */
885*51667Smckusick void
88638460Smckusick nextfield(cp, endcp)
88738460Smckusick 	char **cp;
88838460Smckusick 	char **endcp;
88938460Smckusick {
89038460Smckusick 	register char *p;
89138460Smckusick 
89238460Smckusick 	p = *cp;
89338460Smckusick 	while (*p == ' ' || *p == '\t')
89438460Smckusick 		p++;
89538460Smckusick 	if (*p == '\n' || *p == '\0') {
89638460Smckusick 		*cp = *endcp = p;
89738460Smckusick 		return;
89838460Smckusick 	}
89938460Smckusick 	*cp = p++;
90038460Smckusick 	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
90138460Smckusick 		p++;
90238460Smckusick 	*endcp = p;
90338460Smckusick }
90439681Smckusick 
90539681Smckusick /*
90644015Smckusick  * Parse the option string
90739681Smckusick  */
908*51667Smckusick void
909*51667Smckusick do_opt(cpopt, ep, exflagsp, cr)
91044015Smckusick 	register char *cpopt;
911*51667Smckusick 	struct exportlist *ep;
912*51667Smckusick 	int *exflagsp;
913*51667Smckusick 	struct ucred *cr;
91439681Smckusick {
91544015Smckusick 	register char *cpoptarg, *cpoptend;
916*51667Smckusick 	int allflag;
91739681Smckusick 
91844015Smckusick 	while (cpopt && *cpopt) {
91944015Smckusick 		if (cpoptend = index(cpopt, ','))
92044015Smckusick 			*cpoptend++ = '\0';
92144015Smckusick 		if (cpoptarg = index(cpopt, '='))
92244015Smckusick 			*cpoptarg++ = '\0';
92344015Smckusick 		if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) {
924*51667Smckusick 			*exflagsp |= MNT_EXRDONLY;
925*51667Smckusick 		} else if ((!strcmp(cpopt, "root") || !strcmp(cpopt, "r") ||
926*51667Smckusick 		    !(allflag = strcmp(cpopt, "allanon"))) && cpoptarg) {
927*51667Smckusick 			parsecred(cpoptarg, cr);
928*51667Smckusick 			if (allflag == 0)
929*51667Smckusick 				*exflagsp |= MNT_EXPORTANON;
930*51667Smckusick 		} else if (!strcmp(cpopt, "kerb") || !strcmp(cpopt, "k")) {
931*51667Smckusick 			*exflagsp |= MNT_EXKERB;
93244015Smckusick 		} else
933*51667Smckusick 			syslog(LOG_ERR, "opt %s ignored for %s", cpopt,
93444015Smckusick 			       ep->ex_dirp);
93544015Smckusick 		cpopt = cpoptend;
93644015Smckusick 	}
93744015Smckusick }
93844015Smckusick 
939*51667Smckusick /*
940*51667Smckusick  * Parse a description of a credential.
941*51667Smckusick  */
942*51667Smckusick parsecred(namelist, cr)
943*51667Smckusick 	char *namelist;
944*51667Smckusick 	register struct ucred *cr;
945*51667Smckusick {
946*51667Smckusick 	register char *name;
947*51667Smckusick 	register int cnt;
948*51667Smckusick 	char *names;
949*51667Smckusick 	struct passwd *pw;
950*51667Smckusick 	struct group *gr;
951*51667Smckusick 	int ngroups, groups[NGROUPS + 1];
952*51667Smckusick 
953*51667Smckusick 	/*
954*51667Smckusick 	 * Set up the unpriviledged user.
955*51667Smckusick 	 */
956*51667Smckusick 	cr->cr_ref = 1;
957*51667Smckusick 	cr->cr_uid = -2;
958*51667Smckusick 	cr->cr_groups[0] = -2;
959*51667Smckusick 	cr->cr_ngroups = 1;
960*51667Smckusick 	/*
961*51667Smckusick 	 * Get the user's password table entry.
962*51667Smckusick 	 */
963*51667Smckusick 	names = strsep(&namelist, " \t\n");
964*51667Smckusick 	name = strsep(&names, ":");
965*51667Smckusick 	if (isdigit(*name) || *name == '-')
966*51667Smckusick 		pw = getpwuid(atoi(name));
967*51667Smckusick 	else
968*51667Smckusick 		pw = getpwnam(name);
969*51667Smckusick 	/*
970*51667Smckusick 	 * Credentials specified as those of a user.
971*51667Smckusick 	 */
972*51667Smckusick 	if (names == NULL) {
973*51667Smckusick 		if (pw == NULL) {
974*51667Smckusick 			syslog(LOG_ERR, "Unknown user: %s\n", name);
975*51667Smckusick 			return;
976*51667Smckusick 		}
977*51667Smckusick 		cr->cr_uid = pw->pw_uid;
978*51667Smckusick 		ngroups = NGROUPS + 1;
979*51667Smckusick 		if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups))
980*51667Smckusick 			syslog(LOG_ERR, "Too many groups\n");
981*51667Smckusick 		/*
982*51667Smckusick 		 * Convert from int's to gid_t's and compress out duplicate
983*51667Smckusick 		 */
984*51667Smckusick 		cr->cr_ngroups = ngroups - 1;
985*51667Smckusick 		cr->cr_groups[0] = groups[0];
986*51667Smckusick 		for (cnt = 2; cnt < ngroups; cnt++)
987*51667Smckusick 			cr->cr_groups[cnt - 1] = groups[cnt];
988*51667Smckusick 		return;
989*51667Smckusick 	}
990*51667Smckusick 	/*
991*51667Smckusick 	 * Explicit credential specified as a colon separated list:
992*51667Smckusick 	 *	uid:gid:gid:...
993*51667Smckusick 	 */
994*51667Smckusick 	if (pw != NULL)
995*51667Smckusick 		cr->cr_uid = pw->pw_uid;
996*51667Smckusick 	else if (isdigit(*name) || *name == '-')
997*51667Smckusick 		cr->cr_uid = atoi(name);
998*51667Smckusick 	else {
999*51667Smckusick 		syslog(LOG_ERR, "Unknown user: %s\n", name);
1000*51667Smckusick 		return;
1001*51667Smckusick 	}
1002*51667Smckusick 	cr->cr_ngroups = 0;
1003*51667Smckusick 	while (names != NULL && *names != '\0' && cr->cr_ngroups < NGROUPS) {
1004*51667Smckusick 		name = strsep(&names, ":");
1005*51667Smckusick 		if (isdigit(*name) || *name == '-') {
1006*51667Smckusick 			cr->cr_groups[cr->cr_ngroups++] = atoi(name);
1007*51667Smckusick 		} else {
1008*51667Smckusick 			if ((gr = getgrnam(name)) == NULL) {
1009*51667Smckusick 				syslog(LOG_ERR, "Unknown group: %s\n", name);
1010*51667Smckusick 				continue;
1011*51667Smckusick 			}
1012*51667Smckusick 			cr->cr_groups[cr->cr_ngroups++] = gr->gr_gid;
1013*51667Smckusick 		}
1014*51667Smckusick 	}
1015*51667Smckusick 	if (names != NULL && *names != '\0' && cr->cr_ngroups == NGROUPS)
1016*51667Smckusick 		syslog(LOG_ERR, "Too many groups\n");
1017*51667Smckusick }
1018*51667Smckusick 
101944015Smckusick #define	STRSIZ	(RPCMNT_NAMELEN+RPCMNT_PATHLEN+50)
102044015Smckusick /*
102144015Smckusick  * Routines that maintain the remote mounttab
102244015Smckusick  */
1023*51667Smckusick void
1024*51667Smckusick get_mountlist()
102544015Smckusick {
102644015Smckusick 	register struct mountlist *mlp, **mlpp;
102744015Smckusick 	register char *eos, *dirp;
102844015Smckusick 	int len;
102944015Smckusick 	char str[STRSIZ];
103044015Smckusick 	FILE *mlfile;
103144015Smckusick 
103244338Smckusick 	if (((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) &&
103344338Smckusick 	    ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL)) {
1034*51667Smckusick 		syslog(LOG_ERR, "Can't open %s", _PATH_RMOUNTLIST);
103544015Smckusick 		return;
103644015Smckusick 	}
103744015Smckusick 	mlpp = &mlhead;
103844015Smckusick 	while (fgets(str, STRSIZ, mlfile) != NULL) {
103944015Smckusick 		if ((dirp = index(str, '\t')) == NULL &&
104044015Smckusick 		    (dirp = index(str, ' ')) == NULL)
104144015Smckusick 			continue;
104244015Smckusick 		mlp = (struct mountlist *)malloc(sizeof (*mlp));
104344015Smckusick 		len = dirp-str;
104444015Smckusick 		if (len > RPCMNT_NAMELEN)
104544015Smckusick 			len = RPCMNT_NAMELEN;
104644015Smckusick 		bcopy(str, mlp->ml_host, len);
104744015Smckusick 		mlp->ml_host[len] = '\0';
104844015Smckusick 		while (*dirp == '\t' || *dirp == ' ')
104944015Smckusick 			dirp++;
105044015Smckusick 		if ((eos = index(dirp, '\t')) == NULL &&
105144015Smckusick 		    (eos = index(dirp, ' ')) == NULL &&
105244015Smckusick 		    (eos = index(dirp, '\n')) == NULL)
105344015Smckusick 			len = strlen(dirp);
105444015Smckusick 		else
105544015Smckusick 			len = eos-dirp;
105644015Smckusick 		if (len > RPCMNT_PATHLEN)
105744015Smckusick 			len = RPCMNT_PATHLEN;
105844015Smckusick 		bcopy(dirp, mlp->ml_dirp, len);
105944015Smckusick 		mlp->ml_dirp[len] = '\0';
106044015Smckusick 		mlp->ml_next = (struct mountlist *)0;
106144015Smckusick 		*mlpp = mlp;
106244015Smckusick 		mlpp = &mlp->ml_next;
106344015Smckusick 	}
106444015Smckusick 	fclose(mlfile);
106544015Smckusick }
106644015Smckusick 
1067*51667Smckusick void
1068*51667Smckusick del_mlist(hostp, dirp)
106944015Smckusick 	register char *hostp, *dirp;
107044015Smckusick {
107144015Smckusick 	register struct mountlist *mlp, **mlpp;
107244015Smckusick 	FILE *mlfile;
107344015Smckusick 	int fnd = 0;
107444015Smckusick 
107544015Smckusick 	mlpp = &mlhead;
107644015Smckusick 	mlp = mlhead;
107744015Smckusick 	while (mlp) {
107844015Smckusick 		if (!strcmp(mlp->ml_host, hostp) &&
107944015Smckusick 		    (!dirp || !strcmp(mlp->ml_dirp, dirp))) {
108044015Smckusick 			fnd = 1;
108144015Smckusick 			*mlpp = mlp->ml_next;
108244015Smckusick 			free((caddr_t)mlp);
108339681Smckusick 		}
108444015Smckusick 		mlpp = &mlp->ml_next;
108544015Smckusick 		mlp = mlp->ml_next;
108639681Smckusick 	}
108744015Smckusick 	if (fnd) {
108844015Smckusick 		if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) {
1089*51667Smckusick 			syslog(LOG_WARNING,"Can't update %s", _PATH_RMOUNTLIST);
109044015Smckusick 			return;
109144015Smckusick 		}
109244015Smckusick 		mlp = mlhead;
109344015Smckusick 		while (mlp) {
109444015Smckusick 			fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp);
109544015Smckusick 			mlp = mlp->ml_next;
109644015Smckusick 		}
109744015Smckusick 		fclose(mlfile);
109844015Smckusick 	}
109939681Smckusick }
110044015Smckusick 
1101*51667Smckusick void
1102*51667Smckusick add_mlist(hostp, dirp)
110344015Smckusick 	register char *hostp, *dirp;
110444015Smckusick {
110544015Smckusick 	register struct mountlist *mlp, **mlpp;
110644015Smckusick 	FILE *mlfile;
110744015Smckusick 
110844015Smckusick 	mlpp = &mlhead;
110944015Smckusick 	mlp = mlhead;
111044015Smckusick 	while (mlp) {
111144015Smckusick 		if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp))
111244015Smckusick 			return;
111344015Smckusick 		mlpp = &mlp->ml_next;
111444015Smckusick 		mlp = mlp->ml_next;
111544015Smckusick 	}
111644015Smckusick 	mlp = (struct mountlist *)malloc(sizeof (*mlp));
111744015Smckusick 	strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN);
111844015Smckusick 	mlp->ml_host[RPCMNT_NAMELEN] = '\0';
111944015Smckusick 	strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN);
112044015Smckusick 	mlp->ml_dirp[RPCMNT_PATHLEN] = '\0';
112144015Smckusick 	mlp->ml_next = (struct mountlist *)0;
112244015Smckusick 	*mlpp = mlp;
112344015Smckusick 	if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) {
112444015Smckusick 		syslog(LOG_WARNING, "Can't update %s", _PATH_RMOUNTLIST);
112544015Smckusick 		return;
112644015Smckusick 	}
112744015Smckusick 	fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp);
112844015Smckusick 	fclose(mlfile);
112944015Smckusick }
113044015Smckusick 
113144015Smckusick /*
113244015Smckusick  * This function is called via. SIGTERM when the system is going down.
113344015Smckusick  * It sends a broadcast RPCMNT_UMNTALL.
113444015Smckusick  */
113546709Sbostic void
113644015Smckusick send_umntall()
113744015Smckusick {
113844015Smckusick 	(void) clnt_broadcast(RPCPROG_MNT, RPCMNT_VER1, RPCMNT_UMNTALL,
113944015Smckusick 		xdr_void, (caddr_t)0, xdr_void, (caddr_t)0, umntall_each);
1140*51667Smckusick 	exit(0);
114144015Smckusick }
114244015Smckusick 
114344015Smckusick umntall_each(resultsp, raddr)
114444015Smckusick 	caddr_t resultsp;
114544015Smckusick 	struct sockaddr_in *raddr;
114644015Smckusick {
114744015Smckusick 	return (1);
114844015Smckusick }
114944015Smckusick 
115044015Smckusick /*
115144015Smckusick  * Free up an exports list component
115244015Smckusick  */
1153*51667Smckusick void
115444015Smckusick free_exp(ep)
115544015Smckusick 	register struct exportlist *ep;
115644015Smckusick {
115744015Smckusick 	register struct grouplist *grp;
115844015Smckusick 	struct grouplist *grp2;
115944015Smckusick 
116044015Smckusick 	grp = ep->ex_groups;
116144015Smckusick 	while (grp != NULL) {
116244015Smckusick 		grp2 = grp;
116344015Smckusick 		grp = grp->gr_next;
1164*51667Smckusick 		free_grp(grp2);
116544015Smckusick 	}
116644015Smckusick 	free((caddr_t)ep);
116744015Smckusick }
1168*51667Smckusick 
1169*51667Smckusick /*
1170*51667Smckusick  * Free up a group list.
1171*51667Smckusick  */
1172*51667Smckusick void
1173*51667Smckusick free_grp(grp)
1174*51667Smckusick 	register struct grouplist *grp;
1175*51667Smckusick {
1176*51667Smckusick 	register char **addrp;
1177*51667Smckusick 
1178*51667Smckusick 	if (grp->type == MNT_HOST) {
1179*51667Smckusick 		addrp = grp->gr_ptr.gt_hostent->h_addr_list;
1180*51667Smckusick 		while (addrp && *addrp)
1181*51667Smckusick 			free(*addrp++);
1182*51667Smckusick 		free((caddr_t)grp->gr_ptr.gt_hostent->h_addr_list);
1183*51667Smckusick 		free(grp->gr_ptr.gt_hostent->h_name);
1184*51667Smckusick 		free((caddr_t)grp->gr_ptr.gt_hostent);
1185*51667Smckusick 	}
1186*51667Smckusick #ifdef ISO
1187*51667Smckusick 	else if (grp->type == MNT_ISO)
1188*51667Smckusick 		free((caddr_t)grp->gr_ptr.gt_isoaddr);
1189*51667Smckusick #endif
1190*51667Smckusick 	free((caddr_t)grp);
1191*51667Smckusick }
1192*51667Smckusick 
1193*51667Smckusick void
1194*51667Smckusick get_group(line, ep)
1195*51667Smckusick 	char *line;
1196*51667Smckusick 	struct export_list *ep;
1197*51667Smckusick {
1198*51667Smckusick 	int done;
1199*51667Smckusick 	struct grouplist *grp;
1200*51667Smckusick 	struct groupnames *t_gn;
1201*51667Smckusick 	char *cp, *endcp, savedc;
1202*51667Smckusick 
1203*51667Smckusick 	cp = line;
1204*51667Smckusick 	nextfield(&cp, &endcp);
1205*51667Smckusick 	savedc = *endcp;
1206*51667Smckusick 	*endcp = NULL;
1207*51667Smckusick 	if (*(endcp-1) == '=') {
1208*51667Smckusick 		*(endcp-1) = NULL;
1209*51667Smckusick 	}
1210*51667Smckusick 	/* check to see if this group exists already */
1211*51667Smckusick 	t_gn = grpnames;
1212*51667Smckusick 	while(t_gn != NULL) {
1213*51667Smckusick 		if (strcmp(t_gn->gn_name,cp) == 0) {
1214*51667Smckusick 			syslog(LOG_ERR,"Group redifined, second ignored.");
1215*51667Smckusick 			return;
1216*51667Smckusick 		}
1217*51667Smckusick 		t_gn = t_gn->gn_next;
1218*51667Smckusick 	}
1219*51667Smckusick 
1220*51667Smckusick 	/* make a new group list entry */
1221*51667Smckusick 	t_gn = (struct groupnames *)malloc(sizeof(struct groupnames));
1222*51667Smckusick 	if (t_gn == NULL) {
1223*51667Smckusick 		syslog(LOG_ERR,"Group: Couldn't Malloc.");
1224*51667Smckusick 		exit(2);
1225*51667Smckusick 	}
1226*51667Smckusick 	strcpy(t_gn->gn_name,cp);
1227*51667Smckusick 	t_gn->gn_next = grpnames;
1228*51667Smckusick 	grpnames = t_gn;
1229*51667Smckusick 	t_gn->gn_glist = NULL;
1230*51667Smckusick 	*endcp = savedc;
1231*51667Smckusick 	cp = endcp;
1232*51667Smckusick 	done = FALSE;
1233*51667Smckusick 	while(!done) {
1234*51667Smckusick 		nextfield(&cp, &endcp);
1235*51667Smckusick 		if (cp == endcp)
1236*51667Smckusick 			done = TRUE;
1237*51667Smckusick 		else {
1238*51667Smckusick 			savedc = *endcp;
1239*51667Smckusick 			*endcp = NULL;
1240*51667Smckusick 			if (strcmp(cp, "=")) {
1241*51667Smckusick 				/* add to group list */
1242*51667Smckusick 				get_host(cp, endcp, ep, &grp);
1243*51667Smckusick 				if (grp != NULL) {
1244*51667Smckusick 					grp->gr_next = t_gn->gn_glist;
1245*51667Smckusick 					t_gn->gn_glist = grp;
1246*51667Smckusick 				}
1247*51667Smckusick 			}
1248*51667Smckusick 			*endcp = savedc;
1249*51667Smckusick 			cp = endcp;
1250*51667Smckusick 		}
1251*51667Smckusick 	}
1252*51667Smckusick }
1253*51667Smckusick 
1254*51667Smckusick void
1255*51667Smckusick get_host(cp, endcp, ep, gp)
1256*51667Smckusick 	char *cp, *endcp;
1257*51667Smckusick 	struct exportlist *ep;
1258*51667Smckusick 	struct grouplist **gp;
1259*51667Smckusick {
1260*51667Smckusick 	register struct hostent *hp, *nhp;
1261*51667Smckusick 	register struct grouplist *grp;
1262*51667Smckusick 	register char **addrp, **naddrp;
1263*51667Smckusick 	struct hostent t_host;
1264*51667Smckusick 	int i;
1265*51667Smckusick 	u_long saddr;
1266*51667Smckusick 	char *aptr[2];
1267*51667Smckusick #ifdef ISO
1268*51667Smckusick 	struct iso_addr *isop;
1269*51667Smckusick 	struct sockaddr_iso *isoaddr;
1270*51667Smckusick #endif
1271*51667Smckusick 
1272*51667Smckusick 	if (isdigit(*cp)) {
1273*51667Smckusick 		saddr = inet_addr(cp);
1274*51667Smckusick 		if (saddr == -1) {
1275*51667Smckusick 			syslog(LOG_ERR,
1276*51667Smckusick 			    "Bad Exports File, %s: %s", cp,
1277*51667Smckusick 			    "inet_addr failed, ignored");
1278*51667Smckusick 			*gp = NULL;
1279*51667Smckusick 			return;
1280*51667Smckusick 		}
1281*51667Smckusick 		hp = &t_host;
1282*51667Smckusick 		hp->h_name = cp;
1283*51667Smckusick 		hp->h_addrtype = AF_INET;
1284*51667Smckusick 		hp->h_length = sizeof (u_long);
1285*51667Smckusick 		hp->h_addr_list = aptr;
1286*51667Smckusick 		aptr[0] = (char *)&saddr;
1287*51667Smckusick 		aptr[1] = (char *)0;
1288*51667Smckusick #ifdef ISO
1289*51667Smckusick 	} else if (!strncmp(cp, "iso=", 4)) {
1290*51667Smckusick 		if ((isop = iso_addr(cp + 4)) == NULL) {
1291*51667Smckusick 			syslog(LOG_ERR,
1292*51667Smckusick 			    "Bad Exports File, %s: %s", cp,
1293*51667Smckusick 			    "iso_addr failed, ignored");
1294*51667Smckusick 			*gp = NULL;
1295*51667Smckusick 			return;
1296*51667Smckusick 		}
1297*51667Smckusick 		isoaddr = (struct sockaddr_iso *)
1298*51667Smckusick 		    malloc(sizeof (struct sockaddr_iso));
1299*51667Smckusick 		if (isoaddr == NULL)
1300*51667Smckusick 			goto err1;
1301*51667Smckusick 		bzero((caddr_t)isoaddr, sizeof (struct sockaddr_iso));
1302*51667Smckusick 		bcopy((caddr_t)isop, (caddr_t)isoaddr->siso_addr,
1303*51667Smckusick 			sizeof (struct iso_addr));
1304*51667Smckusick 		isoaddr->siso_len = sizeof (struct sockaddr_iso);
1305*51667Smckusick 		isoaddr->siso_family = AF_ISO;
1306*51667Smckusick 		grp = (struct grouplist *)
1307*51667Smckusick 			malloc(sizeof(struct grouplist));
1308*51667Smckusick 		if (grp == NULL)
1309*51667Smckusick 			goto err1;
1310*51667Smckusick 		grp->type = MNT_ISO;
1311*51667Smckusick 		grp->gr_ptr.gt_isoaddr = isoaddr;
1312*51667Smckusick 		*gp = grp;
1313*51667Smckusick 		return;
1314*51667Smckusick #endif	/* ISO */
1315*51667Smckusick 	} else if ((hp = gethostbyname(cp)) == NULL) {
1316*51667Smckusick 		syslog(LOG_ERR, "Bad Exports File, %s: %s",
1317*51667Smckusick 		    cp, "Gethostbyname failed, ignored");
1318*51667Smckusick 		*gp = NULL;
1319*51667Smckusick 		return;
1320*51667Smckusick 	}
1321*51667Smckusick 	grp = (struct grouplist *)
1322*51667Smckusick 		malloc(sizeof(struct grouplist));
1323*51667Smckusick 	if (grp == NULL)
1324*51667Smckusick 		goto err1;
1325*51667Smckusick 	grp->type = MNT_HOST;
1326*51667Smckusick 	nhp = grp->gr_ptr.gt_hostent = (struct hostent *)
1327*51667Smckusick 		malloc(sizeof(struct hostent));
1328*51667Smckusick 	if (nhp == NULL)
1329*51667Smckusick 		goto err1;
1330*51667Smckusick 	bcopy((caddr_t)hp, (caddr_t)nhp,
1331*51667Smckusick 		sizeof(struct hostent));
1332*51667Smckusick 	i = strlen(hp->h_name)+1;
1333*51667Smckusick 	nhp->h_name = (char *)malloc(i);
1334*51667Smckusick 	if (nhp->h_name == NULL)
1335*51667Smckusick 		goto err1;
1336*51667Smckusick 	bcopy(hp->h_name, nhp->h_name, i);
1337*51667Smckusick 	addrp = hp->h_addr_list;
1338*51667Smckusick 	i = 1;
1339*51667Smckusick 	while (*addrp++)
1340*51667Smckusick 		i++;
1341*51667Smckusick 	naddrp = nhp->h_addr_list = (char **)
1342*51667Smckusick 		malloc(i*sizeof(char *));
1343*51667Smckusick 	if (naddrp == NULL)
1344*51667Smckusick 		goto err1;
1345*51667Smckusick 	addrp = hp->h_addr_list;
1346*51667Smckusick 	while (*addrp) {
1347*51667Smckusick 		*naddrp = (char *)
1348*51667Smckusick 		    malloc(hp->h_length);
1349*51667Smckusick 		if (*naddrp == NULL)
1350*51667Smckusick 		    goto err1;
1351*51667Smckusick 		bcopy(*addrp, *naddrp,
1352*51667Smckusick 			hp->h_length);
1353*51667Smckusick 		addrp++;
1354*51667Smckusick 		naddrp++;
1355*51667Smckusick 	}
1356*51667Smckusick 	*naddrp = (char *)0;
1357*51667Smckusick 	*gp = grp;
1358*51667Smckusick 	return;
1359*51667Smckusick err1:
1360*51667Smckusick 	syslog(LOG_ERR, "No more memory: mountd Failed");
1361*51667Smckusick 	exit(2);
1362*51667Smckusick }
1363*51667Smckusick 
1364*51667Smckusick void
1365*51667Smckusick do_group(cp, endcp, gp)
1366*51667Smckusick 	char *cp, *endcp;
1367*51667Smckusick 	struct grouplist **gp;
1368*51667Smckusick {
1369*51667Smckusick 	int found;
1370*51667Smckusick 	struct groupnames *t_gn;
1371*51667Smckusick 
1372*51667Smckusick 	t_gn = grpnames;
1373*51667Smckusick 	found = FALSE;
1374*51667Smckusick 	while((t_gn != NULL) && !found) {
1375*51667Smckusick 		if(strcmp(t_gn->gn_name,cp) == 0) {
1376*51667Smckusick 			found = TRUE;
1377*51667Smckusick 			*gp = (struct grouplist *)
1378*51667Smckusick 			    malloc(sizeof(struct grouplist));
1379*51667Smckusick 			if (*gp == NULL) {
1380*51667Smckusick 				syslog(LOG_ERR,"No more memory: mountd Failed");
1381*51667Smckusick 				exit(2);
1382*51667Smckusick 			}
1383*51667Smckusick 			(*gp)->gr_ptr.gt_grpname = (struct groupnames *)
1384*51667Smckusick 			    malloc(sizeof(struct groupnames));
1385*51667Smckusick 			if ((*gp)->gr_ptr.gt_grpname == NULL) {
1386*51667Smckusick 				syslog(LOG_ERR,"No more memory: mountd Failed");
1387*51667Smckusick 				exit(2);
1388*51667Smckusick 			}
1389*51667Smckusick 			(*gp)->gr_ptr.gt_grpname->gn_glist = t_gn->gn_glist;
1390*51667Smckusick 			return;
1391*51667Smckusick 		}
1392*51667Smckusick 		t_gn = t_gn->gn_next;
1393*51667Smckusick 	}
1394*51667Smckusick 	*gp = NULL;
1395*51667Smckusick }
1396*51667Smckusick 
1397*51667Smckusick /*
1398*51667Smckusick  * char *realpath(const char *path, char resolved_path[MAXPATHLEN])
1399*51667Smckusick  *
1400*51667Smckusick  * find the real name of path, by removing all ".", ".."
1401*51667Smckusick  * and symlink components.
1402*51667Smckusick  *
1403*51667Smckusick  * Jan-Simon Pendry, September 1991.
1404*51667Smckusick  */
1405*51667Smckusick char *
1406*51667Smckusick realpath(path, resolved)
1407*51667Smckusick 	char *path;
1408*51667Smckusick 	char resolved[MAXPATHLEN];
1409*51667Smckusick {
1410*51667Smckusick 	int d = open(".", O_RDONLY);
1411*51667Smckusick 	int rootd = 0;
1412*51667Smckusick 	char *p, *q;
1413*51667Smckusick 	struct stat stb;
1414*51667Smckusick 	char wbuf[MAXPATHLEN];
1415*51667Smckusick 
1416*51667Smckusick 	strcpy(resolved, path);
1417*51667Smckusick 
1418*51667Smckusick 	if (d < 0)
1419*51667Smckusick 		return 0;
1420*51667Smckusick 
1421*51667Smckusick loop:;
1422*51667Smckusick 	q = strrchr(resolved, '/');
1423*51667Smckusick 	if (q) {
1424*51667Smckusick 		p = q + 1;
1425*51667Smckusick 		if (q == resolved)
1426*51667Smckusick 			q = "/";
1427*51667Smckusick 		else {
1428*51667Smckusick 			do
1429*51667Smckusick 				--q;
1430*51667Smckusick 			while (q > resolved && *q == '/');
1431*51667Smckusick 			q[1] = '\0';
1432*51667Smckusick 			q = resolved;
1433*51667Smckusick 		}
1434*51667Smckusick 		if (chdir(q) < 0)
1435*51667Smckusick 			goto out;
1436*51667Smckusick 	} else
1437*51667Smckusick 		p = resolved;
1438*51667Smckusick 
1439*51667Smckusick 	if (lstat(p, &stb) == 0) {
1440*51667Smckusick 		if (S_ISLNK(stb.st_mode)) {
1441*51667Smckusick 			int n = readlink(p, resolved, MAXPATHLEN);
1442*51667Smckusick 			if (n < 0)
1443*51667Smckusick 				goto out;
1444*51667Smckusick 			resolved[n] = '\0';
1445*51667Smckusick 			goto loop;
1446*51667Smckusick 		}
1447*51667Smckusick 		if (S_ISDIR(stb.st_mode)) {
1448*51667Smckusick 			if (chdir(p) < 0)
1449*51667Smckusick 				goto out;
1450*51667Smckusick 			p = "";
1451*51667Smckusick 		}
1452*51667Smckusick 	}
1453*51667Smckusick 
1454*51667Smckusick 	strcpy(wbuf, p);
1455*51667Smckusick 	if (getcwd(resolved, MAXPATHLEN) == 0)
1456*51667Smckusick 		goto out;
1457*51667Smckusick 	if (resolved[0] == '/' && resolved[1] == '\0')
1458*51667Smckusick 		rootd = 1;
1459*51667Smckusick 
1460*51667Smckusick 	if (*wbuf) {
1461*51667Smckusick 		if (strlen(resolved) + strlen(wbuf) + rootd + 1 > MAXPATHLEN) {
1462*51667Smckusick 			errno = ENAMETOOLONG;
1463*51667Smckusick 			goto out;
1464*51667Smckusick 		}
1465*51667Smckusick 		if (rootd == 0)
1466*51667Smckusick 			strcat(resolved, "/");
1467*51667Smckusick 		strcat(resolved, wbuf);
1468*51667Smckusick 	}
1469*51667Smckusick 
1470*51667Smckusick 	if (fchdir(d) < 0)
1471*51667Smckusick 		goto out;
1472*51667Smckusick 	(void) close(d);
1473*51667Smckusick 
1474*51667Smckusick 	return resolved;
1475*51667Smckusick 
1476*51667Smckusick out:;
1477*51667Smckusick 	(void) close(d);
1478*51667Smckusick 	return 0;
1479*51667Smckusick }
1480