138494Sobrien/* 2310490Scy * Copyright (c) 1997-2014 Erez Zadok 338494Sobrien * Copyright (c) 1990 Jan-Simon Pendry 438494Sobrien * Copyright (c) 1990 Imperial College of Science, Technology & Medicine 538494Sobrien * Copyright (c) 1990 The Regents of the University of California. 638494Sobrien * All rights reserved. 738494Sobrien * 838494Sobrien * This code is derived from software contributed to Berkeley by 938494Sobrien * Jan-Simon Pendry at Imperial College, London. 1038494Sobrien * 1138494Sobrien * Redistribution and use in source and binary forms, with or without 1238494Sobrien * modification, are permitted provided that the following conditions 1338494Sobrien * are met: 1438494Sobrien * 1. Redistributions of source code must retain the above copyright 1538494Sobrien * notice, this list of conditions and the following disclaimer. 1638494Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1738494Sobrien * notice, this list of conditions and the following disclaimer in the 1838494Sobrien * documentation and/or other materials provided with the distribution. 19310490Scy * 3. Neither the name of the University nor the names of its contributors 2038494Sobrien * may be used to endorse or promote products derived from this software 2138494Sobrien * without specific prior written permission. 2238494Sobrien * 2338494Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2438494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2538494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2638494Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2738494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2838494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2938494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3038494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3138494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3238494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3338494Sobrien * SUCH DAMAGE. 3438494Sobrien * 3538494Sobrien * 36174313Sobrien * File: am-utils/amq/amq.c 3738494Sobrien * 3838494Sobrien */ 3938494Sobrien 4038494Sobrien/* 4138494Sobrien * Automounter query tool 4238494Sobrien */ 4338494Sobrien 4438494Sobrien#ifdef HAVE_CONFIG_H 4538494Sobrien# include <config.h> 4638494Sobrien#endif /* HAVE_CONFIG_H */ 4738494Sobrien#include <am_defs.h> 4838494Sobrien#include <amq.h> 4938494Sobrien 5038494Sobrien/* locals */ 5138494Sobrienstatic int flush_flag; 52310490Scystatic int getpid_flag; 53310490Scystatic int getpwd_flag; 54310490Scystatic int getvers_flag; 5538494Sobrienstatic int minfo_flag; 56310490Scystatic int mapinfo_flag; 57310490Scystatic int quiet_flag; 58310490Scystatic int stats_flag; 5938494Sobrienstatic int unmount_flag; 60310490Scystatic int use_tcp_flag; 61310490Scystatic int use_udp_flag; 62310490Scystatic u_long amd_program_number = AMQ_PROGRAM; 6338494Sobrienstatic char *debug_opts; 6438494Sobrienstatic char *amq_logfile; 6538494Sobrienstatic char *xlog_optstr; 6638494Sobrienstatic char localhost[] = "localhost"; 6738494Sobrienstatic char *def_server = localhost; 6838494Sobrien 6938494Sobrien/* externals */ 7038494Sobrienextern int optind; 7138494Sobrienextern char *optarg; 7238494Sobrien 7338494Sobrien/* structures */ 7438494Sobrienenum show_opt { 7538494Sobrien Full, Stats, Calc, Short, ShowDone 7638494Sobrien}; 7738494Sobrien 7838494Sobrien 79310490Scystatic void 80310490Scytime_print(time_type tt) 81310490Scy{ 82335734Scy time_t t = (time_t)(intptr_t)tt; 83310490Scy struct tm *tp = localtime(&t); 84310490Scy printf("%02d/%02d/%04d %02d:%02d:%02d", 85310490Scy tp->tm_mon + 1, tp->tm_mday, 86310490Scy tp->tm_year < 1900 ? tp->tm_year + 1900 : tp->tm_year, 87310490Scy tp->tm_hour, tp->tm_min, tp->tm_sec); 88310490Scy} 89310490Scy 9038494Sobrien/* 9138494Sobrien * If (e) is Calc then just calculate the sizes 9238494Sobrien * Otherwise display the mount node on stdout 9338494Sobrien */ 9438494Sobrienstatic void 9538494Sobrienshow_mti(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *twid) 9638494Sobrien{ 9738494Sobrien switch (e) { 9838494Sobrien case Calc: 9938494Sobrien { 10038494Sobrien int mw = strlen(mt->mt_mountinfo); 10138494Sobrien int dw = strlen(mt->mt_directory); 10238494Sobrien int tw = strlen(mt->mt_type); 10338494Sobrien if (mw > *mwid) 10438494Sobrien *mwid = mw; 10538494Sobrien if (dw > *dwid) 10638494Sobrien *dwid = dw; 10738494Sobrien if (tw > *twid) 10838494Sobrien *twid = tw; 10938494Sobrien } 11038494Sobrien break; 11138494Sobrien 11238494Sobrien case Full: 11338494Sobrien { 114310490Scy printf("%-*.*s %-*.*s %-*.*s %s\n\t%-5d %-7d %-6d %-7d %-7d %-6d", 11538494Sobrien *dwid, *dwid, 11638494Sobrien *mt->mt_directory ? mt->mt_directory : "/", /* XXX */ 11738494Sobrien *twid, *twid, 11838494Sobrien mt->mt_type, 11938494Sobrien *mwid, *mwid, 12038494Sobrien mt->mt_mountinfo, 12138494Sobrien mt->mt_mountpoint, 12238494Sobrien 12338494Sobrien mt->mt_mountuid, 12438494Sobrien mt->mt_getattr, 12538494Sobrien mt->mt_lookup, 12638494Sobrien mt->mt_readdir, 12738494Sobrien mt->mt_readlink, 128310490Scy mt->mt_statfs); 129310490Scy time_print(mt->mt_mounttime); 130310490Scy printf("\n"); 13138494Sobrien } 13238494Sobrien break; 13338494Sobrien 13438494Sobrien case Stats: 13538494Sobrien { 136310490Scy printf("%-*.*s %-5d %-7d %-6d %-7d %-7d %-6d ", 13738494Sobrien *dwid, *dwid, 13838494Sobrien *mt->mt_directory ? mt->mt_directory : "/", /* XXX */ 13938494Sobrien 14038494Sobrien mt->mt_mountuid, 14138494Sobrien mt->mt_getattr, 14238494Sobrien mt->mt_lookup, 14338494Sobrien mt->mt_readdir, 14438494Sobrien mt->mt_readlink, 145310490Scy mt->mt_statfs); 146310490Scy time_print(mt->mt_mounttime); 147310490Scy printf("\n"); 14838494Sobrien } 14938494Sobrien break; 15038494Sobrien 15138494Sobrien case Short: 15238494Sobrien { 15338494Sobrien printf("%-*.*s %-*.*s %-*.*s %s\n", 15438494Sobrien *dwid, *dwid, 15538494Sobrien *mt->mt_directory ? mt->mt_directory : "/", 15638494Sobrien *twid, *twid, 15738494Sobrien mt->mt_type, 15838494Sobrien *mwid, *mwid, 15938494Sobrien mt->mt_mountinfo, 16038494Sobrien mt->mt_mountpoint); 16138494Sobrien } 16238494Sobrien break; 16338494Sobrien 16438494Sobrien default: 16538494Sobrien break; 16638494Sobrien } 16738494Sobrien} 16838494Sobrien 16982801Sobrien 17038494Sobrien/* 17182801Sobrien * Display a pwd data 17282801Sobrien */ 17382801Sobrienstatic void 174174313Sobrienshow_pwd(amq_mount_tree *mt, char *path, size_t l, int *flag) 17582801Sobrien{ 17682801Sobrien int len; 17782801Sobrien 17882801Sobrien while (mt) { 17982801Sobrien len = strlen(mt->mt_mountpoint); 18082801Sobrien if (NSTREQ(path, mt->mt_mountpoint, len) && 18182801Sobrien !STREQ(mt->mt_directory, mt->mt_mountpoint)) { 182174313Sobrien char buf[MAXPATHLEN+1]; /* must be same size as 'path' */ 183174313Sobrien xstrlcpy(buf, mt->mt_directory, sizeof(buf)); 184174313Sobrien xstrlcat(buf, &path[len], sizeof(buf)); 185174313Sobrien xstrlcpy(path, buf, l); 18682801Sobrien *flag = 1; 18782801Sobrien } 188174313Sobrien show_pwd(mt->mt_next, path, l, flag); 18982801Sobrien mt = mt->mt_child; 19082801Sobrien } 19182801Sobrien} 19282801Sobrien 19382801Sobrien 19482801Sobrien/* 19538494Sobrien * Display a mount tree. 19638494Sobrien */ 19738494Sobrienstatic void 19838494Sobrienshow_mt(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *pwid) 19938494Sobrien{ 20038494Sobrien while (mt) { 20138494Sobrien show_mti(mt, e, mwid, dwid, pwid); 20238494Sobrien show_mt(mt->mt_next, e, mwid, dwid, pwid); 20338494Sobrien mt = mt->mt_child; 20438494Sobrien } 20538494Sobrien} 20638494Sobrien 20782801Sobrien 20838494Sobrienstatic void 20938494Sobrienshow_mi(amq_mount_info_list *ml, enum show_opt e, int *mwid, int *dwid, int *twid) 21038494Sobrien{ 211174313Sobrien u_int i; 21238494Sobrien 21338494Sobrien switch (e) { 21438494Sobrien 21538494Sobrien case Calc: 21638494Sobrien { 21738494Sobrien for (i = 0; i < ml->amq_mount_info_list_len; i++) { 21838494Sobrien amq_mount_info *mi = &ml->amq_mount_info_list_val[i]; 21938494Sobrien int mw = strlen(mi->mi_mountinfo); 22038494Sobrien int dw = strlen(mi->mi_mountpt); 22138494Sobrien int tw = strlen(mi->mi_type); 22238494Sobrien if (mw > *mwid) 22338494Sobrien *mwid = mw; 22438494Sobrien if (dw > *dwid) 22538494Sobrien *dwid = dw; 22638494Sobrien if (tw > *twid) 22738494Sobrien *twid = tw; 22838494Sobrien } 22938494Sobrien } 23038494Sobrien break; 23138494Sobrien 23238494Sobrien case Full: 23338494Sobrien { 23438494Sobrien for (i = 0; i < ml->amq_mount_info_list_len; i++) { 23538494Sobrien amq_mount_info *mi = &ml->amq_mount_info_list_val[i]; 236310490Scy printf("%-*.*s %-*.*s %-*.*s %-3d %s is %s ", 23738494Sobrien *mwid, *mwid, mi->mi_mountinfo, 23838494Sobrien *dwid, *dwid, mi->mi_mountpt, 23938494Sobrien *twid, *twid, mi->mi_type, 24038494Sobrien mi->mi_refc, mi->mi_fserver, 24138494Sobrien mi->mi_up > 0 ? "up" : 24238494Sobrien mi->mi_up < 0 ? "starting" : "down"); 24338494Sobrien if (mi->mi_error > 0) { 244174313Sobrien printf(" (%s)", strerror(mi->mi_error)); 24538494Sobrien } else if (mi->mi_error < 0) { 24638494Sobrien fputs(" (in progress)", stdout); 24738494Sobrien } 24838494Sobrien fputc('\n', stdout); 24938494Sobrien } 25038494Sobrien } 25138494Sobrien break; 25238494Sobrien 25338494Sobrien default: 25438494Sobrien break; 25538494Sobrien } 25638494Sobrien} 25738494Sobrien 258310490Scystatic void 259310490Scyshow_map(amq_map_info *mi) 260310490Scy{ 261310490Scy} 26238494Sobrien 263310490Scystatic void 264310490Scyshow_mapinfo(amq_map_info_list *ml, enum show_opt e, int *nwid, int *wwid) 265310490Scy{ 266310490Scy u_int i; 267310490Scy 268310490Scy switch (e) { 269310490Scy 270310490Scy case Calc: 271310490Scy { 272310490Scy for (i = 0; i < ml->amq_map_info_list_len; i++) { 273310490Scy amq_map_info *mi = &ml->amq_map_info_list_val[i]; 274310490Scy int nw = strlen(mi->mi_name); 275310490Scy int ww = strlen(mi->mi_wildcard ? mi->mi_wildcard : "(null"); 276310490Scy if (nw > *nwid) 277310490Scy *nwid = nw; 278310490Scy if (ww > *wwid) 279310490Scy *wwid = ww; 280310490Scy } 281310490Scy } 282310490Scy break; 283310490Scy 284310490Scy case Full: 285310490Scy { 286310490Scy printf("%-*.*s %-*.*s %-8.8s %-7.7s %-7.7s %-7.7s %-s Modified\n", 287310490Scy *nwid, *nwid, "Name", 288310490Scy *wwid, *wwid, "Wild", 289310490Scy "Flags", "Refcnt", "Entries", "Reloads", "Stat"); 290310490Scy for (i = 0; i < ml->amq_map_info_list_len; i++) { 291310490Scy amq_map_info *mi = &ml->amq_map_info_list_val[i]; 292310490Scy printf("%-*.*s %*.*s %-8x %-7d %-7d %-7d %s ", 293310490Scy *nwid, *nwid, mi->mi_name, 294310490Scy *wwid, *wwid, mi->mi_wildcard, 295310490Scy mi->mi_flags, mi->mi_refc, mi->mi_nentries, mi->mi_reloads, 296310490Scy mi->mi_up == -1 ? "root" : (mi->mi_up ? " up" : "down")); 297310490Scy time_print(mi->mi_modify); 298310490Scy fputc('\n', stdout); 299310490Scy } 300310490Scy } 301310490Scy break; 302310490Scy 303310490Scy default: 304310490Scy break; 305310490Scy } 306310490Scy} 307310490Scy 30838494Sobrien/* 30938494Sobrien * Display general mount statistics 31038494Sobrien */ 31138494Sobrienstatic void 31238494Sobrienshow_ms(amq_mount_stats *ms) 31338494Sobrien{ 31438494Sobrien printf("\ 31538494Sobrienrequests stale mount mount unmount\n\ 31638494Sobriendeferred fhandles ok failed failed\n\ 31738494Sobrien%-9d %-9d %-9d %-9d %-9d\n", 31838494Sobrien ms->as_drops, ms->as_stale, ms->as_mok, ms->as_merr, ms->as_uerr); 31938494Sobrien} 32038494Sobrien 32138494Sobrien 32238494Sobrien#if defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) 32338494Sobrienstatic char * 32438494Sobriencluster_server(void) 32538494Sobrien{ 32638494Sobrien struct cct_entry *cp; 32738494Sobrien 32838494Sobrien if (cnodeid() == 0) { 32938494Sobrien /* 33038494Sobrien * Not clustered 33138494Sobrien */ 33238494Sobrien return def_server; 33338494Sobrien } 33438494Sobrien while (cp = getccent()) 33538494Sobrien if (cp->cnode_type == 'r') 33638494Sobrien return cp->cnode_name; 33738494Sobrien 33838494Sobrien return def_server; 33938494Sobrien} 34038494Sobrien#endif /* defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) */ 34138494Sobrien 34238494Sobrien 343310490Scystatic void 344310490Scyprint_umnt_error(amq_sync_umnt *rv, const char *fs) 345310490Scy{ 346310490Scy 347310490Scy switch (rv->au_etype) { 348310490Scy case AMQ_UMNT_OK: 349310490Scy break; 350310490Scy case AMQ_UMNT_FAILED: 351310490Scy printf("unmount failed: %s\n", strerror(rv->au_errno)); 352310490Scy break; 353310490Scy case AMQ_UMNT_FORK: 354310490Scy if (rv->au_errno == 0) 355310490Scy printf("%s is not mounted\n", fs); 356310490Scy else 357310490Scy printf("falling back to asynchronous unmount: %s\n", 358310490Scy strerror(rv->au_errno)); 359310490Scy break; 360310490Scy case AMQ_UMNT_READ: 361310490Scy printf("pipe read error: %s\n", strerror(rv->au_errno)); 362310490Scy break; 363310490Scy case AMQ_UMNT_SERVER: 364310490Scy printf("amd server down\n"); 365310490Scy break; 366310490Scy case AMQ_UMNT_SIGNAL: 367310490Scy printf("got signal: %d\n", rv->au_signal); 368310490Scy break; 369310490Scy /* 370310490Scy * Omit default so the compiler can check for missing cases. 371310490Scy * 372310490Scy default: 373310490Scy break; 374310490Scy */ 375310490Scy } 376310490Scy} 377310490Scy 378310490Scy 379310490Scystatic int 380310490Scyamu_sync_umnt_to_retval(amq_sync_umnt *rv) 381310490Scy{ 382310490Scy switch (rv->au_etype) { 383310490Scy case AMQ_UMNT_FORK: 384310490Scy if (rv->au_errno == 0) { 385310490Scy /* 386310490Scy * We allow this error so that things like: 387310490Scy * amq -uu /l/cd0d && eject cd0 388310490Scy * will work when /l/cd0d is not mounted. 389310490Scy * XXX - We still print an error message. 390310490Scy */ 391310490Scy return 0; 392310490Scy } 393310490Scy /*FALLTHROUGH*/ 394310490Scy default: 395310490Scy return rv->au_etype; 396310490Scy } 397310490Scy} 398310490Scy 399310490Scy 400310490Scystatic int 401310490Scyclnt_failed(CLIENT *clnt, char *server) 402310490Scy{ 403310490Scy fprintf(stderr, "%s: ", am_get_progname()); 404310490Scy clnt_perror(clnt, server); 405310490Scy return 1; 406310490Scy} 407310490Scy 408310490Scy 40938494Sobrien/* 41038494Sobrien * MAIN 41138494Sobrien */ 41238494Sobrienint 41338494Sobrienmain(int argc, char *argv[]) 41438494Sobrien{ 41538494Sobrien int opt_ch; 41638494Sobrien int errs = 0; 41738494Sobrien char *server; 41838494Sobrien struct sockaddr_in server_addr; 41938494Sobrien CLIENT *clnt = NULL; 42038494Sobrien struct hostent *hp; 42138494Sobrien int nodefault = 0; 42238494Sobrien struct timeval tv; 42342633Sobrien char *progname = NULL; 42438494Sobrien 42538494Sobrien /* 42638494Sobrien * Compute program name 42738494Sobrien */ 42838494Sobrien if (argv[0]) { 42938494Sobrien progname = strrchr(argv[0], '/'); 43038494Sobrien if (progname && progname[1]) 43138494Sobrien progname++; 43238494Sobrien else 43338494Sobrien progname = argv[0]; 43438494Sobrien } 43538494Sobrien if (!progname) 43638494Sobrien progname = "amq"; 43742633Sobrien am_set_progname(progname); 43838494Sobrien 43938494Sobrien /* 44038494Sobrien * Parse arguments 44138494Sobrien */ 442310490Scy while ((opt_ch = getopt(argc, argv, "Hfh:il:mqsuvx:D:pP:TUw")) != -1) 44338494Sobrien switch (opt_ch) { 44482801Sobrien case 'H': 44582801Sobrien goto show_usage; 44682801Sobrien break; 44782801Sobrien 44838494Sobrien case 'f': 44938494Sobrien flush_flag = 1; 45038494Sobrien nodefault = 1; 45138494Sobrien break; 45238494Sobrien 45338494Sobrien case 'h': 45438494Sobrien def_server = optarg; 45538494Sobrien break; 45638494Sobrien 457310490Scy case 'i': 458310490Scy mapinfo_flag = 1; 459310490Scy nodefault = 1; 460310490Scy break; 461310490Scy 46238494Sobrien case 'l': 46338494Sobrien amq_logfile = optarg; 46438494Sobrien nodefault = 1; 46538494Sobrien break; 46638494Sobrien 46738494Sobrien case 'm': 46838494Sobrien minfo_flag = 1; 46938494Sobrien nodefault = 1; 47038494Sobrien break; 47138494Sobrien 47238494Sobrien case 'p': 47338494Sobrien getpid_flag = 1; 47438494Sobrien nodefault = 1; 47538494Sobrien break; 47638494Sobrien 477310490Scy case 'q': 478310490Scy quiet_flag = 1; 479310490Scy nodefault = 1; 480310490Scy break; 481310490Scy 48238494Sobrien case 's': 48338494Sobrien stats_flag = 1; 48438494Sobrien nodefault = 1; 48538494Sobrien break; 48638494Sobrien 48738494Sobrien case 'u': 488310490Scy unmount_flag++; 48938494Sobrien nodefault = 1; 49038494Sobrien break; 49138494Sobrien 49238494Sobrien case 'v': 49338494Sobrien getvers_flag = 1; 49438494Sobrien nodefault = 1; 49538494Sobrien break; 49638494Sobrien 49738494Sobrien case 'x': 49838494Sobrien xlog_optstr = optarg; 49938494Sobrien nodefault = 1; 50038494Sobrien break; 50138494Sobrien 50238494Sobrien case 'D': 50338494Sobrien debug_opts = optarg; 50438494Sobrien nodefault = 1; 50538494Sobrien break; 50638494Sobrien 50738494Sobrien case 'P': 50838494Sobrien amd_program_number = atoi(optarg); 50938494Sobrien break; 51038494Sobrien 51138494Sobrien case 'T': 51238494Sobrien use_tcp_flag = 1; 51338494Sobrien break; 51438494Sobrien 51538494Sobrien case 'U': 51638494Sobrien use_udp_flag = 1; 51738494Sobrien break; 51838494Sobrien 51982801Sobrien case 'w': 52082801Sobrien getpwd_flag = 1; 52182801Sobrien break; 52282801Sobrien 52338494Sobrien default: 52438494Sobrien errs = 1; 52538494Sobrien break; 52638494Sobrien } 52738494Sobrien 52838494Sobrien if (optind == argc) { 52938494Sobrien if (unmount_flag) 53038494Sobrien errs = 1; 53138494Sobrien } 53238494Sobrien if (errs) { 53338494Sobrien show_usage: 53438494Sobrien fprintf(stderr, "\ 535310490ScyUsage: %s [-fimpqsvwHTU] [-h hostname] [-l log_file|\"syslog\"]\n\ 53682801Sobrien\t[-x log_options] [-D debug_options]\n\ 537310490Scy\t[-P program_number] [[-u[u]] directory ...]\n", 53882801Sobrien am_get_progname() 53951300Sobrien ); 54038494Sobrien exit(1); 54138494Sobrien } 54238494Sobrien 54351300Sobrien 54438494Sobrien /* set use_udp and use_tcp flags both to on if none are defined */ 54538494Sobrien if (!use_tcp_flag && !use_udp_flag) 54638494Sobrien use_tcp_flag = use_udp_flag = 1; 54738494Sobrien 54838494Sobrien#if defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) 54938494Sobrien /* 55038494Sobrien * Figure out root server of cluster 55138494Sobrien */ 55238494Sobrien if (def_server == localhost) 55338494Sobrien server = cluster_server(); 55438494Sobrien else 55538494Sobrien#endif /* defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) */ 55638494Sobrien server = def_server; 55738494Sobrien 55838494Sobrien /* 55938494Sobrien * Get address of server 56038494Sobrien */ 56138494Sobrien if ((hp = gethostbyname(server)) == 0 && !STREQ(server, localhost)) { 56242633Sobrien fprintf(stderr, "%s: Can't get address of %s\n", 56342633Sobrien am_get_progname(), server); 56438494Sobrien exit(1); 56538494Sobrien } 566174313Sobrien memset(&server_addr, 0, sizeof(server_addr)); 567174313Sobrien /* as per POSIX, sin_len need not be set (used internally by kernel) */ 56838494Sobrien server_addr.sin_family = AF_INET; 56938494Sobrien if (hp) { 57038494Sobrien memmove((voidp) &server_addr.sin_addr, (voidp) hp->h_addr, 57138494Sobrien sizeof(server_addr.sin_addr)); 57238494Sobrien } else { 57338494Sobrien /* fake "localhost" */ 57438494Sobrien server_addr.sin_addr.s_addr = htonl(0x7f000001); 57538494Sobrien } 57638494Sobrien 57738494Sobrien /* 57838494Sobrien * Create RPC endpoint 57938494Sobrien */ 58038494Sobrien tv.tv_sec = 5; /* 5 seconds for timeout or per retry */ 58138494Sobrien tv.tv_usec = 0; 58238494Sobrien 58382801Sobrien if (use_tcp_flag) /* try tcp first */ 58438494Sobrien clnt = clnt_create(server, amd_program_number, AMQ_VERSION, "tcp"); 58538494Sobrien if (!clnt && use_udp_flag) { /* try udp next */ 58638494Sobrien clnt = clnt_create(server, amd_program_number, AMQ_VERSION, "udp"); 58738494Sobrien /* if ok, set timeout (valid for connectionless transports only) */ 58838494Sobrien if (clnt) 58938494Sobrien clnt_control(clnt, CLSET_RETRY_TIMEOUT, (char *) &tv); 59038494Sobrien } 59138494Sobrien if (!clnt) { 59242633Sobrien fprintf(stderr, "%s: ", am_get_progname()); 59338494Sobrien clnt_pcreateerror(server); 59438494Sobrien exit(1); 59538494Sobrien } 59638494Sobrien 59738494Sobrien /* 59838494Sobrien * Control debugging 59938494Sobrien */ 60038494Sobrien if (debug_opts) { 60138494Sobrien int *rc; 60238494Sobrien amq_setopt opt; 60338494Sobrien opt.as_opt = AMOPT_DEBUG; 60438494Sobrien opt.as_str = debug_opts; 60538494Sobrien rc = amqproc_setopt_1(&opt, clnt); 60638494Sobrien if (rc && *rc < 0) { 60742633Sobrien fprintf(stderr, "%s: daemon not compiled for debug\n", 60842633Sobrien am_get_progname()); 60938494Sobrien errs = 1; 61038494Sobrien } else if (!rc || *rc > 0) { 61142633Sobrien fprintf(stderr, "%s: debug setting for \"%s\" failed\n", 61242633Sobrien am_get_progname(), debug_opts); 61338494Sobrien errs = 1; 61438494Sobrien } 61538494Sobrien } 61638494Sobrien 61738494Sobrien /* 61838494Sobrien * Control logging 61938494Sobrien */ 62038494Sobrien if (xlog_optstr) { 62138494Sobrien int *rc; 62238494Sobrien amq_setopt opt; 62338494Sobrien opt.as_opt = AMOPT_XLOG; 62438494Sobrien opt.as_str = xlog_optstr; 62538494Sobrien rc = amqproc_setopt_1(&opt, clnt); 62638494Sobrien if (!rc || *rc) { 62742633Sobrien fprintf(stderr, "%s: setting log level to \"%s\" failed\n", 62842633Sobrien am_get_progname(), xlog_optstr); 62938494Sobrien errs = 1; 63038494Sobrien } 63138494Sobrien } 63238494Sobrien 63338494Sobrien /* 63438494Sobrien * Control log file 63538494Sobrien */ 63638494Sobrien if (amq_logfile) { 63738494Sobrien int *rc; 63838494Sobrien amq_setopt opt; 63938494Sobrien opt.as_opt = AMOPT_LOGFILE; 64038494Sobrien opt.as_str = amq_logfile; 64138494Sobrien rc = amqproc_setopt_1(&opt, clnt); 64238494Sobrien if (!rc || *rc) { 64342633Sobrien fprintf(stderr, "%s: setting logfile to \"%s\" failed\n", 64442633Sobrien am_get_progname(), amq_logfile); 64538494Sobrien errs = 1; 64638494Sobrien } 64738494Sobrien } 64838494Sobrien 64938494Sobrien /* 65038494Sobrien * Flush map cache 65138494Sobrien */ 65238494Sobrien if (flush_flag) { 65338494Sobrien int *rc; 65438494Sobrien amq_setopt opt; 65538494Sobrien opt.as_opt = AMOPT_FLUSHMAPC; 65638494Sobrien opt.as_str = ""; 65738494Sobrien rc = amqproc_setopt_1(&opt, clnt); 65838494Sobrien if (!rc || *rc) { 65942633Sobrien fprintf(stderr, "%s: amd on %s cannot flush the map cache\n", 66042633Sobrien am_get_progname(), server); 66138494Sobrien errs = 1; 66238494Sobrien } 66338494Sobrien } 66438494Sobrien 66538494Sobrien /* 66682801Sobrien * getpwd info 66782801Sobrien */ 66882801Sobrien if (getpwd_flag) { 66982801Sobrien char path[MAXPATHLEN+1]; 670310490Scy char *wd; 671310490Scy amq_mount_tree_list *mlp; 67282801Sobrien amq_mount_tree_p mt; 673174313Sobrien u_int i; 674174313Sobrien int flag; 67582801Sobrien 676310490Scy wd = getcwd(path, MAXPATHLEN+1); 67782801Sobrien if (!wd) { 678310490Scy fprintf(stderr, "%s: getcwd failed (%s)", am_get_progname(), 679310490Scy strerror(errno)); 68082801Sobrien exit(1); 68182801Sobrien } 682310490Scy mlp = amqproc_export_1((voidp) 0, clnt); 68382801Sobrien for (i = 0; mlp && i < mlp->amq_mount_tree_list_len; i++) { 68482801Sobrien mt = mlp->amq_mount_tree_list_val[i]; 68582801Sobrien while (1) { 68682801Sobrien flag = 0; 687174313Sobrien show_pwd(mt, path, sizeof(path), &flag); 68882801Sobrien if (!flag) { 68982801Sobrien printf("%s\n", path); 69082801Sobrien break; 69182801Sobrien } 69282801Sobrien } 69382801Sobrien } 69482801Sobrien exit(0); 69582801Sobrien } 69682801Sobrien 69782801Sobrien /* 69838494Sobrien * Mount info 69938494Sobrien */ 70038494Sobrien if (minfo_flag) { 70138494Sobrien int dummy; 70238494Sobrien amq_mount_info_list *ml = amqproc_getmntfs_1(&dummy, clnt); 70338494Sobrien if (ml) { 70438494Sobrien int mwid = 0, dwid = 0, twid = 0; 70538494Sobrien show_mi(ml, Calc, &mwid, &dwid, &twid); 70638494Sobrien mwid++; 70738494Sobrien dwid++; 70838494Sobrien twid++; 70938494Sobrien show_mi(ml, Full, &mwid, &dwid, &twid); 71038494Sobrien 71138494Sobrien } else { 71242633Sobrien fprintf(stderr, "%s: amd on %s cannot provide mount info\n", 71342633Sobrien am_get_progname(), server); 71438494Sobrien } 71538494Sobrien } 71638494Sobrien 717310490Scy 71838494Sobrien /* 719310490Scy * Map 720310490Scy */ 721310490Scy if (mapinfo_flag) { 722310490Scy int dummy; 723310490Scy amq_map_info_list *ml = amqproc_getmapinfo_1(&dummy, clnt); 724310490Scy if (ml) { 725310490Scy int mwid = 0, wwid = 0; 726310490Scy show_mapinfo(ml, Calc, &mwid, &wwid); 727310490Scy mwid++; 728310490Scy if (wwid) 729310490Scy wwid++; 730310490Scy show_mapinfo(ml, Full, &mwid, &wwid); 731310490Scy } else { 732310490Scy fprintf(stderr, "%s: amd on %s cannot provide map info\n", 733310490Scy am_get_progname(), server); 734310490Scy } 735310490Scy } 736310490Scy 737310490Scy /* 73838494Sobrien * Get Version 73938494Sobrien */ 74038494Sobrien if (getvers_flag) { 74138494Sobrien amq_string *spp = amqproc_getvers_1((voidp) 0, clnt); 74238494Sobrien if (spp && *spp) { 74338494Sobrien fputs(*spp, stdout); 74438494Sobrien XFREE(*spp); 74538494Sobrien } else { 74642633Sobrien fprintf(stderr, "%s: failed to get version information\n", 74742633Sobrien am_get_progname()); 74838494Sobrien errs = 1; 74938494Sobrien } 75038494Sobrien } 75138494Sobrien 75238494Sobrien /* 75338494Sobrien * Get PID of amd 75438494Sobrien */ 75538494Sobrien if (getpid_flag) { 75638494Sobrien int *ip = amqproc_getpid_1((voidp) 0, clnt); 75738494Sobrien if (ip && *ip) { 75838494Sobrien printf("%d\n", *ip); 75938494Sobrien } else { 76042633Sobrien fprintf(stderr, "%s: failed to get PID of amd\n", am_get_progname()); 76138494Sobrien errs = 1; 76238494Sobrien } 76338494Sobrien } 76438494Sobrien 76538494Sobrien /* 76638494Sobrien * Apply required operation to all remaining arguments 76738494Sobrien */ 76838494Sobrien if (optind < argc) { 76938494Sobrien do { 77038494Sobrien char *fs = argv[optind++]; 771310490Scy if (unmount_flag > 1) { 772310490Scy amq_sync_umnt *sup; 77338494Sobrien /* 774310490Scy * Synchronous unmount request 775310490Scy */ 776310490Scy sup = amqproc_sync_umnt_1(&fs, clnt); 777310490Scy if (sup) { 778310490Scy if (quiet_flag == 0) 779310490Scy print_umnt_error(sup, fs); 780310490Scy errs = amu_sync_umnt_to_retval(sup); 781310490Scy } else { 782310490Scy errs = clnt_failed(clnt, server); 783310490Scy } 784310490Scy } else if (unmount_flag) { 785310490Scy /* 78638494Sobrien * Unmount request 78738494Sobrien */ 78838494Sobrien amqproc_umnt_1(&fs, clnt); 78938494Sobrien } else { 79038494Sobrien /* 79138494Sobrien * Stats request 79238494Sobrien */ 79338494Sobrien amq_mount_tree_p *mtp = amqproc_mnttree_1(&fs, clnt); 79438494Sobrien if (mtp) { 79538494Sobrien amq_mount_tree *mt = *mtp; 79638494Sobrien if (mt) { 79738494Sobrien int mwid = 0, dwid = 0, twid = 0; 79838494Sobrien show_mt(mt, Calc, &mwid, &dwid, &twid); 79938494Sobrien mwid++; 80038494Sobrien dwid++, twid++; 80138494Sobrien printf("%-*.*s Uid Getattr Lookup RdDir RdLnk Statfs Mounted@\n", 80238494Sobrien dwid, dwid, "What"); 80338494Sobrien show_mt(mt, Stats, &mwid, &dwid, &twid); 80438494Sobrien } else { 80542633Sobrien fprintf(stderr, "%s: %s not automounted\n", am_get_progname(), fs); 80638494Sobrien } 80738494Sobrien xdr_pri_free((XDRPROC_T_TYPE) xdr_amq_mount_tree_p, (caddr_t) mtp); 80838494Sobrien } else { 809310490Scy errs = clnt_failed(clnt, server); 81038494Sobrien } 81138494Sobrien } 81238494Sobrien } while (optind < argc); 81338494Sobrien 81438494Sobrien } else if (unmount_flag) { 81538494Sobrien goto show_usage; 81638494Sobrien 81738494Sobrien } else if (stats_flag) { 81838494Sobrien amq_mount_stats *ms = amqproc_stats_1((voidp) 0, clnt); 81938494Sobrien if (ms) { 82038494Sobrien show_ms(ms); 82138494Sobrien } else { 822310490Scy errs = clnt_failed(clnt, server); 82338494Sobrien } 82438494Sobrien 82538494Sobrien } else if (!nodefault) { 82638494Sobrien amq_mount_tree_list *mlp = amqproc_export_1((voidp) 0, clnt); 82738494Sobrien if (mlp) { 82838494Sobrien enum show_opt e = Calc; 82938494Sobrien int mwid = 0, dwid = 0, pwid = 0; 830174313Sobrien 83138494Sobrien while (e != ShowDone) { 832174313Sobrien u_int i; 83338494Sobrien for (i = 0; i < mlp->amq_mount_tree_list_len; i++) { 83438494Sobrien show_mt(mlp->amq_mount_tree_list_val[i], 83538494Sobrien e, &mwid, &dwid, &pwid); 83638494Sobrien } 83738494Sobrien mwid++; 83838494Sobrien dwid++, pwid++; 83938494Sobrien if (e == Calc) 84038494Sobrien e = Short; 84138494Sobrien else if (e == Short) 84238494Sobrien e = ShowDone; 84338494Sobrien } 84438494Sobrien 84538494Sobrien } else { 846310490Scy errs = clnt_failed(clnt, server); 84738494Sobrien } 84838494Sobrien } 84938494Sobrien exit(errs); 85042633Sobrien return errs; /* should never reach here */ 85138494Sobrien} 852