xref: /freebsd/usr.bin/showmount/showmount.c (revision f901ebcf)
19b50d902SRodney W. Grimes /*
2439165e5SPhilippe Charnier  * Copyright (c) 1989, 1993, 1995
39b50d902SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
49b50d902SRodney W. Grimes  *
59b50d902SRodney W. Grimes  * This code is derived from software contributed to Berkeley by
69b50d902SRodney W. Grimes  * Rick Macklem at The University of Guelph.
79b50d902SRodney W. Grimes  *
89b50d902SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
99b50d902SRodney W. Grimes  * modification, are permitted provided that the following conditions
109b50d902SRodney W. Grimes  * are met:
119b50d902SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
129b50d902SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
139b50d902SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
149b50d902SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
159b50d902SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
169b50d902SRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
179b50d902SRodney W. Grimes  *    must display the following acknowledgement:
189b50d902SRodney W. Grimes  *	This product includes software developed by the University of
199b50d902SRodney W. Grimes  *	California, Berkeley and its contributors.
209b50d902SRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
219b50d902SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
229b50d902SRodney W. Grimes  *    without specific prior written permission.
239b50d902SRodney W. Grimes  *
249b50d902SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
259b50d902SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
269b50d902SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
279b50d902SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
289b50d902SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
299b50d902SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
309b50d902SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
319b50d902SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
329b50d902SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
339b50d902SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
349b50d902SRodney W. Grimes  * SUCH DAMAGE.
359b50d902SRodney W. Grimes  */
369b50d902SRodney W. Grimes 
379b50d902SRodney W. Grimes #ifndef lint
38439165e5SPhilippe Charnier static const char copyright[] =
39439165e5SPhilippe Charnier "@(#) Copyright (c) 1989, 1993, 1995\n\
409b50d902SRodney W. Grimes 	The Regents of the University of California.  All rights reserved.\n";
41d4906adbSDima Dorfman #endif /* not lint */
429b50d902SRodney W. Grimes 
439b50d902SRodney W. Grimes #ifndef lint
44439165e5SPhilippe Charnier #if 0
45439165e5SPhilippe Charnier static char sccsid[] = "@(#)showmount.c	8.3 (Berkeley) 3/29/95";
46439165e5SPhilippe Charnier #endif
47439165e5SPhilippe Charnier static const char rcsid[] =
48c3aac50fSPeter Wemm   "$FreeBSD$";
49d4906adbSDima Dorfman #endif /* not lint */
509b50d902SRodney W. Grimes 
519b50d902SRodney W. Grimes #include <sys/types.h>
5248750b4cSDavid Greenman #include <sys/queue.h>
539b50d902SRodney W. Grimes #include <sys/file.h>
549b50d902SRodney W. Grimes #include <sys/socket.h>
559b50d902SRodney W. Grimes #include <sys/socketvar.h>
56439165e5SPhilippe Charnier 
57439165e5SPhilippe Charnier #include <err.h>
589b50d902SRodney W. Grimes #include <netdb.h>
599b50d902SRodney W. Grimes #include <rpc/rpc.h>
609b50d902SRodney W. Grimes #include <rpc/pmap_clnt.h>
619b50d902SRodney W. Grimes #include <rpc/pmap_prot.h>
629b50d902SRodney W. Grimes #include <nfs/rpcv2.h>
63439165e5SPhilippe Charnier 
649b50d902SRodney W. Grimes #include <stdio.h>
65439165e5SPhilippe Charnier #include <stdlib.h>
669b50d902SRodney W. Grimes #include <string.h>
67439165e5SPhilippe Charnier #include <unistd.h>
689b50d902SRodney W. Grimes 
699b50d902SRodney W. Grimes /* Constant defs */
709b50d902SRodney W. Grimes #define	ALL	1
719b50d902SRodney W. Grimes #define	DIRS	2
729b50d902SRodney W. Grimes 
739b50d902SRodney W. Grimes #define	DODUMP		0x1
749b50d902SRodney W. Grimes #define	DOEXPORTS	0x2
759b50d902SRodney W. Grimes 
769b50d902SRodney W. Grimes struct mountlist {
779b50d902SRodney W. Grimes 	struct mountlist *ml_left;
789b50d902SRodney W. Grimes 	struct mountlist *ml_right;
799b50d902SRodney W. Grimes 	char	ml_host[RPCMNT_NAMELEN+1];
809b50d902SRodney W. Grimes 	char	ml_dirp[RPCMNT_PATHLEN+1];
819b50d902SRodney W. Grimes };
829b50d902SRodney W. Grimes 
839b50d902SRodney W. Grimes struct grouplist {
849b50d902SRodney W. Grimes 	struct grouplist *gr_next;
859b50d902SRodney W. Grimes 	char	gr_name[RPCMNT_NAMELEN+1];
869b50d902SRodney W. Grimes };
879b50d902SRodney W. Grimes 
889b50d902SRodney W. Grimes struct exportslist {
899b50d902SRodney W. Grimes 	struct exportslist *ex_next;
909b50d902SRodney W. Grimes 	struct grouplist *ex_groups;
919b50d902SRodney W. Grimes 	char	ex_dirp[RPCMNT_PATHLEN+1];
929b50d902SRodney W. Grimes };
939b50d902SRodney W. Grimes 
949b50d902SRodney W. Grimes static struct mountlist *mntdump;
959b50d902SRodney W. Grimes static struct exportslist *exports;
969b50d902SRodney W. Grimes static int type = 0;
97439165e5SPhilippe Charnier 
983f330d7dSWarner Losh void print_dump(struct mountlist *);
993f330d7dSWarner Losh static void usage(void);
1003f330d7dSWarner Losh int xdr_mntdump(XDR *, struct mountlist **);
1013f330d7dSWarner Losh int xdr_exports(XDR *, struct exportslist **);
1023f330d7dSWarner Losh int tcp_callrpc(const char *host, int prognum, int versnum, int procnum,
1033f330d7dSWarner Losh 		xdrproc_t inproc, char *in, xdrproc_t outproc, char *out);
1049b50d902SRodney W. Grimes 
1059b50d902SRodney W. Grimes /*
1069b50d902SRodney W. Grimes  * This command queries the NFS mount daemon for it's mount list and/or
1079b50d902SRodney W. Grimes  * it's exports list and prints them out.
1089b50d902SRodney W. Grimes  * See "NFS: Network File System Protocol Specification, RFC1094, Appendix A"
109a62dc406SDoug Rabson  * and the "Network File System Protocol XXX.."
1109b50d902SRodney W. Grimes  * for detailed information on the protocol.
1119b50d902SRodney W. Grimes  */
112439165e5SPhilippe Charnier int
1139b50d902SRodney W. Grimes main(argc, argv)
1149b50d902SRodney W. Grimes 	int argc;
1159b50d902SRodney W. Grimes 	char **argv;
1169b50d902SRodney W. Grimes {
1179b50d902SRodney W. Grimes 	register struct exportslist *exp;
1189b50d902SRodney W. Grimes 	register struct grouplist *grp;
119a62dc406SDoug Rabson 	register int rpcs = 0, mntvers = 1;
1206e878749SDavid Malone 	const char *host;
121f901ebcfSStefan Farfeleder 	int ch, estat;
1229b50d902SRodney W. Grimes 
1231c8af878SWarner Losh 	while ((ch = getopt(argc, argv, "ade3")) != -1)
124f901ebcfSStefan Farfeleder 		switch (ch) {
1259b50d902SRodney W. Grimes 		case 'a':
1269b50d902SRodney W. Grimes 			if (type == 0) {
1279b50d902SRodney W. Grimes 				type = ALL;
1289b50d902SRodney W. Grimes 				rpcs |= DODUMP;
1299b50d902SRodney W. Grimes 			} else
1309b50d902SRodney W. Grimes 				usage();
1319b50d902SRodney W. Grimes 			break;
1329b50d902SRodney W. Grimes 		case 'd':
1339b50d902SRodney W. Grimes 			if (type == 0) {
1349b50d902SRodney W. Grimes 				type = DIRS;
1359b50d902SRodney W. Grimes 				rpcs |= DODUMP;
1369b50d902SRodney W. Grimes 			} else
1379b50d902SRodney W. Grimes 				usage();
1389b50d902SRodney W. Grimes 			break;
1399b50d902SRodney W. Grimes 		case 'e':
1409b50d902SRodney W. Grimes 			rpcs |= DOEXPORTS;
1419b50d902SRodney W. Grimes 			break;
142a62dc406SDoug Rabson 		case '3':
143a62dc406SDoug Rabson 			mntvers = 3;
144a62dc406SDoug Rabson 			break;
1459b50d902SRodney W. Grimes 		case '?':
1469b50d902SRodney W. Grimes 		default:
1479b50d902SRodney W. Grimes 			usage();
1489b50d902SRodney W. Grimes 		}
1499b50d902SRodney W. Grimes 	argc -= optind;
1509b50d902SRodney W. Grimes 	argv += optind;
1519b50d902SRodney W. Grimes 
1529b50d902SRodney W. Grimes 	if (argc > 0)
1539b50d902SRodney W. Grimes 		host = *argv;
1549b50d902SRodney W. Grimes 	else
1559b50d902SRodney W. Grimes 		host = "localhost";
1569b50d902SRodney W. Grimes 
1579b50d902SRodney W. Grimes 	if (rpcs == 0)
1589b50d902SRodney W. Grimes 		rpcs = DODUMP;
1599b50d902SRodney W. Grimes 
1609b50d902SRodney W. Grimes 	if (rpcs & DODUMP)
1615ab88c41STor Egge 		if ((estat = tcp_callrpc(host, RPCPROG_MNT, mntvers,
1620c65eed7SPeter Wemm 			RPCMNT_DUMP, (xdrproc_t)xdr_void, (char *)0,
1630c65eed7SPeter Wemm 			(xdrproc_t)xdr_mntdump, (char *)&mntdump)) != 0) {
1649b50d902SRodney W. Grimes 			clnt_perrno(estat);
165439165e5SPhilippe Charnier 			errx(1, "can't do mountdump rpc");
1669b50d902SRodney W. Grimes 		}
1679b50d902SRodney W. Grimes 	if (rpcs & DOEXPORTS)
1685ab88c41STor Egge 		if ((estat = tcp_callrpc(host, RPCPROG_MNT, mntvers,
1690c65eed7SPeter Wemm 			RPCMNT_EXPORT, (xdrproc_t)xdr_void, (char *)0,
1700c65eed7SPeter Wemm 			(xdrproc_t)xdr_exports, (char *)&exports)) != 0) {
1719b50d902SRodney W. Grimes 			clnt_perrno(estat);
172439165e5SPhilippe Charnier 			errx(1, "can't do exports rpc");
1739b50d902SRodney W. Grimes 		}
1749b50d902SRodney W. Grimes 
1759b50d902SRodney W. Grimes 	/* Now just print out the results */
1769b50d902SRodney W. Grimes 	if (rpcs & DODUMP) {
1779b50d902SRodney W. Grimes 		switch (type) {
1789b50d902SRodney W. Grimes 		case ALL:
1799b50d902SRodney W. Grimes 			printf("All mount points on %s:\n", host);
1809b50d902SRodney W. Grimes 			break;
1819b50d902SRodney W. Grimes 		case DIRS:
1829b50d902SRodney W. Grimes 			printf("Directories on %s:\n", host);
1839b50d902SRodney W. Grimes 			break;
1849b50d902SRodney W. Grimes 		default:
1859b50d902SRodney W. Grimes 			printf("Hosts on %s:\n", host);
1869b50d902SRodney W. Grimes 			break;
1879b50d902SRodney W. Grimes 		};
1889b50d902SRodney W. Grimes 		print_dump(mntdump);
1899b50d902SRodney W. Grimes 	}
1909b50d902SRodney W. Grimes 	if (rpcs & DOEXPORTS) {
1919b50d902SRodney W. Grimes 		printf("Exports list on %s:\n", host);
1929b50d902SRodney W. Grimes 		exp = exports;
1939b50d902SRodney W. Grimes 		while (exp) {
1949b50d902SRodney W. Grimes 			printf("%-35s", exp->ex_dirp);
1959b50d902SRodney W. Grimes 			grp = exp->ex_groups;
1969b50d902SRodney W. Grimes 			if (grp == NULL) {
1979b50d902SRodney W. Grimes 				printf("Everyone\n");
1989b50d902SRodney W. Grimes 			} else {
1999b50d902SRodney W. Grimes 				while (grp) {
2009b50d902SRodney W. Grimes 					printf("%s ", grp->gr_name);
2019b50d902SRodney W. Grimes 					grp = grp->gr_next;
2029b50d902SRodney W. Grimes 				}
2039b50d902SRodney W. Grimes 				printf("\n");
2049b50d902SRodney W. Grimes 			}
2059b50d902SRodney W. Grimes 			exp = exp->ex_next;
2069b50d902SRodney W. Grimes 		}
2079b50d902SRodney W. Grimes 	}
208439165e5SPhilippe Charnier 	exit(0);
2099b50d902SRodney W. Grimes }
2109b50d902SRodney W. Grimes 
2119b50d902SRodney W. Grimes /*
2125ab88c41STor Egge  * tcp_callrpc has the same interface as callrpc, but tries to
2135ab88c41STor Egge  * use tcp as transport method in order to handle large replies.
2145ab88c41STor Egge  */
2155ab88c41STor Egge int
2165ab88c41STor Egge tcp_callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
2176e878749SDavid Malone 	const char *host;
2185ab88c41STor Egge 	int prognum;
2195ab88c41STor Egge 	int versnum;
2205ab88c41STor Egge 	int procnum;
2215ab88c41STor Egge 	xdrproc_t inproc;
2225ab88c41STor Egge 	char *in;
2235ab88c41STor Egge 	xdrproc_t outproc;
2245ab88c41STor Egge 	char *out;
2255ab88c41STor Egge {
2265ab88c41STor Egge 	CLIENT *client;
2275ab88c41STor Egge 	struct timeval timeout;
2285ab88c41STor Egge 	int rval;
2295ab88c41STor Egge 
230c2fdb4d1SIan Dowse 	if ((client = clnt_create(host, prognum, versnum, "tcp")) == NULL &&
231c2fdb4d1SIan Dowse 	    (client = clnt_create(host, prognum, versnum, "udp")) == NULL)
2325ab88c41STor Egge 		return ((int) rpc_createerr.cf_stat);
2335ab88c41STor Egge 
2345ab88c41STor Egge 	timeout.tv_sec = 25;
2355ab88c41STor Egge 	timeout.tv_usec = 0;
2365ab88c41STor Egge 	rval = (int) clnt_call(client, procnum,
2375ab88c41STor Egge 			       inproc, in,
2385ab88c41STor Egge 			       outproc, out,
2395ab88c41STor Egge 			       timeout);
2405ab88c41STor Egge 	clnt_destroy(client);
2415ab88c41STor Egge  	return rval;
2425ab88c41STor Egge }
2435ab88c41STor Egge 
2445ab88c41STor Egge /*
2459b50d902SRodney W. Grimes  * Xdr routine for retrieving the mount dump list
2469b50d902SRodney W. Grimes  */
247439165e5SPhilippe Charnier int
2489b50d902SRodney W. Grimes xdr_mntdump(xdrsp, mlp)
2499b50d902SRodney W. Grimes 	XDR *xdrsp;
2509b50d902SRodney W. Grimes 	struct mountlist **mlp;
2519b50d902SRodney W. Grimes {
2529b50d902SRodney W. Grimes 	register struct mountlist *mp;
2539b50d902SRodney W. Grimes 	register struct mountlist *tp;
2549b50d902SRodney W. Grimes 	register struct mountlist **otp;
2559b50d902SRodney W. Grimes 	int val, val2;
2569b50d902SRodney W. Grimes 	int bool;
2579b50d902SRodney W. Grimes 	char *strp;
2589b50d902SRodney W. Grimes 
2599b50d902SRodney W. Grimes 	*mlp = (struct mountlist *)0;
2609b50d902SRodney W. Grimes 	if (!xdr_bool(xdrsp, &bool))
2619b50d902SRodney W. Grimes 		return (0);
2629b50d902SRodney W. Grimes 	while (bool) {
2639b50d902SRodney W. Grimes 		mp = (struct mountlist *)malloc(sizeof(struct mountlist));
2649b50d902SRodney W. Grimes 		if (mp == NULL)
2659b50d902SRodney W. Grimes 			return (0);
2669b50d902SRodney W. Grimes 		mp->ml_left = mp->ml_right = (struct mountlist *)0;
2679b50d902SRodney W. Grimes 		strp = mp->ml_host;
2689b50d902SRodney W. Grimes 		if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN))
2699b50d902SRodney W. Grimes 			return (0);
2709b50d902SRodney W. Grimes 		strp = mp->ml_dirp;
2719b50d902SRodney W. Grimes 		if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))
2729b50d902SRodney W. Grimes 			return (0);
2739b50d902SRodney W. Grimes 
2749b50d902SRodney W. Grimes 		/*
2759b50d902SRodney W. Grimes 		 * Build a binary tree on sorted order of either host or dirp.
2769b50d902SRodney W. Grimes 		 * Drop any duplications.
2779b50d902SRodney W. Grimes 		 */
2789b50d902SRodney W. Grimes 		if (*mlp == NULL) {
2799b50d902SRodney W. Grimes 			*mlp = mp;
2809b50d902SRodney W. Grimes 		} else {
2819b50d902SRodney W. Grimes 			tp = *mlp;
2829b50d902SRodney W. Grimes 			while (tp) {
2839b50d902SRodney W. Grimes 				val = strcmp(mp->ml_host, tp->ml_host);
2849b50d902SRodney W. Grimes 				val2 = strcmp(mp->ml_dirp, tp->ml_dirp);
2859b50d902SRodney W. Grimes 				switch (type) {
2869b50d902SRodney W. Grimes 				case ALL:
2879b50d902SRodney W. Grimes 					if (val == 0) {
2889b50d902SRodney W. Grimes 						if (val2 == 0) {
2899b50d902SRodney W. Grimes 							free((caddr_t)mp);
2909b50d902SRodney W. Grimes 							goto next;
2919b50d902SRodney W. Grimes 						}
2929b50d902SRodney W. Grimes 						val = val2;
2939b50d902SRodney W. Grimes 					}
2949b50d902SRodney W. Grimes 					break;
2959b50d902SRodney W. Grimes 				case DIRS:
2969b50d902SRodney W. Grimes 					if (val2 == 0) {
2979b50d902SRodney W. Grimes 						free((caddr_t)mp);
2989b50d902SRodney W. Grimes 						goto next;
2999b50d902SRodney W. Grimes 					}
3009b50d902SRodney W. Grimes 					val = val2;
3019b50d902SRodney W. Grimes 					break;
3029b50d902SRodney W. Grimes 				default:
3039b50d902SRodney W. Grimes 					if (val == 0) {
3049b50d902SRodney W. Grimes 						free((caddr_t)mp);
3059b50d902SRodney W. Grimes 						goto next;
3069b50d902SRodney W. Grimes 					}
3079b50d902SRodney W. Grimes 					break;
3089b50d902SRodney W. Grimes 				};
3099b50d902SRodney W. Grimes 				if (val < 0) {
3109b50d902SRodney W. Grimes 					otp = &tp->ml_left;
3119b50d902SRodney W. Grimes 					tp = tp->ml_left;
3129b50d902SRodney W. Grimes 				} else {
3139b50d902SRodney W. Grimes 					otp = &tp->ml_right;
3149b50d902SRodney W. Grimes 					tp = tp->ml_right;
3159b50d902SRodney W. Grimes 				}
3169b50d902SRodney W. Grimes 			}
3179b50d902SRodney W. Grimes 			*otp = mp;
3189b50d902SRodney W. Grimes 		}
3199b50d902SRodney W. Grimes next:
3209b50d902SRodney W. Grimes 		if (!xdr_bool(xdrsp, &bool))
3219b50d902SRodney W. Grimes 			return (0);
3229b50d902SRodney W. Grimes 	}
3239b50d902SRodney W. Grimes 	return (1);
3249b50d902SRodney W. Grimes }
3259b50d902SRodney W. Grimes 
3269b50d902SRodney W. Grimes /*
3279b50d902SRodney W. Grimes  * Xdr routine to retrieve exports list
3289b50d902SRodney W. Grimes  */
329439165e5SPhilippe Charnier int
3309b50d902SRodney W. Grimes xdr_exports(xdrsp, exp)
3319b50d902SRodney W. Grimes 	XDR *xdrsp;
3329b50d902SRodney W. Grimes 	struct exportslist **exp;
3339b50d902SRodney W. Grimes {
3349b50d902SRodney W. Grimes 	register struct exportslist *ep;
3359b50d902SRodney W. Grimes 	register struct grouplist *gp;
3369b50d902SRodney W. Grimes 	int bool, grpbool;
3379b50d902SRodney W. Grimes 	char *strp;
3389b50d902SRodney W. Grimes 
3399b50d902SRodney W. Grimes 	*exp = (struct exportslist *)0;
3409b50d902SRodney W. Grimes 	if (!xdr_bool(xdrsp, &bool))
3419b50d902SRodney W. Grimes 		return (0);
3429b50d902SRodney W. Grimes 	while (bool) {
3439b50d902SRodney W. Grimes 		ep = (struct exportslist *)malloc(sizeof(struct exportslist));
3449b50d902SRodney W. Grimes 		if (ep == NULL)
3459b50d902SRodney W. Grimes 			return (0);
3469b50d902SRodney W. Grimes 		ep->ex_groups = (struct grouplist *)0;
3479b50d902SRodney W. Grimes 		strp = ep->ex_dirp;
3489b50d902SRodney W. Grimes 		if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))
3499b50d902SRodney W. Grimes 			return (0);
3509b50d902SRodney W. Grimes 		if (!xdr_bool(xdrsp, &grpbool))
3519b50d902SRodney W. Grimes 			return (0);
3529b50d902SRodney W. Grimes 		while (grpbool) {
3539b50d902SRodney W. Grimes 			gp = (struct grouplist *)malloc(sizeof(struct grouplist));
3549b50d902SRodney W. Grimes 			if (gp == NULL)
3559b50d902SRodney W. Grimes 				return (0);
3569b50d902SRodney W. Grimes 			strp = gp->gr_name;
3579b50d902SRodney W. Grimes 			if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN))
3589b50d902SRodney W. Grimes 				return (0);
3599b50d902SRodney W. Grimes 			gp->gr_next = ep->ex_groups;
3609b50d902SRodney W. Grimes 			ep->ex_groups = gp;
3619b50d902SRodney W. Grimes 			if (!xdr_bool(xdrsp, &grpbool))
3629b50d902SRodney W. Grimes 				return (0);
3639b50d902SRodney W. Grimes 		}
3649b50d902SRodney W. Grimes 		ep->ex_next = *exp;
3659b50d902SRodney W. Grimes 		*exp = ep;
3669b50d902SRodney W. Grimes 		if (!xdr_bool(xdrsp, &bool))
3679b50d902SRodney W. Grimes 			return (0);
3689b50d902SRodney W. Grimes 	}
3699b50d902SRodney W. Grimes 	return (1);
3709b50d902SRodney W. Grimes }
3719b50d902SRodney W. Grimes 
372439165e5SPhilippe Charnier static void
3739b50d902SRodney W. Grimes usage()
3749b50d902SRodney W. Grimes {
375760ddd8cSJuli Mallett 	fprintf(stderr, "usage: showmount [-a | -d] [-e3] host\n");
3769b50d902SRodney W. Grimes 	exit(1);
3779b50d902SRodney W. Grimes }
3789b50d902SRodney W. Grimes 
3799b50d902SRodney W. Grimes /*
3809b50d902SRodney W. Grimes  * Print the binary tree in inorder so that output is sorted.
3819b50d902SRodney W. Grimes  */
382439165e5SPhilippe Charnier void
3839b50d902SRodney W. Grimes print_dump(mp)
3849b50d902SRodney W. Grimes 	struct mountlist *mp;
3859b50d902SRodney W. Grimes {
3869b50d902SRodney W. Grimes 
3879b50d902SRodney W. Grimes 	if (mp == NULL)
3889b50d902SRodney W. Grimes 		return;
3899b50d902SRodney W. Grimes 	if (mp->ml_left)
3909b50d902SRodney W. Grimes 		print_dump(mp->ml_left);
3919b50d902SRodney W. Grimes 	switch (type) {
3929b50d902SRodney W. Grimes 	case ALL:
3939b50d902SRodney W. Grimes 		printf("%s:%s\n", mp->ml_host, mp->ml_dirp);
3949b50d902SRodney W. Grimes 		break;
3959b50d902SRodney W. Grimes 	case DIRS:
3969b50d902SRodney W. Grimes 		printf("%s\n", mp->ml_dirp);
3979b50d902SRodney W. Grimes 		break;
3989b50d902SRodney W. Grimes 	default:
3999b50d902SRodney W. Grimes 		printf("%s\n", mp->ml_host);
4009b50d902SRodney W. Grimes 		break;
4019b50d902SRodney W. Grimes 	};
4029b50d902SRodney W. Grimes 	if (mp->ml_right)
4039b50d902SRodney W. Grimes 		print_dump(mp->ml_right);
4049b50d902SRodney W. Grimes }
405