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