xref: /netbsd-src/usr.bin/showmount/showmount.c (revision b985414b8f8688f3bfa6718c583260b26b0bf1d1)
1*b985414bSchristos /*	$NetBSD: showmount.c,v 1.23 2018/01/09 03:31:15 christos Exp $	*/
20ac05e52Sjtc 
361f28255Scgd /*
43f2b3b5aSjtc  * Copyright (c) 1989, 1993, 1995
50ac05e52Sjtc  *	The Regents of the University of California.  All rights reserved.
661f28255Scgd  *
761f28255Scgd  * This code is derived from software contributed to Berkeley by
861f28255Scgd  * Rick Macklem at The University of Guelph.
961f28255Scgd  *
1061f28255Scgd  * Redistribution and use in source and binary forms, with or without
1161f28255Scgd  * modification, are permitted provided that the following conditions
1261f28255Scgd  * are met:
1361f28255Scgd  * 1. Redistributions of source code must retain the above copyright
1461f28255Scgd  *    notice, this list of conditions and the following disclaimer.
1561f28255Scgd  * 2. Redistributions in binary form must reproduce the above copyright
1661f28255Scgd  *    notice, this list of conditions and the following disclaimer in the
1761f28255Scgd  *    documentation and/or other materials provided with the distribution.
1889aaa1bbSagc  * 3. Neither the name of the University nor the names of its contributors
1961f28255Scgd  *    may be used to endorse or promote products derived from this software
2061f28255Scgd  *    without specific prior written permission.
2161f28255Scgd  *
2261f28255Scgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2361f28255Scgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2461f28255Scgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2561f28255Scgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2661f28255Scgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2761f28255Scgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2861f28255Scgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2961f28255Scgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3061f28255Scgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3161f28255Scgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3261f28255Scgd  * SUCH DAMAGE.
3361f28255Scgd  */
3461f28255Scgd 
35cfd8831aSlukem #include <sys/cdefs.h>
3661f28255Scgd #ifndef lint
3798e5374cSlukem __COPYRIGHT("@(#) Copyright (c) 1989, 1993, 1995\
3898e5374cSlukem  The Regents of the University of California.  All rights reserved.");
39d594ce93Scgd #endif /* not lint */
4061f28255Scgd 
4161f28255Scgd #ifndef lint
420ac05e52Sjtc #if 0
433f2b3b5aSjtc static char sccsid[] = "@(#)showmount.c	8.3 (Berkeley) 3/29/95";
440ac05e52Sjtc #endif
45*b985414bSchristos __RCSID("$NetBSD: showmount.c,v 1.23 2018/01/09 03:31:15 christos Exp $");
46d594ce93Scgd #endif /* not lint */
4761f28255Scgd 
4861f28255Scgd #include <sys/types.h>
4961f28255Scgd #include <sys/file.h>
5061f28255Scgd #include <sys/socket.h>
513f2b3b5aSjtc 
5261f28255Scgd #include <netdb.h>
5361f28255Scgd #include <rpc/rpc.h>
5461f28255Scgd #include <rpc/pmap_clnt.h>
5561f28255Scgd #include <rpc/pmap_prot.h>
5661f28255Scgd #include <nfs/rpcv2.h>
573f2b3b5aSjtc 
5861f28255Scgd #include <stdio.h>
59424af298Scgd #include <stdlib.h>
6061f28255Scgd #include <string.h>
613f2b3b5aSjtc #include <unistd.h>
62*b985414bSchristos #include <err.h>
63*b985414bSchristos #include <vis.h>
6461f28255Scgd 
6561f28255Scgd /* Constant defs */
6661f28255Scgd #define	ALL	1
6761f28255Scgd #define	DIRS	2
6861f28255Scgd 
6961f28255Scgd #define	DODUMP		0x1
7061f28255Scgd #define	DOEXPORTS	0x2
71*b985414bSchristos #define	DOPARSABLEEXPORTS	0x4
7261f28255Scgd 
7361f28255Scgd struct mountlist {
7461f28255Scgd 	struct mountlist *ml_left;
7561f28255Scgd 	struct mountlist *ml_right;
7661f28255Scgd 	char	ml_host[RPCMNT_NAMELEN+1];
7761f28255Scgd 	char	ml_dirp[RPCMNT_PATHLEN+1];
7861f28255Scgd };
7961f28255Scgd 
8061f28255Scgd struct grouplist {
8161f28255Scgd 	struct grouplist *gr_next;
8261f28255Scgd 	char	gr_name[RPCMNT_NAMELEN+1];
8361f28255Scgd };
8461f28255Scgd 
8561f28255Scgd struct exportslist {
8661f28255Scgd 	struct exportslist *ex_next;
8761f28255Scgd 	struct grouplist *ex_groups;
8861f28255Scgd 	char	ex_dirp[RPCMNT_PATHLEN+1];
8961f28255Scgd };
9061f28255Scgd 
9161f28255Scgd static struct mountlist *mntdump;
9261f28255Scgd static struct exportslist *exports;
9361f28255Scgd static int type = 0;
943f2b3b5aSjtc 
95b480aed3Sjoerg static void	print_dump(struct mountlist *);
96b480aed3Sjoerg __dead static void	usage(void);
97b480aed3Sjoerg static int	xdr_mntdump(XDR *, struct mountlist **);
98b480aed3Sjoerg static int	xdr_exports(XDR *, struct exportslist **);
99b480aed3Sjoerg static int	tcp_callrpc(const char *host, int prognum, int versnum,
100b480aed3Sjoerg     int procnum, xdrproc_t inproc, char *in, xdrproc_t outproc, char *out);
10161f28255Scgd 
10261f28255Scgd /*
103f0a7346dSsnj  * This command queries the NFS mount daemon for its mount list and/or
104f0a7346dSsnj  * its exports list and prints them out.
10561f28255Scgd  * See "NFS: Network File System Protocol Specification, RFC1094, Appendix A"
1063f2b3b5aSjtc  * and the "Network File System Protocol XXX.."
10761f28255Scgd  * for detailed information on the protocol.
10861f28255Scgd  */
1093f2b3b5aSjtc int
main(int argc,char ** argv)110b04eff35Srpaulo main(int argc, char **argv)
11161f28255Scgd {
1123f2b3b5aSjtc 	struct exportslist *exp;
1133f2b3b5aSjtc 	struct grouplist *grp;
1143f2b3b5aSjtc 	int estat, rpcs = 0, mntvers = 1;
115a2958081Slukem 	const char *host;
116f8fcb56bSmark 	int ch;
117e6333204Smsaitoh 	int len;
118*b985414bSchristos 	int nbytes;
119*b985414bSchristos 	char strvised[1024 * 4 + 1];
12061f28255Scgd 
121*b985414bSchristos 	while ((ch = getopt(argc, argv, "adEe3")) != -1)
12261f28255Scgd 		switch((char)ch) {
12361f28255Scgd 		case 'a':
12461f28255Scgd 			if (type == 0) {
12561f28255Scgd 				type = ALL;
12661f28255Scgd 				rpcs |= DODUMP;
12761f28255Scgd 			} else
12861f28255Scgd 				usage();
12961f28255Scgd 			break;
13061f28255Scgd 		case 'd':
13161f28255Scgd 			if (type == 0) {
13261f28255Scgd 				type = DIRS;
13361f28255Scgd 				rpcs |= DODUMP;
13461f28255Scgd 			} else
13561f28255Scgd 				usage();
13661f28255Scgd 			break;
137*b985414bSchristos 		case 'E':
138*b985414bSchristos 			rpcs |= DOPARSABLEEXPORTS;
139*b985414bSchristos 			break;
14061f28255Scgd 		case 'e':
14161f28255Scgd 			rpcs |= DOEXPORTS;
14261f28255Scgd 			break;
1433f2b3b5aSjtc 		case '3':
1443f2b3b5aSjtc 			mntvers = 3;
1453f2b3b5aSjtc 			break;
14661f28255Scgd 		case '?':
14761f28255Scgd 		default:
14861f28255Scgd 			usage();
14961f28255Scgd 		}
15061f28255Scgd 	argc -= optind;
15161f28255Scgd 	argv += optind;
15261f28255Scgd 
153*b985414bSchristos 	if ((rpcs & DOPARSABLEEXPORTS) != 0) {
154*b985414bSchristos 		if ((rpcs & DOEXPORTS) != 0)
155*b985414bSchristos 			errx(1, "-E cannot be used with -e");
156*b985414bSchristos 		if ((rpcs & DODUMP) != 0)
157*b985414bSchristos 			errx(1, "-E cannot be used with -a or -d");
158*b985414bSchristos 	}
159*b985414bSchristos 
16061f28255Scgd 	if (argc > 0)
16161f28255Scgd 		host = *argv;
16261f28255Scgd 	else
16361f28255Scgd 		host = "localhost";
16461f28255Scgd 
16561f28255Scgd 	if (rpcs == 0)
16661f28255Scgd 		rpcs = DODUMP;
16761f28255Scgd 
16861f28255Scgd 	if (rpcs & DODUMP)
169de443fd9Smycroft 		if ((estat = tcp_callrpc(host, RPCPROG_MNT, mntvers,
170ed70d746Schristos 			 RPCMNT_DUMP, (xdrproc_t)xdr_void, NULL,
17187d4f607Splunky 			 (xdrproc_t)xdr_mntdump, (char *)&mntdump)) != 0) {
172d0ec1c6bScgd 			fprintf(stderr, "showmount: Can't do Mountdump rpc: ");
17361f28255Scgd 			clnt_perrno(estat);
17461f28255Scgd 			exit(1);
17561f28255Scgd 		}
176*b985414bSchristos 	if (rpcs & (DOEXPORTS | DOPARSABLEEXPORTS))
177de443fd9Smycroft 		if ((estat = tcp_callrpc(host, RPCPROG_MNT, mntvers,
178ed70d746Schristos 			 RPCMNT_EXPORT, (xdrproc_t)xdr_void, NULL,
17987d4f607Splunky 			 (xdrproc_t)xdr_exports, (char *)&exports)) != 0) {
180d0ec1c6bScgd 			fprintf(stderr, "showmount: Can't do Exports rpc: ");
18161f28255Scgd 			clnt_perrno(estat);
18261f28255Scgd 			exit(1);
18361f28255Scgd 		}
18461f28255Scgd 
18561f28255Scgd 	/* Now just print out the results */
18661f28255Scgd 	if (rpcs & DODUMP) {
18761f28255Scgd 		switch (type) {
18861f28255Scgd 		case ALL:
18961f28255Scgd 			printf("All mount points on %s:\n", host);
19061f28255Scgd 			break;
19161f28255Scgd 		case DIRS:
19261f28255Scgd 			printf("Directories on %s:\n", host);
19361f28255Scgd 			break;
19461f28255Scgd 		default:
19561f28255Scgd 			printf("Hosts on %s:\n", host);
19661f28255Scgd 			break;
19761f28255Scgd 		};
19861f28255Scgd 		print_dump(mntdump);
19961f28255Scgd 	}
20061f28255Scgd 	if (rpcs & DOEXPORTS) {
20161f28255Scgd 		printf("Exports list on %s:\n", host);
20261f28255Scgd 		exp = exports;
20361f28255Scgd 		while (exp) {
204e6333204Smsaitoh 			len = printf("%-35s", exp->ex_dirp);
205e6333204Smsaitoh 			if (len > 35)
206e6333204Smsaitoh 				printf("\t");
20761f28255Scgd 			grp = exp->ex_groups;
20861f28255Scgd 			if (grp == NULL) {
20961f28255Scgd 				printf("Everyone\n");
21061f28255Scgd 			} else {
21161f28255Scgd 				while (grp) {
21261f28255Scgd 					printf("%s ", grp->gr_name);
21361f28255Scgd 					grp = grp->gr_next;
21461f28255Scgd 				}
21561f28255Scgd 				printf("\n");
21661f28255Scgd 			}
21761f28255Scgd 			exp = exp->ex_next;
21861f28255Scgd 		}
21961f28255Scgd 	}
220*b985414bSchristos 	if (rpcs & DOPARSABLEEXPORTS) {
221*b985414bSchristos 		exp = exports;
222*b985414bSchristos 		while (exp) {
223*b985414bSchristos 			nbytes = strnvis(strvised, sizeof(strvised),
224*b985414bSchristos 			    exp->ex_dirp, VIS_GLOB | VIS_NL);
225*b985414bSchristos 			if (nbytes == -1)
226*b985414bSchristos 				err(1, "strsnvis");
227*b985414bSchristos 			printf("%s\n", strvised);
228*b985414bSchristos 			exp = exp->ex_next;
229*b985414bSchristos 		}
230*b985414bSchristos 	}
2313f2b3b5aSjtc 	exit(0);
23261f28255Scgd }
23361f28255Scgd 
23461f28255Scgd /*
235de443fd9Smycroft  * tcp_callrpc has the same interface as callrpc, but tries to
236de443fd9Smycroft  * use tcp as transport method in order to handle large replies.
237de443fd9Smycroft  */
238de443fd9Smycroft 
239b480aed3Sjoerg static int
tcp_callrpc(const char * host,int prognum,int versnum,int procnum,xdrproc_t inproc,char * in,xdrproc_t outproc,char * out)240b04eff35Srpaulo tcp_callrpc(const char *host, int prognum, int versnum, int procnum,
241b04eff35Srpaulo     xdrproc_t inproc, char *in, xdrproc_t outproc, char *out)
242de443fd9Smycroft {
243de443fd9Smycroft 	CLIENT *client;
244de443fd9Smycroft 	struct timeval timeout;
245de443fd9Smycroft 	int rval;
246de443fd9Smycroft 
247ff2bab1cSrpaulo 	if ((client = clnt_create(host, prognum, versnum, "tcp")) == NULL &&
248ff2bab1cSrpaulo 	    (client = clnt_create(host, prognum, versnum, "udp")) == NULL)
249de443fd9Smycroft 		return ((int) rpc_createerr.cf_stat);
250de443fd9Smycroft 
251de443fd9Smycroft 	timeout.tv_sec = 25;
252de443fd9Smycroft 	timeout.tv_usec = 0;
253de443fd9Smycroft 	rval = (int) clnt_call(client, procnum,
254de443fd9Smycroft 			       inproc, in,
255de443fd9Smycroft 			       outproc, out,
256de443fd9Smycroft 			       timeout);
257de443fd9Smycroft 	clnt_destroy(client);
258de443fd9Smycroft  	return rval;
259de443fd9Smycroft }
260de443fd9Smycroft 
261ed70d746Schristos static void
mountlist_free(struct mountlist * ml)262ed70d746Schristos mountlist_free(struct mountlist *ml)
263ed70d746Schristos {
264ed70d746Schristos 	if (ml == NULL)
265ed70d746Schristos 		return;
266ed70d746Schristos 	mountlist_free(ml->ml_left);
267ed70d746Schristos 	mountlist_free(ml->ml_right);
268ed70d746Schristos 	free(ml);
269ed70d746Schristos }
270ed70d746Schristos 
271de443fd9Smycroft /*
27261f28255Scgd  * Xdr routine for retrieving the mount dump list
27361f28255Scgd  */
274b480aed3Sjoerg static int
xdr_mntdump(XDR * xdrsp,struct mountlist ** mlp)275b04eff35Srpaulo xdr_mntdump(XDR *xdrsp, struct mountlist **mlp)
27661f28255Scgd {
2773f2b3b5aSjtc 	struct mountlist *mp, **otp, *tp;
278336c1525Smbalmer 	int bool_int, val, val2;
27961f28255Scgd 	char *strp;
28061f28255Scgd 
281cfd8831aSlukem 	otp = NULL;
282ed70d746Schristos 	*mlp = NULL;
283336c1525Smbalmer 	if (!xdr_bool(xdrsp, &bool_int))
284ed70d746Schristos 		return 0;
285336c1525Smbalmer 	while (bool_int) {
286ed70d746Schristos 		mp = malloc(sizeof(*mp));
28761f28255Scgd 		if (mp == NULL)
288ed70d746Schristos 			goto out;
289ed70d746Schristos 		mp->ml_left = mp->ml_right = NULL;
29061f28255Scgd 		strp = mp->ml_host;
291ed70d746Schristos 		if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) {
292ed70d746Schristos 			free(mp);
293ed70d746Schristos 			goto out;
294ed70d746Schristos 		}
29561f28255Scgd 		strp = mp->ml_dirp;
296ed70d746Schristos 		if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) {
297ed70d746Schristos 			free(mp);
298ed70d746Schristos 			goto out;
299ed70d746Schristos 		}
30061f28255Scgd 
30161f28255Scgd 		/*
30261f28255Scgd 		 * Build a binary tree on sorted order of either host or dirp.
30361f28255Scgd 		 * Drop any duplications.
30461f28255Scgd 		 */
30561f28255Scgd 		if (*mlp == NULL) {
30661f28255Scgd 			*mlp = mp;
30761f28255Scgd 		} else {
30861f28255Scgd 			tp = *mlp;
30961f28255Scgd 			while (tp) {
31061f28255Scgd 				val = strcmp(mp->ml_host, tp->ml_host);
31161f28255Scgd 				val2 = strcmp(mp->ml_dirp, tp->ml_dirp);
31261f28255Scgd 				switch (type) {
31361f28255Scgd 				case ALL:
31461f28255Scgd 					if (val == 0) {
31561f28255Scgd 						if (val2 == 0) {
316ed70d746Schristos 							free(mp);
31761f28255Scgd 							goto next;
31861f28255Scgd 						}
31961f28255Scgd 						val = val2;
32061f28255Scgd 					}
32161f28255Scgd 					break;
32261f28255Scgd 				case DIRS:
32361f28255Scgd 					if (val2 == 0) {
324ed70d746Schristos 						free(mp);
32561f28255Scgd 						goto next;
32661f28255Scgd 					}
32761f28255Scgd 					val = val2;
32861f28255Scgd 					break;
32961f28255Scgd 				default:
33061f28255Scgd 					if (val == 0) {
331ed70d746Schristos 						free(mp);
33261f28255Scgd 						goto next;
33361f28255Scgd 					}
33461f28255Scgd 					break;
33561f28255Scgd 				};
33661f28255Scgd 				if (val < 0) {
33761f28255Scgd 					otp = &tp->ml_left;
33861f28255Scgd 					tp = tp->ml_left;
33961f28255Scgd 				} else {
34061f28255Scgd 					otp = &tp->ml_right;
34161f28255Scgd 					tp = tp->ml_right;
34261f28255Scgd 				}
34361f28255Scgd 			}
34461f28255Scgd 			*otp = mp;
34561f28255Scgd 		}
34661f28255Scgd next:
347336c1525Smbalmer 		if (!xdr_bool(xdrsp, &bool_int))
348ed70d746Schristos 			goto out;
34961f28255Scgd 	}
350ed70d746Schristos 	return 1;
351ed70d746Schristos out:
352ed70d746Schristos 	mountlist_free(*mlp);
353ed70d746Schristos 	return 0;
354ed70d746Schristos }
355ed70d746Schristos 
356ed70d746Schristos static void
grouplist_free(struct grouplist * gp)357ed70d746Schristos grouplist_free(struct grouplist *gp)
358ed70d746Schristos {
359ed70d746Schristos 	if (gp == NULL)
360ed70d746Schristos 		return;
361ed70d746Schristos 	grouplist_free(gp->gr_next);
362ed70d746Schristos 	free(gp);
363ed70d746Schristos }
364ed70d746Schristos 
365ed70d746Schristos static void
exportslist_free(struct exportslist * ep)366ed70d746Schristos exportslist_free(struct exportslist *ep)
367ed70d746Schristos {
368ed70d746Schristos 	if (ep == NULL)
369ed70d746Schristos 		return;
370ed70d746Schristos 	exportslist_free(ep->ex_next);
371ed70d746Schristos 	grouplist_free(ep->ex_groups);
372ed70d746Schristos 	free(ep);
37361f28255Scgd }
37461f28255Scgd 
37561f28255Scgd /*
37661f28255Scgd  * Xdr routine to retrieve exports list
37761f28255Scgd  */
378b480aed3Sjoerg static int
xdr_exports(XDR * xdrsp,struct exportslist ** exp)379b04eff35Srpaulo xdr_exports(XDR *xdrsp, struct exportslist **exp)
38061f28255Scgd {
381ed70d746Schristos 	struct exportslist *ep = NULL;
3823f2b3b5aSjtc 	struct grouplist *gp;
383336c1525Smbalmer 	int bool_int, grpbool;
38461f28255Scgd 	char *strp;
38561f28255Scgd 
386ed70d746Schristos 	*exp = NULL;
387336c1525Smbalmer 	if (!xdr_bool(xdrsp, &bool_int))
388ed70d746Schristos 		return 0;
389336c1525Smbalmer 	while (bool_int) {
390ed70d746Schristos 		ep = malloc(sizeof(*ep));
39161f28255Scgd 		if (ep == NULL)
392ed70d746Schristos 			goto out;
393ed70d746Schristos 		ep->ex_groups = NULL;
39461f28255Scgd 		strp = ep->ex_dirp;
39561f28255Scgd 		if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))
396ed70d746Schristos 			goto out;
39761f28255Scgd 		if (!xdr_bool(xdrsp, &grpbool))
398ed70d746Schristos 			goto out;
39961f28255Scgd 		while (grpbool) {
400ed70d746Schristos 			gp = malloc(sizeof(*gp));
40161f28255Scgd 			if (gp == NULL)
402ed70d746Schristos 				goto out;
40361f28255Scgd 			gp->gr_next = ep->ex_groups;
40461f28255Scgd 			ep->ex_groups = gp;
405ed70d746Schristos 			strp = gp->gr_name;
406ed70d746Schristos 			if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN))
407ed70d746Schristos 				goto out;
40861f28255Scgd 			if (!xdr_bool(xdrsp, &grpbool))
409ed70d746Schristos 				goto out;
41061f28255Scgd 		}
41161f28255Scgd 		ep->ex_next = *exp;
41261f28255Scgd 		*exp = ep;
413ed70d746Schristos 		ep = NULL;
414336c1525Smbalmer 		if (!xdr_bool(xdrsp, &bool_int))
415ed70d746Schristos 			goto out;
41661f28255Scgd 	}
417ed70d746Schristos 	return 1;
418ed70d746Schristos out:
419ed70d746Schristos 	exportslist_free(ep);
420ed70d746Schristos 	exportslist_free(*exp);
421ed70d746Schristos 	return 0;
42261f28255Scgd }
42361f28255Scgd 
424b480aed3Sjoerg static void
usage(void)425b480aed3Sjoerg usage(void)
42661f28255Scgd {
4273f2b3b5aSjtc 
428d0ec1c6bScgd 	fprintf(stderr, "usage: showmount [-ade3] host\n");
42961f28255Scgd 	exit(1);
43061f28255Scgd }
43161f28255Scgd 
43261f28255Scgd /*
43361f28255Scgd  * Print the binary tree in inorder so that output is sorted.
43461f28255Scgd  */
435b480aed3Sjoerg static void
print_dump(struct mountlist * mp)436b04eff35Srpaulo print_dump(struct mountlist *mp)
43761f28255Scgd {
43861f28255Scgd 
43961f28255Scgd 	if (mp == NULL)
44061f28255Scgd 		return;
44161f28255Scgd 	if (mp->ml_left)
44261f28255Scgd 		print_dump(mp->ml_left);
44361f28255Scgd 	switch (type) {
44461f28255Scgd 	case ALL:
44561f28255Scgd 		printf("%s:%s\n", mp->ml_host, mp->ml_dirp);
44661f28255Scgd 		break;
44761f28255Scgd 	case DIRS:
44861f28255Scgd 		printf("%s\n", mp->ml_dirp);
44961f28255Scgd 		break;
45061f28255Scgd 	default:
45161f28255Scgd 		printf("%s\n", mp->ml_host);
45261f28255Scgd 		break;
45361f28255Scgd 	};
45461f28255Scgd 	if (mp->ml_right)
45561f28255Scgd 		print_dump(mp->ml_right);
45661f28255Scgd }
457