--- src/sbin/mount_nfs/mount_nfs.c-	Mon Nov 20 03:18:26 2006
+++ src/sbin/mount_nfs/mount_nfs.c	Wed May 16 07:39:46 2007
@@ -165,7 +165,10 @@
 u_short port_no = 0;
 int force2 = 0;
 int force3 = 0;
+int nflag, vflag;
 
+void printnfsargs(struct nfs_args *nfsargsp);
+int gethargs(char *hargs, char *spec, struct nfs_args *nfsargsp);
 int	getnfsargs(char *, struct nfs_args *);
 void	set_rpc_maxgrouplist(int);
 __dead	void usage(void);
@@ -181,6 +184,7 @@
 	int mntflags, num;
 	char name[MAXPATHLEN], *options = NULL, *spec;
 	const char *p;
+	char *hargs = NULL;
 	union mntval value;
 
 	retrycnt = DEF_RETRY;
@@ -189,7 +193,7 @@
 	nfsargs = nfsdefargs;
 	nfsargsp = &nfsargs;
 	while ((c = getopt(argc, argv,
-	    "23a:bcdD:g:I:iL:lo:PR:r:sTt:w:x:U")) != -1)
+	    "23a:bcdD:g:h:I:iL:lno:PR:r:sTt:vw:x:U")) != -1)
 		switch (c) {
 		case '3':
 			if (force2)
@@ -229,6 +233,9 @@
 			nfsargsp->maxgrouplist = num;
 			nfsargsp->flags |= NFSMNT_MAXGRPS;
 			break;
+		case 'h':
+			hargs = optarg;
+			break;
 		case 'I':
 			num = (int) strtonum(optarg, 1, INT_MAX, &p);
 			if (p)
@@ -245,6 +252,9 @@
 		case 'l':
 			nfsargsp->flags |= NFSMNT_RDIRPLUS;
 			break;
+		case 'n':
+			nflag = 1;
+			break;
 		case 'o':
 			options = optarg;
 			while (options != NULL) {
@@ -352,6 +362,9 @@
 			nfsargsp->timeo = num;
 			nfsargsp->flags |= NFSMNT_TIMEO;
 			break;
+		case 'v':
+			vflag = 1;
+			break;
 		case 'w':
 			num = (int) strtonum(optarg, 1, INT_MAX, &p);
 			if (p)
@@ -383,15 +396,80 @@
 	if (realpath(*argv, name) == NULL)
 		err(1, "realpath %s", *argv);
 
-	if (!getnfsargs(spec, nfsargsp))
-		exit(1);
-	if (mount(MOUNT_NFS, name, mntflags, nfsargsp)) {
+	if (hargs) {
+		if (!gethargs(hargs, spec, nfsargsp))
+			exit(1);
+	} else {
+		if (!getnfsargs(spec, nfsargsp))
+			exit(1);
+	}
+	if (vflag)
+		printnfsargs(nfsargsp);
+	if (!nflag && mount(MOUNT_NFS, name, mntflags, nfsargsp)) {
 		if (errno == EOPNOTSUPP)
 			errx(1, "%s: Filesystem not supported by kernel", name);
 		else
 			err(1, "%s", name);
 	}
 	exit(0);
+}
+
+char *
+fhtoa(u_char *fh, int fhn)
+{
+	int i;
+	static char s[NFSX_V3FHMAX * 2 + 2];
+
+	s[0] = '\0';
+	for (i = 0; i < fhn; i++)
+		snprintf(&s[i * 2], sizeof s - (i * 2), "%02.2x", (int) fh[i]);
+	return s;
+}
+
+void
+printnfsargs(struct nfs_args *nfsargsp)
+{
+	struct sockaddr_in *saddrp = (struct sockaddr_in *) nfsargsp->addr;
+
+	printf("%s:%d:%s %s\n",
+	       inet_ntoa(saddrp->sin_addr), ntohs(saddrp->sin_port),
+	       fhtoa(nfsargsp->fh, nfsargsp->fhsize), nfsargsp->hostname);
+}
+
+int
+gethargs(char *hargs, char *spec, struct nfs_args *nfsargsp)
+{
+	static char nam[MNAMELEN + 1];
+	char hostp[16], fhs[NFSX_V3FHMAX * 2 + 2];
+	static u_char fh[NFSX_V3FHMAX];
+	unsigned short port;
+	static struct sockaddr_in saddr;
+	int b, fhn = 0;
+
+	if (strlcpy(nam, spec, sizeof(nam)) >= sizeof(nam)) {
+		errx(1, "hostname too long");
+	}
+
+	if (sscanf(hargs, "%[^:]:%hu:%[^:]", hostp, &port, fhs) != 3)
+		return 0;
+
+	inet_aton(hostp, &saddr.sin_addr);
+	saddr.sin_family = AF_INET;
+	saddr.sin_port = htons(port);
+
+	while (1) {
+		if (sscanf(&fhs[fhn * 2], "%2x", &b) != 1)
+			break;
+		fh[fhn++] = b;
+	}
+
+	nfsargsp->addr = (struct sockaddr *) &saddr;
+	nfsargsp->addrlen = sizeof (saddr);
+	nfsargsp->fh = fh;
+	nfsargsp->fhsize = fhn;
+	nfsargsp->hostname = nam;
+
+	return 1;
 }
 
 int
