/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * University Copyright- Copyright (c) 1982, 1986, 1988 * The Regents of the University of California * All Rights Reserved * * University Acknowledgment- Portions of this document are derived from * software developed by the University of California, Berkeley, and its * contributors. */ #pragma ident "%Z%%M% %I% %E% SMI" /* * showmount */ #include #include #include #include #include #include #include #include #include #include #include int sorthost(); int sortpath(); void pr_err(char *, ...); void printex(); void usage(); /* * Dynamically-sized array of pointers to mountlist entries. Each element * points into the linked list returned by the RPC call. We use an array * so that we can conveniently sort the entries. */ static struct mountbody **table; struct timeval rpc_totout_new = {15, 0}; main(argc, argv) int argc; char **argv; { int aflg = 0, dflg = 0, eflg = 0; int err; struct mountbody *result_list = NULL; struct mountbody *ml = NULL; struct mountbody **tb; /* pointer into table */ char *host, hostbuf[256]; char *last; CLIENT *cl; extern int optind; extern char *optarg; int c; struct timeval tout, rpc_totout_old; int numentries; (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) #define TEXT_DOMAIN "SYS_TEST" #endif (void) textdomain(TEXT_DOMAIN); while ((c = getopt(argc, argv, "ade")) != EOF) { switch (c) { case 'a': aflg++; break; case 'd': dflg++; break; case 'e': eflg++; break; default: usage(); exit(1); } } switch (argc - optind) { case 0: /* no args */ if (gethostname(hostbuf, sizeof (hostbuf)) < 0) { pr_err("gethostname: %s\n", strerror(errno)); exit(1); } host = hostbuf; break; case 1: /* one arg */ host = argv[optind]; break; default: /* too many args */ usage(); exit(1); } __rpc_control(CLCR_GET_RPCB_TIMEOUT, &rpc_totout_old); __rpc_control(CLCR_SET_RPCB_TIMEOUT, &rpc_totout_new); /* * First try circuit, then drop back to datagram if * circuit is unavailable (an old version of mountd perhaps) * Using circuit is preferred because it can handle * arbitrarily long export lists. */ cl = clnt_create(host, MOUNTPROG, MOUNTVERS, "circuit_n"); if (cl == NULL) { if (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED) cl = clnt_create(host, MOUNTPROG, MOUNTVERS, "datagram_n"); if (cl == NULL) { pr_err(""); clnt_pcreateerror(host); __rpc_control(CLCR_SET_RPCB_TIMEOUT, &rpc_totout_old); exit(1); } } __rpc_control(CLCR_SET_RPCB_TIMEOUT, &rpc_totout_old); if (eflg) { printex(cl, host); if (aflg + dflg == 0) { exit(0); } } tout.tv_sec = 10; tout.tv_usec = 0; if (err = clnt_call(cl, MOUNTPROC_DUMP, xdr_void, 0, xdr_mountlist, (caddr_t)&result_list, tout)) { pr_err("%s\n", clnt_sperrno(err)); exit(1); } /* * Count the number of entries in the list. If the list is empty, * quit now. */ numentries = 0; for (ml = result_list; ml != NULL; ml = ml->ml_next) numentries++; if (numentries == 0) exit(0); /* * Allocate memory for the array and initialize the array. */ table = (struct mountbody **)calloc(numentries, sizeof (struct mountbody *)); if (table == NULL) { pr_err(gettext("not enough memory for %d entries\n"), numentries); exit(1); } for (ml = result_list, tb = &table[0]; ml != NULL; ml = ml->ml_next, tb++) { *tb = ml; } /* * Sort the entries and print the results. */ if (dflg) qsort(table, numentries, sizeof (struct mountbody *), sortpath); else qsort(table, numentries, sizeof (struct mountbody *), sorthost); if (aflg) { for (tb = table; tb < table + numentries; tb++) printf("%s:%s\n", (*tb)->ml_hostname, (*tb)->ml_directory); } else if (dflg) { last = ""; for (tb = table; tb < table + numentries; tb++) { if (strcmp(last, (*tb)->ml_directory)) printf("%s\n", (*tb)->ml_directory); last = (*tb)->ml_directory; } } else { last = ""; for (tb = table; tb < table + numentries; tb++) { if (strcmp(last, (*tb)->ml_hostname)) printf("%s\n", (*tb)->ml_hostname); last = (*tb)->ml_hostname; } } return (0); } sorthost(a, b) struct mountbody **a, **b; { return (strcmp((*a)->ml_hostname, (*b)->ml_hostname)); } sortpath(a, b) struct mountbody **a, **b; { return (strcmp((*a)->ml_directory, (*b)->ml_directory)); } void usage() { (void) fprintf(stderr, gettext("Usage: showmount [-a] [-d] [-e] [host]\n")); } void pr_err(char *fmt, ...) { va_list ap; va_start(ap, fmt); (void) fprintf(stderr, "showmount: "); (void) vfprintf(stderr, fmt, ap); va_end(ap); } void printex(cl, host) CLIENT *cl; char *host; { struct exportnode *ex = NULL; struct exportnode *e; struct groupnode *gr; enum clnt_stat err; int max; struct timeval tout; tout.tv_sec = 10; tout.tv_usec = 0; if (err = clnt_call(cl, MOUNTPROC_EXPORT, xdr_void, 0, xdr_exports, (caddr_t) &ex, tout)) { pr_err("%s\n", clnt_sperrno(err)); exit(1); } if (ex == NULL) { printf(gettext("no exported file systems for %s\n"), host); } else { printf(gettext("export list for %s:\n"), host); } max = 0; for (e = ex; e != NULL; e = e->ex_next) { if (strlen(e->ex_dir) > max) { max = strlen(e->ex_dir); } } while (ex) { printf("%-*s ", max, ex->ex_dir); gr = ex->ex_groups; if (gr == NULL) { printf(gettext("(everyone)")); } while (gr) { printf("%s", gr->gr_name); gr = gr->gr_next; if (gr) { printf(","); } } printf("\n"); ex = ex->ex_next; } }