xref: /csrg-svn/sbin/mount_nfs/mount_nfs.c (revision 56600)
152112Smckusick /*
252112Smckusick  * Copyright (c) 1992 The Regents of the University of California.
352112Smckusick  * 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
1252112Smckusick char copyright[] =
1352112Smckusick "@(#) Copyright (c) 1992 The Regents of the University of California.\n\
1452112Smckusick  All rights reserved.\n";
1552112Smckusick #endif /* not lint */
1652112Smckusick 
1752112Smckusick #ifndef lint
18*56600Smckusick static char sccsid[] = "@(#)mount_nfs.c	5.8 (Berkeley) 10/21/92";
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
3752112Smckusick #include <kerberosIV/krb.h>
3852112Smckusick #endif
3956407Sbostic 
4052112Smckusick #include <nfs/rpcv2.h>
4152112Smckusick #include <nfs/nfsv2.h>
4256407Sbostic #define KERNEL
4352112Smckusick #include <nfs/nfs.h>
4456407Sbostic #undef KERNEL
4552112Smckusick #include <nfs/nqnfs.h>
4652112Smckusick 
4756407Sbostic #include <arpa/inet.h>
4856407Sbostic 
4956407Sbostic #include <ctype.h>
5056407Sbostic #include <errno.h>
5156407Sbostic #include <fcntl.h>
5256407Sbostic #include <netdb.h>
5356407Sbostic #include <signal.h>
5456407Sbostic #include <stdio.h>
5556407Sbostic #include <stdlib.h>
5656407Sbostic #include <strings.h>
5756407Sbostic #include <unistd.h>
5856407Sbostic 
5952112Smckusick struct nfs_args nfsdefargs = {
6052112Smckusick 	(struct sockaddr *)0,
6152112Smckusick 	sizeof (struct sockaddr_in),
6252112Smckusick 	SOCK_DGRAM,
6352112Smckusick 	0,
6452112Smckusick 	(nfsv2fh_t *)0,
6552112Smckusick 	0,
6652112Smckusick 	NFS_WSIZE,
6752112Smckusick 	NFS_RSIZE,
6852112Smckusick 	NFS_TIMEO,
6952112Smckusick 	NFS_RETRANS,
7052112Smckusick 	NFS_MAXGRPS,
7152112Smckusick 	NFS_DEFRAHEAD,
7252112Smckusick 	NQ_DEFLEASE,
7352112Smckusick 	NQ_DEADTHRESH,
7452112Smckusick 	(char *)0,
7552112Smckusick };
7652112Smckusick 
7752112Smckusick struct nfhret {
7852112Smckusick 	u_long	stat;
7952112Smckusick 	nfsv2fh_t nfh;
8052112Smckusick };
8152112Smckusick #define	DEF_RETRY	10000
8252112Smckusick #define	BGRND	1
8352112Smckusick #define	ISBGRND	2
8452112Smckusick int retrycnt = DEF_RETRY;
8552112Smckusick int opflags = 0;
8652112Smckusick 
8752112Smckusick #ifdef KERBEROS
8852112Smckusick char inst[INST_SZ];
8952112Smckusick char realm[REALM_SZ];
9052112Smckusick KTEXT_ST kt;
9152112Smckusick #endif
9252112Smckusick 
9356407Sbostic void	err __P((const char *, ...));
9456407Sbostic int	getnfsargs __P((char *, struct nfs_args *));
9556407Sbostic #ifdef ISO
9656407Sbostic struct	iso_addr *iso_addr __P((const char *));
9756407Sbostic #endif
9856407Sbostic void	set_rpc_maxgrouplist __P((int));
9956407Sbostic __dead	void usage __P((void));
10056407Sbostic void	warn __P((const char *, ...));
10156407Sbostic int	xdr_dir __P((XDR *, char *));
10256407Sbostic int	xdr_fh __P((XDR *, struct nfhret *));
10356407Sbostic 
10456407Sbostic int
10556407Sbostic main(argc, argv)
10652112Smckusick 	int argc;
10756407Sbostic 	char *argv[];
10852112Smckusick {
10956407Sbostic 	register int c;
11056407Sbostic 	register struct nfs_args *nfsargsp;
11152112Smckusick 	struct nfs_args nfsargs;
11252112Smckusick 	struct nfsd_cargs ncd;
11356407Sbostic 	int flags, i, nfssvc_flag, num;
11456407Sbostic 	char *name, *p, *spec;
11556407Sbostic #ifdef KERBEROS
11656407Sbostic 	uid_t last_ruid;
11756407Sbostic #endif
11852112Smckusick 
11952112Smckusick #ifdef KERBEROS
12056407Sbostic 	last_ruid = -1;
12156407Sbostic 	(void)strcpy(realm, KRB_REALM);
12252112Smckusick #endif
12352112Smckusick 	retrycnt = DEF_RETRY;
12456407Sbostic 
12552112Smckusick 	if (argc <= 1)
12656407Sbostic 		usage();
12756407Sbostic 
12856407Sbostic 	flags = 0;
12956407Sbostic 	nfsargs = nfsdefargs;
13056407Sbostic 	nfsargsp = &nfsargs;
13156407Sbostic 	while ((c = getopt(argc, argv,
13256407Sbostic 	    "a:bcdD:F:g:iKklL:Mm:PpqR:r:sTt:w:x:")) != EOF)
13352112Smckusick 		switch (c) {
13456407Sbostic 		case 'a':
13556407Sbostic 			num = strtol(optarg, &p, 10);
13656407Sbostic 			if (*p || num < 0)
13756407Sbostic 				err("illegal -a value -- %s", optarg);
13856407Sbostic 			nfsargsp->readahead = num;
13956407Sbostic 			nfsargsp->flags |= NFSMNT_READAHEAD;
14056407Sbostic 			break;
14152112Smckusick 		case 'b':
14252112Smckusick 			opflags |= BGRND;
14352112Smckusick 			break;
14456407Sbostic 		case 'c':
14556407Sbostic 			nfsargsp->flags |= NFSMNT_NOCONN;
14652112Smckusick 			break;
14756407Sbostic 		case 'D':
14856407Sbostic 			num = strtol(optarg, &p, 10);
14956407Sbostic 			if (*p || num <= 0)
15056407Sbostic 				err("illegal -D value -- %s", optarg);
15156407Sbostic 			nfsargsp->deadthresh = num;
15256407Sbostic 			nfsargsp->flags |= NFSMNT_DEADTHRESH;
15356407Sbostic 			break;
15456407Sbostic 		case 'd':
15556407Sbostic 			nfsargsp->flags |= NFSMNT_DUMBTIMR;
15656407Sbostic 			break;
15756407Sbostic 		case 'F':
15856407Sbostic 			num = strtol(optarg, &p, 10);
159*56600Smckusick 			if (*p)
16056407Sbostic 				err("illegal -F value -- %s", optarg);
161*56600Smckusick 			if (num != 0)
162*56600Smckusick 				flags = num;
16356407Sbostic 			break;
16456407Sbostic 		case 'g':
16556407Sbostic 			num = strtol(optarg, &p, 10);
16656407Sbostic 			if (*p || num > 0)
16756407Sbostic 				err("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)
18656407Sbostic 				err("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
20252989Smckusick 		case 'P':
20352989Smckusick 			nfsargsp->flags |= NFSMNT_RESVPORT;
20452989Smckusick 			break;
20556407Sbostic #ifdef ISO
20656407Sbostic 		case 'p':
20756407Sbostic 			nfsargsp->sotype = SOCK_SEQPACKET;
20852112Smckusick 			break;
20956407Sbostic #endif
21056407Sbostic 		case 'q':
21156407Sbostic 			nfsargsp->flags |= NFSMNT_NQNFS;
21256407Sbostic 			break;
21352112Smckusick 		case 'R':
21456407Sbostic 			num = strtol(optarg, &p, 10);
21556407Sbostic 			if (*p || num <= 0)
21656407Sbostic 				err("illegal -R value -- %s", optarg);
21756407Sbostic 			retrycnt = num;
21852112Smckusick 			break;
21952112Smckusick 		case 'r':
22056407Sbostic 			num = strtol(optarg, &p, 10);
22156407Sbostic 			if (*p || num <= 0)
22256407Sbostic 				err("illegal -r value -- %s", optarg);
22356407Sbostic 			nfsargsp->rsize = num;
22456407Sbostic 			nfsargsp->flags |= NFSMNT_RSIZE;
22552112Smckusick 			break;
22656407Sbostic 		case 's':
22756407Sbostic 			nfsargsp->flags |= NFSMNT_SOFT;
22852112Smckusick 			break;
22956407Sbostic 		case 'T':
23056407Sbostic 			nfsargsp->sotype = SOCK_STREAM;
23156407Sbostic 			break;
23252112Smckusick 		case 't':
23356407Sbostic 			num = strtol(optarg, &p, 10);
23456407Sbostic 			if (*p || num <= 0)
23556407Sbostic 				err("illegal -t value -- %s", optarg);
23656407Sbostic 			nfsargsp->timeo = num;
23756407Sbostic 			nfsargsp->flags |= NFSMNT_TIMEO;
23852112Smckusick 			break;
23956407Sbostic 		case 'w':
24056407Sbostic 			num = strtol(optarg, &p, 10);
24156407Sbostic 			if (*p || num <= 0)
24256407Sbostic 				err("illegal -w value -- %s", optarg);
24356407Sbostic 			nfsargsp->wsize = num;
24456407Sbostic 			nfsargsp->flags |= NFSMNT_WSIZE;
24556407Sbostic 			break;
24652112Smckusick 		case 'x':
24756407Sbostic 			num = strtol(optarg, &p, 10);
24856407Sbostic 			if (*p || num <= 0)
24956407Sbostic 				err("illegal -x value -- %s", optarg);
25056407Sbostic 			nfsargsp->retrans = num;
25156407Sbostic 			nfsargsp->flags |= NFSMNT_RETRANS;
25252112Smckusick 			break;
25352112Smckusick 		default:
25456407Sbostic 			usage();
25552112Smckusick 		};
25656407Sbostic 
25756407Sbostic 	if ((argc - optind) != 2)
25856407Sbostic 		usage();
25956407Sbostic 
26056407Sbostic 	spec = argv[optind];
26156407Sbostic 	name = argv[optind + 1];
26256407Sbostic 
26356407Sbostic 	if (!getnfsargs(spec, nfsargsp))
26456407Sbostic 		exit(1);
26556407Sbostic 	if (mount(MOUNT_NFS, name, flags, nfsargsp))
26656426Sbostic 		err("mount: %s: %s", name, strerror(errno));
26756407Sbostic 	if (nfsargsp->flags & (NFSMNT_NQNFS | NFSMNT_KERB)) {
26856407Sbostic 		if ((opflags & ISBGRND) == 0) {
26956407Sbostic 			if (i = fork()) {
27056407Sbostic 				if (i == -1)
27156426Sbostic 					err("nqnfs 1: %s", strerror(errno));
27256407Sbostic 				exit(0);
27352112Smckusick 			}
27456407Sbostic 			(void) setsid();
27556407Sbostic 			(void) close(STDIN_FILENO);
27656407Sbostic 			(void) close(STDOUT_FILENO);
27756407Sbostic 			(void) close(STDERR_FILENO);
27856407Sbostic 			(void) chdir("/");
27956407Sbostic 		}
28056407Sbostic 		openlog("mount_nfs:", LOG_PID, LOG_DAEMON);
28156407Sbostic 		nfssvc_flag = NFSSVC_MNTD;
28256407Sbostic 		ncd.ncd_dirp = name;
28356407Sbostic 		while (nfssvc(nfssvc_flag, (caddr_t)&ncd) < 0) {
28456407Sbostic 			if (errno != ENEEDAUTH) {
28556407Sbostic 				syslog(LOG_ERR, "nfssvc err %m");
28656407Sbostic 				continue;
28756407Sbostic 			}
28852112Smckusick syslog(LOG_ERR, "in eacces");
28956407Sbostic 			nfssvc_flag =
29056407Sbostic 			    NFSSVC_MNTD | NFSSVC_GOTAUTH | NFSSVC_AUTHINFAIL;
29152112Smckusick #ifdef KERBEROS
29256407Sbostic syslog(LOG_ERR,
29356407Sbostic     "Calling krb uid=%d inst=%s realm=%s", ncd.ncd_authuid, inst,realm);
29456407Sbostic 			/*
29556407Sbostic 			 * Set up as ncd_authuid for the kerberos call.
29656407Sbostic 			 * Must set ruid to ncd_authuid and reset the
29756407Sbostic 			 * ticket name iff ncd_authuid is not the same
29856407Sbostic 			 * as last time, so that the right ticket file
29956407Sbostic 			 * is found.
30056407Sbostic 			 */
30156407Sbostic 			if (ncd.ncd_authuid != last_ruid) {
30256407Sbostic 				krb_set_tkt_string("");
30356407Sbostic 				last_ruid = ncd.ncd_authuid;
30456407Sbostic 			}
30556407Sbostic 			setreuid(ncd.ncd_authuid, 0);
30656407Sbostic 			if (krb_mk_req(&kt, "rcmd", inst, realm, 0) ==
30756407Sbostic 			    KSUCCESS &&
30856407Sbostic 			    kt.length <= (RPCAUTH_MAXSIZ - 2 * NFSX_UNSIGNED)) {
30956407Sbostic syslog(LOG_ERR, "Got it\n");
31056407Sbostic 				ncd.ncd_authtype = RPCAUTH_NQNFS;
31156407Sbostic 				ncd.ncd_authlen = kt.length;
31256407Sbostic 				ncd.ncd_authstr = (char *)kt.dat;
31356407Sbostic 				nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH;
31456407Sbostic 			}
31556407Sbostic 			setreuid(0, 0);
31656407Sbostic syslog(LOG_ERR, "ktlen=%d\n", kt.length);
31752112Smckusick #endif /* KERBEROS */
31852112Smckusick 		}
31956407Sbostic 	}
32056407Sbostic 	exit(0);
32152112Smckusick }
32252112Smckusick 
32356407Sbostic int
32452112Smckusick getnfsargs(spec, nfsargsp)
32552112Smckusick 	char *spec;
32652112Smckusick 	struct nfs_args *nfsargsp;
32752112Smckusick {
32852112Smckusick 	register CLIENT *clp;
32952112Smckusick 	struct hostent *hp;
33052112Smckusick 	static struct sockaddr_in saddr;
33152112Smckusick #ifdef ISO
33252112Smckusick 	static struct sockaddr_iso isoaddr;
33352112Smckusick 	struct iso_addr *isop;
33456407Sbostic 	int isoflag = 0;
33552112Smckusick #endif
33652112Smckusick 	struct timeval pertry, try;
33752112Smckusick 	enum clnt_stat clnt_stat;
33856407Sbostic 	int so = RPC_ANYSOCK, i;
33956407Sbostic 	char *hostp, *delimp;
34056407Sbostic #ifdef KERBEROS
34156407Sbostic 	char *cp;
34256407Sbostic #endif
34352112Smckusick 	u_short tport;
34452112Smckusick 	static struct nfhret nfhret;
34552112Smckusick 	static char nam[MNAMELEN + 1];
34652112Smckusick 
34752112Smckusick 	strncpy(nam, spec, MNAMELEN);
34852112Smckusick 	nam[MNAMELEN] = '\0';
34952112Smckusick 	if ((delimp = index(spec, '@')) != NULL) {
35052112Smckusick 		hostp = delimp + 1;
35152112Smckusick 	} else if ((delimp = index(spec, ':')) != NULL) {
35252112Smckusick 		hostp = spec;
35352112Smckusick 		spec = delimp + 1;
35452112Smckusick 	} else {
35556407Sbostic 		warn("no <host>:<dirpath> or <dirpath>@<host> spec");
35652112Smckusick 		return (0);
35752112Smckusick 	}
35852112Smckusick 	*delimp = '\0';
35952112Smckusick 	/*
36052112Smckusick 	 * DUMB!! Until the mount protocol works on iso transport, we must
36152112Smckusick 	 * supply both an iso and an inet address for the host.
36252112Smckusick 	 */
36352112Smckusick #ifdef ISO
36452112Smckusick 	if (!strncmp(hostp, "iso=", 4)) {
36552112Smckusick 		u_short isoport;
36652112Smckusick 
36752112Smckusick 		hostp += 4;
36852112Smckusick 		isoflag++;
36952112Smckusick 		if ((delimp = index(hostp, '+')) == NULL) {
37056407Sbostic 			warn("no iso+inet address");
37152112Smckusick 			return (0);
37252112Smckusick 		}
37352112Smckusick 		*delimp = '\0';
37452112Smckusick 		if ((isop = iso_addr(hostp)) == NULL) {
37556407Sbostic 			warn("bad ISO address");
37652112Smckusick 			return (0);
37752112Smckusick 		}
37852112Smckusick 		bzero((caddr_t)&isoaddr, sizeof (isoaddr));
37952112Smckusick 		bcopy((caddr_t)isop, (caddr_t)&isoaddr.siso_addr,
38052112Smckusick 			sizeof (struct iso_addr));
38152112Smckusick 		isoaddr.siso_len = sizeof (isoaddr);
38252112Smckusick 		isoaddr.siso_family = AF_ISO;
38352112Smckusick 		isoaddr.siso_tlen = 2;
38452112Smckusick 		isoport = htons(NFS_PORT);
38552112Smckusick 		bcopy((caddr_t)&isoport, TSEL(&isoaddr), isoaddr.siso_tlen);
38652112Smckusick 		hostp = delimp + 1;
38752112Smckusick 	}
38852112Smckusick #endif /* ISO */
38952112Smckusick 
39052112Smckusick 	/*
39152112Smckusick 	 * Handle an internet host address and reverse resolve it if
39252112Smckusick 	 * doing Kerberos.
39352112Smckusick 	 */
39452112Smckusick 	if (isdigit(*hostp)) {
39552112Smckusick 		if ((saddr.sin_addr.s_addr = inet_addr(hostp)) == -1) {
39656407Sbostic 			warn("bad net address %s\n", hostp);
39752112Smckusick 			return (0);
39852112Smckusick 		}
39952112Smckusick 		if ((nfsargsp->flags & NFSMNT_KERB) &&
40052112Smckusick 		    (hp = gethostbyaddr((char *)&saddr.sin_addr.s_addr,
40156407Sbostic 		    sizeof (u_long), AF_INET)) == (struct hostent *)0) {
40256407Sbostic 			warn("can't reverse resolve net address");
40352112Smckusick 			return (0);
40452112Smckusick 		}
40552112Smckusick 	} else if ((hp = gethostbyname(hostp)) == NULL) {
40656407Sbostic 		warn("can't get net id for host");
40752112Smckusick 		return (0);
40852112Smckusick 	}
40952112Smckusick #ifdef KERBEROS
41052112Smckusick 	if (nfsargsp->flags & NFSMNT_KERB) {
41152112Smckusick 		strncpy(inst, hp->h_name, INST_SZ);
41252112Smckusick 		inst[INST_SZ - 1] = '\0';
41352112Smckusick 		if (cp = index(inst, '.'))
41452112Smckusick 			*cp = '\0';
41552112Smckusick 	}
41652112Smckusick #endif /* KERBEROS */
41752112Smckusick 
41852112Smckusick 	bcopy(hp->h_addr, (caddr_t)&saddr.sin_addr, hp->h_length);
41952112Smckusick 	nfhret.stat = EACCES;	/* Mark not yet successful */
42052112Smckusick 	while (retrycnt > 0) {
42152112Smckusick 		saddr.sin_family = AF_INET;
42252112Smckusick 		saddr.sin_port = htons(PMAPPORT);
42352112Smckusick 		if ((tport = pmap_getport(&saddr, RPCPROG_NFS,
42452112Smckusick 		    NFS_VER2, IPPROTO_UDP)) == 0) {
42552112Smckusick 			if ((opflags & ISBGRND) == 0)
42652112Smckusick 				clnt_pcreateerror("NFS Portmap");
42752112Smckusick 		} else {
42852112Smckusick 			saddr.sin_port = 0;
42952112Smckusick 			pertry.tv_sec = 10;
43052112Smckusick 			pertry.tv_usec = 0;
43152112Smckusick 			if ((clp = clntudp_create(&saddr, RPCPROG_MNT,
43252112Smckusick 			    RPCMNT_VER1, pertry, &so)) == NULL) {
43352112Smckusick 				if ((opflags & ISBGRND) == 0)
43452112Smckusick 					clnt_pcreateerror("Cannot MNT PRC");
43552112Smckusick 			} else {
43652112Smckusick 				clp->cl_auth = authunix_create_default();
43752112Smckusick 				try.tv_sec = 10;
43852112Smckusick 				try.tv_usec = 0;
43952112Smckusick 				clnt_stat = clnt_call(clp, RPCMNT_MOUNT,
44052112Smckusick 				    xdr_dir, spec, xdr_fh, &nfhret, try);
44152112Smckusick 				if (clnt_stat != RPC_SUCCESS) {
44256407Sbostic 					if ((opflags & ISBGRND) == 0) {
44356407Sbostic 						warn("%s", clnt_sperror(clp,
44456407Sbostic 						    "bad MNT RPC"));
44556407Sbostic 					}
44652112Smckusick 				} else {
44752112Smckusick 					auth_destroy(clp->cl_auth);
44852112Smckusick 					clnt_destroy(clp);
44952112Smckusick 					retrycnt = 0;
45052112Smckusick 				}
45152112Smckusick 			}
45252112Smckusick 		}
45352112Smckusick 		if (--retrycnt > 0) {
45452112Smckusick 			if (opflags & BGRND) {
45552112Smckusick 				opflags &= ~BGRND;
45652112Smckusick 				if (i = fork()) {
45756407Sbostic 					if (i == -1)
45856426Sbostic 						err("nqnfs 2: %s",
45956407Sbostic 						    strerror(errno));
46053128Storek 					exit(0);
46152112Smckusick 				}
46252112Smckusick 				(void) setsid();
46356407Sbostic 				(void) close(STDIN_FILENO);
46456407Sbostic 				(void) close(STDOUT_FILENO);
46556407Sbostic 				(void) close(STDERR_FILENO);
46652112Smckusick 				(void) chdir("/");
46752112Smckusick 				opflags |= ISBGRND;
46856407Sbostic 			}
46952112Smckusick 			sleep(60);
47052112Smckusick 		}
47152112Smckusick 	}
47252112Smckusick 	if (nfhret.stat) {
47352112Smckusick 		if (opflags & ISBGRND)
47452112Smckusick 			exit(1);
47556407Sbostic 		warn("can't access %s: %s\n", spec, strerror(nfhret.stat));
47652112Smckusick 		return (0);
47752112Smckusick 	}
47852112Smckusick 	saddr.sin_port = htons(tport);
47952112Smckusick #ifdef ISO
48052112Smckusick 	if (isoflag) {
48152112Smckusick 		nfsargsp->addr = (struct sockaddr *) &isoaddr;
48252112Smckusick 		nfsargsp->addrlen = sizeof (isoaddr);
48352112Smckusick 	} else
48452112Smckusick #endif /* ISO */
48552112Smckusick 	{
48652112Smckusick 		nfsargsp->addr = (struct sockaddr *) &saddr;
48752112Smckusick 		nfsargsp->addrlen = sizeof (saddr);
48852112Smckusick 	}
48952112Smckusick 	nfsargsp->fh = &nfhret.nfh;
49052112Smckusick 	nfsargsp->hostname = nam;
49152112Smckusick 	return (1);
49252112Smckusick }
49352112Smckusick 
49452112Smckusick /*
49552112Smckusick  * xdr routines for mount rpc's
49652112Smckusick  */
49756407Sbostic int
49852112Smckusick xdr_dir(xdrsp, dirp)
49952112Smckusick 	XDR *xdrsp;
50052112Smckusick 	char *dirp;
50152112Smckusick {
50252112Smckusick 	return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
50352112Smckusick }
50452112Smckusick 
50556407Sbostic int
50652112Smckusick xdr_fh(xdrsp, np)
50752112Smckusick 	XDR *xdrsp;
50852112Smckusick 	struct nfhret *np;
50952112Smckusick {
51052112Smckusick 	if (!xdr_u_long(xdrsp, &(np->stat)))
51152112Smckusick 		return (0);
51252112Smckusick 	if (np->stat)
51352112Smckusick 		return (1);
51452112Smckusick 	return (xdr_opaque(xdrsp, (caddr_t)&(np->nfh), NFSX_FH));
51552112Smckusick }
51652112Smckusick 
51756407Sbostic __dead void
51856407Sbostic usage()
51952112Smckusick {
52056407Sbostic 	(void)fprintf(stderr, "usage: mount_nfs %s\n%s\n%s\n%s\n",
52156407Sbostic "[-bcdiKklMPqsT] [-a maxreadahead] [-D deadthresh]",
52256407Sbostic "\t[-g maxgroups] [-L leaseterm] [-m realm] [-R retrycnt]",
52356407Sbostic "\t[-r readsize] [-t timeout] [-w writesize] [-x retrans]",
52456407Sbostic "\trhost:path node");
52556407Sbostic 	exit(1);
52656407Sbostic }
52752112Smckusick 
52856407Sbostic #if __STDC__
52956407Sbostic #include <stdarg.h>
53056407Sbostic #else
53156407Sbostic #include <varargs.h>
53256407Sbostic #endif
53356407Sbostic 
53456407Sbostic void
53556407Sbostic #if __STDC__
53656407Sbostic err(const char *fmt, ...)
53756407Sbostic #else
53856407Sbostic err(fmt, va_alist)
53956407Sbostic 	char *fmt;
54056407Sbostic         va_dcl
54156407Sbostic #endif
54256407Sbostic {
54356407Sbostic 	va_list ap;
54456407Sbostic #if __STDC__
54556407Sbostic 	va_start(ap, fmt);
54656407Sbostic #else
54756407Sbostic 	va_start(ap);
54856407Sbostic #endif
54956407Sbostic 	(void)fprintf(stderr, "mount_nfs: ");
55056407Sbostic 	(void)vfprintf(stderr, fmt, ap);
55156407Sbostic 	va_end(ap);
55256407Sbostic 	(void)fprintf(stderr, "\n");
55352112Smckusick 	exit(1);
55456407Sbostic 	/* NOTREACHED */
55552112Smckusick }
55656407Sbostic 
55756407Sbostic void
55856407Sbostic #if __STDC__
55956407Sbostic warn(const char *fmt, ...)
56056407Sbostic #else
56156407Sbostic warn(fmt, va_alist)
56256407Sbostic 	char *fmt;
56356407Sbostic         va_dcl
56456407Sbostic #endif
56556407Sbostic {
56656407Sbostic 	va_list ap;
56756407Sbostic #if __STDC__
56856407Sbostic 	va_start(ap, fmt);
56956407Sbostic #else
57056407Sbostic 	va_start(ap);
57156407Sbostic #endif
57256407Sbostic 	(void)fprintf(stderr, "mount_nfs: ");
57356407Sbostic 	(void)vfprintf(stderr, fmt, ap);
57456407Sbostic 	va_end(ap);
57556407Sbostic 	(void)fprintf(stderr, "\n");
57656407Sbostic }
577