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.2 (Berkeley) 01/28/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 * for detailed information on the protocol. 76 */ 77 int 78 main(argc, argv) 79 int argc; 80 char **argv; 81 { 82 struct exportslist *exp; 83 struct grouplist *grp; 84 int estat, rpcs = 0; 85 char ch, *host; 86 87 while ((ch = getopt(argc, argv, "ade")) != EOF) 88 switch((char)ch) { 89 case 'a': 90 if (type == 0) { 91 type = ALL; 92 rpcs |= DODUMP; 93 } else 94 usage(); 95 break; 96 case 'd': 97 if (type == 0) { 98 type = DIRS; 99 rpcs |= DODUMP; 100 } else 101 usage(); 102 break; 103 case 'e': 104 rpcs |= DOEXPORTS; 105 break; 106 case '?': 107 default: 108 usage(); 109 } 110 argc -= optind; 111 argv += optind; 112 113 if (argc > 0) 114 host = *argv; 115 else 116 host = "localhost"; 117 118 if (rpcs == 0) 119 rpcs = DODUMP; 120 121 if (rpcs & DODUMP) 122 if ((estat = callrpc(host, RPCPROG_MNT, RPCMNT_VER1, 123 RPCMNT_DUMP, xdr_void, (char *)0, 124 xdr_mntdump, (char *)&mntdump)) != 0) { 125 clnt_perrno(estat); 126 fprintf(stderr, ": Can't do Mountdump rpc\n"); 127 exit(1); 128 } 129 if (rpcs & DOEXPORTS) 130 if ((estat = callrpc(host, RPCPROG_MNT, RPCMNT_VER1, 131 RPCMNT_EXPORT, xdr_void, (char *)0, 132 xdr_exports, (char *)&exports)) != 0) { 133 clnt_perrno(estat); 134 fprintf(stderr, ": Can't do Exports rpc\n"); 135 exit(1); 136 } 137 138 /* Now just print out the results */ 139 if (rpcs & DODUMP) { 140 switch (type) { 141 case ALL: 142 printf("All mount points on %s:\n", host); 143 break; 144 case DIRS: 145 printf("Directories on %s:\n", host); 146 break; 147 default: 148 printf("Hosts on %s:\n", host); 149 break; 150 }; 151 print_dump(mntdump); 152 } 153 if (rpcs & DOEXPORTS) { 154 printf("Exports list on %s:\n", host); 155 exp = exports; 156 while (exp) { 157 printf("%-35s", exp->ex_dirp); 158 grp = exp->ex_groups; 159 if (grp == NULL) { 160 printf("Everyone\n"); 161 } else { 162 while (grp) { 163 printf("%s ", grp->gr_name); 164 grp = grp->gr_next; 165 } 166 printf("\n"); 167 } 168 exp = exp->ex_next; 169 } 170 } 171 172 exit(0); 173 } 174 175 /* 176 * Xdr routine for retrieving the mount dump list 177 */ 178 int 179 xdr_mntdump(xdrsp, mlp) 180 XDR *xdrsp; 181 struct mountlist **mlp; 182 { 183 struct mountlist *mp, **otp, *tp; 184 int bool, val, val2; 185 char *strp; 186 187 *mlp = (struct mountlist *)0; 188 if (!xdr_bool(xdrsp, &bool)) 189 return (0); 190 while (bool) { 191 mp = (struct mountlist *)malloc(sizeof(struct mountlist)); 192 if (mp == NULL) 193 return (0); 194 mp->ml_left = mp->ml_right = (struct mountlist *)0; 195 strp = mp->ml_host; 196 if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 197 return (0); 198 strp = mp->ml_dirp; 199 if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 200 return (0); 201 202 /* 203 * Build a binary tree on sorted order of either host or dirp. 204 * Drop any duplications. 205 */ 206 if (*mlp == NULL) { 207 *mlp = mp; 208 } else { 209 tp = *mlp; 210 while (tp) { 211 val = strcmp(mp->ml_host, tp->ml_host); 212 val2 = strcmp(mp->ml_dirp, tp->ml_dirp); 213 switch (type) { 214 case ALL: 215 if (val == 0) { 216 if (val2 == 0) { 217 free((caddr_t)mp); 218 goto next; 219 } 220 val = val2; 221 } 222 break; 223 case DIRS: 224 if (val2 == 0) { 225 free((caddr_t)mp); 226 goto next; 227 } 228 val = val2; 229 break; 230 default: 231 if (val == 0) { 232 free((caddr_t)mp); 233 goto next; 234 } 235 break; 236 }; 237 if (val < 0) { 238 otp = &tp->ml_left; 239 tp = tp->ml_left; 240 } else { 241 otp = &tp->ml_right; 242 tp = tp->ml_right; 243 } 244 } 245 *otp = mp; 246 } 247 next: 248 if (!xdr_bool(xdrsp, &bool)) 249 return (0); 250 } 251 return (1); 252 } 253 254 /* 255 * Xdr routine to retrieve exports list 256 */ 257 int 258 xdr_exports(xdrsp, exp) 259 XDR *xdrsp; 260 struct exportslist **exp; 261 { 262 struct exportslist *ep; 263 struct grouplist *gp; 264 int bool, grpbool; 265 char *strp; 266 267 *exp = (struct exportslist *)0; 268 if (!xdr_bool(xdrsp, &bool)) 269 return (0); 270 while (bool) { 271 ep = (struct exportslist *)malloc(sizeof(struct exportslist)); 272 if (ep == NULL) 273 return (0); 274 ep->ex_groups = (struct grouplist *)0; 275 strp = ep->ex_dirp; 276 if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 277 return (0); 278 if (!xdr_bool(xdrsp, &grpbool)) 279 return (0); 280 while (grpbool) { 281 gp = (struct grouplist *)malloc(sizeof(struct grouplist)); 282 if (gp == NULL) 283 return (0); 284 strp = gp->gr_name; 285 if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 286 return (0); 287 gp->gr_next = ep->ex_groups; 288 ep->ex_groups = gp; 289 if (!xdr_bool(xdrsp, &grpbool)) 290 return (0); 291 } 292 ep->ex_next = *exp; 293 *exp = ep; 294 if (!xdr_bool(xdrsp, &bool)) 295 return (0); 296 } 297 return (1); 298 } 299 300 void 301 usage() 302 { 303 304 fprintf(stderr, "usage: showmount [-ade] host\n"); 305 exit(1); 306 } 307 308 /* 309 * Print the binary tree in inorder so that output is sorted. 310 */ 311 void 312 print_dump(mp) 313 struct mountlist *mp; 314 { 315 316 if (mp == NULL) 317 return; 318 if (mp->ml_left) 319 print_dump(mp->ml_left); 320 switch (type) { 321 case ALL: 322 printf("%s:%s\n", mp->ml_host, mp->ml_dirp); 323 break; 324 case DIRS: 325 printf("%s\n", mp->ml_dirp); 326 break; 327 default: 328 printf("%s\n", mp->ml_host); 329 break; 330 }; 331 if (mp->ml_right) 332 print_dump(mp->ml_right); 333 } 334