xref: /csrg-svn/sbin/mount_nfs/mount_nfs.c (revision 56426)
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*56426Sbostic static char sccsid[] = "@(#)mount_nfs.c	5.7 (Berkeley) 10/05/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);
15956407Sbostic 			if (*p || num != 0)
16056407Sbostic 				err("illegal -F value -- %s", optarg);
16156407Sbostic 			flags = num;
16256407Sbostic 			break;
16356407Sbostic 		case 'g':
16456407Sbostic 			num = strtol(optarg, &p, 10);
16556407Sbostic 			if (*p || num > 0)
16656407Sbostic 				err("illegal -g value -- %s", optarg);
16756407Sbostic 			set_rpc_maxgrouplist(num);
16856407Sbostic 			nfsargsp->maxgrouplist = num;
16956407Sbostic 			nfsargsp->flags |= NFSMNT_MAXGRPS;
17056407Sbostic 			break;
17152112Smckusick 		case 'i':
17252112Smckusick 			nfsargsp->flags |= NFSMNT_INT;
17352112Smckusick 			break;
17456407Sbostic #ifdef KERBEROS
17556407Sbostic 		case 'K':
17656407Sbostic 			nfsargsp->flags |= NFSMNT_KERB;
17752112Smckusick 			break;
17852112Smckusick #endif
17956407Sbostic 		case 'k':
18056407Sbostic 			nfsargsp->flags |= NFSMNT_NQLOOKLEASE;
18152112Smckusick 			break;
18256407Sbostic 		case 'L':
18356407Sbostic 			num = strtol(optarg, &p, 10);
18456407Sbostic 			if (*p || num < 2)
18556407Sbostic 				err("illegal -L value -- %s", optarg);
18656407Sbostic 			nfsargsp->leaseterm = num;
18756407Sbostic 			nfsargsp->flags |= NFSMNT_LEASETERM;
18856407Sbostic 			break;
18952112Smckusick 		case 'l':
19052112Smckusick 			nfsargsp->flags |= NFSMNT_RDIRALOOK;
19152112Smckusick 			break;
19256407Sbostic 		case 'M':
19356407Sbostic 			nfsargsp->flags |= NFSMNT_MYWRITE;
19452112Smckusick 			break;
19556407Sbostic #ifdef KERBEROS
19656407Sbostic 		case 'm':
19756407Sbostic 			(void)strncpy(realm, optarg, REALM_SZ - 1);
19856407Sbostic 			realm[REALM_SZ - 1] = '\0';
19952112Smckusick 			break;
20056407Sbostic #endif
20152989Smckusick 		case 'P':
20252989Smckusick 			nfsargsp->flags |= NFSMNT_RESVPORT;
20352989Smckusick 			break;
20456407Sbostic #ifdef ISO
20556407Sbostic 		case 'p':
20656407Sbostic 			nfsargsp->sotype = SOCK_SEQPACKET;
20752112Smckusick 			break;
20856407Sbostic #endif
20956407Sbostic 		case 'q':
21056407Sbostic 			nfsargsp->flags |= NFSMNT_NQNFS;
21156407Sbostic 			break;
21252112Smckusick 		case 'R':
21356407Sbostic 			num = strtol(optarg, &p, 10);
21456407Sbostic 			if (*p || num <= 0)
21556407Sbostic 				err("illegal -R value -- %s", optarg);
21656407Sbostic 			retrycnt = num;
21752112Smckusick 			break;
21852112Smckusick 		case 'r':
21956407Sbostic 			num = strtol(optarg, &p, 10);
22056407Sbostic 			if (*p || num <= 0)
22156407Sbostic 				err("illegal -r value -- %s", optarg);
22256407Sbostic 			nfsargsp->rsize = num;
22356407Sbostic 			nfsargsp->flags |= NFSMNT_RSIZE;
22452112Smckusick 			break;
22556407Sbostic 		case 's':
22656407Sbostic 			nfsargsp->flags |= NFSMNT_SOFT;
22752112Smckusick 			break;
22856407Sbostic 		case 'T':
22956407Sbostic 			nfsargsp->sotype = SOCK_STREAM;
23056407Sbostic 			break;
23152112Smckusick 		case 't':
23256407Sbostic 			num = strtol(optarg, &p, 10);
23356407Sbostic 			if (*p || num <= 0)
23456407Sbostic 				err("illegal -t value -- %s", optarg);
23556407Sbostic 			nfsargsp->timeo = num;
23656407Sbostic 			nfsargsp->flags |= NFSMNT_TIMEO;
23752112Smckusick 			break;
23856407Sbostic 		case 'w':
23956407Sbostic 			num = strtol(optarg, &p, 10);
24056407Sbostic 			if (*p || num <= 0)
24156407Sbostic 				err("illegal -w value -- %s", optarg);
24256407Sbostic 			nfsargsp->wsize = num;
24356407Sbostic 			nfsargsp->flags |= NFSMNT_WSIZE;
24456407Sbostic 			break;
24552112Smckusick 		case 'x':
24656407Sbostic 			num = strtol(optarg, &p, 10);
24756407Sbostic 			if (*p || num <= 0)
24856407Sbostic 				err("illegal -x value -- %s", optarg);
24956407Sbostic 			nfsargsp->retrans = num;
25056407Sbostic 			nfsargsp->flags |= NFSMNT_RETRANS;
25152112Smckusick 			break;
25252112Smckusick 		default:
25356407Sbostic 			usage();
25452112Smckusick 		};
25556407Sbostic 
25656407Sbostic 	if ((argc - optind) != 2)
25756407Sbostic 		usage();
25856407Sbostic 
25956407Sbostic 	spec = argv[optind];
26056407Sbostic 	name = argv[optind + 1];
26156407Sbostic 
26256407Sbostic 	if (!getnfsargs(spec, nfsargsp))
26356407Sbostic 		exit(1);
26456407Sbostic 	if (mount(MOUNT_NFS, name, flags, nfsargsp))
265*56426Sbostic 		err("mount: %s: %s", name, strerror(errno));
26656407Sbostic 	if (nfsargsp->flags & (NFSMNT_NQNFS | NFSMNT_KERB)) {
26756407Sbostic 		if ((opflags & ISBGRND) == 0) {
26856407Sbostic 			if (i = fork()) {
26956407Sbostic 				if (i == -1)
270*56426Sbostic 					err("nqnfs 1: %s", strerror(errno));
27156407Sbostic 				exit(0);
27252112Smckusick 			}
27356407Sbostic 			(void) setsid();
27456407Sbostic 			(void) close(STDIN_FILENO);
27556407Sbostic 			(void) close(STDOUT_FILENO);
27656407Sbostic 			(void) close(STDERR_FILENO);
27756407Sbostic 			(void) chdir("/");
27856407Sbostic 		}
27956407Sbostic 		openlog("mount_nfs:", LOG_PID, LOG_DAEMON);
28056407Sbostic 		nfssvc_flag = NFSSVC_MNTD;
28156407Sbostic 		ncd.ncd_dirp = name;
28256407Sbostic 		while (nfssvc(nfssvc_flag, (caddr_t)&ncd) < 0) {
28356407Sbostic 			if (errno != ENEEDAUTH) {
28456407Sbostic 				syslog(LOG_ERR, "nfssvc err %m");
28556407Sbostic 				continue;
28656407Sbostic 			}
28752112Smckusick syslog(LOG_ERR, "in eacces");
28856407Sbostic 			nfssvc_flag =
28956407Sbostic 			    NFSSVC_MNTD | NFSSVC_GOTAUTH | NFSSVC_AUTHINFAIL;
29052112Smckusick #ifdef KERBEROS
29156407Sbostic syslog(LOG_ERR,
29256407Sbostic     "Calling krb uid=%d inst=%s realm=%s", ncd.ncd_authuid, inst,realm);
29356407Sbostic 			/*
29456407Sbostic 			 * Set up as ncd_authuid for the kerberos call.
29556407Sbostic 			 * Must set ruid to ncd_authuid and reset the
29656407Sbostic 			 * ticket name iff ncd_authuid is not the same
29756407Sbostic 			 * as last time, so that the right ticket file
29856407Sbostic 			 * is found.
29956407Sbostic 			 */
30056407Sbostic 			if (ncd.ncd_authuid != last_ruid) {
30156407Sbostic 				krb_set_tkt_string("");
30256407Sbostic 				last_ruid = ncd.ncd_authuid;
30356407Sbostic 			}
30456407Sbostic 			setreuid(ncd.ncd_authuid, 0);
30556407Sbostic 			if (krb_mk_req(&kt, "rcmd", inst, realm, 0) ==
30656407Sbostic 			    KSUCCESS &&
30756407Sbostic 			    kt.length <= (RPCAUTH_MAXSIZ - 2 * NFSX_UNSIGNED)) {
30856407Sbostic syslog(LOG_ERR, "Got it\n");
30956407Sbostic 				ncd.ncd_authtype = RPCAUTH_NQNFS;
31056407Sbostic 				ncd.ncd_authlen = kt.length;
31156407Sbostic 				ncd.ncd_authstr = (char *)kt.dat;
31256407Sbostic 				nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH;
31356407Sbostic 			}
31456407Sbostic 			setreuid(0, 0);
31556407Sbostic syslog(LOG_ERR, "ktlen=%d\n", kt.length);
31652112Smckusick #endif /* KERBEROS */
31752112Smckusick 		}
31856407Sbostic 	}
31956407Sbostic 	exit(0);
32052112Smckusick }
32152112Smckusick 
32256407Sbostic int
32352112Smckusick getnfsargs(spec, nfsargsp)
32452112Smckusick 	char *spec;
32552112Smckusick 	struct nfs_args *nfsargsp;
32652112Smckusick {
32752112Smckusick 	register CLIENT *clp;
32852112Smckusick 	struct hostent *hp;
32952112Smckusick 	static struct sockaddr_in saddr;
33052112Smckusick #ifdef ISO
33152112Smckusick 	static struct sockaddr_iso isoaddr;
33252112Smckusick 	struct iso_addr *isop;
33356407Sbostic 	int isoflag = 0;
33452112Smckusick #endif
33552112Smckusick 	struct timeval pertry, try;
33652112Smckusick 	enum clnt_stat clnt_stat;
33756407Sbostic 	int so = RPC_ANYSOCK, i;
33856407Sbostic 	char *hostp, *delimp;
33956407Sbostic #ifdef KERBEROS
34056407Sbostic 	char *cp;
34156407Sbostic #endif
34252112Smckusick 	u_short tport;
34352112Smckusick 	static struct nfhret nfhret;
34452112Smckusick 	static char nam[MNAMELEN + 1];
34552112Smckusick 
34652112Smckusick 	strncpy(nam, spec, MNAMELEN);
34752112Smckusick 	nam[MNAMELEN] = '\0';
34852112Smckusick 	if ((delimp = index(spec, '@')) != NULL) {
34952112Smckusick 		hostp = delimp + 1;
35052112Smckusick 	} else if ((delimp = index(spec, ':')) != NULL) {
35152112Smckusick 		hostp = spec;
35252112Smckusick 		spec = delimp + 1;
35352112Smckusick 	} else {
35456407Sbostic 		warn("no <host>:<dirpath> or <dirpath>@<host> spec");
35552112Smckusick 		return (0);
35652112Smckusick 	}
35752112Smckusick 	*delimp = '\0';
35852112Smckusick 	/*
35952112Smckusick 	 * DUMB!! Until the mount protocol works on iso transport, we must
36052112Smckusick 	 * supply both an iso and an inet address for the host.
36152112Smckusick 	 */
36252112Smckusick #ifdef ISO
36352112Smckusick 	if (!strncmp(hostp, "iso=", 4)) {
36452112Smckusick 		u_short isoport;
36552112Smckusick 
36652112Smckusick 		hostp += 4;
36752112Smckusick 		isoflag++;
36852112Smckusick 		if ((delimp = index(hostp, '+')) == NULL) {
36956407Sbostic 			warn("no iso+inet address");
37052112Smckusick 			return (0);
37152112Smckusick 		}
37252112Smckusick 		*delimp = '\0';
37352112Smckusick 		if ((isop = iso_addr(hostp)) == NULL) {
37456407Sbostic 			warn("bad ISO address");
37552112Smckusick 			return (0);
37652112Smckusick 		}
37752112Smckusick 		bzero((caddr_t)&isoaddr, sizeof (isoaddr));
37852112Smckusick 		bcopy((caddr_t)isop, (caddr_t)&isoaddr.siso_addr,
37952112Smckusick 			sizeof (struct iso_addr));
38052112Smckusick 		isoaddr.siso_len = sizeof (isoaddr);
38152112Smckusick 		isoaddr.siso_family = AF_ISO;
38252112Smckusick 		isoaddr.siso_tlen = 2;
38352112Smckusick 		isoport = htons(NFS_PORT);
38452112Smckusick 		bcopy((caddr_t)&isoport, TSEL(&isoaddr), isoaddr.siso_tlen);
38552112Smckusick 		hostp = delimp + 1;
38652112Smckusick 	}
38752112Smckusick #endif /* ISO */
38852112Smckusick 
38952112Smckusick 	/*
39052112Smckusick 	 * Handle an internet host address and reverse resolve it if
39152112Smckusick 	 * doing Kerberos.
39252112Smckusick 	 */
39352112Smckusick 	if (isdigit(*hostp)) {
39452112Smckusick 		if ((saddr.sin_addr.s_addr = inet_addr(hostp)) == -1) {
39556407Sbostic 			warn("bad net address %s\n", hostp);
39652112Smckusick 			return (0);
39752112Smckusick 		}
39852112Smckusick 		if ((nfsargsp->flags & NFSMNT_KERB) &&
39952112Smckusick 		    (hp = gethostbyaddr((char *)&saddr.sin_addr.s_addr,
40056407Sbostic 		    sizeof (u_long), AF_INET)) == (struct hostent *)0) {
40156407Sbostic 			warn("can't reverse resolve net address");
40252112Smckusick 			return (0);
40352112Smckusick 		}
40452112Smckusick 	} else if ((hp = gethostbyname(hostp)) == NULL) {
40556407Sbostic 		warn("can't get net id for host");
40652112Smckusick 		return (0);
40752112Smckusick 	}
40852112Smckusick #ifdef KERBEROS
40952112Smckusick 	if (nfsargsp->flags & NFSMNT_KERB) {
41052112Smckusick 		strncpy(inst, hp->h_name, INST_SZ);
41152112Smckusick 		inst[INST_SZ - 1] = '\0';
41252112Smckusick 		if (cp = index(inst, '.'))
41352112Smckusick 			*cp = '\0';
41452112Smckusick 	}
41552112Smckusick #endif /* KERBEROS */
41652112Smckusick 
41752112Smckusick 	bcopy(hp->h_addr, (caddr_t)&saddr.sin_addr, hp->h_length);
41852112Smckusick 	nfhret.stat = EACCES;	/* Mark not yet successful */
41952112Smckusick 	while (retrycnt > 0) {
42052112Smckusick 		saddr.sin_family = AF_INET;
42152112Smckusick 		saddr.sin_port = htons(PMAPPORT);
42252112Smckusick 		if ((tport = pmap_getport(&saddr, RPCPROG_NFS,
42352112Smckusick 		    NFS_VER2, IPPROTO_UDP)) == 0) {
42452112Smckusick 			if ((opflags & ISBGRND) == 0)
42552112Smckusick 				clnt_pcreateerror("NFS Portmap");
42652112Smckusick 		} else {
42752112Smckusick 			saddr.sin_port = 0;
42852112Smckusick 			pertry.tv_sec = 10;
42952112Smckusick 			pertry.tv_usec = 0;
43052112Smckusick 			if ((clp = clntudp_create(&saddr, RPCPROG_MNT,
43152112Smckusick 			    RPCMNT_VER1, pertry, &so)) == NULL) {
43252112Smckusick 				if ((opflags & ISBGRND) == 0)
43352112Smckusick 					clnt_pcreateerror("Cannot MNT PRC");
43452112Smckusick 			} else {
43552112Smckusick 				clp->cl_auth = authunix_create_default();
43652112Smckusick 				try.tv_sec = 10;
43752112Smckusick 				try.tv_usec = 0;
43852112Smckusick 				clnt_stat = clnt_call(clp, RPCMNT_MOUNT,
43952112Smckusick 				    xdr_dir, spec, xdr_fh, &nfhret, try);
44052112Smckusick 				if (clnt_stat != RPC_SUCCESS) {
44156407Sbostic 					if ((opflags & ISBGRND) == 0) {
44256407Sbostic 						warn("%s", clnt_sperror(clp,
44356407Sbostic 						    "bad MNT RPC"));
44456407Sbostic 					}
44552112Smckusick 				} else {
44652112Smckusick 					auth_destroy(clp->cl_auth);
44752112Smckusick 					clnt_destroy(clp);
44852112Smckusick 					retrycnt = 0;
44952112Smckusick 				}
45052112Smckusick 			}
45152112Smckusick 		}
45252112Smckusick 		if (--retrycnt > 0) {
45352112Smckusick 			if (opflags & BGRND) {
45452112Smckusick 				opflags &= ~BGRND;
45552112Smckusick 				if (i = fork()) {
45656407Sbostic 					if (i == -1)
457*56426Sbostic 						err("nqnfs 2: %s",
45856407Sbostic 						    strerror(errno));
45953128Storek 					exit(0);
46052112Smckusick 				}
46152112Smckusick 				(void) setsid();
46256407Sbostic 				(void) close(STDIN_FILENO);
46356407Sbostic 				(void) close(STDOUT_FILENO);
46456407Sbostic 				(void) close(STDERR_FILENO);
46552112Smckusick 				(void) chdir("/");
46652112Smckusick 				opflags |= ISBGRND;
46756407Sbostic 			}
46852112Smckusick 			sleep(60);
46952112Smckusick 		}
47052112Smckusick 	}
47152112Smckusick 	if (nfhret.stat) {
47252112Smckusick 		if (opflags & ISBGRND)
47352112Smckusick 			exit(1);
47456407Sbostic 		warn("can't access %s: %s\n", spec, strerror(nfhret.stat));
47552112Smckusick 		return (0);
47652112Smckusick 	}
47752112Smckusick 	saddr.sin_port = htons(tport);
47852112Smckusick #ifdef ISO
47952112Smckusick 	if (isoflag) {
48052112Smckusick 		nfsargsp->addr = (struct sockaddr *) &isoaddr;
48152112Smckusick 		nfsargsp->addrlen = sizeof (isoaddr);
48252112Smckusick 	} else
48352112Smckusick #endif /* ISO */
48452112Smckusick 	{
48552112Smckusick 		nfsargsp->addr = (struct sockaddr *) &saddr;
48652112Smckusick 		nfsargsp->addrlen = sizeof (saddr);
48752112Smckusick 	}
48852112Smckusick 	nfsargsp->fh = &nfhret.nfh;
48952112Smckusick 	nfsargsp->hostname = nam;
49052112Smckusick 	return (1);
49152112Smckusick }
49252112Smckusick 
49352112Smckusick /*
49452112Smckusick  * xdr routines for mount rpc's
49552112Smckusick  */
49656407Sbostic int
49752112Smckusick xdr_dir(xdrsp, dirp)
49852112Smckusick 	XDR *xdrsp;
49952112Smckusick 	char *dirp;
50052112Smckusick {
50152112Smckusick 	return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
50252112Smckusick }
50352112Smckusick 
50456407Sbostic int
50552112Smckusick xdr_fh(xdrsp, np)
50652112Smckusick 	XDR *xdrsp;
50752112Smckusick 	struct nfhret *np;
50852112Smckusick {
50952112Smckusick 	if (!xdr_u_long(xdrsp, &(np->stat)))
51052112Smckusick 		return (0);
51152112Smckusick 	if (np->stat)
51252112Smckusick 		return (1);
51352112Smckusick 	return (xdr_opaque(xdrsp, (caddr_t)&(np->nfh), NFSX_FH));
51452112Smckusick }
51552112Smckusick 
51656407Sbostic __dead void
51756407Sbostic usage()
51852112Smckusick {
51956407Sbostic 	(void)fprintf(stderr, "usage: mount_nfs %s\n%s\n%s\n%s\n",
52056407Sbostic "[-bcdiKklMPqsT] [-a maxreadahead] [-D deadthresh]",
52156407Sbostic "\t[-g maxgroups] [-L leaseterm] [-m realm] [-R retrycnt]",
52256407Sbostic "\t[-r readsize] [-t timeout] [-w writesize] [-x retrans]",
52356407Sbostic "\trhost:path node");
52456407Sbostic 	exit(1);
52556407Sbostic }
52652112Smckusick 
52756407Sbostic #if __STDC__
52856407Sbostic #include <stdarg.h>
52956407Sbostic #else
53056407Sbostic #include <varargs.h>
53156407Sbostic #endif
53256407Sbostic 
53356407Sbostic void
53456407Sbostic #if __STDC__
53556407Sbostic err(const char *fmt, ...)
53656407Sbostic #else
53756407Sbostic err(fmt, va_alist)
53856407Sbostic 	char *fmt;
53956407Sbostic         va_dcl
54056407Sbostic #endif
54156407Sbostic {
54256407Sbostic 	va_list ap;
54356407Sbostic #if __STDC__
54456407Sbostic 	va_start(ap, fmt);
54556407Sbostic #else
54656407Sbostic 	va_start(ap);
54756407Sbostic #endif
54856407Sbostic 	(void)fprintf(stderr, "mount_nfs: ");
54956407Sbostic 	(void)vfprintf(stderr, fmt, ap);
55056407Sbostic 	va_end(ap);
55156407Sbostic 	(void)fprintf(stderr, "\n");
55252112Smckusick 	exit(1);
55356407Sbostic 	/* NOTREACHED */
55452112Smckusick }
55556407Sbostic 
55656407Sbostic void
55756407Sbostic #if __STDC__
55856407Sbostic warn(const char *fmt, ...)
55956407Sbostic #else
56056407Sbostic warn(fmt, va_alist)
56156407Sbostic 	char *fmt;
56256407Sbostic         va_dcl
56356407Sbostic #endif
56456407Sbostic {
56556407Sbostic 	va_list ap;
56656407Sbostic #if __STDC__
56756407Sbostic 	va_start(ap, fmt);
56856407Sbostic #else
56956407Sbostic 	va_start(ap);
57056407Sbostic #endif
57156407Sbostic 	(void)fprintf(stderr, "mount_nfs: ");
57256407Sbostic 	(void)vfprintf(stderr, fmt, ap);
57356407Sbostic 	va_end(ap);
57456407Sbostic 	(void)fprintf(stderr, "\n");
57556407Sbostic }
576