xref: /freebsd/usr.bin/showmount/showmount.c (revision fbbd9655)
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.
16fbbd9655SWarner Losh  * 3. Neither the name of the University nor the names of its contributors
179b50d902SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
189b50d902SRodney W. Grimes  *    without specific prior written permission.
199b50d902SRodney W. Grimes  *
209b50d902SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
219b50d902SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
229b50d902SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
239b50d902SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
249b50d902SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
259b50d902SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
269b50d902SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
279b50d902SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
289b50d902SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
299b50d902SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
309b50d902SRodney W. Grimes  * SUCH DAMAGE.
319b50d902SRodney W. Grimes  */
329b50d902SRodney W. Grimes 
339b50d902SRodney W. Grimes #ifndef lint
34439165e5SPhilippe Charnier static const char copyright[] =
35439165e5SPhilippe Charnier "@(#) Copyright (c) 1989, 1993, 1995\n\
369b50d902SRodney W. Grimes 	The Regents of the University of California.  All rights reserved.\n";
37d4906adbSDima Dorfman #endif /* not lint */
389b50d902SRodney W. Grimes 
399b50d902SRodney W. Grimes #ifndef lint
40439165e5SPhilippe Charnier #if 0
41439165e5SPhilippe Charnier static char sccsid[] = "@(#)showmount.c	8.3 (Berkeley) 3/29/95";
42439165e5SPhilippe Charnier #endif
43439165e5SPhilippe Charnier static const char rcsid[] =
44c3aac50fSPeter Wemm   "$FreeBSD$";
45d4906adbSDima Dorfman #endif /* not lint */
469b50d902SRodney W. Grimes 
479b50d902SRodney W. Grimes #include <sys/types.h>
4848750b4cSDavid Greenman #include <sys/queue.h>
499b50d902SRodney W. Grimes #include <sys/file.h>
509b50d902SRodney W. Grimes #include <sys/socket.h>
519b50d902SRodney W. Grimes #include <sys/socketvar.h>
52439165e5SPhilippe Charnier 
53439165e5SPhilippe Charnier #include <err.h>
54821df508SXin LI #include <netdb.h>
559b50d902SRodney W. Grimes #include <rpc/rpc.h>
569b50d902SRodney W. Grimes #include <rpc/pmap_clnt.h>
579b50d902SRodney W. Grimes #include <rpc/pmap_prot.h>
580775314bSDoug Rabson #include <rpcsvc/mount.h>
59439165e5SPhilippe Charnier 
609b50d902SRodney W. Grimes #include <stdio.h>
61439165e5SPhilippe Charnier #include <stdlib.h>
629b50d902SRodney W. Grimes #include <string.h>
63439165e5SPhilippe Charnier #include <unistd.h>
64e299e01fSEdward Tomasz Napierala #include <vis.h>
659b50d902SRodney W. Grimes 
669b50d902SRodney W. Grimes /* Constant defs */
679b50d902SRodney W. Grimes #define	ALL	1
689b50d902SRodney W. Grimes #define	DIRS	2
699b50d902SRodney W. Grimes 
709b50d902SRodney W. Grimes #define	DODUMP			0x1
719b50d902SRodney W. Grimes #define	DOEXPORTS		0x2
72e299e01fSEdward Tomasz Napierala #define	DOPARSABLEEXPORTS	0x4
739b50d902SRodney W. Grimes 
749b50d902SRodney W. Grimes struct mountlist {
759b50d902SRodney W. Grimes 	struct mountlist *ml_left;
769b50d902SRodney W. Grimes 	struct mountlist *ml_right;
770775314bSDoug Rabson 	char	ml_host[MNTNAMLEN+1];
780775314bSDoug Rabson 	char	ml_dirp[MNTPATHLEN+1];
799b50d902SRodney W. Grimes };
809b50d902SRodney W. Grimes 
819b50d902SRodney W. Grimes struct grouplist {
829b50d902SRodney W. Grimes 	struct grouplist *gr_next;
830775314bSDoug Rabson 	char	gr_name[MNTNAMLEN+1];
849b50d902SRodney W. Grimes };
859b50d902SRodney W. Grimes 
869b50d902SRodney W. Grimes struct exportslist {
879b50d902SRodney W. Grimes 	struct exportslist *ex_next;
889b50d902SRodney W. Grimes 	struct grouplist *ex_groups;
890775314bSDoug Rabson 	char	ex_dirp[MNTPATHLEN+1];
909b50d902SRodney W. Grimes };
919b50d902SRodney W. Grimes 
929b50d902SRodney W. Grimes static struct mountlist *mntdump;
930775314bSDoug Rabson static struct exportslist *exportslist;
949b50d902SRodney W. Grimes static int type = 0;
95439165e5SPhilippe Charnier 
963f330d7dSWarner Losh void print_dump(struct mountlist *);
973f330d7dSWarner Losh static void usage(void);
983f330d7dSWarner Losh int xdr_mntdump(XDR *, struct mountlist **);
990775314bSDoug Rabson int xdr_exportslist(XDR *, struct exportslist **);
1003f330d7dSWarner Losh int tcp_callrpc(const char *host, int prognum, int versnum, int procnum,
1013f330d7dSWarner Losh 		xdrproc_t inproc, char *in, xdrproc_t outproc, char *out);
1029b50d902SRodney W. Grimes 
1039b50d902SRodney W. Grimes /*
1049b50d902SRodney W. Grimes  * This command queries the NFS mount daemon for it's mount list and/or
1059b50d902SRodney W. Grimes  * it's exports list and prints them out.
1069b50d902SRodney W. Grimes  * See "NFS: Network File System Protocol Specification, RFC1094, Appendix A"
107a62dc406SDoug Rabson  * and the "Network File System Protocol XXX.."
1089b50d902SRodney W. Grimes  * for detailed information on the protocol.
1099b50d902SRodney W. Grimes  */
110439165e5SPhilippe Charnier int
111ef636796SEd Schouten main(int argc, char **argv)
1129b50d902SRodney W. Grimes {
113e299e01fSEdward Tomasz Napierala 	char strvised[MNTPATHLEN * 4 + 1];
1149b50d902SRodney W. Grimes 	register struct exportslist *exp;
1159b50d902SRodney W. Grimes 	register struct grouplist *grp;
1161b31334cSPeter Wemm 	register int rpcs = 0, mntvers = 3;
1176e878749SDavid Malone 	const char *host;
118e299e01fSEdward Tomasz Napierala 	int ch, estat, nbytes;
1199b50d902SRodney W. Grimes 
120e299e01fSEdward Tomasz Napierala 	while ((ch = getopt(argc, argv, "adEe13")) != -1)
121f901ebcfSStefan Farfeleder 		switch (ch) {
1229b50d902SRodney W. Grimes 		case 'a':
1239b50d902SRodney W. Grimes 			if (type == 0) {
1249b50d902SRodney W. Grimes 				type = ALL;
1259b50d902SRodney W. Grimes 				rpcs |= DODUMP;
1269b50d902SRodney W. Grimes 			} else
1279b50d902SRodney W. Grimes 				usage();
1289b50d902SRodney W. Grimes 			break;
1299b50d902SRodney W. Grimes 		case 'd':
1309b50d902SRodney W. Grimes 			if (type == 0) {
1319b50d902SRodney W. Grimes 				type = DIRS;
1329b50d902SRodney W. Grimes 				rpcs |= DODUMP;
1339b50d902SRodney W. Grimes 			} else
1349b50d902SRodney W. Grimes 				usage();
1359b50d902SRodney W. Grimes 			break;
136e299e01fSEdward Tomasz Napierala 		case 'E':
137e299e01fSEdward Tomasz Napierala 			rpcs |= DOPARSABLEEXPORTS;
138e299e01fSEdward Tomasz Napierala 			break;
1399b50d902SRodney W. Grimes 		case 'e':
1409b50d902SRodney W. Grimes 			rpcs |= DOEXPORTS;
1419b50d902SRodney W. Grimes 			break;
1421b31334cSPeter Wemm 		case '1':
1431b31334cSPeter Wemm 			mntvers = 1;
1441b31334cSPeter Wemm 			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 
155e299e01fSEdward Tomasz Napierala 	if ((rpcs & DOPARSABLEEXPORTS) != 0) {
156e299e01fSEdward Tomasz Napierala 		if ((rpcs & DOEXPORTS) != 0)
157e299e01fSEdward Tomasz Napierala 			errx(1, "-E cannot be used with -e");
158e299e01fSEdward Tomasz Napierala 		if ((rpcs & DODUMP) != 0)
159e299e01fSEdward Tomasz Napierala 			errx(1, "-E cannot be used with -a or -d");
160e299e01fSEdward Tomasz Napierala 	}
161e299e01fSEdward Tomasz Napierala 
1629b50d902SRodney W. Grimes 	if (argc > 0)
1639b50d902SRodney W. Grimes 		host = *argv;
1649b50d902SRodney W. Grimes 	else
1659b50d902SRodney W. Grimes 		host = "localhost";
1669b50d902SRodney W. Grimes 
1679b50d902SRodney W. Grimes 	if (rpcs == 0)
1689b50d902SRodney W. Grimes 		rpcs = DODUMP;
1699b50d902SRodney W. Grimes 
1709b50d902SRodney W. Grimes 	if (rpcs & DODUMP)
1710775314bSDoug Rabson 		if ((estat = tcp_callrpc(host, MOUNTPROG, mntvers,
1720775314bSDoug Rabson 			MOUNTPROC_DUMP, (xdrproc_t)xdr_void, (char *)0,
1730c65eed7SPeter Wemm 			(xdrproc_t)xdr_mntdump, (char *)&mntdump)) != 0) {
1749b50d902SRodney W. Grimes 			clnt_perrno(estat);
175439165e5SPhilippe Charnier 			errx(1, "can't do mountdump rpc");
1769b50d902SRodney W. Grimes 		}
177e299e01fSEdward Tomasz Napierala 	if (rpcs & (DOEXPORTS | DOPARSABLEEXPORTS))
1780775314bSDoug Rabson 		if ((estat = tcp_callrpc(host, MOUNTPROG, mntvers,
1790775314bSDoug Rabson 			MOUNTPROC_EXPORT, (xdrproc_t)xdr_void, (char *)0,
1800775314bSDoug Rabson 			(xdrproc_t)xdr_exportslist, (char *)&exportslist)) != 0) {
1819b50d902SRodney W. Grimes 			clnt_perrno(estat);
182439165e5SPhilippe Charnier 			errx(1, "can't do exports rpc");
1839b50d902SRodney W. Grimes 		}
1849b50d902SRodney W. Grimes 
1859b50d902SRodney W. Grimes 	/* Now just print out the results */
1869b50d902SRodney W. Grimes 	if (rpcs & DODUMP) {
1879b50d902SRodney W. Grimes 		switch (type) {
1889b50d902SRodney W. Grimes 		case ALL:
1899b50d902SRodney W. Grimes 			printf("All mount points on %s:\n", host);
1909b50d902SRodney W. Grimes 			break;
1919b50d902SRodney W. Grimes 		case DIRS:
1929b50d902SRodney W. Grimes 			printf("Directories on %s:\n", host);
1939b50d902SRodney W. Grimes 			break;
1949b50d902SRodney W. Grimes 		default:
1959b50d902SRodney W. Grimes 			printf("Hosts on %s:\n", host);
1969b50d902SRodney W. Grimes 			break;
19780c7cc1cSPedro F. Giffuni 		}
1989b50d902SRodney W. Grimes 		print_dump(mntdump);
1999b50d902SRodney W. Grimes 	}
2009b50d902SRodney W. Grimes 	if (rpcs & DOEXPORTS) {
2019b50d902SRodney W. Grimes 		printf("Exports list on %s:\n", host);
2020775314bSDoug Rabson 		exp = exportslist;
2039b50d902SRodney W. Grimes 		while (exp) {
20471737f5aSRuslan Ermilov 			printf("%-34s ", exp->ex_dirp);
2059b50d902SRodney W. Grimes 			grp = exp->ex_groups;
2069b50d902SRodney W. Grimes 			if (grp == NULL) {
2079b50d902SRodney W. Grimes 				printf("Everyone\n");
2089b50d902SRodney W. Grimes 			} else {
2099b50d902SRodney W. Grimes 				while (grp) {
2109b50d902SRodney W. Grimes 					printf("%s ", grp->gr_name);
2119b50d902SRodney W. Grimes 					grp = grp->gr_next;
2129b50d902SRodney W. Grimes 				}
2139b50d902SRodney W. Grimes 				printf("\n");
2149b50d902SRodney W. Grimes 			}
2159b50d902SRodney W. Grimes 			exp = exp->ex_next;
2169b50d902SRodney W. Grimes 		}
2179b50d902SRodney W. Grimes 	}
218e299e01fSEdward Tomasz Napierala 	if (rpcs & DOPARSABLEEXPORTS) {
219e299e01fSEdward Tomasz Napierala 		exp = exportslist;
220e299e01fSEdward Tomasz Napierala 		while (exp) {
221e299e01fSEdward Tomasz Napierala 			nbytes = strsnvis(strvised, sizeof(strvised),
222e299e01fSEdward Tomasz Napierala 			    exp->ex_dirp, VIS_GLOB | VIS_NL, "\"'$");
223e299e01fSEdward Tomasz Napierala 			if (nbytes == -1)
224e299e01fSEdward Tomasz Napierala 				err(1, "strsnvis");
225e299e01fSEdward Tomasz Napierala 			printf("%s\n", strvised);
226e299e01fSEdward Tomasz Napierala 			exp = exp->ex_next;
227e299e01fSEdward Tomasz Napierala 		}
228e299e01fSEdward Tomasz Napierala 	}
229439165e5SPhilippe Charnier 	exit(0);
2309b50d902SRodney W. Grimes }
2319b50d902SRodney W. Grimes 
2329b50d902SRodney W. Grimes /*
2335ab88c41STor Egge  * tcp_callrpc has the same interface as callrpc, but tries to
2345ab88c41STor Egge  * use tcp as transport method in order to handle large replies.
2355ab88c41STor Egge  */
2365ab88c41STor Egge int
237ef636796SEd Schouten tcp_callrpc(const char *host, int prognum, int versnum, int procnum,
238ef636796SEd Schouten     xdrproc_t inproc, char *in, xdrproc_t outproc, char *out)
2395ab88c41STor Egge {
2405ab88c41STor Egge 	CLIENT *client;
2415ab88c41STor Egge 	struct timeval timeout;
2425ab88c41STor Egge 	int rval;
2435ab88c41STor Egge 
244c2fdb4d1SIan Dowse 	if ((client = clnt_create(host, prognum, versnum, "tcp")) == NULL &&
245c2fdb4d1SIan Dowse 	    (client = clnt_create(host, prognum, versnum, "udp")) == NULL)
2465ab88c41STor Egge 		return ((int) rpc_createerr.cf_stat);
2475ab88c41STor Egge 
2485ab88c41STor Egge 	timeout.tv_sec = 25;
2495ab88c41STor Egge 	timeout.tv_usec = 0;
2505ab88c41STor Egge 	rval = (int) clnt_call(client, procnum,
2515ab88c41STor Egge 			       inproc, in,
2525ab88c41STor Egge 			       outproc, out,
2535ab88c41STor Egge 			       timeout);
2545ab88c41STor Egge 	clnt_destroy(client);
2555ab88c41STor Egge  	return rval;
2565ab88c41STor Egge }
2575ab88c41STor Egge 
2585ab88c41STor Egge /*
2599b50d902SRodney W. Grimes  * Xdr routine for retrieving the mount dump list
2609b50d902SRodney W. Grimes  */
261439165e5SPhilippe Charnier int
262ef636796SEd Schouten xdr_mntdump(XDR *xdrsp, struct mountlist **mlp)
2639b50d902SRodney W. Grimes {
2649b50d902SRodney W. Grimes 	register struct mountlist *mp;
2659b50d902SRodney W. Grimes 	register struct mountlist *tp;
2669b50d902SRodney W. Grimes 	register struct mountlist **otp;
2679b50d902SRodney W. Grimes 	int val, val2;
2689b50d902SRodney W. Grimes 	int bool;
2699b50d902SRodney W. Grimes 	char *strp;
2709b50d902SRodney W. Grimes 
2719b50d902SRodney W. Grimes 	*mlp = (struct mountlist *)0;
2729b50d902SRodney W. Grimes 	if (!xdr_bool(xdrsp, &bool))
2739b50d902SRodney W. Grimes 		return (0);
2749b50d902SRodney W. Grimes 	while (bool) {
2759b50d902SRodney W. Grimes 		mp = (struct mountlist *)malloc(sizeof(struct mountlist));
2769b50d902SRodney W. Grimes 		if (mp == NULL)
2779b50d902SRodney W. Grimes 			return (0);
2789b50d902SRodney W. Grimes 		mp->ml_left = mp->ml_right = (struct mountlist *)0;
2799b50d902SRodney W. Grimes 		strp = mp->ml_host;
2800775314bSDoug Rabson 		if (!xdr_string(xdrsp, &strp, MNTNAMLEN))
2819b50d902SRodney W. Grimes 			return (0);
2829b50d902SRodney W. Grimes 		strp = mp->ml_dirp;
2830775314bSDoug Rabson 		if (!xdr_string(xdrsp, &strp, MNTPATHLEN))
2849b50d902SRodney W. Grimes 			return (0);
2859b50d902SRodney W. Grimes 
2869b50d902SRodney W. Grimes 		/*
2879b50d902SRodney W. Grimes 		 * Build a binary tree on sorted order of either host or dirp.
2889b50d902SRodney W. Grimes 		 * Drop any duplications.
2899b50d902SRodney W. Grimes 		 */
2909b50d902SRodney W. Grimes 		if (*mlp == NULL) {
2919b50d902SRodney W. Grimes 			*mlp = mp;
2929b50d902SRodney W. Grimes 		} else {
2939b50d902SRodney W. Grimes 			tp = *mlp;
2949b50d902SRodney W. Grimes 			while (tp) {
2959b50d902SRodney W. Grimes 				val = strcmp(mp->ml_host, tp->ml_host);
2969b50d902SRodney W. Grimes 				val2 = strcmp(mp->ml_dirp, tp->ml_dirp);
2979b50d902SRodney W. Grimes 				switch (type) {
2989b50d902SRodney W. Grimes 				case ALL:
2999b50d902SRodney W. Grimes 					if (val == 0) {
3009b50d902SRodney W. Grimes 						if (val2 == 0) {
3019b50d902SRodney W. Grimes 							free((caddr_t)mp);
3029b50d902SRodney W. Grimes 							goto next;
3039b50d902SRodney W. Grimes 						}
3049b50d902SRodney W. Grimes 						val = val2;
3059b50d902SRodney W. Grimes 					}
3069b50d902SRodney W. Grimes 					break;
3079b50d902SRodney W. Grimes 				case DIRS:
3089b50d902SRodney W. Grimes 					if (val2 == 0) {
3099b50d902SRodney W. Grimes 						free((caddr_t)mp);
3109b50d902SRodney W. Grimes 						goto next;
3119b50d902SRodney W. Grimes 					}
3129b50d902SRodney W. Grimes 					val = val2;
3139b50d902SRodney W. Grimes 					break;
3149b50d902SRodney W. Grimes 				default:
3159b50d902SRodney W. Grimes 					if (val == 0) {
3169b50d902SRodney W. Grimes 						free((caddr_t)mp);
3179b50d902SRodney W. Grimes 						goto next;
3189b50d902SRodney W. Grimes 					}
3199b50d902SRodney W. Grimes 					break;
32080c7cc1cSPedro F. Giffuni 				}
3219b50d902SRodney W. Grimes 				if (val < 0) {
3229b50d902SRodney W. Grimes 					otp = &tp->ml_left;
3239b50d902SRodney W. Grimes 					tp = tp->ml_left;
3249b50d902SRodney W. Grimes 				} else {
3259b50d902SRodney W. Grimes 					otp = &tp->ml_right;
3269b50d902SRodney W. Grimes 					tp = tp->ml_right;
3279b50d902SRodney W. Grimes 				}
3289b50d902SRodney W. Grimes 			}
3299b50d902SRodney W. Grimes 			*otp = mp;
3309b50d902SRodney W. Grimes 		}
3319b50d902SRodney W. Grimes next:
3329b50d902SRodney W. Grimes 		if (!xdr_bool(xdrsp, &bool))
3339b50d902SRodney W. Grimes 			return (0);
3349b50d902SRodney W. Grimes 	}
3359b50d902SRodney W. Grimes 	return (1);
3369b50d902SRodney W. Grimes }
3379b50d902SRodney W. Grimes 
3389b50d902SRodney W. Grimes /*
3399b50d902SRodney W. Grimes  * Xdr routine to retrieve exports list
3409b50d902SRodney W. Grimes  */
341439165e5SPhilippe Charnier int
342ef636796SEd Schouten xdr_exportslist(XDR *xdrsp, struct exportslist **exp)
3439b50d902SRodney W. Grimes {
3449b50d902SRodney W. Grimes 	register struct exportslist *ep;
3459b50d902SRodney W. Grimes 	register struct grouplist *gp;
3469b50d902SRodney W. Grimes 	int bool, grpbool;
3479b50d902SRodney W. Grimes 	char *strp;
3489b50d902SRodney W. Grimes 
3499b50d902SRodney W. Grimes 	*exp = (struct exportslist *)0;
3509b50d902SRodney W. Grimes 	if (!xdr_bool(xdrsp, &bool))
3519b50d902SRodney W. Grimes 		return (0);
3529b50d902SRodney W. Grimes 	while (bool) {
3539b50d902SRodney W. Grimes 		ep = (struct exportslist *)malloc(sizeof(struct exportslist));
3549b50d902SRodney W. Grimes 		if (ep == NULL)
3559b50d902SRodney W. Grimes 			return (0);
3569b50d902SRodney W. Grimes 		ep->ex_groups = (struct grouplist *)0;
3579b50d902SRodney W. Grimes 		strp = ep->ex_dirp;
3580775314bSDoug Rabson 		if (!xdr_string(xdrsp, &strp, MNTPATHLEN))
3599b50d902SRodney W. Grimes 			return (0);
3609b50d902SRodney W. Grimes 		if (!xdr_bool(xdrsp, &grpbool))
3619b50d902SRodney W. Grimes 			return (0);
3629b50d902SRodney W. Grimes 		while (grpbool) {
3639b50d902SRodney W. Grimes 			gp = (struct grouplist *)malloc(sizeof(struct grouplist));
3649b50d902SRodney W. Grimes 			if (gp == NULL)
3659b50d902SRodney W. Grimes 				return (0);
3669b50d902SRodney W. Grimes 			strp = gp->gr_name;
3670775314bSDoug Rabson 			if (!xdr_string(xdrsp, &strp, MNTNAMLEN))
3689b50d902SRodney W. Grimes 				return (0);
3699b50d902SRodney W. Grimes 			gp->gr_next = ep->ex_groups;
3709b50d902SRodney W. Grimes 			ep->ex_groups = gp;
3719b50d902SRodney W. Grimes 			if (!xdr_bool(xdrsp, &grpbool))
3729b50d902SRodney W. Grimes 				return (0);
3739b50d902SRodney W. Grimes 		}
3749b50d902SRodney W. Grimes 		ep->ex_next = *exp;
3759b50d902SRodney W. Grimes 		*exp = ep;
3769b50d902SRodney W. Grimes 		if (!xdr_bool(xdrsp, &bool))
3779b50d902SRodney W. Grimes 			return (0);
3789b50d902SRodney W. Grimes 	}
3799b50d902SRodney W. Grimes 	return (1);
3809b50d902SRodney W. Grimes }
3819b50d902SRodney W. Grimes 
382439165e5SPhilippe Charnier static void
383ef636796SEd Schouten usage(void)
3849b50d902SRodney W. Grimes {
385f682f10cSRuslan Ermilov 	fprintf(stderr, "usage: showmount [-a | -d] [-e3] [host]\n");
3869b50d902SRodney W. Grimes 	exit(1);
3879b50d902SRodney W. Grimes }
3889b50d902SRodney W. Grimes 
3899b50d902SRodney W. Grimes /*
3909b50d902SRodney W. Grimes  * Print the binary tree in inorder so that output is sorted.
3919b50d902SRodney W. Grimes  */
392439165e5SPhilippe Charnier void
393ef636796SEd Schouten print_dump(struct mountlist *mp)
3949b50d902SRodney W. Grimes {
3959b50d902SRodney W. Grimes 
3969b50d902SRodney W. Grimes 	if (mp == NULL)
3979b50d902SRodney W. Grimes 		return;
3989b50d902SRodney W. Grimes 	if (mp->ml_left)
3999b50d902SRodney W. Grimes 		print_dump(mp->ml_left);
4009b50d902SRodney W. Grimes 	switch (type) {
4019b50d902SRodney W. Grimes 	case ALL:
4029b50d902SRodney W. Grimes 		printf("%s:%s\n", mp->ml_host, mp->ml_dirp);
4039b50d902SRodney W. Grimes 		break;
4049b50d902SRodney W. Grimes 	case DIRS:
4059b50d902SRodney W. Grimes 		printf("%s\n", mp->ml_dirp);
4069b50d902SRodney W. Grimes 		break;
4079b50d902SRodney W. Grimes 	default:
4089b50d902SRodney W. Grimes 		printf("%s\n", mp->ml_host);
4099b50d902SRodney W. Grimes 		break;
41080c7cc1cSPedro F. Giffuni 	}
4119b50d902SRodney W. Grimes 	if (mp->ml_right)
4129b50d902SRodney W. Grimes 		print_dump(mp->ml_right);
4139b50d902SRodney W. Grimes }
414