2 * showmount.c -- show mount information for an NFS server
3 * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
22 #include <rpc/pmap_prot.h>
23 #include <sys/socket.h>
24 #include <netinet/in.h>
27 #include <sys/types.h>
34 #include <arpa/inet.h>
43 #define TOTAL_TIMEOUT 20
45 static char * version = "showmount for " VERSION;
46 static char * program_name;
47 static int headers = 1;
53 static struct option longopts[] =
56 { "directories", 0, 0, 'd' },
57 { "exports", 0, 0, 'e' },
58 { "no-headers", 0, &headers, 0 },
59 { "version", 0, 0, 'v' },
60 { "help", 0, 0, 'h' },
64 #define MAXHOSTLEN 256
66 static int dump_cmp(const void *pv, const void *qv)
68 const char **p = (const char **)pv;
69 const char **q = (const char **)qv;
70 return strcmp(*p, *q);
73 static void usage(FILE *fp, int n)
75 fprintf(fp, "Usage: %s [-adehv]\n", program_name);
76 fprintf(fp, " [--all] [--directories] [--exports]\n");
77 fprintf(fp, " [--no-headers] [--help] [--version] [host]\n");
81 static const char *mount_pgm_tbl[] = {
88 static const rpcvers_t mount_vers_tbl[] = {
93 static const unsigned int max_vers_tblsz =
94 (sizeof(mount_vers_tbl)/sizeof(mount_vers_tbl[0]));
97 * Generate an RPC client handle connected to the mountd service
98 * at @hostname, or die trying.
100 * Supports both AF_INET and AF_INET6 server addresses.
102 static CLIENT *nfs_get_mount_client(const char *hostname, rpcvers_t vers)
104 rpcprog_t program = nfs_getrpcbyname(MOUNTPROG, mount_pgm_tbl);
107 client = clnt_create(hostname, program, vers, "tcp");
110 client = clnt_create(hostname, program, vers, "udp");
114 clnt_pcreateerror("clnt_create");
118 int main(int argc, char **argv)
120 char hostname_buf[MAXHOSTLEN];
122 enum clnt_stat clnt_stat;
123 struct timeval total_timeout;
127 exports exportlist, exl;
136 program_name = argv[0];
137 while ((c = getopt_long(argc, argv, "adehv", longopts, NULL)) != EOF) {
152 printf("%s\n", version);
165 switch (aflag + dflag + eflag) {
172 fprintf(stderr, "%s: only one of -a, -d or -e is allowed\n",
180 if (gethostname(hostname_buf, MAXHOSTLEN) < 0) {
181 perror("getting hostname");
184 hostname = hostname_buf;
190 fprintf(stderr, "%s: only one hostname is allowed\n",
196 mclient = nfs_get_mount_client(hostname, mount_vers_tbl[vers]);
197 mclient->cl_auth = nfs_authsys_create();
198 if (mclient->cl_auth == NULL) {
199 fprintf(stderr, "%s: unable to create RPC auth handle.\n",
201 clnt_destroy(mclient);
204 total_timeout.tv_sec = TOTAL_TIMEOUT;
205 total_timeout.tv_usec = 0;
209 memset(&exportlist, '\0', sizeof(exportlist));
211 clnt_stat = clnt_call(mclient, MOUNTPROC_EXPORT,
212 (xdrproc_t) xdr_void, NULL,
213 (xdrproc_t) xdr_exports, (caddr_t) &exportlist,
215 if (clnt_stat == RPC_PROGVERSMISMATCH) {
216 if (++vers < max_vers_tblsz) {
217 (void)CLNT_CONTROL(mclient, CLSET_VERS,
218 (void *)&mount_vers_tbl[vers]);
222 if (clnt_stat != RPC_SUCCESS) {
223 clnt_perror(mclient, "rpc mount export");
224 clnt_destroy(mclient);
228 printf("Export list for %s:\n", hostname);
230 for (exl = exportlist; exl; exl = exl->ex_next) {
231 if ((n = strlen(exl->ex_dir)) > maxlen)
235 printf("%-*s ", maxlen, exportlist->ex_dir);
236 grouplist = exportlist->ex_groups;
239 printf("%s%s", grouplist->gr_name,
240 grouplist->gr_next ? "," : "");
241 grouplist = grouplist->gr_next;
244 printf("(everyone)");
246 exportlist = exportlist->ex_next;
248 clnt_destroy(mclient);
252 memset(&dumplist, '\0', sizeof(dumplist));
253 clnt_stat = clnt_call(mclient, MOUNTPROC_DUMP,
254 (xdrproc_t) xdr_void, NULL,
255 (xdrproc_t) xdr_mountlist, (caddr_t) &dumplist,
257 if (clnt_stat == RPC_PROGVERSMISMATCH) {
258 if (++vers < max_vers_tblsz) {
259 (void)CLNT_CONTROL(mclient, CLSET_VERS,
260 (void *)&mount_vers_tbl[vers]);
264 if (clnt_stat != RPC_SUCCESS) {
265 clnt_perror(mclient, "rpc mount dump");
266 clnt_destroy(mclient);
269 clnt_destroy(mclient);
272 for (list = dumplist; list; list = list->ml_next)
274 dumpv = (char **) calloc(n, sizeof (char *));
276 fprintf(stderr, "%s: out of memory\n", program_name);
283 printf("Hosts on %s:\n", hostname);
285 dumpv[i++] = dumplist->ml_hostname;
286 dumplist = dumplist->ml_next;
291 printf("All mount points on %s:\n", hostname);
295 t=malloc(strlen(dumplist->ml_hostname)+strlen(dumplist->ml_directory)+2);
298 fprintf(stderr, "%s: out of memory\n", program_name);
301 sprintf(t, "%s:%s", dumplist->ml_hostname, dumplist->ml_directory);
303 dumplist = dumplist->ml_next;
308 printf("Directories on %s:\n", hostname);
310 dumpv[i++] = dumplist->ml_directory;
311 dumplist = dumplist->ml_next;
315 qsort(dumpv, n, sizeof (char *), dump_cmp);
317 for (i = 0; i < n; i++) {
318 if (i == 0 || strcmp(dumpv[i], dumpv[i - 1]) != 0)
319 printf("%s\n", dumpv[i]);