2 * Copyright (c) 1997-2004 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
41 * $Id: amq.c,v 1.7.2.9 2004/01/06 03:15:16 ezk Exp $
45 #include <sys/cdefs.h>
46 __FBSDID("$FreeBSD$");
49 * Automounter query tool
54 @(#)Copyright (c) 1997-2004 Erez Zadok\n\
55 @(#)Copyright (c) 1990 Jan-Simon Pendry\n\
56 @(#)Copyright (c) 1990 Imperial College of Science, Technology & Medicine\n\
57 @(#)Copyright (c) 1990 The Regents of the University of California.\n\
58 @(#)All rights reserved.\n";
60 static char rcsid[] = "$Id: amq.c,v 1.7.2.9 2004/01/06 03:15:16 ezk Exp $";
61 static char sccsid[] = "%W% (Berkeley) %G%";
62 #endif /* __GNUC__ < 2 */
67 #endif /* HAVE_CONFIG_H */
72 static int flush_flag;
73 static int minfo_flag;
74 static int getpid_flag;
75 static int unmount_flag;
76 static int stats_flag;
77 static int getvers_flag;
78 static int amd_program_number = AMQ_PROGRAM;
79 static int use_tcp_flag, use_udp_flag;
80 static int getpwd_flag;
81 static char *debug_opts;
82 static char *amq_logfile;
83 static char *xlog_optstr;
84 static char localhost[] = "localhost";
85 static char *def_server = localhost;
93 Full, Stats, Calc, Short, ShowDone
98 * If (e) is Calc then just calculate the sizes
99 * Otherwise display the mount node on stdout
102 show_mti(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *twid)
107 int mw = strlen(mt->mt_mountinfo);
108 int dw = strlen(mt->mt_directory);
109 int tw = strlen(mt->mt_type);
121 struct tm *tp = localtime((time_t *) &mt->mt_mounttime);
122 printf("%-*.*s %-*.*s %-*.*s %s\n\t%-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%02d %02d:%02d:%02d\n",
124 *mt->mt_directory ? mt->mt_directory : "/", /* XXX */
138 tp->tm_year > 99 ? tp->tm_year - 100 : tp->tm_year,
139 tp->tm_mon + 1, tp->tm_mday,
140 tp->tm_hour, tp->tm_min, tp->tm_sec);
146 struct tm *tp = localtime((time_t *) &mt->mt_mounttime);
147 printf("%-*.*s %-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%02d %02d:%02d:%02d\n",
149 *mt->mt_directory ? mt->mt_directory : "/", /* XXX */
158 tp->tm_year > 99 ? tp->tm_year - 100 : tp->tm_year,
159 tp->tm_mon + 1, tp->tm_mday,
160 tp->tm_hour, tp->tm_min, tp->tm_sec);
166 printf("%-*.*s %-*.*s %-*.*s %s\n",
168 *mt->mt_directory ? mt->mt_directory : "/",
187 show_pwd(amq_mount_tree *mt, char *path, int *flag)
192 len = strlen(mt->mt_mountpoint);
193 if (NSTREQ(path, mt->mt_mountpoint, len) &&
194 !STREQ(mt->mt_directory, mt->mt_mountpoint)) {
195 char buf[MAXPATHLEN+1];
196 strcpy(buf, mt->mt_directory);
197 strcat(buf, &path[len]);
201 show_pwd(mt->mt_next, path, flag);
208 * Display a mount tree.
211 show_mt(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *pwid)
214 show_mti(mt, e, mwid, dwid, pwid);
215 show_mt(mt->mt_next, e, mwid, dwid, pwid);
222 show_mi(amq_mount_info_list *ml, enum show_opt e, int *mwid, int *dwid, int *twid)
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 int mw = strlen(mi->mi_mountinfo);
233 int dw = strlen(mi->mi_mountpt);
234 int tw = strlen(mi->mi_type);
247 for (i = 0; i < ml->amq_mount_info_list_len; i++) {
248 amq_mount_info *mi = &ml->amq_mount_info_list_val[i];
249 printf("%-*.*s %-*.*s %-*.*s %-3d %s is %s",
250 *mwid, *mwid, mi->mi_mountinfo,
251 *dwid, *dwid, mi->mi_mountpt,
252 *twid, *twid, mi->mi_type,
253 mi->mi_refc, mi->mi_fserver,
254 mi->mi_up > 0 ? "up" :
255 mi->mi_up < 0 ? "starting" : "down");
256 if (mi->mi_error > 0) {
257 if (mi->mi_error < sys_nerr)
259 printf(" (%s)", strerror(mi->mi_error));
260 #else /* not HAVE_STRERROR */
261 printf(" (%s)", sys_errlist[mi->mi_error]);
262 #endif /* not HAVE_STRERROR */
264 printf(" (Error %d)", mi->mi_error);
265 } else if (mi->mi_error < 0) {
266 fputs(" (in progress)", stdout);
280 * Display general mount statistics
283 show_ms(amq_mount_stats *ms)
286 requests stale mount mount unmount\n\
287 deferred fhandles ok failed failed\n\
288 %-9d %-9d %-9d %-9d %-9d\n",
289 ms->as_drops, ms->as_stale, ms->as_mok, ms->as_merr, ms->as_uerr);
293 #if defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT)
297 struct cct_entry *cp;
299 if (cnodeid() == 0) {
305 while (cp = getccent())
306 if (cp->cnode_type == 'r')
307 return cp->cnode_name;
311 #endif /* defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) */
318 main(int argc, char *argv[])
323 struct sockaddr_in server_addr;
328 char *progname = NULL;
331 * Compute program name
334 progname = strrchr(argv[0], '/');
335 if (progname && progname[1])
342 am_set_progname(progname);
347 while ((opt_ch = getopt(argc, argv, "Hfh:l:msuvx:D:pP:TUw")) != -1)
363 amq_logfile = optarg;
393 xlog_optstr = optarg;
403 amd_program_number = atoi(optarg);
423 if (optind == argc) {
430 Usage: %s [-fmpsvwHTU] [-h hostname] [-l log_file|\"syslog\"]\n\
431 \t[-x log_options] [-D debug_options]\n\
432 \t[-P program_number] [[-u] directory ...]\n",
439 /* set use_udp and use_tcp flags both to on if none are defined */
440 if (!use_tcp_flag && !use_udp_flag)
441 use_tcp_flag = use_udp_flag = 1;
443 #if defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT)
445 * Figure out root server of cluster
447 if (def_server == localhost)
448 server = cluster_server();
450 #endif /* defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) */
454 * Get address of server
456 if ((hp = gethostbyname(server)) == 0 && !STREQ(server, localhost)) {
457 fprintf(stderr, "%s: Can't get address of %s\n",
458 am_get_progname(), server);
461 memset(&server_addr, 0, sizeof server_addr);
462 server_addr.sin_family = AF_INET;
464 memmove((voidp) &server_addr.sin_addr, (voidp) hp->h_addr,
465 sizeof(server_addr.sin_addr));
467 /* fake "localhost" */
468 server_addr.sin_addr.s_addr = htonl(0x7f000001);
472 * Create RPC endpoint
474 tv.tv_sec = 5; /* 5 seconds for timeout or per retry */
477 if (use_tcp_flag) /* try tcp first */
478 clnt = clnt_create(server, amd_program_number, AMQ_VERSION, "tcp");
479 if (!clnt && use_udp_flag) { /* try udp next */
480 clnt = clnt_create(server, amd_program_number, AMQ_VERSION, "udp");
481 /* if ok, set timeout (valid for connectionless transports only) */
483 clnt_control(clnt, CLSET_RETRY_TIMEOUT, (char *) &tv);
486 fprintf(stderr, "%s: ", am_get_progname());
487 clnt_pcreateerror(server);
497 opt.as_opt = AMOPT_DEBUG;
498 opt.as_str = debug_opts;
499 rc = amqproc_setopt_1(&opt, clnt);
501 fprintf(stderr, "%s: daemon not compiled for debug\n",
504 } else if (!rc || *rc > 0) {
505 fprintf(stderr, "%s: debug setting for \"%s\" failed\n",
506 am_get_progname(), debug_opts);
517 opt.as_opt = AMOPT_XLOG;
518 opt.as_str = xlog_optstr;
519 rc = amqproc_setopt_1(&opt, clnt);
521 fprintf(stderr, "%s: setting log level to \"%s\" failed\n",
522 am_get_progname(), xlog_optstr);
533 opt.as_opt = AMOPT_LOGFILE;
534 opt.as_str = amq_logfile;
535 rc = amqproc_setopt_1(&opt, clnt);
537 fprintf(stderr, "%s: setting logfile to \"%s\" failed\n",
538 am_get_progname(), amq_logfile);
549 opt.as_opt = AMOPT_FLUSHMAPC;
551 rc = amqproc_setopt_1(&opt, clnt);
553 fprintf(stderr, "%s: amd on %s cannot flush the map cache\n",
554 am_get_progname(), server);
563 char path[MAXPATHLEN+1];
564 char *wd = getcwd(path, MAXPATHLEN+1);
565 amq_mount_tree_list *mlp = amqproc_export_1((voidp) 0, clnt);
573 for (i = 0; mlp && i < mlp->amq_mount_tree_list_len; i++) {
574 mt = mlp->amq_mount_tree_list_val[i];
577 show_pwd(mt, path, &flag);
579 printf("%s\n", path);
592 amq_mount_info_list *ml = amqproc_getmntfs_1(&dummy, clnt);
594 int mwid = 0, dwid = 0, twid = 0;
595 show_mi(ml, Calc, &mwid, &dwid, &twid);
599 show_mi(ml, Full, &mwid, &dwid, &twid);
602 fprintf(stderr, "%s: amd on %s cannot provide mount info\n",
603 am_get_progname(), server);
611 amq_string *spp = amqproc_getvers_1((voidp) 0, clnt);
616 fprintf(stderr, "%s: failed to get version information\n",
626 int *ip = amqproc_getpid_1((voidp) 0, clnt);
630 fprintf(stderr, "%s: failed to get PID of amd\n", am_get_progname());
636 * Apply required operation to all remaining arguments
640 char *fs = argv[optind++];
645 amqproc_umnt_1(&fs, clnt);
650 amq_mount_tree_p *mtp = amqproc_mnttree_1(&fs, clnt);
652 amq_mount_tree *mt = *mtp;
654 int mwid = 0, dwid = 0, twid = 0;
655 show_mt(mt, Calc, &mwid, &dwid, &twid);
658 printf("%-*.*s Uid Getattr Lookup RdDir RdLnk Statfs Mounted@\n",
660 show_mt(mt, Stats, &mwid, &dwid, &twid);
662 fprintf(stderr, "%s: %s not automounted\n", am_get_progname(), fs);
664 xdr_pri_free((XDRPROC_T_TYPE) xdr_amq_mount_tree_p, (caddr_t) mtp);
666 fprintf(stderr, "%s: ", am_get_progname());
667 clnt_perror(clnt, server);
671 } while (optind < argc);
673 } else if (unmount_flag) {
676 } else if (stats_flag) {
677 amq_mount_stats *ms = amqproc_stats_1((voidp) 0, clnt);
681 fprintf(stderr, "%s: ", am_get_progname());
682 clnt_perror(clnt, server);
686 } else if (!nodefault) {
687 amq_mount_tree_list *mlp = amqproc_export_1((voidp) 0, clnt);
689 enum show_opt e = Calc;
690 int mwid = 0, dwid = 0, pwid = 0;
691 while (e != ShowDone) {
693 for (i = 0; i < mlp->amq_mount_tree_list_len; i++) {
694 show_mt(mlp->amq_mount_tree_list_val[i],
695 e, &mwid, &dwid, &pwid);
706 fprintf(stderr, "%s: ", am_get_progname());
707 clnt_perror(clnt, server);
712 return errs; /* should never reach here */