xref: /csrg-svn/sbin/mount_nfs/mount_nfs.c (revision 56407)
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*56407Sbostic static char sccsid[] = "@(#)mount_nfs.c	5.5 (Berkeley) 10/04/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>
25*56407Sbostic #include <sys/stat.h>
26*56407Sbostic #include <sys/syslog.h>
27*56407Sbostic 
2852112Smckusick #include <rpc/rpc.h>
2952112Smckusick #include <rpc/pmap_clnt.h>
3052112Smckusick #include <rpc/pmap_prot.h>
31*56407Sbostic 
3252112Smckusick #ifdef ISO
3352112Smckusick #include <netiso/iso.h>
3452112Smckusick #endif
35*56407Sbostic 
3652112Smckusick #ifdef KERBEROS
3752112Smckusick #include <kerberosIV/krb.h>
3852112Smckusick #endif
39*56407Sbostic 
4052112Smckusick #include <nfs/rpcv2.h>
4152112Smckusick #include <nfs/nfsv2.h>
42*56407Sbostic #define KERNEL
4352112Smckusick #include <nfs/nfs.h>
44*56407Sbostic #undef KERNEL
4552112Smckusick #include <nfs/nqnfs.h>
4652112Smckusick 
47*56407Sbostic #include <arpa/inet.h>
48*56407Sbostic 
49*56407Sbostic #include <ctype.h>
50*56407Sbostic #include <errno.h>
51*56407Sbostic #include <fcntl.h>
52*56407Sbostic #include <netdb.h>
53*56407Sbostic #include <signal.h>
54*56407Sbostic #include <stdio.h>
55*56407Sbostic #include <stdlib.h>
56*56407Sbostic #include <strings.h>
57*56407Sbostic #include <unistd.h>
58*56407Sbostic 
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 
93*56407Sbostic void	err __P((const char *, ...));
94*56407Sbostic int	getnfsargs __P((char *, struct nfs_args *));
95*56407Sbostic #ifdef ISO
96*56407Sbostic struct	iso_addr *iso_addr __P((const char *));
97*56407Sbostic #endif
98*56407Sbostic void	set_rpc_maxgrouplist __P((int));
99*56407Sbostic __dead	void usage __P((void));
100*56407Sbostic void	warn __P((const char *, ...));
101*56407Sbostic int	xdr_dir __P((XDR *, char *));
102*56407Sbostic int	xdr_fh __P((XDR *, struct nfhret *));
103*56407Sbostic 
104*56407Sbostic int
105*56407Sbostic main(argc, argv)
10652112Smckusick 	int argc;
107*56407Sbostic 	char *argv[];
10852112Smckusick {
109*56407Sbostic 	register int c;
110*56407Sbostic 	register struct nfs_args *nfsargsp;
11152112Smckusick 	struct nfs_args nfsargs;
11252112Smckusick 	struct nfsd_cargs ncd;
113*56407Sbostic 	struct stat sb;
114*56407Sbostic 	int flags, i, nfssvc_flag, num;
115*56407Sbostic 	char *name, *p, *spec;
116*56407Sbostic #ifdef KERBEROS
117*56407Sbostic 	uid_t last_ruid;
118*56407Sbostic #endif
11952112Smckusick 
12052112Smckusick #ifdef KERBEROS
121*56407Sbostic 	last_ruid = -1;
122*56407Sbostic 	(void)strcpy(realm, KRB_REALM);
12352112Smckusick #endif
12452112Smckusick 	retrycnt = DEF_RETRY;
125*56407Sbostic 
12652112Smckusick 	if (argc <= 1)
127*56407Sbostic 		usage();
128*56407Sbostic 
129*56407Sbostic 	flags = 0;
130*56407Sbostic 	nfsargs = nfsdefargs;
131*56407Sbostic 	nfsargsp = &nfsargs;
132*56407Sbostic 	while ((c = getopt(argc, argv,
133*56407Sbostic 	    "a:bcdD:F:g:iKklL:Mm:PpqR:r:sTt:w:x:")) != EOF)
13452112Smckusick 		switch (c) {
135*56407Sbostic 		case 'a':
136*56407Sbostic 			num = strtol(optarg, &p, 10);
137*56407Sbostic 			if (*p || num < 0)
138*56407Sbostic 				err("illegal -a value -- %s", optarg);
139*56407Sbostic 			nfsargsp->readahead = num;
140*56407Sbostic 			nfsargsp->flags |= NFSMNT_READAHEAD;
141*56407Sbostic 			break;
14252112Smckusick 		case 'b':
14352112Smckusick 			opflags |= BGRND;
14452112Smckusick 			break;
145*56407Sbostic 		case 'c':
146*56407Sbostic 			nfsargsp->flags |= NFSMNT_NOCONN;
14752112Smckusick 			break;
148*56407Sbostic 		case 'D':
149*56407Sbostic 			num = strtol(optarg, &p, 10);
150*56407Sbostic 			if (*p || num <= 0)
151*56407Sbostic 				err("illegal -D value -- %s", optarg);
152*56407Sbostic 			nfsargsp->deadthresh = num;
153*56407Sbostic 			nfsargsp->flags |= NFSMNT_DEADTHRESH;
154*56407Sbostic 			break;
155*56407Sbostic 		case 'd':
156*56407Sbostic 			nfsargsp->flags |= NFSMNT_DUMBTIMR;
157*56407Sbostic 			break;
158*56407Sbostic 		case 'F':
159*56407Sbostic 			num = strtol(optarg, &p, 10);
160*56407Sbostic 			if (*p || num != 0)
161*56407Sbostic 				err("illegal -F value -- %s", optarg);
162*56407Sbostic 			flags = num;
163*56407Sbostic 			break;
164*56407Sbostic 		case 'g':
165*56407Sbostic 			num = strtol(optarg, &p, 10);
166*56407Sbostic 			if (*p || num > 0)
167*56407Sbostic 				err("illegal -g value -- %s", optarg);
168*56407Sbostic 			set_rpc_maxgrouplist(num);
169*56407Sbostic 			nfsargsp->maxgrouplist = num;
170*56407Sbostic 			nfsargsp->flags |= NFSMNT_MAXGRPS;
171*56407Sbostic 			break;
17252112Smckusick 		case 'i':
17352112Smckusick 			nfsargsp->flags |= NFSMNT_INT;
17452112Smckusick 			break;
175*56407Sbostic #ifdef KERBEROS
176*56407Sbostic 		case 'K':
177*56407Sbostic 			nfsargsp->flags |= NFSMNT_KERB;
17852112Smckusick 			break;
17952112Smckusick #endif
180*56407Sbostic 		case 'k':
181*56407Sbostic 			nfsargsp->flags |= NFSMNT_NQLOOKLEASE;
18252112Smckusick 			break;
183*56407Sbostic 		case 'L':
184*56407Sbostic 			num = strtol(optarg, &p, 10);
185*56407Sbostic 			if (*p || num < 2)
186*56407Sbostic 				err("illegal -L value -- %s", optarg);
187*56407Sbostic 			nfsargsp->leaseterm = num;
188*56407Sbostic 			nfsargsp->flags |= NFSMNT_LEASETERM;
189*56407Sbostic 			break;
19052112Smckusick 		case 'l':
19152112Smckusick 			nfsargsp->flags |= NFSMNT_RDIRALOOK;
19252112Smckusick 			break;
193*56407Sbostic 		case 'M':
194*56407Sbostic 			nfsargsp->flags |= NFSMNT_MYWRITE;
19552112Smckusick 			break;
196*56407Sbostic #ifdef KERBEROS
197*56407Sbostic 		case 'm':
198*56407Sbostic 			(void)strncpy(realm, optarg, REALM_SZ - 1);
199*56407Sbostic 			realm[REALM_SZ - 1] = '\0';
20052112Smckusick 			break;
201*56407Sbostic #endif
20252989Smckusick 		case 'P':
20352989Smckusick 			nfsargsp->flags |= NFSMNT_RESVPORT;
20452989Smckusick 			break;
205*56407Sbostic #ifdef ISO
206*56407Sbostic 		case 'p':
207*56407Sbostic 			nfsargsp->sotype = SOCK_SEQPACKET;
20852112Smckusick 			break;
209*56407Sbostic #endif
210*56407Sbostic 		case 'q':
211*56407Sbostic 			nfsargsp->flags |= NFSMNT_NQNFS;
212*56407Sbostic 			break;
21352112Smckusick 		case 'R':
214*56407Sbostic 			num = strtol(optarg, &p, 10);
215*56407Sbostic 			if (*p || num <= 0)
216*56407Sbostic 				err("illegal -R value -- %s", optarg);
217*56407Sbostic 			retrycnt = num;
21852112Smckusick 			break;
21952112Smckusick 		case 'r':
220*56407Sbostic 			num = strtol(optarg, &p, 10);
221*56407Sbostic 			if (*p || num <= 0)
222*56407Sbostic 				err("illegal -r value -- %s", optarg);
223*56407Sbostic 			nfsargsp->rsize = num;
224*56407Sbostic 			nfsargsp->flags |= NFSMNT_RSIZE;
22552112Smckusick 			break;
226*56407Sbostic 		case 's':
227*56407Sbostic 			nfsargsp->flags |= NFSMNT_SOFT;
22852112Smckusick 			break;
229*56407Sbostic 		case 'T':
230*56407Sbostic 			nfsargsp->sotype = SOCK_STREAM;
231*56407Sbostic 			break;
23252112Smckusick 		case 't':
233*56407Sbostic 			num = strtol(optarg, &p, 10);
234*56407Sbostic 			if (*p || num <= 0)
235*56407Sbostic 				err("illegal -t value -- %s", optarg);
236*56407Sbostic 			nfsargsp->timeo = num;
237*56407Sbostic 			nfsargsp->flags |= NFSMNT_TIMEO;
23852112Smckusick 			break;
239*56407Sbostic 		case 'w':
240*56407Sbostic 			num = strtol(optarg, &p, 10);
241*56407Sbostic 			if (*p || num <= 0)
242*56407Sbostic 				err("illegal -w value -- %s", optarg);
243*56407Sbostic 			nfsargsp->wsize = num;
244*56407Sbostic 			nfsargsp->flags |= NFSMNT_WSIZE;
245*56407Sbostic 			break;
24652112Smckusick 		case 'x':
247*56407Sbostic 			num = strtol(optarg, &p, 10);
248*56407Sbostic 			if (*p || num <= 0)
249*56407Sbostic 				err("illegal -x value -- %s", optarg);
250*56407Sbostic 			nfsargsp->retrans = num;
251*56407Sbostic 			nfsargsp->flags |= NFSMNT_RETRANS;
25252112Smckusick 			break;
25352112Smckusick 		default:
254*56407Sbostic 			usage();
25552112Smckusick 		};
256*56407Sbostic 
257*56407Sbostic 	if ((argc - optind) != 2)
258*56407Sbostic 		usage();
259*56407Sbostic 
260*56407Sbostic 	spec = argv[optind];
261*56407Sbostic 	name = argv[optind + 1];
262*56407Sbostic 
263*56407Sbostic 	if (!getnfsargs(spec, nfsargsp))
264*56407Sbostic 		exit(1);
265*56407Sbostic 	if (stat(name, &sb) < 0)
266*56407Sbostic 		err("%s: %s", name, strerror(errno));
267*56407Sbostic 	if (!S_ISDIR(sb.st_mode))
268*56407Sbostic 		err("%s: not a directory", name);
269*56407Sbostic 	if (mount(MOUNT_NFS, name, flags, nfsargsp))
270*56407Sbostic 		err("mount: %s: %s\n", name, strerror(errno));
271*56407Sbostic 	if (nfsargsp->flags & (NFSMNT_NQNFS | NFSMNT_KERB)) {
272*56407Sbostic 		if ((opflags & ISBGRND) == 0) {
273*56407Sbostic 			if (i = fork()) {
274*56407Sbostic 				if (i == -1)
275*56407Sbostic 					err("nqnfs 1: %s\n", strerror(errno));
276*56407Sbostic 				exit(0);
27752112Smckusick 			}
278*56407Sbostic 			(void) setsid();
279*56407Sbostic 			(void) close(STDIN_FILENO);
280*56407Sbostic 			(void) close(STDOUT_FILENO);
281*56407Sbostic 			(void) close(STDERR_FILENO);
282*56407Sbostic 			(void) chdir("/");
283*56407Sbostic 		}
284*56407Sbostic 		openlog("mount_nfs:", LOG_PID, LOG_DAEMON);
285*56407Sbostic 		nfssvc_flag = NFSSVC_MNTD;
286*56407Sbostic 		ncd.ncd_dirp = name;
287*56407Sbostic 		while (nfssvc(nfssvc_flag, (caddr_t)&ncd) < 0) {
288*56407Sbostic 			if (errno != ENEEDAUTH) {
289*56407Sbostic 				syslog(LOG_ERR, "nfssvc err %m");
290*56407Sbostic 				continue;
291*56407Sbostic 			}
29252112Smckusick syslog(LOG_ERR, "in eacces");
293*56407Sbostic 			nfssvc_flag =
294*56407Sbostic 			    NFSSVC_MNTD | NFSSVC_GOTAUTH | NFSSVC_AUTHINFAIL;
29552112Smckusick #ifdef KERBEROS
296*56407Sbostic syslog(LOG_ERR,
297*56407Sbostic     "Calling krb uid=%d inst=%s realm=%s", ncd.ncd_authuid, inst,realm);
298*56407Sbostic 			/*
299*56407Sbostic 			 * Set up as ncd_authuid for the kerberos call.
300*56407Sbostic 			 * Must set ruid to ncd_authuid and reset the
301*56407Sbostic 			 * ticket name iff ncd_authuid is not the same
302*56407Sbostic 			 * as last time, so that the right ticket file
303*56407Sbostic 			 * is found.
304*56407Sbostic 			 */
305*56407Sbostic 			if (ncd.ncd_authuid != last_ruid) {
306*56407Sbostic 				krb_set_tkt_string("");
307*56407Sbostic 				last_ruid = ncd.ncd_authuid;
308*56407Sbostic 			}
309*56407Sbostic 			setreuid(ncd.ncd_authuid, 0);
310*56407Sbostic 			if (krb_mk_req(&kt, "rcmd", inst, realm, 0) ==
311*56407Sbostic 			    KSUCCESS &&
312*56407Sbostic 			    kt.length <= (RPCAUTH_MAXSIZ - 2 * NFSX_UNSIGNED)) {
313*56407Sbostic syslog(LOG_ERR, "Got it\n");
314*56407Sbostic 				ncd.ncd_authtype = RPCAUTH_NQNFS;
315*56407Sbostic 				ncd.ncd_authlen = kt.length;
316*56407Sbostic 				ncd.ncd_authstr = (char *)kt.dat;
317*56407Sbostic 				nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH;
318*56407Sbostic 			}
319*56407Sbostic 			setreuid(0, 0);
320*56407Sbostic syslog(LOG_ERR, "ktlen=%d\n", kt.length);
32152112Smckusick #endif /* KERBEROS */
32252112Smckusick 		}
323*56407Sbostic 	}
324*56407Sbostic 	exit(0);
32552112Smckusick }
32652112Smckusick 
327*56407Sbostic int
32852112Smckusick getnfsargs(spec, nfsargsp)
32952112Smckusick 	char *spec;
33052112Smckusick 	struct nfs_args *nfsargsp;
33152112Smckusick {
33252112Smckusick 	register CLIENT *clp;
33352112Smckusick 	struct hostent *hp;
33452112Smckusick 	static struct sockaddr_in saddr;
33552112Smckusick #ifdef ISO
33652112Smckusick 	static struct sockaddr_iso isoaddr;
33752112Smckusick 	struct iso_addr *isop;
338*56407Sbostic 	int isoflag = 0;
33952112Smckusick #endif
34052112Smckusick 	struct timeval pertry, try;
34152112Smckusick 	enum clnt_stat clnt_stat;
342*56407Sbostic 	int so = RPC_ANYSOCK, i;
343*56407Sbostic 	char *hostp, *delimp;
344*56407Sbostic #ifdef KERBEROS
345*56407Sbostic 	char *cp;
346*56407Sbostic #endif
34752112Smckusick 	u_short tport;
34852112Smckusick 	static struct nfhret nfhret;
34952112Smckusick 	static char nam[MNAMELEN + 1];
35052112Smckusick 
35152112Smckusick 	strncpy(nam, spec, MNAMELEN);
35252112Smckusick 	nam[MNAMELEN] = '\0';
35352112Smckusick 	if ((delimp = index(spec, '@')) != NULL) {
35452112Smckusick 		hostp = delimp + 1;
35552112Smckusick 	} else if ((delimp = index(spec, ':')) != NULL) {
35652112Smckusick 		hostp = spec;
35752112Smckusick 		spec = delimp + 1;
35852112Smckusick 	} else {
359*56407Sbostic 		warn("no <host>:<dirpath> or <dirpath>@<host> spec");
36052112Smckusick 		return (0);
36152112Smckusick 	}
36252112Smckusick 	*delimp = '\0';
36352112Smckusick 	/*
36452112Smckusick 	 * DUMB!! Until the mount protocol works on iso transport, we must
36552112Smckusick 	 * supply both an iso and an inet address for the host.
36652112Smckusick 	 */
36752112Smckusick #ifdef ISO
36852112Smckusick 	if (!strncmp(hostp, "iso=", 4)) {
36952112Smckusick 		u_short isoport;
37052112Smckusick 
37152112Smckusick 		hostp += 4;
37252112Smckusick 		isoflag++;
37352112Smckusick 		if ((delimp = index(hostp, '+')) == NULL) {
374*56407Sbostic 			warn("no iso+inet address");
37552112Smckusick 			return (0);
37652112Smckusick 		}
37752112Smckusick 		*delimp = '\0';
37852112Smckusick 		if ((isop = iso_addr(hostp)) == NULL) {
379*56407Sbostic 			warn("bad ISO address");
38052112Smckusick 			return (0);
38152112Smckusick 		}
38252112Smckusick 		bzero((caddr_t)&isoaddr, sizeof (isoaddr));
38352112Smckusick 		bcopy((caddr_t)isop, (caddr_t)&isoaddr.siso_addr,
38452112Smckusick 			sizeof (struct iso_addr));
38552112Smckusick 		isoaddr.siso_len = sizeof (isoaddr);
38652112Smckusick 		isoaddr.siso_family = AF_ISO;
38752112Smckusick 		isoaddr.siso_tlen = 2;
38852112Smckusick 		isoport = htons(NFS_PORT);
38952112Smckusick 		bcopy((caddr_t)&isoport, TSEL(&isoaddr), isoaddr.siso_tlen);
39052112Smckusick 		hostp = delimp + 1;
39152112Smckusick 	}
39252112Smckusick #endif /* ISO */
39352112Smckusick 
39452112Smckusick 	/*
39552112Smckusick 	 * Handle an internet host address and reverse resolve it if
39652112Smckusick 	 * doing Kerberos.
39752112Smckusick 	 */
39852112Smckusick 	if (isdigit(*hostp)) {
39952112Smckusick 		if ((saddr.sin_addr.s_addr = inet_addr(hostp)) == -1) {
400*56407Sbostic 			warn("bad net address %s\n", hostp);
40152112Smckusick 			return (0);
40252112Smckusick 		}
40352112Smckusick 		if ((nfsargsp->flags & NFSMNT_KERB) &&
40452112Smckusick 		    (hp = gethostbyaddr((char *)&saddr.sin_addr.s_addr,
405*56407Sbostic 		    sizeof (u_long), AF_INET)) == (struct hostent *)0) {
406*56407Sbostic 			warn("can't reverse resolve net address");
40752112Smckusick 			return (0);
40852112Smckusick 		}
40952112Smckusick 	} else if ((hp = gethostbyname(hostp)) == NULL) {
410*56407Sbostic 		warn("can't get net id for host");
41152112Smckusick 		return (0);
41252112Smckusick 	}
41352112Smckusick #ifdef KERBEROS
41452112Smckusick 	if (nfsargsp->flags & NFSMNT_KERB) {
41552112Smckusick 		strncpy(inst, hp->h_name, INST_SZ);
41652112Smckusick 		inst[INST_SZ - 1] = '\0';
41752112Smckusick 		if (cp = index(inst, '.'))
41852112Smckusick 			*cp = '\0';
41952112Smckusick 	}
42052112Smckusick #endif /* KERBEROS */
42152112Smckusick 
42252112Smckusick 	bcopy(hp->h_addr, (caddr_t)&saddr.sin_addr, hp->h_length);
42352112Smckusick 	nfhret.stat = EACCES;	/* Mark not yet successful */
42452112Smckusick 	while (retrycnt > 0) {
42552112Smckusick 		saddr.sin_family = AF_INET;
42652112Smckusick 		saddr.sin_port = htons(PMAPPORT);
42752112Smckusick 		if ((tport = pmap_getport(&saddr, RPCPROG_NFS,
42852112Smckusick 		    NFS_VER2, IPPROTO_UDP)) == 0) {
42952112Smckusick 			if ((opflags & ISBGRND) == 0)
43052112Smckusick 				clnt_pcreateerror("NFS Portmap");
43152112Smckusick 		} else {
43252112Smckusick 			saddr.sin_port = 0;
43352112Smckusick 			pertry.tv_sec = 10;
43452112Smckusick 			pertry.tv_usec = 0;
43552112Smckusick 			if ((clp = clntudp_create(&saddr, RPCPROG_MNT,
43652112Smckusick 			    RPCMNT_VER1, pertry, &so)) == NULL) {
43752112Smckusick 				if ((opflags & ISBGRND) == 0)
43852112Smckusick 					clnt_pcreateerror("Cannot MNT PRC");
43952112Smckusick 			} else {
44052112Smckusick 				clp->cl_auth = authunix_create_default();
44152112Smckusick 				try.tv_sec = 10;
44252112Smckusick 				try.tv_usec = 0;
44352112Smckusick 				clnt_stat = clnt_call(clp, RPCMNT_MOUNT,
44452112Smckusick 				    xdr_dir, spec, xdr_fh, &nfhret, try);
44552112Smckusick 				if (clnt_stat != RPC_SUCCESS) {
446*56407Sbostic 					if ((opflags & ISBGRND) == 0) {
447*56407Sbostic 						warn("%s", clnt_sperror(clp,
448*56407Sbostic 						    "bad MNT RPC"));
449*56407Sbostic 					}
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()) {
461*56407Sbostic 					if (i == -1)
462*56407Sbostic 						err("nqnfs 2: %s\n",
463*56407Sbostic 						    strerror(errno));
46453128Storek 					exit(0);
46552112Smckusick 				}
46652112Smckusick 				(void) setsid();
467*56407Sbostic 				(void) close(STDIN_FILENO);
468*56407Sbostic 				(void) close(STDOUT_FILENO);
469*56407Sbostic 				(void) close(STDERR_FILENO);
47052112Smckusick 				(void) chdir("/");
47152112Smckusick 				opflags |= ISBGRND;
472*56407Sbostic 			}
47352112Smckusick 			sleep(60);
47452112Smckusick 		}
47552112Smckusick 	}
47652112Smckusick 	if (nfhret.stat) {
47752112Smckusick 		if (opflags & ISBGRND)
47852112Smckusick 			exit(1);
479*56407Sbostic 		warn("can't access %s: %s\n", spec, strerror(nfhret.stat));
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  */
501*56407Sbostic int
50252112Smckusick xdr_dir(xdrsp, dirp)
50352112Smckusick 	XDR *xdrsp;
50452112Smckusick 	char *dirp;
50552112Smckusick {
50652112Smckusick 	return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
50752112Smckusick }
50852112Smckusick 
509*56407Sbostic 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 
521*56407Sbostic __dead void
522*56407Sbostic usage()
52352112Smckusick {
524*56407Sbostic 	(void)fprintf(stderr, "usage: mount_nfs %s\n%s\n%s\n%s\n",
525*56407Sbostic "[-bcdiKklMPqsT] [-a maxreadahead] [-D deadthresh]",
526*56407Sbostic "\t[-g maxgroups] [-L leaseterm] [-m realm] [-R retrycnt]",
527*56407Sbostic "\t[-r readsize] [-t timeout] [-w writesize] [-x retrans]",
528*56407Sbostic "\trhost:path node");
529*56407Sbostic 	exit(1);
530*56407Sbostic }
53152112Smckusick 
532*56407Sbostic #if __STDC__
533*56407Sbostic #include <stdarg.h>
534*56407Sbostic #else
535*56407Sbostic #include <varargs.h>
536*56407Sbostic #endif
537*56407Sbostic 
538*56407Sbostic void
539*56407Sbostic #if __STDC__
540*56407Sbostic err(const char *fmt, ...)
541*56407Sbostic #else
542*56407Sbostic err(fmt, va_alist)
543*56407Sbostic 	char *fmt;
544*56407Sbostic         va_dcl
545*56407Sbostic #endif
546*56407Sbostic {
547*56407Sbostic 	va_list ap;
548*56407Sbostic #if __STDC__
549*56407Sbostic 	va_start(ap, fmt);
550*56407Sbostic #else
551*56407Sbostic 	va_start(ap);
552*56407Sbostic #endif
553*56407Sbostic 	(void)fprintf(stderr, "mount_nfs: ");
554*56407Sbostic 	(void)vfprintf(stderr, fmt, ap);
555*56407Sbostic 	va_end(ap);
556*56407Sbostic 	(void)fprintf(stderr, "\n");
55752112Smckusick 	exit(1);
558*56407Sbostic 	/* NOTREACHED */
55952112Smckusick }
560*56407Sbostic 
561*56407Sbostic void
562*56407Sbostic #if __STDC__
563*56407Sbostic warn(const char *fmt, ...)
564*56407Sbostic #else
565*56407Sbostic warn(fmt, va_alist)
566*56407Sbostic 	char *fmt;
567*56407Sbostic         va_dcl
568*56407Sbostic #endif
569*56407Sbostic {
570*56407Sbostic 	va_list ap;
571*56407Sbostic #if __STDC__
572*56407Sbostic 	va_start(ap, fmt);
573*56407Sbostic #else
574*56407Sbostic 	va_start(ap);
575*56407Sbostic #endif
576*56407Sbostic 	(void)fprintf(stderr, "mount_nfs: ");
577*56407Sbostic 	(void)vfprintf(stderr, fmt, ap);
578*56407Sbostic 	va_end(ap);
579*56407Sbostic 	(void)fprintf(stderr, "\n");
580*56407Sbostic }
581