1/* 2 * Copyright (c) 1997-2014 Erez Zadok 3 * Copyright (c) 1990 Jan-Simon Pendry 4 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine 5 * Copyright (c) 1990 The Regents of the University of California. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Jan-Simon Pendry at Imperial College, London. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * 36 * File: am-utils/amq/amq.c 37 * 38 */ 39 40/* 41 * Automounter query tool 42 */ 43 44#ifdef HAVE_CONFIG_H 45# include <config.h> 46#endif /* HAVE_CONFIG_H */ 47#include <am_defs.h> 48#include <amq.h> 49 50/* locals */ 51static int flush_flag; 52static int getpid_flag; 53static int getpwd_flag; 54static int getvers_flag; 55static int minfo_flag; 56static int mapinfo_flag; 57static int quiet_flag; 58static int stats_flag; 59static int unmount_flag; 60static int use_tcp_flag; 61static int use_udp_flag; 62static u_long amd_program_number = AMQ_PROGRAM; 63static char *debug_opts; 64static char *amq_logfile; 65static char *xlog_optstr; 66static char localhost[] = "localhost"; 67static char *def_server = localhost; 68 69/* externals */ 70extern int optind; 71extern char *optarg; 72 73/* structures */ 74enum show_opt { 75 Full, Stats, Calc, Short, ShowDone 76}; 77 78 79static void 80time_print(time_type tt) 81{ 82 time_t t = (time_t)(intptr_t)tt; 83 struct tm *tp = localtime(&t); 84 printf("%02d/%02d/%04d %02d:%02d:%02d", 85 tp->tm_mon + 1, tp->tm_mday, 86 tp->tm_year < 1900 ? tp->tm_year + 1900 : tp->tm_year, 87 tp->tm_hour, tp->tm_min, tp->tm_sec); 88} 89 90/* 91 * If (e) is Calc then just calculate the sizes 92 * Otherwise display the mount node on stdout 93 */ 94static void 95show_mti(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *twid) 96{ 97 switch (e) { 98 case Calc: 99 { 100 int mw = strlen(mt->mt_mountinfo); 101 int dw = strlen(mt->mt_directory); 102 int tw = strlen(mt->mt_type); 103 if (mw > *mwid) 104 *mwid = mw; 105 if (dw > *dwid) 106 *dwid = dw; 107 if (tw > *twid) 108 *twid = tw; 109 } 110 break; 111 112 case Full: 113 { 114 printf("%-*.*s %-*.*s %-*.*s %s\n\t%-5d %-7d %-6d %-7d %-7d %-6d", 115 *dwid, *dwid, 116 *mt->mt_directory ? mt->mt_directory : "/", /* XXX */ 117 *twid, *twid, 118 mt->mt_type, 119 *mwid, *mwid, 120 mt->mt_mountinfo, 121 mt->mt_mountpoint, 122 123 mt->mt_mountuid, 124 mt->mt_getattr, 125 mt->mt_lookup, 126 mt->mt_readdir, 127 mt->mt_readlink, 128 mt->mt_statfs); 129 time_print(mt->mt_mounttime); 130 printf("\n"); 131 } 132 break; 133 134 case Stats: 135 { 136 printf("%-*.*s %-5d %-7d %-6d %-7d %-7d %-6d ", 137 *dwid, *dwid, 138 *mt->mt_directory ? mt->mt_directory : "/", /* XXX */ 139 140 mt->mt_mountuid, 141 mt->mt_getattr, 142 mt->mt_lookup, 143 mt->mt_readdir, 144 mt->mt_readlink, 145 mt->mt_statfs); 146 time_print(mt->mt_mounttime); 147 printf("\n"); 148 } 149 break; 150 151 case Short: 152 { 153 printf("%-*.*s %-*.*s %-*.*s %s\n", 154 *dwid, *dwid, 155 *mt->mt_directory ? mt->mt_directory : "/", 156 *twid, *twid, 157 mt->mt_type, 158 *mwid, *mwid, 159 mt->mt_mountinfo, 160 mt->mt_mountpoint); 161 } 162 break; 163 164 default: 165 break; 166 } 167} 168 169 170/* 171 * Display a pwd data 172 */ 173static void 174show_pwd(amq_mount_tree *mt, char *path, size_t l, int *flag) 175{ 176 int len; 177 178 while (mt) { 179 len = strlen(mt->mt_mountpoint); 180 if (NSTREQ(path, mt->mt_mountpoint, len) && 181 !STREQ(mt->mt_directory, mt->mt_mountpoint)) { 182 char buf[MAXPATHLEN+1]; /* must be same size as 'path' */ 183 xstrlcpy(buf, mt->mt_directory, sizeof(buf)); 184 xstrlcat(buf, &path[len], sizeof(buf)); 185 xstrlcpy(path, buf, l); 186 *flag = 1; 187 } 188 show_pwd(mt->mt_next, path, l, flag); 189 mt = mt->mt_child; 190 } 191} 192 193 194/* 195 * Display a mount tree. 196 */ 197static void 198show_mt(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *pwid) 199{ 200 while (mt) { 201 show_mti(mt, e, mwid, dwid, pwid); 202 show_mt(mt->mt_next, e, mwid, dwid, pwid); 203 mt = mt->mt_child; 204 } 205} 206 207 208static void 209show_mi(amq_mount_info_list *ml, enum show_opt e, int *mwid, int *dwid, int *twid) 210{ 211 u_int i; 212 213 switch (e) { 214 215 case Calc: 216 { 217 for (i = 0; i < ml->amq_mount_info_list_len; i++) { 218 amq_mount_info *mi = &ml->amq_mount_info_list_val[i]; 219 int mw = strlen(mi->mi_mountinfo); 220 int dw = strlen(mi->mi_mountpt); 221 int tw = strlen(mi->mi_type); 222 if (mw > *mwid) 223 *mwid = mw; 224 if (dw > *dwid) 225 *dwid = dw; 226 if (tw > *twid) 227 *twid = tw; 228 } 229 } 230 break; 231 232 case Full: 233 { 234 for (i = 0; i < ml->amq_mount_info_list_len; i++) { 235 amq_mount_info *mi = &ml->amq_mount_info_list_val[i]; 236 printf("%-*.*s %-*.*s %-*.*s %-3d %s is %s ", 237 *mwid, *mwid, mi->mi_mountinfo, 238 *dwid, *dwid, mi->mi_mountpt, 239 *twid, *twid, mi->mi_type, 240 mi->mi_refc, mi->mi_fserver, 241 mi->mi_up > 0 ? "up" : 242 mi->mi_up < 0 ? "starting" : "down"); 243 if (mi->mi_error > 0) { 244 printf(" (%s)", strerror(mi->mi_error)); 245 } else if (mi->mi_error < 0) { 246 fputs(" (in progress)", stdout); 247 } 248 fputc('\n', stdout); 249 } 250 } 251 break; 252 253 default: 254 break; 255 } 256} 257 258static void 259show_map(amq_map_info *mi) 260{ 261} 262 263static void 264show_mapinfo(amq_map_info_list *ml, enum show_opt e, int *nwid, int *wwid) 265{ 266 u_int i; 267 268 switch (e) { 269 270 case Calc: 271 { 272 for (i = 0; i < ml->amq_map_info_list_len; i++) { 273 amq_map_info *mi = &ml->amq_map_info_list_val[i]; 274 int nw = strlen(mi->mi_name); 275 int ww = strlen(mi->mi_wildcard ? mi->mi_wildcard : "(null"); 276 if (nw > *nwid) 277 *nwid = nw; 278 if (ww > *wwid) 279 *wwid = ww; 280 } 281 } 282 break; 283 284 case Full: 285 { 286 printf("%-*.*s %-*.*s %-8.8s %-7.7s %-7.7s %-7.7s %-s Modified\n", 287 *nwid, *nwid, "Name", 288 *wwid, *wwid, "Wild", 289 "Flags", "Refcnt", "Entries", "Reloads", "Stat"); 290 for (i = 0; i < ml->amq_map_info_list_len; i++) { 291 amq_map_info *mi = &ml->amq_map_info_list_val[i]; 292 printf("%-*.*s %*.*s %-8x %-7d %-7d %-7d %s ", 293 *nwid, *nwid, mi->mi_name, 294 *wwid, *wwid, mi->mi_wildcard, 295 mi->mi_flags, mi->mi_refc, mi->mi_nentries, mi->mi_reloads, 296 mi->mi_up == -1 ? "root" : (mi->mi_up ? " up" : "down")); 297 time_print(mi->mi_modify); 298 fputc('\n', stdout); 299 } 300 } 301 break; 302 303 default: 304 break; 305 } 306} 307 308/* 309 * Display general mount statistics 310 */ 311static void 312show_ms(amq_mount_stats *ms) 313{ 314 printf("\ 315requests stale mount mount unmount\n\ 316deferred fhandles ok failed failed\n\ 317%-9d %-9d %-9d %-9d %-9d\n", 318 ms->as_drops, ms->as_stale, ms->as_mok, ms->as_merr, ms->as_uerr); 319} 320 321 322#if defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) 323static char * 324cluster_server(void) 325{ 326 struct cct_entry *cp; 327 328 if (cnodeid() == 0) { 329 /* 330 * Not clustered 331 */ 332 return def_server; 333 } 334 while (cp = getccent()) 335 if (cp->cnode_type == 'r') 336 return cp->cnode_name; 337 338 return def_server; 339} 340#endif /* defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) */ 341 342 343static void 344print_umnt_error(amq_sync_umnt *rv, const char *fs) 345{ 346 347 switch (rv->au_etype) { 348 case AMQ_UMNT_OK: 349 break; 350 case AMQ_UMNT_FAILED: 351 printf("unmount failed: %s\n", strerror(rv->au_errno)); 352 break; 353 case AMQ_UMNT_FORK: 354 if (rv->au_errno == 0) 355 printf("%s is not mounted\n", fs); 356 else 357 printf("falling back to asynchronous unmount: %s\n", 358 strerror(rv->au_errno)); 359 break; 360 case AMQ_UMNT_READ: 361 printf("pipe read error: %s\n", strerror(rv->au_errno)); 362 break; 363 case AMQ_UMNT_SERVER: 364 printf("amd server down\n"); 365 break; 366 case AMQ_UMNT_SIGNAL: 367 printf("got signal: %d\n", rv->au_signal); 368 break; 369 /* 370 * Omit default so the compiler can check for missing cases. 371 * 372 default: 373 break; 374 */ 375 } 376} 377 378 379static int 380amu_sync_umnt_to_retval(amq_sync_umnt *rv) 381{ 382 switch (rv->au_etype) { 383 case AMQ_UMNT_FORK: 384 if (rv->au_errno == 0) { 385 /* 386 * We allow this error so that things like: 387 * amq -uu /l/cd0d && eject cd0 388 * will work when /l/cd0d is not mounted. 389 * XXX - We still print an error message. 390 */ 391 return 0; 392 } 393 /*FALLTHROUGH*/ 394 default: 395 return rv->au_etype; 396 } 397} 398 399 400static int 401clnt_failed(CLIENT *clnt, char *server) 402{ 403 fprintf(stderr, "%s: ", am_get_progname()); 404 clnt_perror(clnt, server); 405 return 1; 406} 407 408 409/* 410 * MAIN 411 */ 412int 413main(int argc, char *argv[]) 414{ 415 int opt_ch; 416 int errs = 0; 417 char *server; 418 struct sockaddr_in server_addr; 419 CLIENT *clnt = NULL; 420 struct hostent *hp; 421 int nodefault = 0; 422 struct timeval tv; 423 char *progname = NULL; 424 425 /* 426 * Compute program name 427 */ 428 if (argv[0]) { 429 progname = strrchr(argv[0], '/'); 430 if (progname && progname[1]) 431 progname++; 432 else 433 progname = argv[0]; 434 } 435 if (!progname) 436 progname = "amq"; 437 am_set_progname(progname); 438 439 /* 440 * Parse arguments 441 */ 442 while ((opt_ch = getopt(argc, argv, "Hfh:il:mqsuvx:D:pP:TUw")) != -1) 443 switch (opt_ch) { 444 case 'H': 445 goto show_usage; 446 break; 447 448 case 'f': 449 flush_flag = 1; 450 nodefault = 1; 451 break; 452 453 case 'h': 454 def_server = optarg; 455 break; 456 457 case 'i': 458 mapinfo_flag = 1; 459 nodefault = 1; 460 break; 461 462 case 'l': 463 amq_logfile = optarg; 464 nodefault = 1; 465 break; 466 467 case 'm': 468 minfo_flag = 1; 469 nodefault = 1; 470 break; 471 472 case 'p': 473 getpid_flag = 1; 474 nodefault = 1; 475 break; 476 477 case 'q': 478 quiet_flag = 1; 479 nodefault = 1; 480 break; 481 482 case 's': 483 stats_flag = 1; 484 nodefault = 1; 485 break; 486 487 case 'u': 488 unmount_flag++; 489 nodefault = 1; 490 break; 491 492 case 'v': 493 getvers_flag = 1; 494 nodefault = 1; 495 break; 496 497 case 'x': 498 xlog_optstr = optarg; 499 nodefault = 1; 500 break; 501 502 case 'D': 503 debug_opts = optarg; 504 nodefault = 1; 505 break; 506 507 case 'P': 508 amd_program_number = atoi(optarg); 509 break; 510 511 case 'T': 512 use_tcp_flag = 1; 513 break; 514 515 case 'U': 516 use_udp_flag = 1; 517 break; 518 519 case 'w': 520 getpwd_flag = 1; 521 break; 522 523 default: 524 errs = 1; 525 break; 526 } 527 528 if (optind == argc) { 529 if (unmount_flag) 530 errs = 1; 531 } 532 if (errs) { 533 show_usage: 534 fprintf(stderr, "\ 535Usage: %s [-fimpqsvwHTU] [-h hostname] [-l log_file|\"syslog\"]\n\ 536\t[-x log_options] [-D debug_options]\n\ 537\t[-P program_number] [[-u[u]] directory ...]\n", 538 am_get_progname() 539 ); 540 exit(1); 541 } 542 543 544 /* set use_udp and use_tcp flags both to on if none are defined */ 545 if (!use_tcp_flag && !use_udp_flag) 546 use_tcp_flag = use_udp_flag = 1; 547 548#if defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) 549 /* 550 * Figure out root server of cluster 551 */ 552 if (def_server == localhost) 553 server = cluster_server(); 554 else 555#endif /* defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) */ 556 server = def_server; 557 558 /* 559 * Get address of server 560 */ 561 if ((hp = gethostbyname(server)) == 0 && !STREQ(server, localhost)) { 562 fprintf(stderr, "%s: Can't get address of %s\n", 563 am_get_progname(), server); 564 exit(1); 565 } 566 memset(&server_addr, 0, sizeof(server_addr)); 567 /* as per POSIX, sin_len need not be set (used internally by kernel) */ 568 server_addr.sin_family = AF_INET; 569 if (hp) { 570 memmove((voidp) &server_addr.sin_addr, (voidp) hp->h_addr, 571 sizeof(server_addr.sin_addr)); 572 } else { 573 /* fake "localhost" */ 574 server_addr.sin_addr.s_addr = htonl(0x7f000001); 575 } 576 577 /* 578 * Create RPC endpoint 579 */ 580 tv.tv_sec = 5; /* 5 seconds for timeout or per retry */ 581 tv.tv_usec = 0; 582 583 if (use_tcp_flag) /* try tcp first */ 584 clnt = clnt_create(server, amd_program_number, AMQ_VERSION, "tcp"); 585 if (!clnt && use_udp_flag) { /* try udp next */ 586 clnt = clnt_create(server, amd_program_number, AMQ_VERSION, "udp"); 587 /* if ok, set timeout (valid for connectionless transports only) */ 588 if (clnt) 589 clnt_control(clnt, CLSET_RETRY_TIMEOUT, (char *) &tv); 590 } 591 if (!clnt) { 592 fprintf(stderr, "%s: ", am_get_progname()); 593 clnt_pcreateerror(server); 594 exit(1); 595 } 596 597 /* 598 * Control debugging 599 */ 600 if (debug_opts) { 601 int *rc; 602 amq_setopt opt; 603 opt.as_opt = AMOPT_DEBUG; 604 opt.as_str = debug_opts; 605 rc = amqproc_setopt_1(&opt, clnt); 606 if (rc && *rc < 0) { 607 fprintf(stderr, "%s: daemon not compiled for debug\n", 608 am_get_progname()); 609 errs = 1; 610 } else if (!rc || *rc > 0) { 611 fprintf(stderr, "%s: debug setting for \"%s\" failed\n", 612 am_get_progname(), debug_opts); 613 errs = 1; 614 } 615 } 616 617 /* 618 * Control logging 619 */ 620 if (xlog_optstr) { 621 int *rc; 622 amq_setopt opt; 623 opt.as_opt = AMOPT_XLOG; 624 opt.as_str = xlog_optstr; 625 rc = amqproc_setopt_1(&opt, clnt); 626 if (!rc || *rc) { 627 fprintf(stderr, "%s: setting log level to \"%s\" failed\n", 628 am_get_progname(), xlog_optstr); 629 errs = 1; 630 } 631 } 632 633 /* 634 * Control log file 635 */ 636 if (amq_logfile) { 637 int *rc; 638 amq_setopt opt; 639 opt.as_opt = AMOPT_LOGFILE; 640 opt.as_str = amq_logfile; 641 rc = amqproc_setopt_1(&opt, clnt); 642 if (!rc || *rc) { 643 fprintf(stderr, "%s: setting logfile to \"%s\" failed\n", 644 am_get_progname(), amq_logfile); 645 errs = 1; 646 } 647 } 648 649 /* 650 * Flush map cache 651 */ 652 if (flush_flag) { 653 int *rc; 654 amq_setopt opt; 655 opt.as_opt = AMOPT_FLUSHMAPC; 656 opt.as_str = ""; 657 rc = amqproc_setopt_1(&opt, clnt); 658 if (!rc || *rc) { 659 fprintf(stderr, "%s: amd on %s cannot flush the map cache\n", 660 am_get_progname(), server); 661 errs = 1; 662 } 663 } 664 665 /* 666 * getpwd info 667 */ 668 if (getpwd_flag) { 669 char path[MAXPATHLEN+1]; 670 char *wd; 671 amq_mount_tree_list *mlp; 672 amq_mount_tree_p mt; 673 u_int i; 674 int flag; 675 676 wd = getcwd(path, MAXPATHLEN+1); 677 if (!wd) { 678 fprintf(stderr, "%s: getcwd failed (%s)", am_get_progname(), 679 strerror(errno)); 680 exit(1); 681 } 682 mlp = amqproc_export_1((voidp) 0, clnt); 683 for (i = 0; mlp && i < mlp->amq_mount_tree_list_len; i++) { 684 mt = mlp->amq_mount_tree_list_val[i]; 685 while (1) { 686 flag = 0; 687 show_pwd(mt, path, sizeof(path), &flag); 688 if (!flag) { 689 printf("%s\n", path); 690 break; 691 } 692 } 693 } 694 exit(0); 695 } 696 697 /* 698 * Mount info 699 */ 700 if (minfo_flag) { 701 int dummy; 702 amq_mount_info_list *ml = amqproc_getmntfs_1(&dummy, clnt); 703 if (ml) { 704 int mwid = 0, dwid = 0, twid = 0; 705 show_mi(ml, Calc, &mwid, &dwid, &twid); 706 mwid++; 707 dwid++; 708 twid++; 709 show_mi(ml, Full, &mwid, &dwid, &twid); 710 711 } else { 712 fprintf(stderr, "%s: amd on %s cannot provide mount info\n", 713 am_get_progname(), server); 714 } 715 } 716 717 718 /* 719 * Map 720 */ 721 if (mapinfo_flag) { 722 int dummy; 723 amq_map_info_list *ml = amqproc_getmapinfo_1(&dummy, clnt); 724 if (ml) { 725 int mwid = 0, wwid = 0; 726 show_mapinfo(ml, Calc, &mwid, &wwid); 727 mwid++; 728 if (wwid) 729 wwid++; 730 show_mapinfo(ml, Full, &mwid, &wwid); 731 } else { 732 fprintf(stderr, "%s: amd on %s cannot provide map info\n", 733 am_get_progname(), server); 734 } 735 } 736 737 /* 738 * Get Version 739 */ 740 if (getvers_flag) { 741 amq_string *spp = amqproc_getvers_1((voidp) 0, clnt); 742 if (spp && *spp) { 743 fputs(*spp, stdout); 744 XFREE(*spp); 745 } else { 746 fprintf(stderr, "%s: failed to get version information\n", 747 am_get_progname()); 748 errs = 1; 749 } 750 } 751 752 /* 753 * Get PID of amd 754 */ 755 if (getpid_flag) { 756 int *ip = amqproc_getpid_1((voidp) 0, clnt); 757 if (ip && *ip) { 758 printf("%d\n", *ip); 759 } else { 760 fprintf(stderr, "%s: failed to get PID of amd\n", am_get_progname()); 761 errs = 1; 762 } 763 } 764 765 /* 766 * Apply required operation to all remaining arguments 767 */ 768 if (optind < argc) { 769 do { 770 char *fs = argv[optind++]; 771 if (unmount_flag > 1) { 772 amq_sync_umnt *sup; 773 /* 774 * Synchronous unmount request 775 */ 776 sup = amqproc_sync_umnt_1(&fs, clnt); 777 if (sup) { 778 if (quiet_flag == 0) 779 print_umnt_error(sup, fs); 780 errs = amu_sync_umnt_to_retval(sup); 781 } else { 782 errs = clnt_failed(clnt, server); 783 } 784 } else if (unmount_flag) { 785 /* 786 * Unmount request 787 */ 788 amqproc_umnt_1(&fs, clnt); 789 } else { 790 /* 791 * Stats request 792 */ 793 amq_mount_tree_p *mtp = amqproc_mnttree_1(&fs, clnt); 794 if (mtp) { 795 amq_mount_tree *mt = *mtp; 796 if (mt) { 797 int mwid = 0, dwid = 0, twid = 0; 798 show_mt(mt, Calc, &mwid, &dwid, &twid); 799 mwid++; 800 dwid++, twid++; 801 printf("%-*.*s Uid Getattr Lookup RdDir RdLnk Statfs Mounted@\n", 802 dwid, dwid, "What"); 803 show_mt(mt, Stats, &mwid, &dwid, &twid); 804 } else { 805 fprintf(stderr, "%s: %s not automounted\n", am_get_progname(), fs); 806 } 807 xdr_pri_free((XDRPROC_T_TYPE) xdr_amq_mount_tree_p, (caddr_t) mtp); 808 } else { 809 errs = clnt_failed(clnt, server); 810 } 811 } 812 } while (optind < argc); 813 814 } else if (unmount_flag) { 815 goto show_usage; 816 817 } else if (stats_flag) { 818 amq_mount_stats *ms = amqproc_stats_1((voidp) 0, clnt); 819 if (ms) { 820 show_ms(ms); 821 } else { 822 errs = clnt_failed(clnt, server); 823 } 824 825 } else if (!nodefault) { 826 amq_mount_tree_list *mlp = amqproc_export_1((voidp) 0, clnt); 827 if (mlp) { 828 enum show_opt e = Calc; 829 int mwid = 0, dwid = 0, pwid = 0; 830 831 while (e != ShowDone) { 832 u_int i; 833 for (i = 0; i < mlp->amq_mount_tree_list_len; i++) { 834 show_mt(mlp->amq_mount_tree_list_val[i], 835 e, &mwid, &dwid, &pwid); 836 } 837 mwid++; 838 dwid++, pwid++; 839 if (e == Calc) 840 e = Short; 841 else if (e == Short) 842 e = ShowDone; 843 } 844 845 } else { 846 errs = clnt_failed(clnt, server); 847 } 848 } 849 exit(errs); 850 return errs; /* should never reach here */ 851} 852