xref: /freebsd/usr.bin/showmount/showmount.c (revision 0b8224d1)
18a16b7a1SPedro F. Giffuni /*-
28a16b7a1SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
38a16b7a1SPedro F. Giffuni  *
4439165e5SPhilippe Charnier  * Copyright (c) 1989, 1993, 1995
59b50d902SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
69b50d902SRodney W. Grimes  *
79b50d902SRodney W. Grimes  * This code is derived from software contributed to Berkeley by
89b50d902SRodney W. Grimes  * Rick Macklem at The University of Guelph.
99b50d902SRodney W. Grimes  *
109b50d902SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
119b50d902SRodney W. Grimes  * modification, are permitted provided that the following conditions
129b50d902SRodney W. Grimes  * are met:
139b50d902SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
149b50d902SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
159b50d902SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
169b50d902SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
179b50d902SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
18fbbd9655SWarner Losh  * 3. Neither the name of the University nor the names of its contributors
199b50d902SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
209b50d902SRodney W. Grimes  *    without specific prior written permission.
219b50d902SRodney W. Grimes  *
229b50d902SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
239b50d902SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
249b50d902SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
259b50d902SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
269b50d902SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
279b50d902SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
289b50d902SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
299b50d902SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
309b50d902SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
319b50d902SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
329b50d902SRodney W. Grimes  * SUCH DAMAGE.
339b50d902SRodney W. Grimes  */
349b50d902SRodney W. Grimes 
359b50d902SRodney W. Grimes #include <sys/types.h>
3648750b4cSDavid Greenman #include <sys/queue.h>
379b50d902SRodney W. Grimes #include <sys/file.h>
389b50d902SRodney W. Grimes #include <sys/socket.h>
399b50d902SRodney W. Grimes #include <sys/socketvar.h>
40439165e5SPhilippe Charnier 
41439165e5SPhilippe Charnier #include <err.h>
42a88611b6SEitan Adler #include <getopt.h>
43821df508SXin LI #include <netdb.h>
449b50d902SRodney W. Grimes #include <rpc/rpc.h>
459b50d902SRodney W. Grimes #include <rpc/pmap_clnt.h>
469b50d902SRodney W. Grimes #include <rpc/pmap_prot.h>
470775314bSDoug Rabson #include <rpcsvc/mount.h>
48439165e5SPhilippe Charnier 
499b50d902SRodney W. Grimes #include <stdio.h>
50439165e5SPhilippe Charnier #include <stdlib.h>
519b50d902SRodney W. Grimes #include <string.h>
52439165e5SPhilippe Charnier #include <unistd.h>
53e299e01fSEdward Tomasz Napierala #include <vis.h>
549b50d902SRodney W. Grimes 
559b50d902SRodney W. Grimes /* Constant defs */
569b50d902SRodney W. Grimes #define	ALL	1
579b50d902SRodney W. Grimes #define	DIRS	2
589b50d902SRodney W. Grimes 
599b50d902SRodney W. Grimes #define	DODUMP			0x1
609b50d902SRodney W. Grimes #define	DOEXPORTS		0x2
61e299e01fSEdward Tomasz Napierala #define	DOPARSABLEEXPORTS	0x4
629b50d902SRodney W. Grimes 
639b50d902SRodney W. Grimes struct mountlist {
649b50d902SRodney W. Grimes 	struct mountlist *ml_left;
659b50d902SRodney W. Grimes 	struct mountlist *ml_right;
660775314bSDoug Rabson 	char	ml_host[MNTNAMLEN+1];
670775314bSDoug Rabson 	char	ml_dirp[MNTPATHLEN+1];
689b50d902SRodney W. Grimes };
699b50d902SRodney W. Grimes 
709b50d902SRodney W. Grimes struct grouplist {
719b50d902SRodney W. Grimes 	struct grouplist *gr_next;
720775314bSDoug Rabson 	char	gr_name[MNTNAMLEN+1];
739b50d902SRodney W. Grimes };
749b50d902SRodney W. Grimes 
759b50d902SRodney W. Grimes struct exportslist {
769b50d902SRodney W. Grimes 	struct exportslist *ex_next;
779b50d902SRodney W. Grimes 	struct grouplist *ex_groups;
780775314bSDoug Rabson 	char	ex_dirp[MNTPATHLEN+1];
799b50d902SRodney W. Grimes };
809b50d902SRodney W. Grimes 
819b50d902SRodney W. Grimes static struct mountlist *mntdump;
820775314bSDoug Rabson static struct exportslist *exportslist;
839b50d902SRodney W. Grimes static int type = 0;
84439165e5SPhilippe Charnier 
853f330d7dSWarner Losh void print_dump(struct mountlist *);
86cccdaf50SAlfonso Gregory static void usage(void) __dead2;
873f330d7dSWarner Losh int xdr_mntdump(XDR *, struct mountlist **);
880775314bSDoug Rabson int xdr_exportslist(XDR *, struct exportslist **);
893f330d7dSWarner Losh int tcp_callrpc(const char *host, int prognum, int versnum, int procnum,
903f330d7dSWarner Losh 		xdrproc_t inproc, char *in, xdrproc_t outproc, char *out);
919b50d902SRodney W. Grimes 
92a88611b6SEitan Adler static const struct option long_opts[] = {
93a88611b6SEitan Adler 	{ "all",			no_argument,	NULL,	'a' },
94a88611b6SEitan Adler 	{ "directories",	no_argument,	NULL,	'd' },
95a88611b6SEitan Adler 	{ "exports-script",	no_argument,	NULL,	'E' },
96a88611b6SEitan Adler 	{ "exports",		no_argument,	NULL,	'e' },
97a88611b6SEitan Adler 	{ NULL,				0,				NULL,	0 },
98a88611b6SEitan Adler };
99a88611b6SEitan Adler 
1009b50d902SRodney W. Grimes /*
1019b50d902SRodney W. Grimes  * This command queries the NFS mount daemon for it's mount list and/or
1029b50d902SRodney W. Grimes  * it's exports list and prints them out.
1039b50d902SRodney W. Grimes  * See "NFS: Network File System Protocol Specification, RFC1094, Appendix A"
104a62dc406SDoug Rabson  * and the "Network File System Protocol XXX.."
1059b50d902SRodney W. Grimes  * for detailed information on the protocol.
1069b50d902SRodney W. Grimes  */
107439165e5SPhilippe Charnier int
main(int argc,char ** argv)108ef636796SEd Schouten main(int argc, char **argv)
1099b50d902SRodney W. Grimes {
110e299e01fSEdward Tomasz Napierala 	char strvised[MNTPATHLEN * 4 + 1];
1119b50d902SRodney W. Grimes 	register struct exportslist *exp;
1129b50d902SRodney W. Grimes 	register struct grouplist *grp;
1131b31334cSPeter Wemm 	register int rpcs = 0, mntvers = 3;
1146e878749SDavid Malone 	const char *host;
115e299e01fSEdward Tomasz Napierala 	int ch, estat, nbytes;
1169b50d902SRodney W. Grimes 
117a88611b6SEitan Adler 	while ((ch = getopt_long(argc, argv, "+adEe13", long_opts, NULL)) != -1)
118f901ebcfSStefan Farfeleder 		switch (ch) {
1199b50d902SRodney W. Grimes 		case 'a':
1209b50d902SRodney W. Grimes 			if (type == 0) {
1219b50d902SRodney W. Grimes 				type = ALL;
1229b50d902SRodney W. Grimes 				rpcs |= DODUMP;
1239b50d902SRodney W. Grimes 			} else
1249b50d902SRodney W. Grimes 				usage();
1259b50d902SRodney W. Grimes 			break;
1269b50d902SRodney W. Grimes 		case 'd':
1279b50d902SRodney W. Grimes 			if (type == 0) {
1289b50d902SRodney W. Grimes 				type = DIRS;
1299b50d902SRodney W. Grimes 				rpcs |= DODUMP;
1309b50d902SRodney W. Grimes 			} else
1319b50d902SRodney W. Grimes 				usage();
1329b50d902SRodney W. Grimes 			break;
133e299e01fSEdward Tomasz Napierala 		case 'E':
134e299e01fSEdward Tomasz Napierala 			rpcs |= DOPARSABLEEXPORTS;
135e299e01fSEdward Tomasz Napierala 			break;
1369b50d902SRodney W. Grimes 		case 'e':
1379b50d902SRodney W. Grimes 			rpcs |= DOEXPORTS;
1389b50d902SRodney W. Grimes 			break;
1391b31334cSPeter Wemm 		case '1':
1401b31334cSPeter Wemm 			mntvers = 1;
1411b31334cSPeter Wemm 			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 
152e299e01fSEdward Tomasz Napierala 	if ((rpcs & DOPARSABLEEXPORTS) != 0) {
153e299e01fSEdward Tomasz Napierala 		if ((rpcs & DOEXPORTS) != 0)
154e299e01fSEdward Tomasz Napierala 			errx(1, "-E cannot be used with -e");
155e299e01fSEdward Tomasz Napierala 		if ((rpcs & DODUMP) != 0)
156e299e01fSEdward Tomasz Napierala 			errx(1, "-E cannot be used with -a or -d");
157e299e01fSEdward Tomasz Napierala 	}
158e299e01fSEdward Tomasz Napierala 
1599b50d902SRodney W. Grimes 	if (argc > 0)
1609b50d902SRodney W. Grimes 		host = *argv;
1619b50d902SRodney W. Grimes 	else
1629b50d902SRodney W. Grimes 		host = "localhost";
1639b50d902SRodney W. Grimes 
1649b50d902SRodney W. Grimes 	if (rpcs == 0)
1659b50d902SRodney W. Grimes 		rpcs = DODUMP;
1669b50d902SRodney W. Grimes 
1679b50d902SRodney W. Grimes 	if (rpcs & DODUMP)
1680775314bSDoug Rabson 		if ((estat = tcp_callrpc(host, MOUNTPROG, mntvers,
1690775314bSDoug Rabson 			MOUNTPROC_DUMP, (xdrproc_t)xdr_void, (char *)0,
1700c65eed7SPeter Wemm 			(xdrproc_t)xdr_mntdump, (char *)&mntdump)) != 0) {
1719b50d902SRodney W. Grimes 			clnt_perrno(estat);
172439165e5SPhilippe Charnier 			errx(1, "can't do mountdump rpc");
1739b50d902SRodney W. Grimes 		}
174e299e01fSEdward Tomasz Napierala 	if (rpcs & (DOEXPORTS | DOPARSABLEEXPORTS))
1750775314bSDoug Rabson 		if ((estat = tcp_callrpc(host, MOUNTPROG, mntvers,
1760775314bSDoug Rabson 			MOUNTPROC_EXPORT, (xdrproc_t)xdr_void, (char *)0,
1770775314bSDoug Rabson 			(xdrproc_t)xdr_exportslist, (char *)&exportslist)) != 0) {
1789b50d902SRodney W. Grimes 			clnt_perrno(estat);
179439165e5SPhilippe Charnier 			errx(1, "can't do exports rpc");
1809b50d902SRodney W. Grimes 		}
1819b50d902SRodney W. Grimes 
1829b50d902SRodney W. Grimes 	/* Now just print out the results */
1839b50d902SRodney W. Grimes 	if (rpcs & DODUMP) {
1849b50d902SRodney W. Grimes 		switch (type) {
1859b50d902SRodney W. Grimes 		case ALL:
1869b50d902SRodney W. Grimes 			printf("All mount points on %s:\n", host);
1879b50d902SRodney W. Grimes 			break;
1889b50d902SRodney W. Grimes 		case DIRS:
1899b50d902SRodney W. Grimes 			printf("Directories on %s:\n", host);
1909b50d902SRodney W. Grimes 			break;
1919b50d902SRodney W. Grimes 		default:
1929b50d902SRodney W. Grimes 			printf("Hosts on %s:\n", host);
1939b50d902SRodney W. Grimes 			break;
19480c7cc1cSPedro F. Giffuni 		}
1959b50d902SRodney W. Grimes 		print_dump(mntdump);
1969b50d902SRodney W. Grimes 	}
1979b50d902SRodney W. Grimes 	if (rpcs & DOEXPORTS) {
1989b50d902SRodney W. Grimes 		printf("Exports list on %s:\n", host);
1990775314bSDoug Rabson 		exp = exportslist;
2009b50d902SRodney W. Grimes 		while (exp) {
20171737f5aSRuslan Ermilov 			printf("%-34s ", exp->ex_dirp);
2029b50d902SRodney W. Grimes 			grp = exp->ex_groups;
2039b50d902SRodney W. Grimes 			if (grp == NULL) {
2049b50d902SRodney W. Grimes 				printf("Everyone\n");
2059b50d902SRodney W. Grimes 			} else {
2069b50d902SRodney W. Grimes 				while (grp) {
2079b50d902SRodney W. Grimes 					printf("%s ", grp->gr_name);
2089b50d902SRodney W. Grimes 					grp = grp->gr_next;
2099b50d902SRodney W. Grimes 				}
2109b50d902SRodney W. Grimes 				printf("\n");
2119b50d902SRodney W. Grimes 			}
2129b50d902SRodney W. Grimes 			exp = exp->ex_next;
2139b50d902SRodney W. Grimes 		}
2149b50d902SRodney W. Grimes 	}
215e299e01fSEdward Tomasz Napierala 	if (rpcs & DOPARSABLEEXPORTS) {
216e299e01fSEdward Tomasz Napierala 		exp = exportslist;
217e299e01fSEdward Tomasz Napierala 		while (exp) {
218e299e01fSEdward Tomasz Napierala 			nbytes = strsnvis(strvised, sizeof(strvised),
219e299e01fSEdward Tomasz Napierala 			    exp->ex_dirp, VIS_GLOB | VIS_NL, "\"'$");
220e299e01fSEdward Tomasz Napierala 			if (nbytes == -1)
221e299e01fSEdward Tomasz Napierala 				err(1, "strsnvis");
222e299e01fSEdward Tomasz Napierala 			printf("%s\n", strvised);
223e299e01fSEdward Tomasz Napierala 			exp = exp->ex_next;
224e299e01fSEdward Tomasz Napierala 		}
225e299e01fSEdward Tomasz Napierala 	}
226439165e5SPhilippe Charnier 	exit(0);
2279b50d902SRodney W. Grimes }
2289b50d902SRodney W. Grimes 
2299b50d902SRodney W. Grimes /*
2305ab88c41STor Egge  * tcp_callrpc has the same interface as callrpc, but tries to
2315ab88c41STor Egge  * use tcp as transport method in order to handle large replies.
2325ab88c41STor Egge  */
2335ab88c41STor Egge int
tcp_callrpc(const char * host,int prognum,int versnum,int procnum,xdrproc_t inproc,char * in,xdrproc_t outproc,char * out)234ef636796SEd Schouten tcp_callrpc(const char *host, int prognum, int versnum, int procnum,
235ef636796SEd Schouten     xdrproc_t inproc, char *in, xdrproc_t outproc, char *out)
2365ab88c41STor Egge {
2375ab88c41STor Egge 	CLIENT *client;
2385ab88c41STor Egge 	struct timeval timeout;
2395ab88c41STor Egge 	int rval;
2405ab88c41STor Egge 
241c2fdb4d1SIan Dowse 	if ((client = clnt_create(host, prognum, versnum, "tcp")) == NULL &&
242c2fdb4d1SIan Dowse 	    (client = clnt_create(host, prognum, versnum, "udp")) == NULL)
2435ab88c41STor Egge 		return ((int) rpc_createerr.cf_stat);
2445ab88c41STor Egge 
2455ab88c41STor Egge 	timeout.tv_sec = 25;
2465ab88c41STor Egge 	timeout.tv_usec = 0;
2475ab88c41STor Egge 	rval = (int) clnt_call(client, procnum,
2485ab88c41STor Egge 			       inproc, in,
2495ab88c41STor Egge 			       outproc, out,
2505ab88c41STor Egge 			       timeout);
2515ab88c41STor Egge 	clnt_destroy(client);
2525ab88c41STor Egge  	return rval;
2535ab88c41STor Egge }
2545ab88c41STor Egge 
2555ab88c41STor Egge /*
2569b50d902SRodney W. Grimes  * Xdr routine for retrieving the mount dump list
2579b50d902SRodney W. Grimes  */
258439165e5SPhilippe Charnier int
xdr_mntdump(XDR * xdrsp,struct mountlist ** mlp)259ef636796SEd Schouten xdr_mntdump(XDR *xdrsp, struct mountlist **mlp)
2609b50d902SRodney W. Grimes {
2619b50d902SRodney W. Grimes 	register struct mountlist *mp;
2629b50d902SRodney W. Grimes 	register struct mountlist *tp;
2639b50d902SRodney W. Grimes 	register struct mountlist **otp;
2649b50d902SRodney W. Grimes 	int val, val2;
2659b50d902SRodney W. Grimes 	int bool;
2669b50d902SRodney W. Grimes 	char *strp;
2679b50d902SRodney W. Grimes 
2689b50d902SRodney W. Grimes 	*mlp = (struct mountlist *)0;
2699b50d902SRodney W. Grimes 	if (!xdr_bool(xdrsp, &bool))
2709b50d902SRodney W. Grimes 		return (0);
2719b50d902SRodney W. Grimes 	while (bool) {
2729b50d902SRodney W. Grimes 		mp = (struct mountlist *)malloc(sizeof(struct mountlist));
2739b50d902SRodney W. Grimes 		if (mp == NULL)
2749b50d902SRodney W. Grimes 			return (0);
2759b50d902SRodney W. Grimes 		mp->ml_left = mp->ml_right = (struct mountlist *)0;
2769b50d902SRodney W. Grimes 		strp = mp->ml_host;
277e495018eSWarner Losh 		if (!xdr_string(xdrsp, &strp, MNTNAMLEN)) {
278e495018eSWarner Losh 			free(mp);
2799b50d902SRodney W. Grimes 			return (0);
280e495018eSWarner Losh 		}
2819b50d902SRodney W. Grimes 		strp = mp->ml_dirp;
282e495018eSWarner Losh 		if (!xdr_string(xdrsp, &strp, MNTPATHLEN)) {
283e495018eSWarner Losh 			free(mp);
2849b50d902SRodney W. Grimes 			return (0);
285e495018eSWarner Losh 		}
2869b50d902SRodney W. Grimes 
2879b50d902SRodney W. Grimes 		/*
2889b50d902SRodney W. Grimes 		 * Build a binary tree on sorted order of either host or dirp.
2899b50d902SRodney W. Grimes 		 * Drop any duplications.
2909b50d902SRodney W. Grimes 		 */
2919b50d902SRodney W. Grimes 		if (*mlp == NULL) {
2929b50d902SRodney W. Grimes 			*mlp = mp;
2939b50d902SRodney W. Grimes 		} else {
2949b50d902SRodney W. Grimes 			tp = *mlp;
2959b50d902SRodney W. Grimes 			while (tp) {
2969b50d902SRodney W. Grimes 				val = strcmp(mp->ml_host, tp->ml_host);
2979b50d902SRodney W. Grimes 				val2 = strcmp(mp->ml_dirp, tp->ml_dirp);
2989b50d902SRodney W. Grimes 				switch (type) {
2999b50d902SRodney W. Grimes 				case ALL:
3009b50d902SRodney W. Grimes 					if (val == 0) {
3019b50d902SRodney W. Grimes 						if (val2 == 0) {
3029b50d902SRodney W. Grimes 							free((caddr_t)mp);
3039b50d902SRodney W. Grimes 							goto next;
3049b50d902SRodney W. Grimes 						}
3059b50d902SRodney W. Grimes 						val = val2;
3069b50d902SRodney W. Grimes 					}
3079b50d902SRodney W. Grimes 					break;
3089b50d902SRodney W. Grimes 				case DIRS:
3099b50d902SRodney W. Grimes 					if (val2 == 0) {
3109b50d902SRodney W. Grimes 						free((caddr_t)mp);
3119b50d902SRodney W. Grimes 						goto next;
3129b50d902SRodney W. Grimes 					}
3139b50d902SRodney W. Grimes 					val = val2;
3149b50d902SRodney W. Grimes 					break;
3159b50d902SRodney W. Grimes 				default:
3169b50d902SRodney W. Grimes 					if (val == 0) {
3179b50d902SRodney W. Grimes 						free((caddr_t)mp);
3189b50d902SRodney W. Grimes 						goto next;
3199b50d902SRodney W. Grimes 					}
3209b50d902SRodney W. Grimes 					break;
32180c7cc1cSPedro F. Giffuni 				}
3229b50d902SRodney W. Grimes 				if (val < 0) {
3239b50d902SRodney W. Grimes 					otp = &tp->ml_left;
3249b50d902SRodney W. Grimes 					tp = tp->ml_left;
3259b50d902SRodney W. Grimes 				} else {
3269b50d902SRodney W. Grimes 					otp = &tp->ml_right;
3279b50d902SRodney W. Grimes 					tp = tp->ml_right;
3289b50d902SRodney W. Grimes 				}
3299b50d902SRodney W. Grimes 			}
3309b50d902SRodney W. Grimes 			*otp = mp;
3319b50d902SRodney W. Grimes 		}
3329b50d902SRodney W. Grimes next:
3339b50d902SRodney W. Grimes 		if (!xdr_bool(xdrsp, &bool))
3349b50d902SRodney W. Grimes 			return (0);
3359b50d902SRodney W. Grimes 	}
3369b50d902SRodney W. Grimes 	return (1);
3379b50d902SRodney W. Grimes }
3389b50d902SRodney W. Grimes 
3399b50d902SRodney W. Grimes /*
3409b50d902SRodney W. Grimes  * Xdr routine to retrieve exports list
3419b50d902SRodney W. Grimes  */
342439165e5SPhilippe Charnier int
xdr_exportslist(XDR * xdrsp,struct exportslist ** exp)343ef636796SEd Schouten xdr_exportslist(XDR *xdrsp, struct exportslist **exp)
3449b50d902SRodney W. Grimes {
3459b50d902SRodney W. Grimes 	register struct exportslist *ep;
3469b50d902SRodney W. Grimes 	register struct grouplist *gp;
3479b50d902SRodney W. Grimes 	int bool, grpbool;
3489b50d902SRodney W. Grimes 	char *strp;
3499b50d902SRodney W. Grimes 
3509b50d902SRodney W. Grimes 	*exp = (struct exportslist *)0;
3519b50d902SRodney W. Grimes 	if (!xdr_bool(xdrsp, &bool))
3529b50d902SRodney W. Grimes 		return (0);
3539b50d902SRodney W. Grimes 	while (bool) {
3549b50d902SRodney W. Grimes 		ep = (struct exportslist *)malloc(sizeof(struct exportslist));
3559b50d902SRodney W. Grimes 		if (ep == NULL)
3569b50d902SRodney W. Grimes 			return (0);
3579b50d902SRodney W. Grimes 		ep->ex_groups = (struct grouplist *)0;
3589b50d902SRodney W. Grimes 		strp = ep->ex_dirp;
3590775314bSDoug Rabson 		if (!xdr_string(xdrsp, &strp, MNTPATHLEN))
3609b50d902SRodney W. Grimes 			return (0);
3619b50d902SRodney W. Grimes 		if (!xdr_bool(xdrsp, &grpbool))
3629b50d902SRodney W. Grimes 			return (0);
3639b50d902SRodney W. Grimes 		while (grpbool) {
3649b50d902SRodney W. Grimes 			gp = (struct grouplist *)malloc(sizeof(struct grouplist));
3659b50d902SRodney W. Grimes 			if (gp == NULL)
3669b50d902SRodney W. Grimes 				return (0);
3679b50d902SRodney W. Grimes 			strp = gp->gr_name;
3680775314bSDoug Rabson 			if (!xdr_string(xdrsp, &strp, MNTNAMLEN))
3699b50d902SRodney W. Grimes 				return (0);
3709b50d902SRodney W. Grimes 			gp->gr_next = ep->ex_groups;
3719b50d902SRodney W. Grimes 			ep->ex_groups = gp;
3729b50d902SRodney W. Grimes 			if (!xdr_bool(xdrsp, &grpbool))
3739b50d902SRodney W. Grimes 				return (0);
3749b50d902SRodney W. Grimes 		}
3759b50d902SRodney W. Grimes 		ep->ex_next = *exp;
3769b50d902SRodney W. Grimes 		*exp = ep;
3779b50d902SRodney W. Grimes 		if (!xdr_bool(xdrsp, &bool))
3789b50d902SRodney W. Grimes 			return (0);
3799b50d902SRodney W. Grimes 	}
3809b50d902SRodney W. Grimes 	return (1);
3819b50d902SRodney W. Grimes }
3829b50d902SRodney W. Grimes 
383439165e5SPhilippe Charnier static void
usage(void)384ef636796SEd Schouten usage(void)
3859b50d902SRodney W. Grimes {
386f682f10cSRuslan Ermilov 	fprintf(stderr, "usage: showmount [-a | -d] [-e3] [host]\n");
3879b50d902SRodney W. Grimes 	exit(1);
3889b50d902SRodney W. Grimes }
3899b50d902SRodney W. Grimes 
3909b50d902SRodney W. Grimes /*
3919b50d902SRodney W. Grimes  * Print the binary tree in inorder so that output is sorted.
3929b50d902SRodney W. Grimes  */
393439165e5SPhilippe Charnier void
print_dump(struct mountlist * mp)394ef636796SEd Schouten print_dump(struct mountlist *mp)
3959b50d902SRodney W. Grimes {
3969b50d902SRodney W. Grimes 
3979b50d902SRodney W. Grimes 	if (mp == NULL)
3989b50d902SRodney W. Grimes 		return;
3999b50d902SRodney W. Grimes 	if (mp->ml_left)
4009b50d902SRodney W. Grimes 		print_dump(mp->ml_left);
4019b50d902SRodney W. Grimes 	switch (type) {
4029b50d902SRodney W. Grimes 	case ALL:
4039b50d902SRodney W. Grimes 		printf("%s:%s\n", mp->ml_host, mp->ml_dirp);
4049b50d902SRodney W. Grimes 		break;
4059b50d902SRodney W. Grimes 	case DIRS:
4069b50d902SRodney W. Grimes 		printf("%s\n", mp->ml_dirp);
4079b50d902SRodney W. Grimes 		break;
4089b50d902SRodney W. Grimes 	default:
4099b50d902SRodney W. Grimes 		printf("%s\n", mp->ml_host);
4109b50d902SRodney W. Grimes 		break;
41180c7cc1cSPedro F. Giffuni 	}
4129b50d902SRodney W. Grimes 	if (mp->ml_right)
4139b50d902SRodney W. Grimes 		print_dump(mp->ml_right);
4149b50d902SRodney W. Grimes }
415