Remove some unneeded semicolons across the tree.
[dragonfly.git] / usr.bin / showmount / showmount.c
1 /*
2  * Copyright (c) 1989, 1993, 1995
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Rick Macklem at The University of Guelph.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by the University of
19  *      California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * @(#) Copyright (c) 1989, 1993, 1995 The Regents of the University of California.  All rights reserved.
37  * @(#)showmount.c      8.3 (Berkeley) 3/29/95
38  * $FreeBSD: src/usr.bin/showmount/showmount.c,v 1.16 2005/05/21 09:55:08 ru Exp $
39  */
40
41 #include <sys/types.h>
42 #include <sys/queue.h>
43 #include <sys/file.h>
44 #include <sys/socket.h>
45 #include <sys/socketvar.h>
46
47 #include <err.h>
48 #include <netdb.h>
49 #include <rpc/rpc.h>
50 #include <rpc/pmap_clnt.h>
51 #include <rpc/pmap_prot.h>
52 #include <nfs/rpcv2.h>
53
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <unistd.h>
58
59 /* Constant defs */
60 #define ALL     1
61 #define DIRS    2
62
63 #define DODUMP          0x1
64 #define DOEXPORTS       0x2
65
66 struct mountlist {
67         struct mountlist *ml_left;
68         struct mountlist *ml_right;
69         char    ml_host[RPCMNT_NAMELEN+1];
70         char    ml_dirp[RPCMNT_PATHLEN+1];
71 };
72
73 struct grouplist {
74         struct grouplist *gr_next;
75         char    gr_name[RPCMNT_NAMELEN+1];
76 };
77
78 struct exportslist {
79         struct exportslist *ex_next;
80         struct grouplist *ex_groups;
81         char    ex_dirp[RPCMNT_PATHLEN+1];
82 };
83
84 static struct mountlist *mntdump;
85 static struct exportslist *exports;
86 static int type = 0;
87
88 void print_dump(struct mountlist *);
89 static void usage(void);
90 int xdr_mntdump(XDR *, struct mountlist **);
91 int xdr_exports(XDR *, struct exportslist **);
92 int tcp_callrpc(const char *, int, int, int, xdrproc_t, char *, xdrproc_t,
93                 char *);
94
95 /*
96  * This command queries the NFS mount daemon for it's mount list and/or
97  * it's exports list and prints them out.
98  * See "NFS: Network File System Protocol Specification, RFC1094, Appendix A"
99  * and the "Network File System Protocol XXX.."
100  * for detailed information on the protocol.
101  */
102 int
103 main(int argc, char **argv)
104 {
105         struct exportslist *exp;
106         struct grouplist *grp;
107         int rpcs = 0, mntvers = 1;
108         const char *host;
109         int ch, estat;
110
111         while ((ch = getopt(argc, argv, "ade3")) != -1)
112                 switch (ch) {
113                 case 'a':
114                         if (type == 0) {
115                                 type = ALL;
116                                 rpcs |= DODUMP;
117                         } else
118                                 usage();
119                         break;
120                 case 'd':
121                         if (type == 0) {
122                                 type = DIRS;
123                                 rpcs |= DODUMP;
124                         } else
125                                 usage();
126                         break;
127                 case 'e':
128                         rpcs |= DOEXPORTS;
129                         break;
130                 case '3':
131                         mntvers = 3;
132                         break;
133                 case '?':
134                 default:
135                         usage();
136                 }
137         argc -= optind;
138         argv += optind;
139
140         if (argc > 0)
141                 host = *argv;
142         else
143                 host = "localhost";
144
145         if (rpcs == 0)
146                 rpcs = DODUMP;
147
148         if (rpcs & DODUMP)
149                 if ((estat = tcp_callrpc(host, RPCPROG_MNT, mntvers,
150                         RPCMNT_DUMP, (xdrproc_t)xdr_void, NULL,
151                         (xdrproc_t)xdr_mntdump, (char *)&mntdump)) != 0) {
152                         clnt_perrno(estat);
153                         errx(1, "can't do mountdump rpc");
154                 }
155         if (rpcs & DOEXPORTS)
156                 if ((estat = tcp_callrpc(host, RPCPROG_MNT, mntvers,
157                         RPCMNT_EXPORT, (xdrproc_t)xdr_void, NULL,
158                         (xdrproc_t)xdr_exports, (char *)&exports)) != 0) {
159                         clnt_perrno(estat);
160                         errx(1, "can't do exports rpc");
161                 }
162
163         /* Now just print out the results */
164         if (rpcs & DODUMP) {
165                 switch (type) {
166                 case ALL:
167                         printf("All mount points on %s:\n", host);
168                         break;
169                 case DIRS:
170                         printf("Directories on %s:\n", host);
171                         break;
172                 default:
173                         printf("Hosts on %s:\n", host);
174                         break;
175                 }
176                 print_dump(mntdump);
177         }
178         if (rpcs & DOEXPORTS) {
179                 printf("Exports list on %s:\n", host);
180                 exp = exports;
181                 while (exp) {
182                         printf("%-35s", exp->ex_dirp);
183                         grp = exp->ex_groups;
184                         if (grp == NULL) {
185                                 printf("Everyone\n");
186                         } else {
187                                 while (grp) {
188                                         printf("%s ", grp->gr_name);
189                                         grp = grp->gr_next;
190                                 }
191                                 printf("\n");
192                         }
193                         exp = exp->ex_next;
194                 }
195         }
196         exit(0);
197 }
198
199 /*
200  * tcp_callrpc has the same interface as callrpc, but tries to
201  * use tcp as transport method in order to handle large replies.
202  */
203 int
204 tcp_callrpc(const char *host, int prognum, int versnum, int procnum,
205             xdrproc_t inproc, char *in, xdrproc_t outproc, char *out)
206 {
207         CLIENT *client;
208         struct timeval timeout;
209         int rval;
210
211         if ((client = clnt_create(host, prognum, versnum, "tcp")) == NULL &&
212             (client = clnt_create(host, prognum, versnum, "udp")) == NULL)
213                 return ((int) rpc_createerr.cf_stat);
214
215         timeout.tv_sec = 25;
216         timeout.tv_usec = 0;
217         rval = (int) clnt_call(client, procnum,
218                                inproc, in,
219                                outproc, out,
220                                timeout);
221         clnt_destroy(client);
222         return rval;
223 }
224
225 /*
226  * Xdr routine for retrieving the mount dump list
227  */
228 int
229 xdr_mntdump(XDR *xdrsp, struct mountlist **mlp)
230 {
231         struct mountlist *mp;
232         struct mountlist *tp;
233         struct mountlist **otp = NULL;
234         int val, val2;
235         int bool;
236         char *strp;
237
238         *mlp = NULL;
239         if (!xdr_bool(xdrsp, &bool))
240                 return (0);
241         while (bool) {
242                 mp = (struct mountlist *)malloc(sizeof(struct mountlist));
243                 if (mp == NULL)
244                         return (0);
245                 mp->ml_left = mp->ml_right = NULL;
246                 strp = mp->ml_host;
247                 if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN))
248                         return (0);
249                 strp = mp->ml_dirp;
250                 if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))
251                         return (0);
252
253                 /*
254                  * Build a binary tree on sorted order of either host or dirp.
255                  * Drop any duplications.
256                  */
257                 if (*mlp == NULL) {
258                         *mlp = mp;
259                 } else {
260                         tp = *mlp;
261                         while (tp) {
262                                 val = strcmp(mp->ml_host, tp->ml_host);
263                                 val2 = strcmp(mp->ml_dirp, tp->ml_dirp);
264                                 switch (type) {
265                                 case ALL:
266                                         if (val == 0) {
267                                                 if (val2 == 0) {
268                                                         free(mp);
269                                                         goto next;
270                                                 }
271                                                 val = val2;
272                                         }
273                                         break;
274                                 case DIRS:
275                                         if (val2 == 0) {
276                                                 free(mp);
277                                                 goto next;
278                                         }
279                                         val = val2;
280                                         break;
281                                 default:
282                                         if (val == 0) {
283                                                 free(mp);
284                                                 goto next;
285                                         }
286                                         break;
287                                 }
288                                 if (val < 0) {
289                                         otp = &tp->ml_left;
290                                         tp = tp->ml_left;
291                                 } else {
292                                         otp = &tp->ml_right;
293                                         tp = tp->ml_right;
294                                 }
295                         }
296                         *otp = mp;
297                 }
298 next:
299                 if (!xdr_bool(xdrsp, &bool))
300                         return (0);
301         }
302         return (1);
303 }
304
305 /*
306  * Xdr routine to retrieve exports list
307  */
308 int
309 xdr_exports(XDR *xdrsp, struct exportslist **exp)
310 {
311         struct exportslist *ep;
312         struct grouplist *gp;
313         int bool, grpbool;
314         char *strp;
315
316         *exp = NULL;
317         if (!xdr_bool(xdrsp, &bool))
318                 return (0);
319         while (bool) {
320                 ep = (struct exportslist *)malloc(sizeof(struct exportslist));
321                 if (ep == NULL)
322                         return (0);
323                 ep->ex_groups = NULL;
324                 strp = ep->ex_dirp;
325                 if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))
326                         return (0);
327                 if (!xdr_bool(xdrsp, &grpbool))
328                         return (0);
329                 while (grpbool) {
330                         gp = (struct grouplist *)malloc(sizeof(struct grouplist));
331                         if (gp == NULL)
332                                 return (0);
333                         strp = gp->gr_name;
334                         if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN))
335                                 return (0);
336                         gp->gr_next = ep->ex_groups;
337                         ep->ex_groups = gp;
338                         if (!xdr_bool(xdrsp, &grpbool))
339                                 return (0);
340                 }
341                 ep->ex_next = *exp;
342                 *exp = ep;
343                 if (!xdr_bool(xdrsp, &bool))
344                         return (0);
345         }
346         return (1);
347 }
348
349 static void
350 usage(void)
351 {
352         fprintf(stderr, "usage: showmount [-a | -d] [-e3] [host]\n");
353         exit(1);
354 }
355
356 /*
357  * Print the binary tree in inorder so that output is sorted.
358  */
359 void
360 print_dump(struct mountlist *mp)
361 {
362
363         if (mp == NULL)
364                 return;
365         if (mp->ml_left)
366                 print_dump(mp->ml_left);
367         switch (type) {
368         case ALL:
369                 printf("%s:%s\n", mp->ml_host, mp->ml_dirp);
370                 break;
371         case DIRS:
372                 printf("%s\n", mp->ml_dirp);
373                 break;
374         default:
375                 printf("%s\n", mp->ml_host);
376                 break;
377         }
378         if (mp->ml_right)
379                 print_dump(mp->ml_right);
380 }