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