xref: /csrg-svn/sbin/mount_nfs/mount_nfs.c (revision 61511)
152112Smckusick /*
2*61511Sbostic  * Copyright (c) 1992, 1993
3*61511Sbostic  *	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
12*61511Sbostic static char copyright[] =
13*61511Sbostic "@(#) Copyright (c) 1992, 1993\n\
14*61511Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1552112Smckusick #endif /* not lint */
1652112Smckusick 
1752112Smckusick #ifndef lint
18*61511Sbostic static char sccsid[] = "@(#)mount_nfs.c	8.1 (Berkeley) 06/05/93";
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>
5156407Sbostic #include <errno.h>
5256407Sbostic #include <fcntl.h>
5356407Sbostic #include <netdb.h>
5456407Sbostic #include <signal.h>
5556407Sbostic #include <stdio.h>
5656407Sbostic #include <stdlib.h>
5756407Sbostic #include <strings.h>
5856407Sbostic #include <unistd.h>
5956407Sbostic 
6052112Smckusick struct nfs_args nfsdefargs = {
6152112Smckusick 	(struct sockaddr *)0,
6252112Smckusick 	sizeof (struct sockaddr_in),
6352112Smckusick 	SOCK_DGRAM,
6452112Smckusick 	0,
6552112Smckusick 	(nfsv2fh_t *)0,
6652112Smckusick 	0,
6752112Smckusick 	NFS_WSIZE,
6852112Smckusick 	NFS_RSIZE,
6952112Smckusick 	NFS_TIMEO,
7052112Smckusick 	NFS_RETRANS,
7152112Smckusick 	NFS_MAXGRPS,
7252112Smckusick 	NFS_DEFRAHEAD,
7352112Smckusick 	NQ_DEFLEASE,
7452112Smckusick 	NQ_DEADTHRESH,
7552112Smckusick 	(char *)0,
7652112Smckusick };
7752112Smckusick 
7852112Smckusick struct nfhret {
7952112Smckusick 	u_long	stat;
8052112Smckusick 	nfsv2fh_t nfh;
8152112Smckusick };
8252112Smckusick #define	DEF_RETRY	10000
8352112Smckusick #define	BGRND	1
8452112Smckusick #define	ISBGRND	2
8552112Smckusick int retrycnt = DEF_RETRY;
8652112Smckusick int opflags = 0;
8752112Smckusick 
8852112Smckusick #ifdef KERBEROS
8952112Smckusick char inst[INST_SZ];
9052112Smckusick char realm[REALM_SZ];
9152112Smckusick KTEXT_ST kt;
9252112Smckusick #endif
9352112Smckusick 
9456407Sbostic void	err __P((const char *, ...));
9556407Sbostic int	getnfsargs __P((char *, struct nfs_args *));
9656407Sbostic #ifdef ISO
9756407Sbostic struct	iso_addr *iso_addr __P((const char *));
9856407Sbostic #endif
9956407Sbostic void	set_rpc_maxgrouplist __P((int));
10056407Sbostic __dead	void usage __P((void));
10156407Sbostic void	warn __P((const char *, ...));
10256407Sbostic int	xdr_dir __P((XDR *, char *));
10356407Sbostic int	xdr_fh __P((XDR *, struct nfhret *));
10456407Sbostic 
10556407Sbostic int
10656407Sbostic main(argc, argv)
10752112Smckusick 	int argc;
10856407Sbostic 	char *argv[];
10952112Smckusick {
11056407Sbostic 	register int c;
11156407Sbostic 	register struct nfs_args *nfsargsp;
11252112Smckusick 	struct nfs_args nfsargs;
11352112Smckusick 	struct nfsd_cargs ncd;
11456407Sbostic 	int flags, i, nfssvc_flag, num;
11556407Sbostic 	char *name, *p, *spec;
11656407Sbostic #ifdef KERBEROS
11756407Sbostic 	uid_t last_ruid;
11856407Sbostic #endif
11952112Smckusick 
12052112Smckusick #ifdef KERBEROS
12156407Sbostic 	last_ruid = -1;
12256407Sbostic 	(void)strcpy(realm, KRB_REALM);
12352112Smckusick #endif
12452112Smckusick 	retrycnt = DEF_RETRY;
12556407Sbostic 
12652112Smckusick 	if (argc <= 1)
12756407Sbostic 		usage();
12856407Sbostic 
12956407Sbostic 	flags = 0;
13056407Sbostic 	nfsargs = nfsdefargs;
13156407Sbostic 	nfsargsp = &nfsargs;
13256407Sbostic 	while ((c = getopt(argc, argv,
13356407Sbostic 	    "a:bcdD:F:g:iKklL:Mm:PpqR:r:sTt:w:x:")) != EOF)
13452112Smckusick 		switch (c) {
13556407Sbostic 		case 'a':
13656407Sbostic 			num = strtol(optarg, &p, 10);
13756407Sbostic 			if (*p || num < 0)
13856407Sbostic 				err("illegal -a value -- %s", optarg);
13956407Sbostic 			nfsargsp->readahead = num;
14056407Sbostic 			nfsargsp->flags |= NFSMNT_READAHEAD;
14156407Sbostic 			break;
14252112Smckusick 		case 'b':
14352112Smckusick 			opflags |= BGRND;
14452112Smckusick 			break;
14556407Sbostic 		case 'c':
14656407Sbostic 			nfsargsp->flags |= NFSMNT_NOCONN;
14752112Smckusick 			break;
14856407Sbostic 		case 'D':
14956407Sbostic 			num = strtol(optarg, &p, 10);
15056407Sbostic 			if (*p || num <= 0)
15156407Sbostic 				err("illegal -D value -- %s", optarg);
15256407Sbostic 			nfsargsp->deadthresh = num;
15356407Sbostic 			nfsargsp->flags |= NFSMNT_DEADTHRESH;
15456407Sbostic 			break;
15556407Sbostic 		case 'd':
15656407Sbostic 			nfsargsp->flags |= NFSMNT_DUMBTIMR;
15756407Sbostic 			break;
15856407Sbostic 		case 'F':
15956407Sbostic 			num = strtol(optarg, &p, 10);
16056600Smckusick 			if (*p)
16156407Sbostic 				err("illegal -F value -- %s", optarg);
16256600Smckusick 			if (num != 0)
16356600Smckusick 				flags = num;
16456407Sbostic 			break;
16556407Sbostic 		case 'g':
16656407Sbostic 			num = strtol(optarg, &p, 10);
16756646Shibler 			if (*p || num <= 0)
16856407Sbostic 				err("illegal -g value -- %s", optarg);
16956407Sbostic 			set_rpc_maxgrouplist(num);
17056407Sbostic 			nfsargsp->maxgrouplist = num;
17156407Sbostic 			nfsargsp->flags |= NFSMNT_MAXGRPS;
17256407Sbostic 			break;
17352112Smckusick 		case 'i':
17452112Smckusick 			nfsargsp->flags |= NFSMNT_INT;
17552112Smckusick 			break;
17656407Sbostic #ifdef KERBEROS
17756407Sbostic 		case 'K':
17856407Sbostic 			nfsargsp->flags |= NFSMNT_KERB;
17952112Smckusick 			break;
18052112Smckusick #endif
18156407Sbostic 		case 'k':
18256407Sbostic 			nfsargsp->flags |= NFSMNT_NQLOOKLEASE;
18352112Smckusick 			break;
18456407Sbostic 		case 'L':
18556407Sbostic 			num = strtol(optarg, &p, 10);
18656407Sbostic 			if (*p || num < 2)
18756407Sbostic 				err("illegal -L value -- %s", optarg);
18856407Sbostic 			nfsargsp->leaseterm = num;
18956407Sbostic 			nfsargsp->flags |= NFSMNT_LEASETERM;
19056407Sbostic 			break;
19152112Smckusick 		case 'l':
19252112Smckusick 			nfsargsp->flags |= NFSMNT_RDIRALOOK;
19352112Smckusick 			break;
19456407Sbostic 		case 'M':
19556407Sbostic 			nfsargsp->flags |= NFSMNT_MYWRITE;
19652112Smckusick 			break;
19756407Sbostic #ifdef KERBEROS
19856407Sbostic 		case 'm':
19956407Sbostic 			(void)strncpy(realm, optarg, REALM_SZ - 1);
20056407Sbostic 			realm[REALM_SZ - 1] = '\0';
20152112Smckusick 			break;
20256407Sbostic #endif
20352989Smckusick 		case 'P':
20452989Smckusick 			nfsargsp->flags |= NFSMNT_RESVPORT;
20552989Smckusick 			break;
20656407Sbostic #ifdef ISO
20756407Sbostic 		case 'p':
20856407Sbostic 			nfsargsp->sotype = SOCK_SEQPACKET;
20952112Smckusick 			break;
21056407Sbostic #endif
21156407Sbostic 		case 'q':
21256407Sbostic 			nfsargsp->flags |= NFSMNT_NQNFS;
21356407Sbostic 			break;
21452112Smckusick 		case 'R':
21556407Sbostic 			num = strtol(optarg, &p, 10);
21656407Sbostic 			if (*p || num <= 0)
21756407Sbostic 				err("illegal -R value -- %s", optarg);
21856407Sbostic 			retrycnt = num;
21952112Smckusick 			break;
22052112Smckusick 		case 'r':
22156407Sbostic 			num = strtol(optarg, &p, 10);
22256407Sbostic 			if (*p || num <= 0)
22356407Sbostic 				err("illegal -r value -- %s", optarg);
22456407Sbostic 			nfsargsp->rsize = num;
22556407Sbostic 			nfsargsp->flags |= NFSMNT_RSIZE;
22652112Smckusick 			break;
22756407Sbostic 		case 's':
22856407Sbostic 			nfsargsp->flags |= NFSMNT_SOFT;
22952112Smckusick 			break;
23056407Sbostic 		case 'T':
23156407Sbostic 			nfsargsp->sotype = SOCK_STREAM;
23256407Sbostic 			break;
23352112Smckusick 		case 't':
23456407Sbostic 			num = strtol(optarg, &p, 10);
23556407Sbostic 			if (*p || num <= 0)
23656407Sbostic 				err("illegal -t value -- %s", optarg);
23756407Sbostic 			nfsargsp->timeo = num;
23856407Sbostic 			nfsargsp->flags |= NFSMNT_TIMEO;
23952112Smckusick 			break;
24056407Sbostic 		case 'w':
24156407Sbostic 			num = strtol(optarg, &p, 10);
24256407Sbostic 			if (*p || num <= 0)
24356407Sbostic 				err("illegal -w value -- %s", optarg);
24456407Sbostic 			nfsargsp->wsize = num;
24556407Sbostic 			nfsargsp->flags |= NFSMNT_WSIZE;
24656407Sbostic 			break;
24752112Smckusick 		case 'x':
24856407Sbostic 			num = strtol(optarg, &p, 10);
24956407Sbostic 			if (*p || num <= 0)
25056407Sbostic 				err("illegal -x value -- %s", optarg);
25156407Sbostic 			nfsargsp->retrans = num;
25256407Sbostic 			nfsargsp->flags |= NFSMNT_RETRANS;
25352112Smckusick 			break;
25452112Smckusick 		default:
25556407Sbostic 			usage();
25652112Smckusick 		};
25756407Sbostic 
25856407Sbostic 	if ((argc - optind) != 2)
25956407Sbostic 		usage();
26056407Sbostic 
26156407Sbostic 	spec = argv[optind];
26256407Sbostic 	name = argv[optind + 1];
26356407Sbostic 
26456407Sbostic 	if (!getnfsargs(spec, nfsargsp))
26556407Sbostic 		exit(1);
26656407Sbostic 	if (mount(MOUNT_NFS, name, flags, nfsargsp))
26756426Sbostic 		err("mount: %s: %s", name, strerror(errno));
26856407Sbostic 	if (nfsargsp->flags & (NFSMNT_NQNFS | NFSMNT_KERB)) {
26956407Sbostic 		if ((opflags & ISBGRND) == 0) {
27056407Sbostic 			if (i = fork()) {
27156407Sbostic 				if (i == -1)
27256426Sbostic 					err("nqnfs 1: %s", strerror(errno));
27356407Sbostic 				exit(0);
27452112Smckusick 			}
27556407Sbostic 			(void) setsid();
27656407Sbostic 			(void) close(STDIN_FILENO);
27756407Sbostic 			(void) close(STDOUT_FILENO);
27856407Sbostic 			(void) close(STDERR_FILENO);
27956407Sbostic 			(void) chdir("/");
28056407Sbostic 		}
28156407Sbostic 		openlog("mount_nfs:", LOG_PID, LOG_DAEMON);
28256407Sbostic 		nfssvc_flag = NFSSVC_MNTD;
28356407Sbostic 		ncd.ncd_dirp = name;
28456407Sbostic 		while (nfssvc(nfssvc_flag, (caddr_t)&ncd) < 0) {
28556407Sbostic 			if (errno != ENEEDAUTH) {
28656407Sbostic 				syslog(LOG_ERR, "nfssvc err %m");
28756407Sbostic 				continue;
28856407Sbostic 			}
28956407Sbostic 			nfssvc_flag =
29056407Sbostic 			    NFSSVC_MNTD | NFSSVC_GOTAUTH | NFSSVC_AUTHINFAIL;
29152112Smckusick #ifdef KERBEROS
29256407Sbostic 			/*
29356407Sbostic 			 * Set up as ncd_authuid for the kerberos call.
29456407Sbostic 			 * Must set ruid to ncd_authuid and reset the
29556407Sbostic 			 * ticket name iff ncd_authuid is not the same
29656407Sbostic 			 * as last time, so that the right ticket file
29756407Sbostic 			 * is found.
29856407Sbostic 			 */
29956407Sbostic 			if (ncd.ncd_authuid != last_ruid) {
30056407Sbostic 				krb_set_tkt_string("");
30156407Sbostic 				last_ruid = ncd.ncd_authuid;
30256407Sbostic 			}
30356407Sbostic 			setreuid(ncd.ncd_authuid, 0);
30456407Sbostic 			if (krb_mk_req(&kt, "rcmd", inst, realm, 0) ==
30556407Sbostic 			    KSUCCESS &&
30656407Sbostic 			    kt.length <= (RPCAUTH_MAXSIZ - 2 * NFSX_UNSIGNED)) {
30756407Sbostic 				ncd.ncd_authtype = RPCAUTH_NQNFS;
30856407Sbostic 				ncd.ncd_authlen = kt.length;
30956407Sbostic 				ncd.ncd_authstr = (char *)kt.dat;
31056407Sbostic 				nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH;
31156407Sbostic 			}
31256407Sbostic 			setreuid(0, 0);
31352112Smckusick #endif /* KERBEROS */
31452112Smckusick 		}
31556407Sbostic 	}
31656407Sbostic 	exit(0);
31752112Smckusick }
31852112Smckusick 
31956407Sbostic int
32052112Smckusick getnfsargs(spec, nfsargsp)
32152112Smckusick 	char *spec;
32252112Smckusick 	struct nfs_args *nfsargsp;
32352112Smckusick {
32452112Smckusick 	register CLIENT *clp;
32552112Smckusick 	struct hostent *hp;
32652112Smckusick 	static struct sockaddr_in saddr;
32752112Smckusick #ifdef ISO
32852112Smckusick 	static struct sockaddr_iso isoaddr;
32952112Smckusick 	struct iso_addr *isop;
33056407Sbostic 	int isoflag = 0;
33152112Smckusick #endif
33252112Smckusick 	struct timeval pertry, try;
33352112Smckusick 	enum clnt_stat clnt_stat;
33456407Sbostic 	int so = RPC_ANYSOCK, i;
33556407Sbostic 	char *hostp, *delimp;
33656407Sbostic #ifdef KERBEROS
33756407Sbostic 	char *cp;
33856407Sbostic #endif
33952112Smckusick 	u_short tport;
34052112Smckusick 	static struct nfhret nfhret;
34152112Smckusick 	static char nam[MNAMELEN + 1];
34252112Smckusick 
34352112Smckusick 	strncpy(nam, spec, MNAMELEN);
34452112Smckusick 	nam[MNAMELEN] = '\0';
34552112Smckusick 	if ((delimp = index(spec, '@')) != NULL) {
34652112Smckusick 		hostp = delimp + 1;
34752112Smckusick 	} else if ((delimp = index(spec, ':')) != NULL) {
34852112Smckusick 		hostp = spec;
34952112Smckusick 		spec = delimp + 1;
35052112Smckusick 	} else {
35156407Sbostic 		warn("no <host>:<dirpath> or <dirpath>@<host> spec");
35252112Smckusick 		return (0);
35352112Smckusick 	}
35452112Smckusick 	*delimp = '\0';
35552112Smckusick 	/*
35652112Smckusick 	 * DUMB!! Until the mount protocol works on iso transport, we must
35752112Smckusick 	 * supply both an iso and an inet address for the host.
35852112Smckusick 	 */
35952112Smckusick #ifdef ISO
36052112Smckusick 	if (!strncmp(hostp, "iso=", 4)) {
36152112Smckusick 		u_short isoport;
36252112Smckusick 
36352112Smckusick 		hostp += 4;
36452112Smckusick 		isoflag++;
36552112Smckusick 		if ((delimp = index(hostp, '+')) == NULL) {
36656407Sbostic 			warn("no iso+inet address");
36752112Smckusick 			return (0);
36852112Smckusick 		}
36952112Smckusick 		*delimp = '\0';
37052112Smckusick 		if ((isop = iso_addr(hostp)) == NULL) {
37156407Sbostic 			warn("bad ISO address");
37252112Smckusick 			return (0);
37352112Smckusick 		}
37452112Smckusick 		bzero((caddr_t)&isoaddr, sizeof (isoaddr));
37552112Smckusick 		bcopy((caddr_t)isop, (caddr_t)&isoaddr.siso_addr,
37652112Smckusick 			sizeof (struct iso_addr));
37752112Smckusick 		isoaddr.siso_len = sizeof (isoaddr);
37852112Smckusick 		isoaddr.siso_family = AF_ISO;
37952112Smckusick 		isoaddr.siso_tlen = 2;
38052112Smckusick 		isoport = htons(NFS_PORT);
38152112Smckusick 		bcopy((caddr_t)&isoport, TSEL(&isoaddr), isoaddr.siso_tlen);
38252112Smckusick 		hostp = delimp + 1;
38352112Smckusick 	}
38452112Smckusick #endif /* ISO */
38552112Smckusick 
38652112Smckusick 	/*
38752112Smckusick 	 * Handle an internet host address and reverse resolve it if
38852112Smckusick 	 * doing Kerberos.
38952112Smckusick 	 */
39052112Smckusick 	if (isdigit(*hostp)) {
39152112Smckusick 		if ((saddr.sin_addr.s_addr = inet_addr(hostp)) == -1) {
39256407Sbostic 			warn("bad net address %s\n", hostp);
39352112Smckusick 			return (0);
39452112Smckusick 		}
39552112Smckusick 		if ((nfsargsp->flags & NFSMNT_KERB) &&
39652112Smckusick 		    (hp = gethostbyaddr((char *)&saddr.sin_addr.s_addr,
39756407Sbostic 		    sizeof (u_long), AF_INET)) == (struct hostent *)0) {
39856407Sbostic 			warn("can't reverse resolve net address");
39952112Smckusick 			return (0);
40052112Smckusick 		}
40152112Smckusick 	} else if ((hp = gethostbyname(hostp)) == NULL) {
40256407Sbostic 		warn("can't get net id for host");
40352112Smckusick 		return (0);
40452112Smckusick 	}
40552112Smckusick #ifdef KERBEROS
40652112Smckusick 	if (nfsargsp->flags & NFSMNT_KERB) {
40752112Smckusick 		strncpy(inst, hp->h_name, INST_SZ);
40852112Smckusick 		inst[INST_SZ - 1] = '\0';
40952112Smckusick 		if (cp = index(inst, '.'))
41052112Smckusick 			*cp = '\0';
41152112Smckusick 	}
41252112Smckusick #endif /* KERBEROS */
41352112Smckusick 
41452112Smckusick 	bcopy(hp->h_addr, (caddr_t)&saddr.sin_addr, hp->h_length);
41552112Smckusick 	nfhret.stat = EACCES;	/* Mark not yet successful */
41652112Smckusick 	while (retrycnt > 0) {
41752112Smckusick 		saddr.sin_family = AF_INET;
41852112Smckusick 		saddr.sin_port = htons(PMAPPORT);
41952112Smckusick 		if ((tport = pmap_getport(&saddr, RPCPROG_NFS,
42052112Smckusick 		    NFS_VER2, IPPROTO_UDP)) == 0) {
42152112Smckusick 			if ((opflags & ISBGRND) == 0)
42252112Smckusick 				clnt_pcreateerror("NFS Portmap");
42352112Smckusick 		} else {
42452112Smckusick 			saddr.sin_port = 0;
42552112Smckusick 			pertry.tv_sec = 10;
42652112Smckusick 			pertry.tv_usec = 0;
42752112Smckusick 			if ((clp = clntudp_create(&saddr, RPCPROG_MNT,
42852112Smckusick 			    RPCMNT_VER1, pertry, &so)) == NULL) {
42952112Smckusick 				if ((opflags & ISBGRND) == 0)
43052112Smckusick 					clnt_pcreateerror("Cannot MNT PRC");
43152112Smckusick 			} else {
43252112Smckusick 				clp->cl_auth = authunix_create_default();
43352112Smckusick 				try.tv_sec = 10;
43452112Smckusick 				try.tv_usec = 0;
43552112Smckusick 				clnt_stat = clnt_call(clp, RPCMNT_MOUNT,
43652112Smckusick 				    xdr_dir, spec, xdr_fh, &nfhret, try);
43752112Smckusick 				if (clnt_stat != RPC_SUCCESS) {
43856407Sbostic 					if ((opflags & ISBGRND) == 0) {
43956407Sbostic 						warn("%s", clnt_sperror(clp,
44056407Sbostic 						    "bad MNT RPC"));
44156407Sbostic 					}
44252112Smckusick 				} else {
44352112Smckusick 					auth_destroy(clp->cl_auth);
44452112Smckusick 					clnt_destroy(clp);
44552112Smckusick 					retrycnt = 0;
44652112Smckusick 				}
44752112Smckusick 			}
44852112Smckusick 		}
44952112Smckusick 		if (--retrycnt > 0) {
45052112Smckusick 			if (opflags & BGRND) {
45152112Smckusick 				opflags &= ~BGRND;
45252112Smckusick 				if (i = fork()) {
45356407Sbostic 					if (i == -1)
45456426Sbostic 						err("nqnfs 2: %s",
45556407Sbostic 						    strerror(errno));
45653128Storek 					exit(0);
45752112Smckusick 				}
45852112Smckusick 				(void) setsid();
45956407Sbostic 				(void) close(STDIN_FILENO);
46056407Sbostic 				(void) close(STDOUT_FILENO);
46156407Sbostic 				(void) close(STDERR_FILENO);
46252112Smckusick 				(void) chdir("/");
46352112Smckusick 				opflags |= ISBGRND;
46456407Sbostic 			}
46552112Smckusick 			sleep(60);
46652112Smckusick 		}
46752112Smckusick 	}
46852112Smckusick 	if (nfhret.stat) {
46952112Smckusick 		if (opflags & ISBGRND)
47052112Smckusick 			exit(1);
47156407Sbostic 		warn("can't access %s: %s\n", spec, strerror(nfhret.stat));
47252112Smckusick 		return (0);
47352112Smckusick 	}
47452112Smckusick 	saddr.sin_port = htons(tport);
47552112Smckusick #ifdef ISO
47652112Smckusick 	if (isoflag) {
47752112Smckusick 		nfsargsp->addr = (struct sockaddr *) &isoaddr;
47852112Smckusick 		nfsargsp->addrlen = sizeof (isoaddr);
47952112Smckusick 	} else
48052112Smckusick #endif /* ISO */
48152112Smckusick 	{
48252112Smckusick 		nfsargsp->addr = (struct sockaddr *) &saddr;
48352112Smckusick 		nfsargsp->addrlen = sizeof (saddr);
48452112Smckusick 	}
48552112Smckusick 	nfsargsp->fh = &nfhret.nfh;
48652112Smckusick 	nfsargsp->hostname = nam;
48752112Smckusick 	return (1);
48852112Smckusick }
48952112Smckusick 
49052112Smckusick /*
49152112Smckusick  * xdr routines for mount rpc's
49252112Smckusick  */
49356407Sbostic int
49452112Smckusick xdr_dir(xdrsp, dirp)
49552112Smckusick 	XDR *xdrsp;
49652112Smckusick 	char *dirp;
49752112Smckusick {
49852112Smckusick 	return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
49952112Smckusick }
50052112Smckusick 
50156407Sbostic int
50252112Smckusick xdr_fh(xdrsp, np)
50352112Smckusick 	XDR *xdrsp;
50452112Smckusick 	struct nfhret *np;
50552112Smckusick {
50652112Smckusick 	if (!xdr_u_long(xdrsp, &(np->stat)))
50752112Smckusick 		return (0);
50852112Smckusick 	if (np->stat)
50952112Smckusick 		return (1);
51052112Smckusick 	return (xdr_opaque(xdrsp, (caddr_t)&(np->nfh), NFSX_FH));
51152112Smckusick }
51252112Smckusick 
51356407Sbostic __dead void
51456407Sbostic usage()
51552112Smckusick {
51656407Sbostic 	(void)fprintf(stderr, "usage: mount_nfs %s\n%s\n%s\n%s\n",
51756407Sbostic "[-bcdiKklMPqsT] [-a maxreadahead] [-D deadthresh]",
51856407Sbostic "\t[-g maxgroups] [-L leaseterm] [-m realm] [-R retrycnt]",
51956407Sbostic "\t[-r readsize] [-t timeout] [-w writesize] [-x retrans]",
52056407Sbostic "\trhost:path node");
52156407Sbostic 	exit(1);
52256407Sbostic }
52352112Smckusick 
52456407Sbostic #if __STDC__
52556407Sbostic #include <stdarg.h>
52656407Sbostic #else
52756407Sbostic #include <varargs.h>
52856407Sbostic #endif
52956407Sbostic 
53056407Sbostic void
53156407Sbostic #if __STDC__
53256407Sbostic err(const char *fmt, ...)
53356407Sbostic #else
53456407Sbostic err(fmt, va_alist)
53556407Sbostic 	char *fmt;
53656407Sbostic         va_dcl
53756407Sbostic #endif
53856407Sbostic {
53956407Sbostic 	va_list ap;
54056407Sbostic #if __STDC__
54156407Sbostic 	va_start(ap, fmt);
54256407Sbostic #else
54356407Sbostic 	va_start(ap);
54456407Sbostic #endif
54556407Sbostic 	(void)fprintf(stderr, "mount_nfs: ");
54656407Sbostic 	(void)vfprintf(stderr, fmt, ap);
54756407Sbostic 	va_end(ap);
54856407Sbostic 	(void)fprintf(stderr, "\n");
54952112Smckusick 	exit(1);
55056407Sbostic 	/* NOTREACHED */
55152112Smckusick }
55256407Sbostic 
55356407Sbostic void
55456407Sbostic #if __STDC__
55556407Sbostic warn(const char *fmt, ...)
55656407Sbostic #else
55756407Sbostic warn(fmt, va_alist)
55856407Sbostic 	char *fmt;
55956407Sbostic         va_dcl
56056407Sbostic #endif
56156407Sbostic {
56256407Sbostic 	va_list ap;
56356407Sbostic #if __STDC__
56456407Sbostic 	va_start(ap, fmt);
56556407Sbostic #else
56656407Sbostic 	va_start(ap);
56756407Sbostic #endif
56856407Sbostic 	(void)fprintf(stderr, "mount_nfs: ");
56956407Sbostic 	(void)vfprintf(stderr, fmt, ap);
57056407Sbostic 	va_end(ap);
57156407Sbostic 	(void)fprintf(stderr, "\n");
57256407Sbostic }
573