xref: /freebsd/usr.bin/showmount/showmount.c (revision ce834215a70ff69e7e222827437116eee2f9ac6f)
1 /*
2  * Copyright (c) 1989, 1993
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 
37 #ifndef lint
38 static char copyright[] =
39 "@(#) Copyright (c) 1989, 1993\n\
40 	The Regents of the University of California.  All rights reserved.\n";
41 #endif not lint
42 
43 #ifndef lint
44 static char sccsid[] = "@(#)showmount.c	8.1 (Berkeley) 6/6/93";
45 #endif not lint
46 
47 #include <sys/types.h>
48 #include <sys/queue.h>
49 #include <sys/file.h>
50 #include <sys/socket.h>
51 #include <sys/socketvar.h>
52 #include <netdb.h>
53 #include <rpc/rpc.h>
54 #include <rpc/pmap_clnt.h>
55 #include <rpc/pmap_prot.h>
56 #include <nfs/rpcv2.h>
57 #include <stdio.h>
58 #include <string.h>
59 
60 /* Constant defs */
61 #define	ALL	1
62 #define	DIRS	2
63 
64 #define	DODUMP		0x1
65 #define	DOEXPORTS	0x2
66 
67 struct mountlist {
68 	struct mountlist *ml_left;
69 	struct mountlist *ml_right;
70 	char	ml_host[RPCMNT_NAMELEN+1];
71 	char	ml_dirp[RPCMNT_PATHLEN+1];
72 };
73 
74 struct grouplist {
75 	struct grouplist *gr_next;
76 	char	gr_name[RPCMNT_NAMELEN+1];
77 };
78 
79 struct exportslist {
80 	struct exportslist *ex_next;
81 	struct grouplist *ex_groups;
82 	char	ex_dirp[RPCMNT_PATHLEN+1];
83 };
84 
85 static struct mountlist *mntdump;
86 static struct exportslist *exports;
87 static int type = 0;
88 int xdr_mntdump(), xdr_exports();
89 
90 /*
91  * This command queries the NFS mount daemon for it's mount list and/or
92  * it's exports list and prints them out.
93  * See "NFS: Network File System Protocol Specification, RFC1094, Appendix A"
94  * and the "Network File System Protocol XXX.."
95  * for detailed information on the protocol.
96  */
97 main(argc, argv)
98 	int argc;
99 	char **argv;
100 {
101 	register struct mountlist *mntp;
102 	register struct exportslist *exp;
103 	register struct grouplist *grp;
104 	extern char *optarg;
105 	extern int optind;
106 	register int rpcs = 0, mntvers = 1;
107 	char ch;
108 	char *host;
109 	int estat;
110 
111 	while ((ch = getopt(argc, argv, "ade3")) != -1)
112 		switch((char)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 = callrpc(host, RPCPROG_MNT, mntvers,
150 			RPCMNT_DUMP, xdr_void, (char *)0,
151 			xdr_mntdump, (char *)&mntdump)) != 0) {
152 			clnt_perrno(estat);
153 			fprintf(stderr, "Can't do Mountdump rpc\n");
154 			exit(1);
155 		}
156 	if (rpcs & DOEXPORTS)
157 		if ((estat = callrpc(host, RPCPROG_MNT, mntvers,
158 			RPCMNT_EXPORT, xdr_void, (char *)0,
159 			xdr_exports, (char *)&exports)) != 0) {
160 			clnt_perrno(estat);
161 			fprintf(stderr, "Can't do Exports rpc\n");
162 			exit(1);
163 		}
164 
165 	/* Now just print out the results */
166 	if (rpcs & DODUMP) {
167 		switch (type) {
168 		case ALL:
169 			printf("All mount points on %s:\n", host);
170 			break;
171 		case DIRS:
172 			printf("Directories on %s:\n", host);
173 			break;
174 		default:
175 			printf("Hosts on %s:\n", host);
176 			break;
177 		};
178 		print_dump(mntdump);
179 	}
180 	if (rpcs & DOEXPORTS) {
181 		printf("Exports list on %s:\n", host);
182 		exp = exports;
183 		while (exp) {
184 			printf("%-35s", exp->ex_dirp);
185 			grp = exp->ex_groups;
186 			if (grp == NULL) {
187 				printf("Everyone\n");
188 			} else {
189 				while (grp) {
190 					printf("%s ", grp->gr_name);
191 					grp = grp->gr_next;
192 				}
193 				printf("\n");
194 			}
195 			exp = exp->ex_next;
196 		}
197 	}
198 }
199 
200 /*
201  * Xdr routine for retrieving the mount dump list
202  */
203 xdr_mntdump(xdrsp, mlp)
204 	XDR *xdrsp;
205 	struct mountlist **mlp;
206 {
207 	register struct mountlist *mp;
208 	register struct mountlist *tp;
209 	register struct mountlist **otp;
210 	int val, val2;
211 	int bool;
212 	char *strp;
213 
214 	*mlp = (struct mountlist *)0;
215 	if (!xdr_bool(xdrsp, &bool))
216 		return (0);
217 	while (bool) {
218 		mp = (struct mountlist *)malloc(sizeof(struct mountlist));
219 		if (mp == NULL)
220 			return (0);
221 		mp->ml_left = mp->ml_right = (struct mountlist *)0;
222 		strp = mp->ml_host;
223 		if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN))
224 			return (0);
225 		strp = mp->ml_dirp;
226 		if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))
227 			return (0);
228 
229 		/*
230 		 * Build a binary tree on sorted order of either host or dirp.
231 		 * Drop any duplications.
232 		 */
233 		if (*mlp == NULL) {
234 			*mlp = mp;
235 		} else {
236 			tp = *mlp;
237 			while (tp) {
238 				val = strcmp(mp->ml_host, tp->ml_host);
239 				val2 = strcmp(mp->ml_dirp, tp->ml_dirp);
240 				switch (type) {
241 				case ALL:
242 					if (val == 0) {
243 						if (val2 == 0) {
244 							free((caddr_t)mp);
245 							goto next;
246 						}
247 						val = val2;
248 					}
249 					break;
250 				case DIRS:
251 					if (val2 == 0) {
252 						free((caddr_t)mp);
253 						goto next;
254 					}
255 					val = val2;
256 					break;
257 				default:
258 					if (val == 0) {
259 						free((caddr_t)mp);
260 						goto next;
261 					}
262 					break;
263 				};
264 				if (val < 0) {
265 					otp = &tp->ml_left;
266 					tp = tp->ml_left;
267 				} else {
268 					otp = &tp->ml_right;
269 					tp = tp->ml_right;
270 				}
271 			}
272 			*otp = mp;
273 		}
274 next:
275 		if (!xdr_bool(xdrsp, &bool))
276 			return (0);
277 	}
278 	return (1);
279 }
280 
281 /*
282  * Xdr routine to retrieve exports list
283  */
284 xdr_exports(xdrsp, exp)
285 	XDR *xdrsp;
286 	struct exportslist **exp;
287 {
288 	register struct exportslist *ep;
289 	register struct grouplist *gp;
290 	int bool, grpbool;
291 	char *strp;
292 
293 	*exp = (struct exportslist *)0;
294 	if (!xdr_bool(xdrsp, &bool))
295 		return (0);
296 	while (bool) {
297 		ep = (struct exportslist *)malloc(sizeof(struct exportslist));
298 		if (ep == NULL)
299 			return (0);
300 		ep->ex_groups = (struct grouplist *)0;
301 		strp = ep->ex_dirp;
302 		if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))
303 			return (0);
304 		if (!xdr_bool(xdrsp, &grpbool))
305 			return (0);
306 		while (grpbool) {
307 			gp = (struct grouplist *)malloc(sizeof(struct grouplist));
308 			if (gp == NULL)
309 				return (0);
310 			strp = gp->gr_name;
311 			if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN))
312 				return (0);
313 			gp->gr_next = ep->ex_groups;
314 			ep->ex_groups = gp;
315 			if (!xdr_bool(xdrsp, &grpbool))
316 				return (0);
317 		}
318 		ep->ex_next = *exp;
319 		*exp = ep;
320 		if (!xdr_bool(xdrsp, &bool))
321 			return (0);
322 	}
323 	return (1);
324 }
325 
326 usage()
327 {
328 	fprintf(stderr, "usage: showmount [-ade3] host\n");
329 	exit(1);
330 }
331 
332 /*
333  * Print the binary tree in inorder so that output is sorted.
334  */
335 print_dump(mp)
336 	struct mountlist *mp;
337 {
338 
339 	if (mp == NULL)
340 		return;
341 	if (mp->ml_left)
342 		print_dump(mp->ml_left);
343 	switch (type) {
344 	case ALL:
345 		printf("%s:%s\n", mp->ml_host, mp->ml_dirp);
346 		break;
347 	case DIRS:
348 		printf("%s\n", mp->ml_dirp);
349 		break;
350 	default:
351 		printf("%s\n", mp->ml_host);
352 		break;
353 	};
354 	if (mp->ml_right)
355 		print_dump(mp->ml_right);
356 }
357