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