xref: /csrg-svn/sbin/mount_nfs/mount_nfs.c (revision 66483)
152112Smckusick /*
2*66483Sbostic  * 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[] =
13*66483Sbostic "@(#) 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*66483Sbostic static char sccsid[] = "@(#)mount_nfs.c	8.2 (Berkeley) 03/27/94";
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>
51*66483Sbostic #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 
61*66483Sbostic #include "mntopts.h"
62*66483Sbostic 
63*66483Sbostic /*
64*66483Sbostic  * XXX
65*66483Sbostic  * This is without question incorrect -- not sure what the right
66*66483Sbostic  * values are.
67*66483Sbostic  */
68*66483Sbostic struct mntopt mopts[] = {
69*66483Sbostic 	MOPT_STDOPTS,
70*66483Sbostic 	MOPT_ASYNC,
71*66483Sbostic 	MOPT_FORCE,
72*66483Sbostic 	MOPT_SYNCHRONOUS,
73*66483Sbostic 	MOPT_UPDATE,
74*66483Sbostic 	{ NULL }
75*66483Sbostic };
76*66483Sbostic 
7752112Smckusick struct nfs_args nfsdefargs = {
7852112Smckusick 	(struct sockaddr *)0,
7952112Smckusick 	sizeof (struct sockaddr_in),
8052112Smckusick 	SOCK_DGRAM,
8152112Smckusick 	0,
8252112Smckusick 	(nfsv2fh_t *)0,
8352112Smckusick 	0,
8452112Smckusick 	NFS_WSIZE,
8552112Smckusick 	NFS_RSIZE,
8652112Smckusick 	NFS_TIMEO,
8752112Smckusick 	NFS_RETRANS,
8852112Smckusick 	NFS_MAXGRPS,
8952112Smckusick 	NFS_DEFRAHEAD,
9052112Smckusick 	NQ_DEFLEASE,
9152112Smckusick 	NQ_DEADTHRESH,
9252112Smckusick 	(char *)0,
9352112Smckusick };
9452112Smckusick 
9552112Smckusick struct nfhret {
9652112Smckusick 	u_long	stat;
9752112Smckusick 	nfsv2fh_t nfh;
9852112Smckusick };
9952112Smckusick #define	DEF_RETRY	10000
10052112Smckusick #define	BGRND	1
10152112Smckusick #define	ISBGRND	2
10252112Smckusick int retrycnt = DEF_RETRY;
10352112Smckusick int opflags = 0;
10452112Smckusick 
10552112Smckusick #ifdef KERBEROS
10652112Smckusick char inst[INST_SZ];
10752112Smckusick char realm[REALM_SZ];
10852112Smckusick KTEXT_ST kt;
10952112Smckusick #endif
11052112Smckusick 
11156407Sbostic int	getnfsargs __P((char *, struct nfs_args *));
11256407Sbostic #ifdef ISO
11356407Sbostic struct	iso_addr *iso_addr __P((const char *));
11456407Sbostic #endif
11556407Sbostic void	set_rpc_maxgrouplist __P((int));
11656407Sbostic __dead	void usage __P((void));
11756407Sbostic int	xdr_dir __P((XDR *, char *));
11856407Sbostic int	xdr_fh __P((XDR *, struct nfhret *));
11956407Sbostic 
12056407Sbostic int
12156407Sbostic main(argc, argv)
12252112Smckusick 	int argc;
12356407Sbostic 	char *argv[];
12452112Smckusick {
12556407Sbostic 	register int c;
12656407Sbostic 	register struct nfs_args *nfsargsp;
12752112Smckusick 	struct nfs_args nfsargs;
12852112Smckusick 	struct nfsd_cargs ncd;
129*66483Sbostic 	int mntflags, i, nfssvc_flag, num;
13056407Sbostic 	char *name, *p, *spec;
131*66483Sbostic 	int error = 0;
13256407Sbostic #ifdef KERBEROS
13356407Sbostic 	uid_t last_ruid;
13456407Sbostic #endif
13552112Smckusick 
13652112Smckusick #ifdef KERBEROS
13756407Sbostic 	last_ruid = -1;
13856407Sbostic 	(void)strcpy(realm, KRB_REALM);
13952112Smckusick #endif
14052112Smckusick 	retrycnt = DEF_RETRY;
14156407Sbostic 
142*66483Sbostic 	mntflags = 0;
14356407Sbostic 	nfsargs = nfsdefargs;
14456407Sbostic 	nfsargsp = &nfsargs;
14556407Sbostic 	while ((c = getopt(argc, argv,
146*66483Sbostic 	    "a:bcdD:g:iKklL:Mm:o:PpqR:r:sTt:w:x:")) != EOF)
14752112Smckusick 		switch (c) {
14856407Sbostic 		case 'a':
14956407Sbostic 			num = strtol(optarg, &p, 10);
15056407Sbostic 			if (*p || num < 0)
151*66483Sbostic 				errx(1, "illegal -a value -- %s", optarg);
15256407Sbostic 			nfsargsp->readahead = num;
15356407Sbostic 			nfsargsp->flags |= NFSMNT_READAHEAD;
15456407Sbostic 			break;
15552112Smckusick 		case 'b':
15652112Smckusick 			opflags |= BGRND;
15752112Smckusick 			break;
15856407Sbostic 		case 'c':
15956407Sbostic 			nfsargsp->flags |= NFSMNT_NOCONN;
16052112Smckusick 			break;
16156407Sbostic 		case 'D':
16256407Sbostic 			num = strtol(optarg, &p, 10);
16356407Sbostic 			if (*p || num <= 0)
164*66483Sbostic 				errx(1, "illegal -D value -- %s", optarg);
16556407Sbostic 			nfsargsp->deadthresh = num;
16656407Sbostic 			nfsargsp->flags |= NFSMNT_DEADTHRESH;
16756407Sbostic 			break;
16856407Sbostic 		case 'd':
16956407Sbostic 			nfsargsp->flags |= NFSMNT_DUMBTIMR;
17056407Sbostic 			break;
17156407Sbostic 		case 'g':
17256407Sbostic 			num = strtol(optarg, &p, 10);
17356646Shibler 			if (*p || num <= 0)
174*66483Sbostic 				errx(1, "illegal -g value -- %s", optarg);
17556407Sbostic 			set_rpc_maxgrouplist(num);
17656407Sbostic 			nfsargsp->maxgrouplist = num;
17756407Sbostic 			nfsargsp->flags |= NFSMNT_MAXGRPS;
17856407Sbostic 			break;
17952112Smckusick 		case 'i':
18052112Smckusick 			nfsargsp->flags |= NFSMNT_INT;
18152112Smckusick 			break;
18256407Sbostic #ifdef KERBEROS
18356407Sbostic 		case 'K':
18456407Sbostic 			nfsargsp->flags |= NFSMNT_KERB;
18552112Smckusick 			break;
18652112Smckusick #endif
18756407Sbostic 		case 'k':
18856407Sbostic 			nfsargsp->flags |= NFSMNT_NQLOOKLEASE;
18952112Smckusick 			break;
19056407Sbostic 		case 'L':
19156407Sbostic 			num = strtol(optarg, &p, 10);
19256407Sbostic 			if (*p || num < 2)
193*66483Sbostic 				errx(1, "illegal -L value -- %s", optarg);
19456407Sbostic 			nfsargsp->leaseterm = num;
19556407Sbostic 			nfsargsp->flags |= NFSMNT_LEASETERM;
19656407Sbostic 			break;
19752112Smckusick 		case 'l':
19852112Smckusick 			nfsargsp->flags |= NFSMNT_RDIRALOOK;
19952112Smckusick 			break;
20056407Sbostic 		case 'M':
20156407Sbostic 			nfsargsp->flags |= NFSMNT_MYWRITE;
20252112Smckusick 			break;
20356407Sbostic #ifdef KERBEROS
20456407Sbostic 		case 'm':
20556407Sbostic 			(void)strncpy(realm, optarg, REALM_SZ - 1);
20656407Sbostic 			realm[REALM_SZ - 1] = '\0';
20752112Smckusick 			break;
20856407Sbostic #endif
209*66483Sbostic 		case 'o':
210*66483Sbostic 			getmntopts(optarg, mopts, &mntflags);
211*66483Sbostic 			break;
21252989Smckusick 		case 'P':
21352989Smckusick 			nfsargsp->flags |= NFSMNT_RESVPORT;
21452989Smckusick 			break;
21556407Sbostic #ifdef ISO
21656407Sbostic 		case 'p':
21756407Sbostic 			nfsargsp->sotype = SOCK_SEQPACKET;
21852112Smckusick 			break;
21956407Sbostic #endif
22056407Sbostic 		case 'q':
22156407Sbostic 			nfsargsp->flags |= NFSMNT_NQNFS;
22256407Sbostic 			break;
22352112Smckusick 		case 'R':
22456407Sbostic 			num = strtol(optarg, &p, 10);
22556407Sbostic 			if (*p || num <= 0)
226*66483Sbostic 				errx(1, "illegal -R value -- %s", optarg);
22756407Sbostic 			retrycnt = num;
22852112Smckusick 			break;
22952112Smckusick 		case 'r':
23056407Sbostic 			num = strtol(optarg, &p, 10);
23156407Sbostic 			if (*p || num <= 0)
232*66483Sbostic 				errx(1, "illegal -r value -- %s", optarg);
23356407Sbostic 			nfsargsp->rsize = num;
23456407Sbostic 			nfsargsp->flags |= NFSMNT_RSIZE;
23552112Smckusick 			break;
23656407Sbostic 		case 's':
23756407Sbostic 			nfsargsp->flags |= NFSMNT_SOFT;
23852112Smckusick 			break;
23956407Sbostic 		case 'T':
24056407Sbostic 			nfsargsp->sotype = SOCK_STREAM;
24156407Sbostic 			break;
24252112Smckusick 		case 't':
24356407Sbostic 			num = strtol(optarg, &p, 10);
24456407Sbostic 			if (*p || num <= 0)
245*66483Sbostic 				errx(1, "illegal -t value -- %s", optarg);
24656407Sbostic 			nfsargsp->timeo = num;
24756407Sbostic 			nfsargsp->flags |= NFSMNT_TIMEO;
24852112Smckusick 			break;
24956407Sbostic 		case 'w':
25056407Sbostic 			num = strtol(optarg, &p, 10);
25156407Sbostic 			if (*p || num <= 0)
252*66483Sbostic 				errx(1, "illegal -w value -- %s", optarg);
25356407Sbostic 			nfsargsp->wsize = num;
25456407Sbostic 			nfsargsp->flags |= NFSMNT_WSIZE;
25556407Sbostic 			break;
25652112Smckusick 		case 'x':
25756407Sbostic 			num = strtol(optarg, &p, 10);
25856407Sbostic 			if (*p || num <= 0)
259*66483Sbostic 				errx(1, "illegal -x value -- %s", optarg);
26056407Sbostic 			nfsargsp->retrans = num;
26156407Sbostic 			nfsargsp->flags |= NFSMNT_RETRANS;
26252112Smckusick 			break;
26352112Smckusick 		default:
26456407Sbostic 			usage();
265*66483Sbostic 			break;
266*66483Sbostic 		}
267*66483Sbostic 	argc -= optind;
268*66483Sbostic 	argv += optind;
26956407Sbostic 
270*66483Sbostic 	if (argc != 2)
271*66483Sbostic 		error = 1;
27256407Sbostic 
273*66483Sbostic 	spec = *argv++;
274*66483Sbostic 	name = *argv;
27556407Sbostic 
27656407Sbostic 	if (!getnfsargs(spec, nfsargsp))
27756407Sbostic 		exit(1);
278*66483Sbostic 	if (mount(MOUNT_NFS, name, mntflags, nfsargsp))
279*66483Sbostic 		err(1, "%s", name);
28056407Sbostic 	if (nfsargsp->flags & (NFSMNT_NQNFS | NFSMNT_KERB)) {
28156407Sbostic 		if ((opflags & ISBGRND) == 0) {
28256407Sbostic 			if (i = fork()) {
28356407Sbostic 				if (i == -1)
284*66483Sbostic 					err(1, "nqnfs 1");
28556407Sbostic 				exit(0);
28652112Smckusick 			}
28756407Sbostic 			(void) setsid();
28856407Sbostic 			(void) close(STDIN_FILENO);
28956407Sbostic 			(void) close(STDOUT_FILENO);
29056407Sbostic 			(void) close(STDERR_FILENO);
29156407Sbostic 			(void) chdir("/");
29256407Sbostic 		}
29356407Sbostic 		openlog("mount_nfs:", LOG_PID, LOG_DAEMON);
29456407Sbostic 		nfssvc_flag = NFSSVC_MNTD;
29556407Sbostic 		ncd.ncd_dirp = name;
29656407Sbostic 		while (nfssvc(nfssvc_flag, (caddr_t)&ncd) < 0) {
29756407Sbostic 			if (errno != ENEEDAUTH) {
29856407Sbostic 				syslog(LOG_ERR, "nfssvc err %m");
29956407Sbostic 				continue;
30056407Sbostic 			}
30156407Sbostic 			nfssvc_flag =
30256407Sbostic 			    NFSSVC_MNTD | NFSSVC_GOTAUTH | NFSSVC_AUTHINFAIL;
30352112Smckusick #ifdef KERBEROS
30456407Sbostic 			/*
30556407Sbostic 			 * Set up as ncd_authuid for the kerberos call.
30656407Sbostic 			 * Must set ruid to ncd_authuid and reset the
30756407Sbostic 			 * ticket name iff ncd_authuid is not the same
30856407Sbostic 			 * as last time, so that the right ticket file
30956407Sbostic 			 * is found.
31056407Sbostic 			 */
31156407Sbostic 			if (ncd.ncd_authuid != last_ruid) {
31256407Sbostic 				krb_set_tkt_string("");
31356407Sbostic 				last_ruid = ncd.ncd_authuid;
31456407Sbostic 			}
31556407Sbostic 			setreuid(ncd.ncd_authuid, 0);
31656407Sbostic 			if (krb_mk_req(&kt, "rcmd", inst, realm, 0) ==
31756407Sbostic 			    KSUCCESS &&
31856407Sbostic 			    kt.length <= (RPCAUTH_MAXSIZ - 2 * NFSX_UNSIGNED)) {
31956407Sbostic 				ncd.ncd_authtype = RPCAUTH_NQNFS;
32056407Sbostic 				ncd.ncd_authlen = kt.length;
32156407Sbostic 				ncd.ncd_authstr = (char *)kt.dat;
32256407Sbostic 				nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH;
32356407Sbostic 			}
32456407Sbostic 			setreuid(0, 0);
32552112Smckusick #endif /* KERBEROS */
32652112Smckusick 		}
32756407Sbostic 	}
32856407Sbostic 	exit(0);
32952112Smckusick }
33052112Smckusick 
33156407Sbostic int
33252112Smckusick getnfsargs(spec, nfsargsp)
33352112Smckusick 	char *spec;
33452112Smckusick 	struct nfs_args *nfsargsp;
33552112Smckusick {
33652112Smckusick 	register CLIENT *clp;
33752112Smckusick 	struct hostent *hp;
33852112Smckusick 	static struct sockaddr_in saddr;
33952112Smckusick #ifdef ISO
34052112Smckusick 	static struct sockaddr_iso isoaddr;
34152112Smckusick 	struct iso_addr *isop;
34256407Sbostic 	int isoflag = 0;
34352112Smckusick #endif
34452112Smckusick 	struct timeval pertry, try;
34552112Smckusick 	enum clnt_stat clnt_stat;
34656407Sbostic 	int so = RPC_ANYSOCK, i;
34756407Sbostic 	char *hostp, *delimp;
34856407Sbostic #ifdef KERBEROS
34956407Sbostic 	char *cp;
35056407Sbostic #endif
35152112Smckusick 	u_short tport;
35252112Smckusick 	static struct nfhret nfhret;
35352112Smckusick 	static char nam[MNAMELEN + 1];
35452112Smckusick 
35552112Smckusick 	strncpy(nam, spec, MNAMELEN);
35652112Smckusick 	nam[MNAMELEN] = '\0';
357*66483Sbostic 	if ((delimp = strchr(spec, '@')) != NULL) {
35852112Smckusick 		hostp = delimp + 1;
359*66483Sbostic 	} else if ((delimp = strchr(spec, ':')) != NULL) {
36052112Smckusick 		hostp = spec;
36152112Smckusick 		spec = delimp + 1;
36252112Smckusick 	} else {
363*66483Sbostic 		warnx("no <host>:<dirpath> or <dirpath>@<host> spec");
36452112Smckusick 		return (0);
36552112Smckusick 	}
36652112Smckusick 	*delimp = '\0';
36752112Smckusick 	/*
36852112Smckusick 	 * DUMB!! Until the mount protocol works on iso transport, we must
36952112Smckusick 	 * supply both an iso and an inet address for the host.
37052112Smckusick 	 */
37152112Smckusick #ifdef ISO
37252112Smckusick 	if (!strncmp(hostp, "iso=", 4)) {
37352112Smckusick 		u_short isoport;
37452112Smckusick 
37552112Smckusick 		hostp += 4;
37652112Smckusick 		isoflag++;
377*66483Sbostic 		if ((delimp = strchr(hostp, '+')) == NULL) {
378*66483Sbostic 			warnx("no iso+inet address");
37952112Smckusick 			return (0);
38052112Smckusick 		}
38152112Smckusick 		*delimp = '\0';
38252112Smckusick 		if ((isop = iso_addr(hostp)) == NULL) {
383*66483Sbostic 			warnx("bad ISO address");
38452112Smckusick 			return (0);
38552112Smckusick 		}
38652112Smckusick 		bzero((caddr_t)&isoaddr, sizeof (isoaddr));
38752112Smckusick 		bcopy((caddr_t)isop, (caddr_t)&isoaddr.siso_addr,
38852112Smckusick 			sizeof (struct iso_addr));
38952112Smckusick 		isoaddr.siso_len = sizeof (isoaddr);
39052112Smckusick 		isoaddr.siso_family = AF_ISO;
39152112Smckusick 		isoaddr.siso_tlen = 2;
39252112Smckusick 		isoport = htons(NFS_PORT);
39352112Smckusick 		bcopy((caddr_t)&isoport, TSEL(&isoaddr), isoaddr.siso_tlen);
39452112Smckusick 		hostp = delimp + 1;
39552112Smckusick 	}
39652112Smckusick #endif /* ISO */
39752112Smckusick 
39852112Smckusick 	/*
39952112Smckusick 	 * Handle an internet host address and reverse resolve it if
40052112Smckusick 	 * doing Kerberos.
40152112Smckusick 	 */
40252112Smckusick 	if (isdigit(*hostp)) {
40352112Smckusick 		if ((saddr.sin_addr.s_addr = inet_addr(hostp)) == -1) {
404*66483Sbostic 			warnx("bad net address %s", hostp);
40552112Smckusick 			return (0);
40652112Smckusick 		}
40752112Smckusick 		if ((nfsargsp->flags & NFSMNT_KERB) &&
40852112Smckusick 		    (hp = gethostbyaddr((char *)&saddr.sin_addr.s_addr,
40956407Sbostic 		    sizeof (u_long), AF_INET)) == (struct hostent *)0) {
410*66483Sbostic 			warnx("can't reverse resolve net address");
41152112Smckusick 			return (0);
41252112Smckusick 		}
41352112Smckusick 	} else if ((hp = gethostbyname(hostp)) == NULL) {
414*66483Sbostic 		warnx("can't get net id for host");
41552112Smckusick 		return (0);
41652112Smckusick 	}
41752112Smckusick #ifdef KERBEROS
41852112Smckusick 	if (nfsargsp->flags & NFSMNT_KERB) {
41952112Smckusick 		strncpy(inst, hp->h_name, INST_SZ);
42052112Smckusick 		inst[INST_SZ - 1] = '\0';
421*66483Sbostic 		if (cp = strchr(inst, '.'))
42252112Smckusick 			*cp = '\0';
42352112Smckusick 	}
42452112Smckusick #endif /* KERBEROS */
42552112Smckusick 
42652112Smckusick 	bcopy(hp->h_addr, (caddr_t)&saddr.sin_addr, hp->h_length);
42752112Smckusick 	nfhret.stat = EACCES;	/* Mark not yet successful */
42852112Smckusick 	while (retrycnt > 0) {
42952112Smckusick 		saddr.sin_family = AF_INET;
43052112Smckusick 		saddr.sin_port = htons(PMAPPORT);
43152112Smckusick 		if ((tport = pmap_getport(&saddr, RPCPROG_NFS,
43252112Smckusick 		    NFS_VER2, IPPROTO_UDP)) == 0) {
43352112Smckusick 			if ((opflags & ISBGRND) == 0)
43452112Smckusick 				clnt_pcreateerror("NFS Portmap");
43552112Smckusick 		} else {
43652112Smckusick 			saddr.sin_port = 0;
43752112Smckusick 			pertry.tv_sec = 10;
43852112Smckusick 			pertry.tv_usec = 0;
43952112Smckusick 			if ((clp = clntudp_create(&saddr, RPCPROG_MNT,
44052112Smckusick 			    RPCMNT_VER1, pertry, &so)) == NULL) {
44152112Smckusick 				if ((opflags & ISBGRND) == 0)
44252112Smckusick 					clnt_pcreateerror("Cannot MNT PRC");
44352112Smckusick 			} else {
44452112Smckusick 				clp->cl_auth = authunix_create_default();
44552112Smckusick 				try.tv_sec = 10;
44652112Smckusick 				try.tv_usec = 0;
44752112Smckusick 				clnt_stat = clnt_call(clp, RPCMNT_MOUNT,
44852112Smckusick 				    xdr_dir, spec, xdr_fh, &nfhret, try);
44952112Smckusick 				if (clnt_stat != RPC_SUCCESS) {
450*66483Sbostic 					if ((opflags & ISBGRND) == 0)
451*66483Sbostic 						warnx("%s", clnt_sperror(clp,
45256407Sbostic 						    "bad MNT RPC"));
45352112Smckusick 				} else {
45452112Smckusick 					auth_destroy(clp->cl_auth);
45552112Smckusick 					clnt_destroy(clp);
45652112Smckusick 					retrycnt = 0;
45752112Smckusick 				}
45852112Smckusick 			}
45952112Smckusick 		}
46052112Smckusick 		if (--retrycnt > 0) {
46152112Smckusick 			if (opflags & BGRND) {
46252112Smckusick 				opflags &= ~BGRND;
46352112Smckusick 				if (i = fork()) {
46456407Sbostic 					if (i == -1)
465*66483Sbostic 						err(1, "nqnfs 2");
46653128Storek 					exit(0);
46752112Smckusick 				}
46852112Smckusick 				(void) setsid();
46956407Sbostic 				(void) close(STDIN_FILENO);
47056407Sbostic 				(void) close(STDOUT_FILENO);
47156407Sbostic 				(void) close(STDERR_FILENO);
47252112Smckusick 				(void) chdir("/");
47352112Smckusick 				opflags |= ISBGRND;
47456407Sbostic 			}
47552112Smckusick 			sleep(60);
47652112Smckusick 		}
47752112Smckusick 	}
47852112Smckusick 	if (nfhret.stat) {
47952112Smckusick 		if (opflags & ISBGRND)
48052112Smckusick 			exit(1);
481*66483Sbostic 		warn("can't access %s", spec);
48252112Smckusick 		return (0);
48352112Smckusick 	}
48452112Smckusick 	saddr.sin_port = htons(tport);
48552112Smckusick #ifdef ISO
48652112Smckusick 	if (isoflag) {
48752112Smckusick 		nfsargsp->addr = (struct sockaddr *) &isoaddr;
48852112Smckusick 		nfsargsp->addrlen = sizeof (isoaddr);
48952112Smckusick 	} else
49052112Smckusick #endif /* ISO */
49152112Smckusick 	{
49252112Smckusick 		nfsargsp->addr = (struct sockaddr *) &saddr;
49352112Smckusick 		nfsargsp->addrlen = sizeof (saddr);
49452112Smckusick 	}
49552112Smckusick 	nfsargsp->fh = &nfhret.nfh;
49652112Smckusick 	nfsargsp->hostname = nam;
49752112Smckusick 	return (1);
49852112Smckusick }
49952112Smckusick 
50052112Smckusick /*
50152112Smckusick  * xdr routines for mount rpc's
50252112Smckusick  */
50356407Sbostic int
50452112Smckusick xdr_dir(xdrsp, dirp)
50552112Smckusick 	XDR *xdrsp;
50652112Smckusick 	char *dirp;
50752112Smckusick {
50852112Smckusick 	return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
50952112Smckusick }
51052112Smckusick 
51156407Sbostic int
51252112Smckusick xdr_fh(xdrsp, np)
51352112Smckusick 	XDR *xdrsp;
51452112Smckusick 	struct nfhret *np;
51552112Smckusick {
51652112Smckusick 	if (!xdr_u_long(xdrsp, &(np->stat)))
51752112Smckusick 		return (0);
51852112Smckusick 	if (np->stat)
51952112Smckusick 		return (1);
52052112Smckusick 	return (xdr_opaque(xdrsp, (caddr_t)&(np->nfh), NFSX_FH));
52152112Smckusick }
52252112Smckusick 
52356407Sbostic __dead void
52456407Sbostic usage()
52552112Smckusick {
52656407Sbostic 	(void)fprintf(stderr, "usage: mount_nfs %s\n%s\n%s\n%s\n",
52756407Sbostic "[-bcdiKklMPqsT] [-a maxreadahead] [-D deadthresh]",
528*66483Sbostic "\t[-g maxgroups] [-L leaseterm] [-m realm] [-o options] [-R retrycnt]",
52956407Sbostic "\t[-r readsize] [-t timeout] [-w writesize] [-x retrans]",
53056407Sbostic "\trhost:path node");
53156407Sbostic 	exit(1);
53256407Sbostic }
533