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