8fb58a2c2e1c13c6936a8cdfea9b64b785d56ece
[nfs-utils.git] / utils / showmount / showmount.c
1 /*
2  * showmount.c -- show mount information for an NFS server
3  * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
4  *
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)
8  * any later version.
9  *
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.
14  */
15
16 #ifdef HAVE_CONFIG_H
17 #include <config.h>
18 #endif
19
20 #include <stdio.h>
21 #include <rpc/rpc.h>
22 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <sys/time.h>
25 #include <string.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28 #include <memory.h>
29 #include <stdlib.h>
30
31 #include <netdb.h>
32 #include <arpa/inet.h>
33 #include <errno.h>
34 #include <getopt.h>
35 #include <mount.h>
36 #include <unistd.h>
37
38 static char *   version = "showmount for " VERSION;
39 static char *   program_name;
40 static int      headers = 1;
41 static int      hflag = 0;
42 static int      aflag = 0;
43 static int      dflag = 0;
44 static int      eflag = 0;
45
46 static struct option longopts[] =
47 {
48         { "all", 0, 0, 'a' },
49         { "directories", 0, 0, 'd' },
50         { "exports", 0, 0, 'e' },
51         { "no-headers", 0, &headers, 0 },
52         { "version", 0, 0, 'v' },
53         { "help", 0, 0, 'h' },
54         { NULL, 0, 0, 0 }
55 };
56
57 #define MAXHOSTLEN 256
58
59 int dump_cmp(p, q)
60 char **p;
61 char **q;
62 {
63         return strcmp(*p, *q);
64 }
65
66 static void usage(fp, n)
67 FILE *fp;
68 int n;
69 {
70         fprintf(fp, "Usage: %s [-adehv]\n", program_name);
71         fprintf(fp, "       [--all] [--directories] [--exports]\n");
72         fprintf(fp, "       [--no-headers] [--help] [--version] [host]\n");
73         exit(n);
74 }
75
76 int main(argc, argv)
77 int argc;
78 char **argv;
79 {
80         char hostname_buf[MAXHOSTLEN];
81         char *hostname;
82         enum clnt_stat clnt_stat;
83         struct hostent *hp;
84         struct sockaddr_in server_addr;
85         int msock;
86         struct timeval total_timeout;
87         struct timeval pertry_timeout;
88         int c;
89         CLIENT *mclient;
90         groups grouplist;
91         exports exportlist, exl;
92         mountlist dumplist;
93         mountlist list;
94         int i;
95         int n;
96         int maxlen;
97         char **dumpv;
98
99         program_name = argv[0];
100         while ((c = getopt_long(argc, argv, "adehv", longopts, NULL)) != EOF) {
101                 switch (c) {
102                 case 'a':
103                         aflag = 1;
104                         break;
105                 case 'd':
106                         dflag = 1;
107                         break;
108                 case 'e':
109                         eflag = 1;
110                         break;
111                 case 'h':
112                         usage(stdout, 0);
113                         break;
114                 case 'v':
115                         printf("%s\n", version);
116                         exit(0);
117                 case 0:
118                         break;
119                 case '?':
120                 default:
121                         usage(stderr, 1);
122                         break;
123                 }
124         }
125         argc -= optind;
126         argv += optind;
127
128         switch (aflag + dflag + eflag) {
129         case 0:
130                 hflag = 1;
131                 break;
132         case 1:
133                 break;
134         default:
135                 fprintf(stderr, "%s: only one of -a, -d or -e is allowed\n",
136                         program_name);
137                 exit(1);
138                 break;
139         }
140
141         switch (argc) {
142         case 0:
143                 if (gethostname(hostname_buf, MAXHOSTLEN) < 0) {
144                         perror("getting hostname");
145                         exit(1);
146                 }
147                 hostname = hostname_buf;
148                 break;
149         case 1:
150                 hostname = argv[0];
151                 break;
152         default:
153                 fprintf(stderr, "%s: only one hostname is allowed\n",
154                         program_name);
155                 exit(1);
156                 break;
157         }
158
159         if (inet_aton(hostname, &server_addr.sin_addr)) {
160                 server_addr.sin_family = AF_INET;
161         }
162         else {
163                 if ((hp = gethostbyname(hostname)) == NULL) {
164                         fprintf(stderr, "%s: can't get address for %s\n",
165                                 program_name, hostname);
166                         exit(1);
167                 }
168                 server_addr.sin_family = AF_INET;
169                 memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length);
170         }
171
172         /* create mount deamon client */
173
174         server_addr.sin_port = 0;
175         msock = RPC_ANYSOCK;
176         if ((mclient = clnttcp_create(&server_addr,
177             MOUNTPROG, MOUNTVERS, &msock, 0, 0)) == NULL) {
178                 server_addr.sin_port = 0;
179                 msock = RPC_ANYSOCK;
180                 pertry_timeout.tv_sec = 3;
181                 pertry_timeout.tv_usec = 0;
182                 if ((mclient = clntudp_create(&server_addr,
183                     MOUNTPROG, MOUNTVERS, pertry_timeout, &msock)) == NULL) {
184                         clnt_pcreateerror("mount clntudp_create");
185                         exit(1);
186                 }
187         }
188         mclient->cl_auth = authunix_create_default();
189         total_timeout.tv_sec = 20;
190         total_timeout.tv_usec = 0;
191
192         if (eflag) {
193                 memset(&exportlist, '\0', sizeof(exportlist));
194                 clnt_stat = clnt_call(mclient, MOUNTPROC_EXPORT,
195                         (xdrproc_t) xdr_void, NULL,
196                         (xdrproc_t) xdr_exports, (caddr_t) &exportlist,
197                         total_timeout);
198                 if (clnt_stat != RPC_SUCCESS) {
199                         clnt_perror(mclient, "rpc mount export");
200                         exit(1);
201                 }
202                 if (headers)
203                         printf("Export list for %s:\n", hostname);
204                 maxlen = 0;
205                 for (exl = exportlist; exl; exl = exl->ex_next) {
206                         if ((n = strlen(exl->ex_dir)) > maxlen)
207                                 maxlen = n;
208                 }
209                 while (exportlist) {
210                         printf("%-*s ", maxlen, exportlist->ex_dir);
211                         grouplist = exportlist->ex_groups;
212                         if (grouplist)
213                                 while (grouplist) {
214                                         printf("%s%s", grouplist->gr_name,
215                                                 grouplist->gr_next ? "," : "");
216                                         grouplist = grouplist->gr_next;
217                                 }
218                         else
219                                 printf("(everyone)");
220                         printf("\n");
221                         exportlist = exportlist->ex_next;
222                 }
223                 exit(0);
224         }
225
226         memset(&dumplist, '\0', sizeof(dumplist));
227         clnt_stat = clnt_call(mclient, MOUNTPROC_DUMP,
228                 (xdrproc_t) xdr_void, NULL,
229                 (xdrproc_t) xdr_mountlist, (caddr_t) &dumplist,
230                 total_timeout);
231         if (clnt_stat != RPC_SUCCESS) {
232                 clnt_perror(mclient, "rpc mount dump");
233                 exit(1);
234         }
235
236         n = 0;
237         for (list = dumplist; list; list = list->ml_next)
238                 n++;
239         dumpv = (char **) calloc(n, sizeof (char *));
240         if (n && !dumpv) {
241                 fprintf(stderr, "%s: out of memory\n", program_name);
242                 exit(1);
243         }
244         i = 0;
245
246         if (hflag) {
247                 if (headers)
248                         printf("Hosts on %s:\n", hostname);
249                 while (dumplist) {
250                         dumpv[i++] = dumplist->ml_hostname;
251                         dumplist = dumplist->ml_next;
252                 }
253         }
254         else if (aflag) {
255                 if (headers)
256                         printf("All mount points on %s:\n", hostname);
257                 while (dumplist) {
258                         char *t;
259
260                         t=malloc(strlen(dumplist->ml_hostname)+strlen(dumplist->ml_directory)+2);
261                         if (!t)
262                         {
263                                 fprintf(stderr, "%s: out of memory\n", program_name);
264                                 exit(1);
265                         }
266                         sprintf(t, "%s:%s", dumplist->ml_hostname, dumplist->ml_directory);
267                         dumpv[i++] = t;
268                         dumplist = dumplist->ml_next;
269                 }
270         }
271         else if (dflag) {
272                 if (headers)
273                         printf("Directories on %s:\n", hostname);
274                 while (dumplist) {
275                         dumpv[i++] = dumplist->ml_directory;
276                         dumplist = dumplist->ml_next;
277                 }
278         }
279
280         qsort(dumpv, n, sizeof (char *), dump_cmp);
281         
282         for (i = 0; i < n; i++) {
283                 if (i == 0 || strcmp(dumpv[i], dumpv[i - 1]) != 0)
284                         printf("%s\n", dumpv[i]);
285         }
286         exit(0);
287 }
288