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