xref: /freebsd/usr.bin/showmount/showmount.c (revision c2fdb4d1)
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";
419b50d902SRodney W. Grimes #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$";
499b50d902SRodney W. Grimes #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 
98439165e5SPhilippe Charnier void print_dump __P((struct mountlist *));
99439165e5SPhilippe Charnier static void usage __P((void));
100439165e5SPhilippe Charnier int xdr_mntdump __P((XDR *, struct mountlist **));
101439165e5SPhilippe Charnier int xdr_exports __P((XDR *, struct exportslist **));
1025ab88c41STor Egge int tcp_callrpc __P((char *host,
1035ab88c41STor Egge 		     int prognum, int versnum, int procnum,
1045ab88c41STor Egge 		     xdrproc_t inproc, char *in,
1055ab88c41STor Egge 		     xdrproc_t outproc, char *out));
1069b50d902SRodney W. Grimes 
1079b50d902SRodney W. Grimes /*
1089b50d902SRodney W. Grimes  * This command queries the NFS mount daemon for it's mount list and/or
1099b50d902SRodney W. Grimes  * it's exports list and prints them out.
1109b50d902SRodney W. Grimes  * See "NFS: Network File System Protocol Specification, RFC1094, Appendix A"
111a62dc406SDoug Rabson  * and the "Network File System Protocol XXX.."
1129b50d902SRodney W. Grimes  * for detailed information on the protocol.
1139b50d902SRodney W. Grimes  */
114439165e5SPhilippe Charnier int
1159b50d902SRodney W. Grimes main(argc, argv)
1169b50d902SRodney W. Grimes 	int argc;
1179b50d902SRodney W. Grimes 	char **argv;
1189b50d902SRodney W. Grimes {
1199b50d902SRodney W. Grimes 	register struct exportslist *exp;
1209b50d902SRodney W. Grimes 	register struct grouplist *grp;
121a62dc406SDoug Rabson 	register int rpcs = 0, mntvers = 1;
1229b50d902SRodney W. Grimes 	char ch;
1239b50d902SRodney W. Grimes 	char *host;
1249b50d902SRodney W. Grimes 	int estat;
1259b50d902SRodney W. Grimes 
1261c8af878SWarner Losh 	while ((ch = getopt(argc, argv, "ade3")) != -1)
1279b50d902SRodney W. Grimes 		switch((char)ch) {
1289b50d902SRodney W. Grimes 		case 'a':
1299b50d902SRodney W. Grimes 			if (type == 0) {
1309b50d902SRodney W. Grimes 				type = ALL;
1319b50d902SRodney W. Grimes 				rpcs |= DODUMP;
1329b50d902SRodney W. Grimes 			} else
1339b50d902SRodney W. Grimes 				usage();
1349b50d902SRodney W. Grimes 			break;
1359b50d902SRodney W. Grimes 		case 'd':
1369b50d902SRodney W. Grimes 			if (type == 0) {
1379b50d902SRodney W. Grimes 				type = DIRS;
1389b50d902SRodney W. Grimes 				rpcs |= DODUMP;
1399b50d902SRodney W. Grimes 			} else
1409b50d902SRodney W. Grimes 				usage();
1419b50d902SRodney W. Grimes 			break;
1429b50d902SRodney W. Grimes 		case 'e':
1439b50d902SRodney W. Grimes 			rpcs |= DOEXPORTS;
1449b50d902SRodney W. Grimes 			break;
145a62dc406SDoug Rabson 		case '3':
146a62dc406SDoug Rabson 			mntvers = 3;
147a62dc406SDoug Rabson 			break;
1489b50d902SRodney W. Grimes 		case '?':
1499b50d902SRodney W. Grimes 		default:
1509b50d902SRodney W. Grimes 			usage();
1519b50d902SRodney W. Grimes 		}
1529b50d902SRodney W. Grimes 	argc -= optind;
1539b50d902SRodney W. Grimes 	argv += optind;
1549b50d902SRodney W. Grimes 
1559b50d902SRodney W. Grimes 	if (argc > 0)
1569b50d902SRodney W. Grimes 		host = *argv;
1579b50d902SRodney W. Grimes 	else
1589b50d902SRodney W. Grimes 		host = "localhost";
1599b50d902SRodney W. Grimes 
1609b50d902SRodney W. Grimes 	if (rpcs == 0)
1619b50d902SRodney W. Grimes 		rpcs = DODUMP;
1629b50d902SRodney W. Grimes 
1639b50d902SRodney W. Grimes 	if (rpcs & DODUMP)
1645ab88c41STor Egge 		if ((estat = tcp_callrpc(host, RPCPROG_MNT, mntvers,
1659b50d902SRodney W. Grimes 			RPCMNT_DUMP, xdr_void, (char *)0,
1669b50d902SRodney W. Grimes 			xdr_mntdump, (char *)&mntdump)) != 0) {
1679b50d902SRodney W. Grimes 			clnt_perrno(estat);
168439165e5SPhilippe Charnier 			errx(1, "can't do mountdump rpc");
1699b50d902SRodney W. Grimes 		}
1709b50d902SRodney W. Grimes 	if (rpcs & DOEXPORTS)
1715ab88c41STor Egge 		if ((estat = tcp_callrpc(host, RPCPROG_MNT, mntvers,
1729b50d902SRodney W. Grimes 			RPCMNT_EXPORT, xdr_void, (char *)0,
1739b50d902SRodney W. Grimes 			xdr_exports, (char *)&exports)) != 0) {
1749b50d902SRodney W. Grimes 			clnt_perrno(estat);
175439165e5SPhilippe Charnier 			errx(1, "can't do exports rpc");
1769b50d902SRodney W. Grimes 		}
1779b50d902SRodney W. Grimes 
1789b50d902SRodney W. Grimes 	/* Now just print out the results */
1799b50d902SRodney W. Grimes 	if (rpcs & DODUMP) {
1809b50d902SRodney W. Grimes 		switch (type) {
1819b50d902SRodney W. Grimes 		case ALL:
1829b50d902SRodney W. Grimes 			printf("All mount points on %s:\n", host);
1839b50d902SRodney W. Grimes 			break;
1849b50d902SRodney W. Grimes 		case DIRS:
1859b50d902SRodney W. Grimes 			printf("Directories on %s:\n", host);
1869b50d902SRodney W. Grimes 			break;
1879b50d902SRodney W. Grimes 		default:
1889b50d902SRodney W. Grimes 			printf("Hosts on %s:\n", host);
1899b50d902SRodney W. Grimes 			break;
1909b50d902SRodney W. Grimes 		};
1919b50d902SRodney W. Grimes 		print_dump(mntdump);
1929b50d902SRodney W. Grimes 	}
1939b50d902SRodney W. Grimes 	if (rpcs & DOEXPORTS) {
1949b50d902SRodney W. Grimes 		printf("Exports list on %s:\n", host);
1959b50d902SRodney W. Grimes 		exp = exports;
1969b50d902SRodney W. Grimes 		while (exp) {
1979b50d902SRodney W. Grimes 			printf("%-35s", exp->ex_dirp);
1989b50d902SRodney W. Grimes 			grp = exp->ex_groups;
1999b50d902SRodney W. Grimes 			if (grp == NULL) {
2009b50d902SRodney W. Grimes 				printf("Everyone\n");
2019b50d902SRodney W. Grimes 			} else {
2029b50d902SRodney W. Grimes 				while (grp) {
2039b50d902SRodney W. Grimes 					printf("%s ", grp->gr_name);
2049b50d902SRodney W. Grimes 					grp = grp->gr_next;
2059b50d902SRodney W. Grimes 				}
2069b50d902SRodney W. Grimes 				printf("\n");
2079b50d902SRodney W. Grimes 			}
2089b50d902SRodney W. Grimes 			exp = exp->ex_next;
2099b50d902SRodney W. Grimes 		}
2109b50d902SRodney W. Grimes 	}
211439165e5SPhilippe Charnier 	exit(0);
2129b50d902SRodney W. Grimes }
2139b50d902SRodney W. Grimes 
2149b50d902SRodney W. Grimes /*
2155ab88c41STor Egge  * tcp_callrpc has the same interface as callrpc, but tries to
2165ab88c41STor Egge  * use tcp as transport method in order to handle large replies.
2175ab88c41STor Egge  */
2185ab88c41STor Egge int
2195ab88c41STor Egge tcp_callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
2205ab88c41STor Egge 	char *host;
2215ab88c41STor Egge 	int prognum;
2225ab88c41STor Egge 	int versnum;
2235ab88c41STor Egge 	int procnum;
2245ab88c41STor Egge 	xdrproc_t inproc;
2255ab88c41STor Egge 	char *in;
2265ab88c41STor Egge 	xdrproc_t outproc;
2275ab88c41STor Egge 	char *out;
2285ab88c41STor Egge {
2295ab88c41STor Egge 	CLIENT *client;
2305ab88c41STor Egge 	struct timeval timeout;
2315ab88c41STor Egge 	int rval;
2325ab88c41STor Egge 
233c2fdb4d1SIan Dowse 	if ((client = clnt_create(host, prognum, versnum, "tcp")) == NULL &&
234c2fdb4d1SIan Dowse 	    (client = clnt_create(host, prognum, versnum, "udp")) == NULL)
2355ab88c41STor Egge 		return ((int) rpc_createerr.cf_stat);
2365ab88c41STor Egge 
2375ab88c41STor Egge 	timeout.tv_sec = 25;
2385ab88c41STor Egge 	timeout.tv_usec = 0;
2395ab88c41STor Egge 	rval = (int) clnt_call(client, procnum,
2405ab88c41STor Egge 			       inproc, in,
2415ab88c41STor Egge 			       outproc, out,
2425ab88c41STor Egge 			       timeout);
2435ab88c41STor Egge 	clnt_destroy(client);
2445ab88c41STor Egge  	return rval;
2455ab88c41STor Egge }
2465ab88c41STor Egge 
2475ab88c41STor Egge /*
2489b50d902SRodney W. Grimes  * Xdr routine for retrieving the mount dump list
2499b50d902SRodney W. Grimes  */
250439165e5SPhilippe Charnier int
2519b50d902SRodney W. Grimes xdr_mntdump(xdrsp, mlp)
2529b50d902SRodney W. Grimes 	XDR *xdrsp;
2539b50d902SRodney W. Grimes 	struct mountlist **mlp;
2549b50d902SRodney W. Grimes {
2559b50d902SRodney W. Grimes 	register struct mountlist *mp;
2569b50d902SRodney W. Grimes 	register struct mountlist *tp;
2579b50d902SRodney W. Grimes 	register struct mountlist **otp;
2589b50d902SRodney W. Grimes 	int val, val2;
2599b50d902SRodney W. Grimes 	int bool;
2609b50d902SRodney W. Grimes 	char *strp;
2619b50d902SRodney W. Grimes 
2629b50d902SRodney W. Grimes 	*mlp = (struct mountlist *)0;
2639b50d902SRodney W. Grimes 	if (!xdr_bool(xdrsp, &bool))
2649b50d902SRodney W. Grimes 		return (0);
2659b50d902SRodney W. Grimes 	while (bool) {
2669b50d902SRodney W. Grimes 		mp = (struct mountlist *)malloc(sizeof(struct mountlist));
2679b50d902SRodney W. Grimes 		if (mp == NULL)
2689b50d902SRodney W. Grimes 			return (0);
2699b50d902SRodney W. Grimes 		mp->ml_left = mp->ml_right = (struct mountlist *)0;
2709b50d902SRodney W. Grimes 		strp = mp->ml_host;
2719b50d902SRodney W. Grimes 		if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN))
2729b50d902SRodney W. Grimes 			return (0);
2739b50d902SRodney W. Grimes 		strp = mp->ml_dirp;
2749b50d902SRodney W. Grimes 		if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))
2759b50d902SRodney W. Grimes 			return (0);
2769b50d902SRodney W. Grimes 
2779b50d902SRodney W. Grimes 		/*
2789b50d902SRodney W. Grimes 		 * Build a binary tree on sorted order of either host or dirp.
2799b50d902SRodney W. Grimes 		 * Drop any duplications.
2809b50d902SRodney W. Grimes 		 */
2819b50d902SRodney W. Grimes 		if (*mlp == NULL) {
2829b50d902SRodney W. Grimes 			*mlp = mp;
2839b50d902SRodney W. Grimes 		} else {
2849b50d902SRodney W. Grimes 			tp = *mlp;
2859b50d902SRodney W. Grimes 			while (tp) {
2869b50d902SRodney W. Grimes 				val = strcmp(mp->ml_host, tp->ml_host);
2879b50d902SRodney W. Grimes 				val2 = strcmp(mp->ml_dirp, tp->ml_dirp);
2889b50d902SRodney W. Grimes 				switch (type) {
2899b50d902SRodney W. Grimes 				case ALL:
2909b50d902SRodney W. Grimes 					if (val == 0) {
2919b50d902SRodney W. Grimes 						if (val2 == 0) {
2929b50d902SRodney W. Grimes 							free((caddr_t)mp);
2939b50d902SRodney W. Grimes 							goto next;
2949b50d902SRodney W. Grimes 						}
2959b50d902SRodney W. Grimes 						val = val2;
2969b50d902SRodney W. Grimes 					}
2979b50d902SRodney W. Grimes 					break;
2989b50d902SRodney W. Grimes 				case DIRS:
2999b50d902SRodney W. Grimes 					if (val2 == 0) {
3009b50d902SRodney W. Grimes 						free((caddr_t)mp);
3019b50d902SRodney W. Grimes 						goto next;
3029b50d902SRodney W. Grimes 					}
3039b50d902SRodney W. Grimes 					val = val2;
3049b50d902SRodney W. Grimes 					break;
3059b50d902SRodney W. Grimes 				default:
3069b50d902SRodney W. Grimes 					if (val == 0) {
3079b50d902SRodney W. Grimes 						free((caddr_t)mp);
3089b50d902SRodney W. Grimes 						goto next;
3099b50d902SRodney W. Grimes 					}
3109b50d902SRodney W. Grimes 					break;
3119b50d902SRodney W. Grimes 				};
3129b50d902SRodney W. Grimes 				if (val < 0) {
3139b50d902SRodney W. Grimes 					otp = &tp->ml_left;
3149b50d902SRodney W. Grimes 					tp = tp->ml_left;
3159b50d902SRodney W. Grimes 				} else {
3169b50d902SRodney W. Grimes 					otp = &tp->ml_right;
3179b50d902SRodney W. Grimes 					tp = tp->ml_right;
3189b50d902SRodney W. Grimes 				}
3199b50d902SRodney W. Grimes 			}
3209b50d902SRodney W. Grimes 			*otp = mp;
3219b50d902SRodney W. Grimes 		}
3229b50d902SRodney W. Grimes next:
3239b50d902SRodney W. Grimes 		if (!xdr_bool(xdrsp, &bool))
3249b50d902SRodney W. Grimes 			return (0);
3259b50d902SRodney W. Grimes 	}
3269b50d902SRodney W. Grimes 	return (1);
3279b50d902SRodney W. Grimes }
3289b50d902SRodney W. Grimes 
3299b50d902SRodney W. Grimes /*
3309b50d902SRodney W. Grimes  * Xdr routine to retrieve exports list
3319b50d902SRodney W. Grimes  */
332439165e5SPhilippe Charnier int
3339b50d902SRodney W. Grimes xdr_exports(xdrsp, exp)
3349b50d902SRodney W. Grimes 	XDR *xdrsp;
3359b50d902SRodney W. Grimes 	struct exportslist **exp;
3369b50d902SRodney W. Grimes {
3379b50d902SRodney W. Grimes 	register struct exportslist *ep;
3389b50d902SRodney W. Grimes 	register struct grouplist *gp;
3399b50d902SRodney W. Grimes 	int bool, grpbool;
3409b50d902SRodney W. Grimes 	char *strp;
3419b50d902SRodney W. Grimes 
3429b50d902SRodney W. Grimes 	*exp = (struct exportslist *)0;
3439b50d902SRodney W. Grimes 	if (!xdr_bool(xdrsp, &bool))
3449b50d902SRodney W. Grimes 		return (0);
3459b50d902SRodney W. Grimes 	while (bool) {
3469b50d902SRodney W. Grimes 		ep = (struct exportslist *)malloc(sizeof(struct exportslist));
3479b50d902SRodney W. Grimes 		if (ep == NULL)
3489b50d902SRodney W. Grimes 			return (0);
3499b50d902SRodney W. Grimes 		ep->ex_groups = (struct grouplist *)0;
3509b50d902SRodney W. Grimes 		strp = ep->ex_dirp;
3519b50d902SRodney W. Grimes 		if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))
3529b50d902SRodney W. Grimes 			return (0);
3539b50d902SRodney W. Grimes 		if (!xdr_bool(xdrsp, &grpbool))
3549b50d902SRodney W. Grimes 			return (0);
3559b50d902SRodney W. Grimes 		while (grpbool) {
3569b50d902SRodney W. Grimes 			gp = (struct grouplist *)malloc(sizeof(struct grouplist));
3579b50d902SRodney W. Grimes 			if (gp == NULL)
3589b50d902SRodney W. Grimes 				return (0);
3599b50d902SRodney W. Grimes 			strp = gp->gr_name;
3609b50d902SRodney W. Grimes 			if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN))
3619b50d902SRodney W. Grimes 				return (0);
3629b50d902SRodney W. Grimes 			gp->gr_next = ep->ex_groups;
3639b50d902SRodney W. Grimes 			ep->ex_groups = gp;
3649b50d902SRodney W. Grimes 			if (!xdr_bool(xdrsp, &grpbool))
3659b50d902SRodney W. Grimes 				return (0);
3669b50d902SRodney W. Grimes 		}
3679b50d902SRodney W. Grimes 		ep->ex_next = *exp;
3689b50d902SRodney W. Grimes 		*exp = ep;
3699b50d902SRodney W. Grimes 		if (!xdr_bool(xdrsp, &bool))
3709b50d902SRodney W. Grimes 			return (0);
3719b50d902SRodney W. Grimes 	}
3729b50d902SRodney W. Grimes 	return (1);
3739b50d902SRodney W. Grimes }
3749b50d902SRodney W. Grimes 
375439165e5SPhilippe Charnier static void
3769b50d902SRodney W. Grimes usage()
3779b50d902SRodney W. Grimes {
3782dc545bbSDavid E. O'Brien 	fprintf(stderr, "usage: showmount [-ade3] host\n");
3799b50d902SRodney W. Grimes 	exit(1);
3809b50d902SRodney W. Grimes }
3819b50d902SRodney W. Grimes 
3829b50d902SRodney W. Grimes /*
3839b50d902SRodney W. Grimes  * Print the binary tree in inorder so that output is sorted.
3849b50d902SRodney W. Grimes  */
385439165e5SPhilippe Charnier void
3869b50d902SRodney W. Grimes print_dump(mp)
3879b50d902SRodney W. Grimes 	struct mountlist *mp;
3889b50d902SRodney W. Grimes {
3899b50d902SRodney W. Grimes 
3909b50d902SRodney W. Grimes 	if (mp == NULL)
3919b50d902SRodney W. Grimes 		return;
3929b50d902SRodney W. Grimes 	if (mp->ml_left)
3939b50d902SRodney W. Grimes 		print_dump(mp->ml_left);
3949b50d902SRodney W. Grimes 	switch (type) {
3959b50d902SRodney W. Grimes 	case ALL:
3969b50d902SRodney W. Grimes 		printf("%s:%s\n", mp->ml_host, mp->ml_dirp);
3979b50d902SRodney W. Grimes 		break;
3989b50d902SRodney W. Grimes 	case DIRS:
3999b50d902SRodney W. Grimes 		printf("%s\n", mp->ml_dirp);
4009b50d902SRodney W. Grimes 		break;
4019b50d902SRodney W. Grimes 	default:
4029b50d902SRodney W. Grimes 		printf("%s\n", mp->ml_host);
4039b50d902SRodney W. Grimes 		break;
4049b50d902SRodney W. Grimes 	};
4059b50d902SRodney W. Grimes 	if (mp->ml_right)
4069b50d902SRodney W. Grimes 		print_dump(mp->ml_right);
4079b50d902SRodney W. Grimes }
408