2 * Copyright (c) 1997-2006 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.
8 * This code is derived from software contributed to Berkeley by
9 * Jan-Simon Pendry at Imperial College, London.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgment:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * File: am-utils/amq/amq.c
45 * Automounter query tool
50 #endif /* HAVE_CONFIG_H */
55 static int flush_flag;
56 static int minfo_flag;
57 static int getpid_flag;
58 static int unmount_flag;
59 static int stats_flag;
60 static int getvers_flag;
61 static int amd_program_number = AMQ_PROGRAM;
62 static int use_tcp_flag, use_udp_flag;
63 static int getpwd_flag;
64 static char *debug_opts;
65 static char *amq_logfile;
66 static char *xlog_optstr;
67 static char localhost[] = "localhost";
68 static char *def_server = localhost;
76 Full, Stats, Calc, Short, ShowDone
81 * If (e) is Calc then just calculate the sizes
82 * Otherwise display the mount node on stdout
85 show_mti(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *twid)
90 int mw = strlen(mt->mt_mountinfo);
91 int dw = strlen(mt->mt_directory);
92 int tw = strlen(mt->mt_type);
104 struct tm *tp = localtime((time_t *) ((voidp) &mt->mt_mounttime));
105 printf("%-*.*s %-*.*s %-*.*s %s\n\t%-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%04d %02d:%02d:%02d\n",
107 *mt->mt_directory ? mt->mt_directory : "/", /* XXX */
121 tp->tm_mon + 1, tp->tm_mday,
122 tp->tm_year < 1900 ? tp->tm_year + 1900 : tp->tm_year,
123 tp->tm_hour, tp->tm_min, tp->tm_sec);
129 struct tm *tp = localtime((time_t *) ((voidp) &mt->mt_mounttime));
130 printf("%-*.*s %-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%02d %02d:%02d:%04d\n",
132 *mt->mt_directory ? mt->mt_directory : "/", /* XXX */
141 tp->tm_mon + 1, tp->tm_mday,
142 tp->tm_year < 1900 ? tp->tm_year + 1900 : tp->tm_year,
143 tp->tm_hour, tp->tm_min, tp->tm_sec);
149 printf("%-*.*s %-*.*s %-*.*s %s\n",
151 *mt->mt_directory ? mt->mt_directory : "/",
170 show_pwd(amq_mount_tree *mt, char *path, size_t l, int *flag)
175 len = strlen(mt->mt_mountpoint);
176 if (NSTREQ(path, mt->mt_mountpoint, len) &&
177 !STREQ(mt->mt_directory, mt->mt_mountpoint)) {
178 char buf[MAXPATHLEN+1]; /* must be same size as 'path' */
179 xstrlcpy(buf, mt->mt_directory, sizeof(buf));
180 xstrlcat(buf, &path[len], sizeof(buf));
181 xstrlcpy(path, buf, l);
184 show_pwd(mt->mt_next, path, l, flag);
191 * Display a mount tree.
194 show_mt(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *pwid)
197 show_mti(mt, e, mwid, dwid, pwid);
198 show_mt(mt->mt_next, e, mwid, dwid, pwid);
205 show_mi(amq_mount_info_list *ml, enum show_opt e, int *mwid, int *dwid, int *twid)
213 for (i = 0; i < ml->amq_mount_info_list_len; i++) {
214 amq_mount_info *mi = &ml->amq_mount_info_list_val[i];
215 int mw = strlen(mi->mi_mountinfo);
216 int dw = strlen(mi->mi_mountpt);
217 int tw = strlen(mi->mi_type);
230 for (i = 0; i < ml->amq_mount_info_list_len; i++) {
231 amq_mount_info *mi = &ml->amq_mount_info_list_val[i];
232 printf("%-*.*s %-*.*s %-*.*s %-3d %s is %s",
233 *mwid, *mwid, mi->mi_mountinfo,
234 *dwid, *dwid, mi->mi_mountpt,
235 *twid, *twid, mi->mi_type,
236 mi->mi_refc, mi->mi_fserver,
237 mi->mi_up > 0 ? "up" :
238 mi->mi_up < 0 ? "starting" : "down");
239 if (mi->mi_error > 0) {
240 printf(" (%s)", strerror(mi->mi_error));
241 } else if (mi->mi_error < 0) {
242 fputs(" (in progress)", stdout);
256 * Display general mount statistics
259 show_ms(amq_mount_stats *ms)
262 requests stale mount mount unmount\n\
263 deferred fhandles ok failed failed\n\
264 %-9d %-9d %-9d %-9d %-9d\n",
265 ms->as_drops, ms->as_stale, ms->as_mok, ms->as_merr, ms->as_uerr);
269 #if defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT)
273 struct cct_entry *cp;
275 if (cnodeid() == 0) {
281 while (cp = getccent())
282 if (cp->cnode_type == 'r')
283 return cp->cnode_name;
287 #endif /* defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) */
294 main(int argc, char *argv[])
299 struct sockaddr_in server_addr;
304 char *progname = NULL;
307 * Compute program name
310 progname = strrchr(argv[0], '/');
311 if (progname && progname[1])
318 am_set_progname(progname);
323 while ((opt_ch = getopt(argc, argv, "Hfh:l:msuvx:D:pP:TUw")) != -1)
339 amq_logfile = optarg;
369 xlog_optstr = optarg;
379 amd_program_number = atoi(optarg);
399 if (optind == argc) {
406 Usage: %s [-fmpsvwHTU] [-h hostname] [-l log_file|\"syslog\"]\n\
407 \t[-x log_options] [-D debug_options]\n\
408 \t[-P program_number] [[-u] directory ...]\n",
415 /* set use_udp and use_tcp flags both to on if none are defined */
416 if (!use_tcp_flag && !use_udp_flag)
417 use_tcp_flag = use_udp_flag = 1;
419 #if defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT)
421 * Figure out root server of cluster
423 if (def_server == localhost)
424 server = cluster_server();
426 #endif /* defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) */
430 * Get address of server
432 if ((hp = gethostbyname(server)) == 0 && !STREQ(server, localhost)) {
433 fprintf(stderr, "%s: Can't get address of %s\n",
434 am_get_progname(), server);
437 memset(&server_addr, 0, sizeof(server_addr));
438 /* as per POSIX, sin_len need not be set (used internally by kernel) */
439 server_addr.sin_family = AF_INET;
441 memmove((voidp) &server_addr.sin_addr, (voidp) hp->h_addr,
442 sizeof(server_addr.sin_addr));
444 /* fake "localhost" */
445 server_addr.sin_addr.s_addr = htonl(0x7f000001);
449 * Create RPC endpoint
451 tv.tv_sec = 5; /* 5 seconds for timeout or per retry */
454 if (use_tcp_flag) /* try tcp first */
455 clnt = clnt_create(server, amd_program_number, AMQ_VERSION, "tcp");
456 if (!clnt && use_udp_flag) { /* try udp next */
457 clnt = clnt_create(server, amd_program_number, AMQ_VERSION, "udp");
458 /* if ok, set timeout (valid for connectionless transports only) */
460 clnt_control(clnt, CLSET_RETRY_TIMEOUT, (char *) &tv);
463 fprintf(stderr, "%s: ", am_get_progname());
464 clnt_pcreateerror(server);
474 opt.as_opt = AMOPT_DEBUG;
475 opt.as_str = debug_opts;
476 rc = amqproc_setopt_1(&opt, clnt);
478 fprintf(stderr, "%s: daemon not compiled for debug\n",
481 } else if (!rc || *rc > 0) {
482 fprintf(stderr, "%s: debug setting for \"%s\" failed\n",
483 am_get_progname(), debug_opts);
494 opt.as_opt = AMOPT_XLOG;
495 opt.as_str = xlog_optstr;
496 rc = amqproc_setopt_1(&opt, clnt);
498 fprintf(stderr, "%s: setting log level to \"%s\" failed\n",
499 am_get_progname(), xlog_optstr);
510 opt.as_opt = AMOPT_LOGFILE;
511 opt.as_str = amq_logfile;
512 rc = amqproc_setopt_1(&opt, clnt);
514 fprintf(stderr, "%s: setting logfile to \"%s\" failed\n",
515 am_get_progname(), amq_logfile);
526 opt.as_opt = AMOPT_FLUSHMAPC;
528 rc = amqproc_setopt_1(&opt, clnt);
530 fprintf(stderr, "%s: amd on %s cannot flush the map cache\n",
531 am_get_progname(), server);
540 char path[MAXPATHLEN+1];
541 char *wd = getcwd(path, MAXPATHLEN+1);
542 amq_mount_tree_list *mlp = amqproc_export_1((voidp) 0, clnt);
551 for (i = 0; mlp && i < mlp->amq_mount_tree_list_len; i++) {
552 mt = mlp->amq_mount_tree_list_val[i];
555 show_pwd(mt, path, sizeof(path), &flag);
557 printf("%s\n", path);
570 amq_mount_info_list *ml = amqproc_getmntfs_1(&dummy, clnt);
572 int mwid = 0, dwid = 0, twid = 0;
573 show_mi(ml, Calc, &mwid, &dwid, &twid);
577 show_mi(ml, Full, &mwid, &dwid, &twid);
580 fprintf(stderr, "%s: amd on %s cannot provide mount info\n",
581 am_get_progname(), server);
589 amq_string *spp = amqproc_getvers_1((voidp) 0, clnt);
594 fprintf(stderr, "%s: failed to get version information\n",
604 int *ip = amqproc_getpid_1((voidp) 0, clnt);
608 fprintf(stderr, "%s: failed to get PID of amd\n", am_get_progname());
614 * Apply required operation to all remaining arguments
618 char *fs = argv[optind++];
623 amqproc_umnt_1(&fs, clnt);
628 amq_mount_tree_p *mtp = amqproc_mnttree_1(&fs, clnt);
630 amq_mount_tree *mt = *mtp;
632 int mwid = 0, dwid = 0, twid = 0;
633 show_mt(mt, Calc, &mwid, &dwid, &twid);
636 printf("%-*.*s Uid Getattr Lookup RdDir RdLnk Statfs Mounted@\n",
638 show_mt(mt, Stats, &mwid, &dwid, &twid);
640 fprintf(stderr, "%s: %s not automounted\n", am_get_progname(), fs);
642 xdr_pri_free((XDRPROC_T_TYPE) xdr_amq_mount_tree_p, (caddr_t) mtp);
644 fprintf(stderr, "%s: ", am_get_progname());
645 clnt_perror(clnt, server);
649 } while (optind < argc);
651 } else if (unmount_flag) {
654 } else if (stats_flag) {
655 amq_mount_stats *ms = amqproc_stats_1((voidp) 0, clnt);
659 fprintf(stderr, "%s: ", am_get_progname());
660 clnt_perror(clnt, server);
664 } else if (!nodefault) {
665 amq_mount_tree_list *mlp = amqproc_export_1((voidp) 0, clnt);
667 enum show_opt e = Calc;
668 int mwid = 0, dwid = 0, pwid = 0;
670 while (e != ShowDone) {
672 for (i = 0; i < mlp->amq_mount_tree_list_len; i++) {
673 show_mt(mlp->amq_mount_tree_list_val[i],
674 e, &mwid, &dwid, &pwid);
685 fprintf(stderr, "%s: ", am_get_progname());
686 clnt_perror(clnt, server);
691 return errs; /* should never reach here */