showmount.c revision 9336
11590Srgrimes/*
21590Srgrimes * Copyright (c) 1989, 1993
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes *
51590Srgrimes * This code is derived from software contributed to Berkeley by
61590Srgrimes * Rick Macklem at The University of Guelph.
71590Srgrimes *
81590Srgrimes * Redistribution and use in source and binary forms, with or without
91590Srgrimes * modification, are permitted provided that the following conditions
101590Srgrimes * are met:
111590Srgrimes * 1. Redistributions of source code must retain the above copyright
121590Srgrimes *    notice, this list of conditions and the following disclaimer.
131590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141590Srgrimes *    notice, this list of conditions and the following disclaimer in the
151590Srgrimes *    documentation and/or other materials provided with the distribution.
161590Srgrimes * 3. All advertising materials mentioning features or use of this software
171590Srgrimes *    must display the following acknowledgement:
181590Srgrimes *	This product includes software developed by the University of
191590Srgrimes *	California, Berkeley and its contributors.
201590Srgrimes * 4. Neither the name of the University nor the names of its contributors
211590Srgrimes *    may be used to endorse or promote products derived from this software
221590Srgrimes *    without specific prior written permission.
231590Srgrimes *
241590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
251590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
261590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
271590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
281590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
291590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
301590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
311590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
321590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
331590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
341590Srgrimes * SUCH DAMAGE.
351590Srgrimes */
361590Srgrimes
371590Srgrimes#ifndef lint
381590Srgrimesstatic char copyright[] =
391590Srgrimes"@(#) Copyright (c) 1989, 1993\n\
401590Srgrimes	The Regents of the University of California.  All rights reserved.\n";
411590Srgrimes#endif not lint
421590Srgrimes
431590Srgrimes#ifndef lint
441590Srgrimesstatic char sccsid[] = "@(#)showmount.c	8.1 (Berkeley) 6/6/93";
451590Srgrimes#endif not lint
461590Srgrimes
471590Srgrimes#include <sys/types.h>
481590Srgrimes#include <sys/file.h>
491590Srgrimes#include <sys/socket.h>
501590Srgrimes#include <sys/socketvar.h>
511590Srgrimes#include <netdb.h>
521590Srgrimes#include <rpc/rpc.h>
531590Srgrimes#include <rpc/pmap_clnt.h>
541590Srgrimes#include <rpc/pmap_prot.h>
551590Srgrimes#include <nfs/rpcv2.h>
561590Srgrimes#include <stdio.h>
571590Srgrimes#include <string.h>
581590Srgrimes
591590Srgrimes/* Constant defs */
601590Srgrimes#define	ALL	1
611590Srgrimes#define	DIRS	2
621590Srgrimes
631590Srgrimes#define	DODUMP		0x1
641590Srgrimes#define	DOEXPORTS	0x2
651590Srgrimes
661590Srgrimesstruct mountlist {
671590Srgrimes	struct mountlist *ml_left;
681590Srgrimes	struct mountlist *ml_right;
691590Srgrimes	char	ml_host[RPCMNT_NAMELEN+1];
701590Srgrimes	char	ml_dirp[RPCMNT_PATHLEN+1];
711590Srgrimes};
721590Srgrimes
731590Srgrimesstruct grouplist {
741590Srgrimes	struct grouplist *gr_next;
751590Srgrimes	char	gr_name[RPCMNT_NAMELEN+1];
761590Srgrimes};
771590Srgrimes
781590Srgrimesstruct exportslist {
791590Srgrimes	struct exportslist *ex_next;
801590Srgrimes	struct grouplist *ex_groups;
811590Srgrimes	char	ex_dirp[RPCMNT_PATHLEN+1];
821590Srgrimes};
831590Srgrimes
841590Srgrimesstatic struct mountlist *mntdump;
851590Srgrimesstatic struct exportslist *exports;
861590Srgrimesstatic int type = 0;
871590Srgrimesint xdr_mntdump(), xdr_exports();
881590Srgrimes
891590Srgrimes/*
901590Srgrimes * This command queries the NFS mount daemon for it's mount list and/or
911590Srgrimes * it's exports list and prints them out.
921590Srgrimes * See "NFS: Network File System Protocol Specification, RFC1094, Appendix A"
939336Sdfr * and the "Network File System Protocol XXX.."
941590Srgrimes * for detailed information on the protocol.
951590Srgrimes */
961590Srgrimesmain(argc, argv)
971590Srgrimes	int argc;
981590Srgrimes	char **argv;
991590Srgrimes{
1001590Srgrimes	register struct mountlist *mntp;
1011590Srgrimes	register struct exportslist *exp;
1021590Srgrimes	register struct grouplist *grp;
1031590Srgrimes	extern char *optarg;
1041590Srgrimes	extern int optind;
1059336Sdfr	register int rpcs = 0, mntvers = 1;
1061590Srgrimes	char ch;
1071590Srgrimes	char *host;
1081590Srgrimes	int estat;
1091590Srgrimes
1109336Sdfr	while ((ch = getopt(argc, argv, "ade3")) != EOF)
1111590Srgrimes		switch((char)ch) {
1121590Srgrimes		case 'a':
1131590Srgrimes			if (type == 0) {
1141590Srgrimes				type = ALL;
1151590Srgrimes				rpcs |= DODUMP;
1161590Srgrimes			} else
1171590Srgrimes				usage();
1181590Srgrimes			break;
1191590Srgrimes		case 'd':
1201590Srgrimes			if (type == 0) {
1211590Srgrimes				type = DIRS;
1221590Srgrimes				rpcs |= DODUMP;
1231590Srgrimes			} else
1241590Srgrimes				usage();
1251590Srgrimes			break;
1261590Srgrimes		case 'e':
1271590Srgrimes			rpcs |= DOEXPORTS;
1281590Srgrimes			break;
1299336Sdfr		case '3':
1309336Sdfr			mntvers = 3;
1319336Sdfr			break;
1321590Srgrimes		case '?':
1331590Srgrimes		default:
1341590Srgrimes			usage();
1351590Srgrimes		}
1361590Srgrimes	argc -= optind;
1371590Srgrimes	argv += optind;
1381590Srgrimes
1391590Srgrimes	if (argc > 0)
1401590Srgrimes		host = *argv;
1411590Srgrimes	else
1421590Srgrimes		host = "localhost";
1431590Srgrimes
1441590Srgrimes	if (rpcs == 0)
1451590Srgrimes		rpcs = DODUMP;
1461590Srgrimes
1471590Srgrimes	if (rpcs & DODUMP)
1489336Sdfr		if ((estat = callrpc(host, RPCPROG_MNT, mntvers,
1491590Srgrimes			RPCMNT_DUMP, xdr_void, (char *)0,
1501590Srgrimes			xdr_mntdump, (char *)&mntdump)) != 0) {
1511590Srgrimes			clnt_perrno(estat);
1521590Srgrimes			fprintf(stderr, "Can't do Mountdump rpc\n");
1531590Srgrimes			exit(1);
1541590Srgrimes		}
1551590Srgrimes	if (rpcs & DOEXPORTS)
1569336Sdfr		if ((estat = callrpc(host, RPCPROG_MNT, mntvers,
1571590Srgrimes			RPCMNT_EXPORT, xdr_void, (char *)0,
1581590Srgrimes			xdr_exports, (char *)&exports)) != 0) {
1591590Srgrimes			clnt_perrno(estat);
1601590Srgrimes			fprintf(stderr, "Can't do Exports rpc\n");
1611590Srgrimes			exit(1);
1621590Srgrimes		}
1631590Srgrimes
1641590Srgrimes	/* Now just print out the results */
1651590Srgrimes	if (rpcs & DODUMP) {
1661590Srgrimes		switch (type) {
1671590Srgrimes		case ALL:
1681590Srgrimes			printf("All mount points on %s:\n", host);
1691590Srgrimes			break;
1701590Srgrimes		case DIRS:
1711590Srgrimes			printf("Directories on %s:\n", host);
1721590Srgrimes			break;
1731590Srgrimes		default:
1741590Srgrimes			printf("Hosts on %s:\n", host);
1751590Srgrimes			break;
1761590Srgrimes		};
1771590Srgrimes		print_dump(mntdump);
1781590Srgrimes	}
1791590Srgrimes	if (rpcs & DOEXPORTS) {
1801590Srgrimes		printf("Exports list on %s:\n", host);
1811590Srgrimes		exp = exports;
1821590Srgrimes		while (exp) {
1831590Srgrimes			printf("%-35s", exp->ex_dirp);
1841590Srgrimes			grp = exp->ex_groups;
1851590Srgrimes			if (grp == NULL) {
1861590Srgrimes				printf("Everyone\n");
1871590Srgrimes			} else {
1881590Srgrimes				while (grp) {
1891590Srgrimes					printf("%s ", grp->gr_name);
1901590Srgrimes					grp = grp->gr_next;
1911590Srgrimes				}
1921590Srgrimes				printf("\n");
1931590Srgrimes			}
1941590Srgrimes			exp = exp->ex_next;
1951590Srgrimes		}
1961590Srgrimes	}
1971590Srgrimes}
1981590Srgrimes
1991590Srgrimes/*
2001590Srgrimes * Xdr routine for retrieving the mount dump list
2011590Srgrimes */
2021590Srgrimesxdr_mntdump(xdrsp, mlp)
2031590Srgrimes	XDR *xdrsp;
2041590Srgrimes	struct mountlist **mlp;
2051590Srgrimes{
2061590Srgrimes	register struct mountlist *mp;
2071590Srgrimes	register struct mountlist *tp;
2081590Srgrimes	register struct mountlist **otp;
2091590Srgrimes	int val, val2;
2101590Srgrimes	int bool;
2111590Srgrimes	char *strp;
2121590Srgrimes
2131590Srgrimes	*mlp = (struct mountlist *)0;
2141590Srgrimes	if (!xdr_bool(xdrsp, &bool))
2151590Srgrimes		return (0);
2161590Srgrimes	while (bool) {
2171590Srgrimes		mp = (struct mountlist *)malloc(sizeof(struct mountlist));
2181590Srgrimes		if (mp == NULL)
2191590Srgrimes			return (0);
2201590Srgrimes		mp->ml_left = mp->ml_right = (struct mountlist *)0;
2211590Srgrimes		strp = mp->ml_host;
2221590Srgrimes		if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN))
2231590Srgrimes			return (0);
2241590Srgrimes		strp = mp->ml_dirp;
2251590Srgrimes		if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))
2261590Srgrimes			return (0);
2271590Srgrimes
2281590Srgrimes		/*
2291590Srgrimes		 * Build a binary tree on sorted order of either host or dirp.
2301590Srgrimes		 * Drop any duplications.
2311590Srgrimes		 */
2321590Srgrimes		if (*mlp == NULL) {
2331590Srgrimes			*mlp = mp;
2341590Srgrimes		} else {
2351590Srgrimes			tp = *mlp;
2361590Srgrimes			while (tp) {
2371590Srgrimes				val = strcmp(mp->ml_host, tp->ml_host);
2381590Srgrimes				val2 = strcmp(mp->ml_dirp, tp->ml_dirp);
2391590Srgrimes				switch (type) {
2401590Srgrimes				case ALL:
2411590Srgrimes					if (val == 0) {
2421590Srgrimes						if (val2 == 0) {
2431590Srgrimes							free((caddr_t)mp);
2441590Srgrimes							goto next;
2451590Srgrimes						}
2461590Srgrimes						val = val2;
2471590Srgrimes					}
2481590Srgrimes					break;
2491590Srgrimes				case DIRS:
2501590Srgrimes					if (val2 == 0) {
2511590Srgrimes						free((caddr_t)mp);
2521590Srgrimes						goto next;
2531590Srgrimes					}
2541590Srgrimes					val = val2;
2551590Srgrimes					break;
2561590Srgrimes				default:
2571590Srgrimes					if (val == 0) {
2581590Srgrimes						free((caddr_t)mp);
2591590Srgrimes						goto next;
2601590Srgrimes					}
2611590Srgrimes					break;
2621590Srgrimes				};
2631590Srgrimes				if (val < 0) {
2641590Srgrimes					otp = &tp->ml_left;
2651590Srgrimes					tp = tp->ml_left;
2661590Srgrimes				} else {
2671590Srgrimes					otp = &tp->ml_right;
2681590Srgrimes					tp = tp->ml_right;
2691590Srgrimes				}
2701590Srgrimes			}
2711590Srgrimes			*otp = mp;
2721590Srgrimes		}
2731590Srgrimesnext:
2741590Srgrimes		if (!xdr_bool(xdrsp, &bool))
2751590Srgrimes			return (0);
2761590Srgrimes	}
2771590Srgrimes	return (1);
2781590Srgrimes}
2791590Srgrimes
2801590Srgrimes/*
2811590Srgrimes * Xdr routine to retrieve exports list
2821590Srgrimes */
2831590Srgrimesxdr_exports(xdrsp, exp)
2841590Srgrimes	XDR *xdrsp;
2851590Srgrimes	struct exportslist **exp;
2861590Srgrimes{
2871590Srgrimes	register struct exportslist *ep;
2881590Srgrimes	register struct grouplist *gp;
2891590Srgrimes	int bool, grpbool;
2901590Srgrimes	char *strp;
2911590Srgrimes
2921590Srgrimes	*exp = (struct exportslist *)0;
2931590Srgrimes	if (!xdr_bool(xdrsp, &bool))
2941590Srgrimes		return (0);
2951590Srgrimes	while (bool) {
2961590Srgrimes		ep = (struct exportslist *)malloc(sizeof(struct exportslist));
2971590Srgrimes		if (ep == NULL)
2981590Srgrimes			return (0);
2991590Srgrimes		ep->ex_groups = (struct grouplist *)0;
3001590Srgrimes		strp = ep->ex_dirp;
3011590Srgrimes		if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))
3021590Srgrimes			return (0);
3031590Srgrimes		if (!xdr_bool(xdrsp, &grpbool))
3041590Srgrimes			return (0);
3051590Srgrimes		while (grpbool) {
3061590Srgrimes			gp = (struct grouplist *)malloc(sizeof(struct grouplist));
3071590Srgrimes			if (gp == NULL)
3081590Srgrimes				return (0);
3091590Srgrimes			strp = gp->gr_name;
3101590Srgrimes			if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN))
3111590Srgrimes				return (0);
3121590Srgrimes			gp->gr_next = ep->ex_groups;
3131590Srgrimes			ep->ex_groups = gp;
3141590Srgrimes			if (!xdr_bool(xdrsp, &grpbool))
3151590Srgrimes				return (0);
3161590Srgrimes		}
3171590Srgrimes		ep->ex_next = *exp;
3181590Srgrimes		*exp = ep;
3191590Srgrimes		if (!xdr_bool(xdrsp, &bool))
3201590Srgrimes			return (0);
3211590Srgrimes	}
3221590Srgrimes	return (1);
3231590Srgrimes}
3241590Srgrimes
3251590Srgrimesusage()
3261590Srgrimes{
3271590Srgrimes	fprintf(stderr, "usage: showmount [-ade] host\n");
3281590Srgrimes	exit(1);
3291590Srgrimes}
3301590Srgrimes
3311590Srgrimes/*
3321590Srgrimes * Print the binary tree in inorder so that output is sorted.
3331590Srgrimes */
3341590Srgrimesprint_dump(mp)
3351590Srgrimes	struct mountlist *mp;
3361590Srgrimes{
3371590Srgrimes
3381590Srgrimes	if (mp == NULL)
3391590Srgrimes		return;
3401590Srgrimes	if (mp->ml_left)
3411590Srgrimes		print_dump(mp->ml_left);
3421590Srgrimes	switch (type) {
3431590Srgrimes	case ALL:
3441590Srgrimes		printf("%s:%s\n", mp->ml_host, mp->ml_dirp);
3451590Srgrimes		break;
3461590Srgrimes	case DIRS:
3471590Srgrimes		printf("%s\n", mp->ml_dirp);
3481590Srgrimes		break;
3491590Srgrimes	default:
3501590Srgrimes		printf("%s\n", mp->ml_host);
3511590Srgrimes		break;
3521590Srgrimes	};
3531590Srgrimes	if (mp->ml_right)
3541590Srgrimes		print_dump(mp->ml_right);
3551590Srgrimes}
356