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