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