xref: /csrg-svn/sbin/mount_nfs/mount_nfs.c (revision 68150)
152112Smckusick /*
266483Sbostic  * Copyright (c) 1992, 1993, 1994
361511Sbostic  *	The Regents of the University of California.  All rights reserved.
452112Smckusick  *
552112Smckusick  * This code is derived from software contributed to Berkeley by
652112Smckusick  * Rick Macklem at The University of Guelph.
752112Smckusick  *
852112Smckusick  * %sccs.include.redist.c%
952112Smckusick  */
1052112Smckusick 
1152112Smckusick #ifndef lint
1261511Sbostic static char copyright[] =
1366483Sbostic "@(#) Copyright (c) 1992, 1993, 1994\n\
1461511Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1552112Smckusick #endif /* not lint */
1652112Smckusick 
1752112Smckusick #ifndef lint
18*68150Smckusick static char sccsid[] = "@(#)mount_nfs.c	8.6 (Berkeley) 01/07/95";
1952112Smckusick #endif /* not lint */
2052112Smckusick 
2152112Smckusick #include <sys/param.h>
2252112Smckusick #include <sys/mount.h>
2352112Smckusick #include <sys/socket.h>
2452112Smckusick #include <sys/socketvar.h>
2556407Sbostic #include <sys/stat.h>
2656407Sbostic #include <sys/syslog.h>
2756407Sbostic 
2852112Smckusick #include <rpc/rpc.h>
2952112Smckusick #include <rpc/pmap_clnt.h>
3052112Smckusick #include <rpc/pmap_prot.h>
3156407Sbostic 
3252112Smckusick #ifdef ISO
3352112Smckusick #include <netiso/iso.h>
3452112Smckusick #endif
3556407Sbostic 
3652112Smckusick #ifdef KERBEROS
3757811Smckusick #include <kerberosIV/des.h>
3852112Smckusick #include <kerberosIV/krb.h>
3952112Smckusick #endif
4056407Sbostic 
4152112Smckusick #include <nfs/rpcv2.h>
4252112Smckusick #include <nfs/nfsv2.h>
4356407Sbostic #define KERNEL
4452112Smckusick #include <nfs/nfs.h>
4556407Sbostic #undef KERNEL
4652112Smckusick #include <nfs/nqnfs.h>
4752112Smckusick 
4856407Sbostic #include <arpa/inet.h>
4956407Sbostic 
5056407Sbostic #include <ctype.h>
5166483Sbostic #include <err.h>
5256407Sbostic #include <errno.h>
5356407Sbostic #include <fcntl.h>
5456407Sbostic #include <netdb.h>
5556407Sbostic #include <signal.h>
5656407Sbostic #include <stdio.h>
5756407Sbostic #include <stdlib.h>
5856407Sbostic #include <strings.h>
5956407Sbostic #include <unistd.h>
6056407Sbostic 
6166483Sbostic #include "mntopts.h"
6266483Sbostic 
6366483Sbostic struct mntopt mopts[] = {
6466483Sbostic 	MOPT_STDOPTS,
6566483Sbostic 	MOPT_FORCE,
6666483Sbostic 	MOPT_UPDATE,
6766483Sbostic 	{ NULL }
6866483Sbostic };
6966483Sbostic 
7052112Smckusick struct nfs_args nfsdefargs = {
7152112Smckusick 	(struct sockaddr *)0,
7252112Smckusick 	sizeof (struct sockaddr_in),
7352112Smckusick 	SOCK_DGRAM,
7452112Smckusick 	0,
7552112Smckusick 	(nfsv2fh_t *)0,
7652112Smckusick 	0,
7752112Smckusick 	NFS_WSIZE,
7852112Smckusick 	NFS_RSIZE,
7952112Smckusick 	NFS_TIMEO,
8052112Smckusick 	NFS_RETRANS,
8152112Smckusick 	NFS_MAXGRPS,
8252112Smckusick 	NFS_DEFRAHEAD,
8352112Smckusick 	NQ_DEFLEASE,
8452112Smckusick 	NQ_DEADTHRESH,
8552112Smckusick 	(char *)0,
8652112Smckusick };
8752112Smckusick 
8852112Smckusick struct nfhret {
8952112Smckusick 	u_long	stat;
9052112Smckusick 	nfsv2fh_t nfh;
9152112Smckusick };
9252112Smckusick #define	DEF_RETRY	10000
9352112Smckusick #define	BGRND	1
9452112Smckusick #define	ISBGRND	2
9552112Smckusick int retrycnt = DEF_RETRY;
9652112Smckusick int opflags = 0;
9752112Smckusick 
9852112Smckusick #ifdef KERBEROS
9952112Smckusick char inst[INST_SZ];
10052112Smckusick char realm[REALM_SZ];
10152112Smckusick KTEXT_ST kt;
10252112Smckusick #endif
10352112Smckusick 
10456407Sbostic int	getnfsargs __P((char *, struct nfs_args *));
10556407Sbostic #ifdef ISO
10656407Sbostic struct	iso_addr *iso_addr __P((const char *));
10756407Sbostic #endif
10856407Sbostic void	set_rpc_maxgrouplist __P((int));
10956407Sbostic __dead	void usage __P((void));
11056407Sbostic int	xdr_dir __P((XDR *, char *));
11156407Sbostic int	xdr_fh __P((XDR *, struct nfhret *));
11256407Sbostic 
11356407Sbostic int
11456407Sbostic main(argc, argv)
11552112Smckusick 	int argc;
11656407Sbostic 	char *argv[];
11752112Smckusick {
11856407Sbostic 	register int c;
11956407Sbostic 	register struct nfs_args *nfsargsp;
12052112Smckusick 	struct nfs_args nfsargs;
12152112Smckusick 	struct nfsd_cargs ncd;
12266483Sbostic 	int mntflags, i, nfssvc_flag, num;
12356407Sbostic 	char *name, *p, *spec;
12466483Sbostic 	int error = 0;
12556407Sbostic #ifdef KERBEROS
12656407Sbostic 	uid_t last_ruid;
12756407Sbostic #endif
12852112Smckusick 
12952112Smckusick #ifdef KERBEROS
13056407Sbostic 	last_ruid = -1;
13156407Sbostic 	(void)strcpy(realm, KRB_REALM);
13252112Smckusick #endif
13352112Smckusick 	retrycnt = DEF_RETRY;
13456407Sbostic 
13566483Sbostic 	mntflags = 0;
13656407Sbostic 	nfsargs = nfsdefargs;
13756407Sbostic 	nfsargsp = &nfsargs;
13856407Sbostic 	while ((c = getopt(argc, argv,
13966483Sbostic 	    "a:bcdD:g:iKklL:Mm:o:PpqR:r:sTt:w:x:")) != EOF)
14052112Smckusick 		switch (c) {
14156407Sbostic 		case 'a':
14256407Sbostic 			num = strtol(optarg, &p, 10);
14356407Sbostic 			if (*p || num < 0)
14466483Sbostic 				errx(1, "illegal -a value -- %s", optarg);
14556407Sbostic 			nfsargsp->readahead = num;
14656407Sbostic 			nfsargsp->flags |= NFSMNT_READAHEAD;
14756407Sbostic 			break;
14852112Smckusick 		case 'b':
14952112Smckusick 			opflags |= BGRND;
15052112Smckusick 			break;
15156407Sbostic 		case 'c':
15256407Sbostic 			nfsargsp->flags |= NFSMNT_NOCONN;
15352112Smckusick 			break;
15456407Sbostic 		case 'D':
15556407Sbostic 			num = strtol(optarg, &p, 10);
15656407Sbostic 			if (*p || num <= 0)
15766483Sbostic 				errx(1, "illegal -D value -- %s", optarg);
15856407Sbostic 			nfsargsp->deadthresh = num;
15956407Sbostic 			nfsargsp->flags |= NFSMNT_DEADTHRESH;
16056407Sbostic 			break;
16156407Sbostic 		case 'd':
16256407Sbostic 			nfsargsp->flags |= NFSMNT_DUMBTIMR;
16356407Sbostic 			break;
16456407Sbostic 		case 'g':
16556407Sbostic 			num = strtol(optarg, &p, 10);
16656646Shibler 			if (*p || num <= 0)
16766483Sbostic 				errx(1, "illegal -g value -- %s", optarg);
16856407Sbostic 			set_rpc_maxgrouplist(num);
16956407Sbostic 			nfsargsp->maxgrouplist = num;
17056407Sbostic 			nfsargsp->flags |= NFSMNT_MAXGRPS;
17156407Sbostic 			break;
17252112Smckusick 		case 'i':
17352112Smckusick 			nfsargsp->flags |= NFSMNT_INT;
17452112Smckusick 			break;
17556407Sbostic #ifdef KERBEROS
17656407Sbostic 		case 'K':
17756407Sbostic 			nfsargsp->flags |= NFSMNT_KERB;
17852112Smckusick 			break;
17952112Smckusick #endif
18056407Sbostic 		case 'k':
18156407Sbostic 			nfsargsp->flags |= NFSMNT_NQLOOKLEASE;
18252112Smckusick 			break;
18356407Sbostic 		case 'L':
18456407Sbostic 			num = strtol(optarg, &p, 10);
18556407Sbostic 			if (*p || num < 2)
18666483Sbostic 				errx(1, "illegal -L value -- %s", optarg);
18756407Sbostic 			nfsargsp->leaseterm = num;
18856407Sbostic 			nfsargsp->flags |= NFSMNT_LEASETERM;
18956407Sbostic 			break;
19052112Smckusick 		case 'l':
19152112Smckusick 			nfsargsp->flags |= NFSMNT_RDIRALOOK;
19252112Smckusick 			break;
19356407Sbostic 		case 'M':
19456407Sbostic 			nfsargsp->flags |= NFSMNT_MYWRITE;
19552112Smckusick 			break;
19656407Sbostic #ifdef KERBEROS
19756407Sbostic 		case 'm':
19856407Sbostic 			(void)strncpy(realm, optarg, REALM_SZ - 1);
19956407Sbostic 			realm[REALM_SZ - 1] = '\0';
20052112Smckusick 			break;
20156407Sbostic #endif
20266483Sbostic 		case 'o':
20366483Sbostic 			getmntopts(optarg, mopts, &mntflags);
20466483Sbostic 			break;
20552989Smckusick 		case 'P':
20652989Smckusick 			nfsargsp->flags |= NFSMNT_RESVPORT;
20752989Smckusick 			break;
20856407Sbostic #ifdef ISO
20956407Sbostic 		case 'p':
21056407Sbostic 			nfsargsp->sotype = SOCK_SEQPACKET;
21152112Smckusick 			break;
21256407Sbostic #endif
21356407Sbostic 		case 'q':
21456407Sbostic 			nfsargsp->flags |= NFSMNT_NQNFS;
21556407Sbostic 			break;
21652112Smckusick 		case 'R':
21756407Sbostic 			num = strtol(optarg, &p, 10);
21856407Sbostic 			if (*p || num <= 0)
21966483Sbostic 				errx(1, "illegal -R value -- %s", optarg);
22056407Sbostic 			retrycnt = num;
22152112Smckusick 			break;
22252112Smckusick 		case 'r':
22356407Sbostic 			num = strtol(optarg, &p, 10);
22456407Sbostic 			if (*p || num <= 0)
22566483Sbostic 				errx(1, "illegal -r value -- %s", optarg);
22656407Sbostic 			nfsargsp->rsize = num;
22756407Sbostic 			nfsargsp->flags |= NFSMNT_RSIZE;
22852112Smckusick 			break;
22956407Sbostic 		case 's':
23056407Sbostic 			nfsargsp->flags |= NFSMNT_SOFT;
23152112Smckusick 			break;
23256407Sbostic 		case 'T':
23356407Sbostic 			nfsargsp->sotype = SOCK_STREAM;
23456407Sbostic 			break;
23552112Smckusick 		case 't':
23656407Sbostic 			num = strtol(optarg, &p, 10);
23756407Sbostic 			if (*p || num <= 0)
23866483Sbostic 				errx(1, "illegal -t value -- %s", optarg);
23956407Sbostic 			nfsargsp->timeo = num;
24056407Sbostic 			nfsargsp->flags |= NFSMNT_TIMEO;
24152112Smckusick 			break;
24256407Sbostic 		case 'w':
24356407Sbostic 			num = strtol(optarg, &p, 10);
24456407Sbostic 			if (*p || num <= 0)
24566483Sbostic 				errx(1, "illegal -w value -- %s", optarg);
24656407Sbostic 			nfsargsp->wsize = num;
24756407Sbostic 			nfsargsp->flags |= NFSMNT_WSIZE;
24856407Sbostic 			break;
24952112Smckusick 		case 'x':
25056407Sbostic 			num = strtol(optarg, &p, 10);
25156407Sbostic 			if (*p || num <= 0)
25266483Sbostic 				errx(1, "illegal -x value -- %s", optarg);
25356407Sbostic 			nfsargsp->retrans = num;
25456407Sbostic 			nfsargsp->flags |= NFSMNT_RETRANS;
25552112Smckusick 			break;
25652112Smckusick 		default:
25756407Sbostic 			usage();
25866483Sbostic 			break;
25966483Sbostic 		}
26066483Sbostic 	argc -= optind;
26166483Sbostic 	argv += optind;
26256407Sbostic 
26366483Sbostic 	if (argc != 2)
264*68150Smckusick 		usage();
26556407Sbostic 
26666483Sbostic 	spec = *argv++;
26766483Sbostic 	name = *argv;
26856407Sbostic 
26956407Sbostic 	if (!getnfsargs(spec, nfsargsp))
27056407Sbostic 		exit(1);
27166483Sbostic 	if (mount(MOUNT_NFS, name, mntflags, nfsargsp))
27266483Sbostic 		err(1, "%s", name);
27356407Sbostic 	if (nfsargsp->flags & (NFSMNT_NQNFS | NFSMNT_KERB)) {
27456407Sbostic 		if ((opflags & ISBGRND) == 0) {
27556407Sbostic 			if (i = fork()) {
27656407Sbostic 				if (i == -1)
27766483Sbostic 					err(1, "nqnfs 1");
27856407Sbostic 				exit(0);
27952112Smckusick 			}
28056407Sbostic 			(void) setsid();
28156407Sbostic 			(void) close(STDIN_FILENO);
28256407Sbostic 			(void) close(STDOUT_FILENO);
28356407Sbostic 			(void) close(STDERR_FILENO);
28456407Sbostic 			(void) chdir("/");
28556407Sbostic 		}
28656407Sbostic 		openlog("mount_nfs:", LOG_PID, LOG_DAEMON);
28756407Sbostic 		nfssvc_flag = NFSSVC_MNTD;
28856407Sbostic 		ncd.ncd_dirp = name;
28956407Sbostic 		while (nfssvc(nfssvc_flag, (caddr_t)&ncd) < 0) {
29056407Sbostic 			if (errno != ENEEDAUTH) {
29156407Sbostic 				syslog(LOG_ERR, "nfssvc err %m");
29256407Sbostic 				continue;
29356407Sbostic 			}
29456407Sbostic 			nfssvc_flag =
29556407Sbostic 			    NFSSVC_MNTD | NFSSVC_GOTAUTH | NFSSVC_AUTHINFAIL;
29652112Smckusick #ifdef KERBEROS
29756407Sbostic 			/*
29856407Sbostic 			 * Set up as ncd_authuid for the kerberos call.
29956407Sbostic 			 * Must set ruid to ncd_authuid and reset the
30056407Sbostic 			 * ticket name iff ncd_authuid is not the same
30156407Sbostic 			 * as last time, so that the right ticket file
30256407Sbostic 			 * is found.
30356407Sbostic 			 */
30456407Sbostic 			if (ncd.ncd_authuid != last_ruid) {
30556407Sbostic 				krb_set_tkt_string("");
30656407Sbostic 				last_ruid = ncd.ncd_authuid;
30756407Sbostic 			}
30856407Sbostic 			setreuid(ncd.ncd_authuid, 0);
30956407Sbostic 			if (krb_mk_req(&kt, "rcmd", inst, realm, 0) ==
31056407Sbostic 			    KSUCCESS &&
31156407Sbostic 			    kt.length <= (RPCAUTH_MAXSIZ - 2 * NFSX_UNSIGNED)) {
31256407Sbostic 				ncd.ncd_authtype = RPCAUTH_NQNFS;
31356407Sbostic 				ncd.ncd_authlen = kt.length;
31456407Sbostic 				ncd.ncd_authstr = (char *)kt.dat;
31556407Sbostic 				nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH;
31656407Sbostic 			}
31756407Sbostic 			setreuid(0, 0);
31852112Smckusick #endif /* KERBEROS */
31952112Smckusick 		}
32056407Sbostic 	}
32156407Sbostic 	exit(0);
32252112Smckusick }
32352112Smckusick 
32456407Sbostic int
32552112Smckusick getnfsargs(spec, nfsargsp)
32652112Smckusick 	char *spec;
32752112Smckusick 	struct nfs_args *nfsargsp;
32852112Smckusick {
32952112Smckusick 	register CLIENT *clp;
33052112Smckusick 	struct hostent *hp;
33152112Smckusick 	static struct sockaddr_in saddr;
33252112Smckusick #ifdef ISO
33352112Smckusick 	static struct sockaddr_iso isoaddr;
33452112Smckusick 	struct iso_addr *isop;
33556407Sbostic 	int isoflag = 0;
33652112Smckusick #endif
33752112Smckusick 	struct timeval pertry, try;
33852112Smckusick 	enum clnt_stat clnt_stat;
33956407Sbostic 	int so = RPC_ANYSOCK, i;
34056407Sbostic 	char *hostp, *delimp;
34156407Sbostic #ifdef KERBEROS
34256407Sbostic 	char *cp;
34356407Sbostic #endif
34452112Smckusick 	u_short tport;
34552112Smckusick 	static struct nfhret nfhret;
34652112Smckusick 	static char nam[MNAMELEN + 1];
34752112Smckusick 
34852112Smckusick 	strncpy(nam, spec, MNAMELEN);
34952112Smckusick 	nam[MNAMELEN] = '\0';
35066483Sbostic 	if ((delimp = strchr(spec, '@')) != NULL) {
35152112Smckusick 		hostp = delimp + 1;
35266483Sbostic 	} else if ((delimp = strchr(spec, ':')) != NULL) {
35352112Smckusick 		hostp = spec;
35452112Smckusick 		spec = delimp + 1;
35552112Smckusick 	} else {
35666483Sbostic 		warnx("no <host>:<dirpath> or <dirpath>@<host> spec");
35752112Smckusick 		return (0);
35852112Smckusick 	}
35952112Smckusick 	*delimp = '\0';
36052112Smckusick 	/*
36152112Smckusick 	 * DUMB!! Until the mount protocol works on iso transport, we must
36252112Smckusick 	 * supply both an iso and an inet address for the host.
36352112Smckusick 	 */
36452112Smckusick #ifdef ISO
36552112Smckusick 	if (!strncmp(hostp, "iso=", 4)) {
36652112Smckusick 		u_short isoport;
36752112Smckusick 
36852112Smckusick 		hostp += 4;
36952112Smckusick 		isoflag++;
37066483Sbostic 		if ((delimp = strchr(hostp, '+')) == NULL) {
37166483Sbostic 			warnx("no iso+inet address");
37252112Smckusick 			return (0);
37352112Smckusick 		}
37452112Smckusick 		*delimp = '\0';
37552112Smckusick 		if ((isop = iso_addr(hostp)) == NULL) {
37666483Sbostic 			warnx("bad ISO address");
37752112Smckusick 			return (0);
37852112Smckusick 		}
37952112Smckusick 		bzero((caddr_t)&isoaddr, sizeof (isoaddr));
38052112Smckusick 		bcopy((caddr_t)isop, (caddr_t)&isoaddr.siso_addr,
38152112Smckusick 			sizeof (struct iso_addr));
38252112Smckusick 		isoaddr.siso_len = sizeof (isoaddr);
38352112Smckusick 		isoaddr.siso_family = AF_ISO;
38452112Smckusick 		isoaddr.siso_tlen = 2;
38552112Smckusick 		isoport = htons(NFS_PORT);
38652112Smckusick 		bcopy((caddr_t)&isoport, TSEL(&isoaddr), isoaddr.siso_tlen);
38752112Smckusick 		hostp = delimp + 1;
38852112Smckusick 	}
38952112Smckusick #endif /* ISO */
39052112Smckusick 
39152112Smckusick 	/*
39252112Smckusick 	 * Handle an internet host address and reverse resolve it if
39352112Smckusick 	 * doing Kerberos.
39452112Smckusick 	 */
39552112Smckusick 	if (isdigit(*hostp)) {
39652112Smckusick 		if ((saddr.sin_addr.s_addr = inet_addr(hostp)) == -1) {
39766483Sbostic 			warnx("bad net address %s", hostp);
39852112Smckusick 			return (0);
39952112Smckusick 		}
40052112Smckusick 		if ((nfsargsp->flags & NFSMNT_KERB) &&
40152112Smckusick 		    (hp = gethostbyaddr((char *)&saddr.sin_addr.s_addr,
40256407Sbostic 		    sizeof (u_long), AF_INET)) == (struct hostent *)0) {
40366483Sbostic 			warnx("can't reverse resolve net address");
40452112Smckusick 			return (0);
40552112Smckusick 		}
40652112Smckusick 	} else if ((hp = gethostbyname(hostp)) == NULL) {
40766483Sbostic 		warnx("can't get net id for host");
40852112Smckusick 		return (0);
40952112Smckusick 	}
41052112Smckusick #ifdef KERBEROS
41152112Smckusick 	if (nfsargsp->flags & NFSMNT_KERB) {
41252112Smckusick 		strncpy(inst, hp->h_name, INST_SZ);
41352112Smckusick 		inst[INST_SZ - 1] = '\0';
41466483Sbostic 		if (cp = strchr(inst, '.'))
41552112Smckusick 			*cp = '\0';
41652112Smckusick 	}
41752112Smckusick #endif /* KERBEROS */
41852112Smckusick 
41952112Smckusick 	bcopy(hp->h_addr, (caddr_t)&saddr.sin_addr, hp->h_length);
42052112Smckusick 	nfhret.stat = EACCES;	/* Mark not yet successful */
42152112Smckusick 	while (retrycnt > 0) {
42252112Smckusick 		saddr.sin_family = AF_INET;
42352112Smckusick 		saddr.sin_port = htons(PMAPPORT);
42452112Smckusick 		if ((tport = pmap_getport(&saddr, RPCPROG_NFS,
42567807Smckusick 		    NFS_VER2, nfsargsp->sotype == SOCK_STREAM ? IPPROTO_TCP :
42667807Smckusick 		    IPPROTO_UDP)) == 0) {
42752112Smckusick 			if ((opflags & ISBGRND) == 0)
42852112Smckusick 				clnt_pcreateerror("NFS Portmap");
42952112Smckusick 		} else {
43052112Smckusick 			saddr.sin_port = 0;
43152112Smckusick 			pertry.tv_sec = 10;
43252112Smckusick 			pertry.tv_usec = 0;
43367807Smckusick 			if ((clp = (nfsargsp->sotype == SOCK_STREAM ?
43467807Smckusick 			    clnttcp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1,
43567807Smckusick 					   &so, 0, 0) :
43667807Smckusick 			    clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1,
43767807Smckusick 					   pertry, &so))) == NULL) {
43852112Smckusick 				if ((opflags & ISBGRND) == 0)
43952112Smckusick 					clnt_pcreateerror("Cannot MNT PRC");
44052112Smckusick 			} else {
44152112Smckusick 				clp->cl_auth = authunix_create_default();
44252112Smckusick 				try.tv_sec = 10;
44352112Smckusick 				try.tv_usec = 0;
44452112Smckusick 				clnt_stat = clnt_call(clp, RPCMNT_MOUNT,
44552112Smckusick 				    xdr_dir, spec, xdr_fh, &nfhret, try);
44652112Smckusick 				if (clnt_stat != RPC_SUCCESS) {
44766483Sbostic 					if ((opflags & ISBGRND) == 0)
44866483Sbostic 						warnx("%s", clnt_sperror(clp,
44956407Sbostic 						    "bad MNT RPC"));
45052112Smckusick 				} else {
45152112Smckusick 					auth_destroy(clp->cl_auth);
45252112Smckusick 					clnt_destroy(clp);
45352112Smckusick 					retrycnt = 0;
45452112Smckusick 				}
45552112Smckusick 			}
45652112Smckusick 		}
45752112Smckusick 		if (--retrycnt > 0) {
45852112Smckusick 			if (opflags & BGRND) {
45952112Smckusick 				opflags &= ~BGRND;
46052112Smckusick 				if (i = fork()) {
46156407Sbostic 					if (i == -1)
46266483Sbostic 						err(1, "nqnfs 2");
46353128Storek 					exit(0);
46452112Smckusick 				}
46552112Smckusick 				(void) setsid();
46656407Sbostic 				(void) close(STDIN_FILENO);
46756407Sbostic 				(void) close(STDOUT_FILENO);
46856407Sbostic 				(void) close(STDERR_FILENO);
46952112Smckusick 				(void) chdir("/");
47052112Smckusick 				opflags |= ISBGRND;
47156407Sbostic 			}
47252112Smckusick 			sleep(60);
47352112Smckusick 		}
47452112Smckusick 	}
47552112Smckusick 	if (nfhret.stat) {
47652112Smckusick 		if (opflags & ISBGRND)
47752112Smckusick 			exit(1);
47867795Smckusick 		errno = nfhret.stat;
47966483Sbostic 		warn("can't access %s", spec);
48052112Smckusick 		return (0);
48152112Smckusick 	}
48252112Smckusick 	saddr.sin_port = htons(tport);
48352112Smckusick #ifdef ISO
48452112Smckusick 	if (isoflag) {
48552112Smckusick 		nfsargsp->addr = (struct sockaddr *) &isoaddr;
48652112Smckusick 		nfsargsp->addrlen = sizeof (isoaddr);
48752112Smckusick 	} else
48852112Smckusick #endif /* ISO */
48952112Smckusick 	{
49052112Smckusick 		nfsargsp->addr = (struct sockaddr *) &saddr;
49152112Smckusick 		nfsargsp->addrlen = sizeof (saddr);
49252112Smckusick 	}
49352112Smckusick 	nfsargsp->fh = &nfhret.nfh;
49452112Smckusick 	nfsargsp->hostname = nam;
49552112Smckusick 	return (1);
49652112Smckusick }
49752112Smckusick 
49852112Smckusick /*
49952112Smckusick  * xdr routines for mount rpc's
50052112Smckusick  */
50156407Sbostic int
50252112Smckusick xdr_dir(xdrsp, dirp)
50352112Smckusick 	XDR *xdrsp;
50452112Smckusick 	char *dirp;
50552112Smckusick {
50652112Smckusick 	return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
50752112Smckusick }
50852112Smckusick 
50956407Sbostic int
51052112Smckusick xdr_fh(xdrsp, np)
51152112Smckusick 	XDR *xdrsp;
51252112Smckusick 	struct nfhret *np;
51352112Smckusick {
51452112Smckusick 	if (!xdr_u_long(xdrsp, &(np->stat)))
51552112Smckusick 		return (0);
51652112Smckusick 	if (np->stat)
51752112Smckusick 		return (1);
51852112Smckusick 	return (xdr_opaque(xdrsp, (caddr_t)&(np->nfh), NFSX_FH));
51952112Smckusick }
52052112Smckusick 
52156407Sbostic __dead void
52256407Sbostic usage()
52352112Smckusick {
52456407Sbostic 	(void)fprintf(stderr, "usage: mount_nfs %s\n%s\n%s\n%s\n",
52556407Sbostic "[-bcdiKklMPqsT] [-a maxreadahead] [-D deadthresh]",
52666483Sbostic "\t[-g maxgroups] [-L leaseterm] [-m realm] [-o options] [-R retrycnt]",
52756407Sbostic "\t[-r readsize] [-t timeout] [-w writesize] [-x retrans]",
52856407Sbostic "\trhost:path node");
52956407Sbostic 	exit(1);
53056407Sbostic }
531