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/amd/get_args.c
3738494Sobrien *
3838494Sobrien */
3938494Sobrien
4038494Sobrien/*
4138494Sobrien * Argument decode
4238494Sobrien */
4338494Sobrien
4438494Sobrien#ifdef HAVE_CONFIG_H
4538494Sobrien# include <config.h>
4638494Sobrien#endif /* HAVE_CONFIG_H */
4738494Sobrien#include <am_defs.h>
4838494Sobrien#include <amd.h>
4938494Sobrien
5038494Sobrien/* include auto-generated version file */
5138494Sobrien#include <build_version.h>
5238494Sobrien
53174313Sobrienchar *amu_conf_file = "/etc/amd.conf"; /* default amd configuration file */
5438494Sobrienchar *conf_tag = NULL;		/* default conf file tags to use */
5538494Sobrienint usage = 0;
5638494Sobrienint use_conf_file = 0;		/* default don't use amd.conf file */
5738494Sobrienchar *mnttab_file_name = NULL;	/* symbol must be available always */
5838494Sobrien
59174313Sobrien
6038494Sobrien/*
6138494Sobrien * Return the version string (dynamic buffer)
6238494Sobrien */
6338494Sobrienchar *
6438494Sobrienget_version_string(void)
6538494Sobrien{
66174313Sobrien  char *vers = NULL;
6738494Sobrien  char tmpbuf[1024];
6838494Sobrien  char *wire_buf;
6938494Sobrien  int wire_buf_len = 0;
70174313Sobrien  size_t len;		  /* max allocated length (to avoid buf overflow) */
7138494Sobrien
72174313Sobrien  /*
73174313Sobrien   * First get dynamic string listing all known networks.
74174313Sobrien   * This could be a long list, if host has lots of interfaces.
75174313Sobrien   */
7638494Sobrien  wire_buf = print_wires();
7738494Sobrien  if (wire_buf)
7838494Sobrien    wire_buf_len = strlen(wire_buf);
7938494Sobrien
80174313Sobrien  len = 2048 + wire_buf_len;
81174313Sobrien  vers = xmalloc(len);
82174313Sobrien  xsnprintf(vers, len, "%s\n%s\n%s\n%s\n",
83310490Scy	    "Copyright (c) 1997-2014 Erez Zadok",
84174313Sobrien	    "Copyright (c) 1990 Jan-Simon Pendry",
85174313Sobrien	    "Copyright (c) 1990 Imperial College of Science, Technology & Medicine",
86174313Sobrien	    "Copyright (c) 1990 The Regents of the University of California.");
87174313Sobrien  xsnprintf(tmpbuf, sizeof(tmpbuf), "%s version %s (build %d).\n",
88174313Sobrien	    PACKAGE_NAME, PACKAGE_VERSION, AMU_BUILD_VERSION);
89310490Scy  xstrlcat(vers, tmpbuf, len);
90174313Sobrien  xsnprintf(tmpbuf, sizeof(tmpbuf), "Report bugs to %s.\n", PACKAGE_BUGREPORT);
91310490Scy  xstrlcat(vers, tmpbuf, len);
92310490Scy#if 0
93310490Scy  /*
94310490Scy   * XXX  This block (between from the #if 0 to #endif was in the
95310490Scy   * XXX  original was in the original merge however in the interest
96310490Scy   * XXX  of reproduceable builds and the fact that this is redundant
97310490Scy   * XXX  information, it is effectively removed.
98310490Scy   */
99174313Sobrien  xsnprintf(tmpbuf, sizeof(tmpbuf), "Configured by %s@%s on date %s.\n",
100174313Sobrien	    USER_NAME, HOST_NAME, CONFIG_DATE);
101310490Scy  xstrlcat(vers, tmpbuf, len);
102310490Scy  xsnprintf(tmpbuf, sizeof(tmpbuf), "Built by %s@%s on date %s.\n",
103310490Scy	    BUILD_USER, BUILD_HOST, BUILD_DATE);
104310490Scy  xstrlcat(vers, tmpbuf, len);
105310490Scy#endif
106310490Scy  xsnprintf(tmpbuf, sizeof(tmpbuf), "Configured by %s@%s on date %s.\n",
107310490Scy	    USER_NAME, HOST_NAME, CONFIG_DATE);
108174313Sobrien  strlcat(vers, tmpbuf, len);
109195626Scperciva  xsnprintf(tmpbuf, sizeof(tmpbuf), "Built by %s@%s.\n",
110195626Scperciva	    BUILD_USER, BUILD_HOST);
111174313Sobrien  strlcat(vers, tmpbuf, len);
112174313Sobrien  xsnprintf(tmpbuf, sizeof(tmpbuf), "cpu=%s (%s-endian), arch=%s, karch=%s.\n",
113174313Sobrien	    cpu, endian, gopt.arch, gopt.karch);
114310490Scy  xstrlcat(vers, tmpbuf, len);
115174313Sobrien  xsnprintf(tmpbuf, sizeof(tmpbuf), "full_os=%s, os=%s, osver=%s, vendor=%s, distro=%s.\n",
116174313Sobrien	    gopt.op_sys_full, gopt.op_sys, gopt.op_sys_ver, gopt.op_sys_vendor, DISTRO_NAME);
117310490Scy  xstrlcat(vers, tmpbuf, len);
118174313Sobrien  xsnprintf(tmpbuf, sizeof(tmpbuf), "domain=%s, host=%s, hostd=%s.\n",
119174313Sobrien	    hostdomain, am_get_hostname(), hostd);
120310490Scy  xstrlcat(vers, tmpbuf, len);
12138494Sobrien
122310490Scy  xstrlcat(vers, "Map support for: ", len);
123174313Sobrien  mapc_showtypes(tmpbuf, sizeof(tmpbuf));
124310490Scy  xstrlcat(vers, tmpbuf, len);
125310490Scy  xstrlcat(vers, ".\nAMFS: ", len);
126174313Sobrien  ops_showamfstypes(tmpbuf, sizeof(tmpbuf));
127310490Scy  xstrlcat(vers, tmpbuf, len);
128310490Scy  xstrlcat(vers, ", inherit.\nFS: ", len); /* hack: "show" that we support type:=inherit */
129174313Sobrien  ops_showfstypes(tmpbuf, sizeof(tmpbuf));
130310490Scy  xstrlcat(vers, tmpbuf, len);
13138494Sobrien
13238494Sobrien  /* append list of networks if available */
13338494Sobrien  if (wire_buf) {
134310490Scy    xstrlcat(vers, wire_buf, len);
13538494Sobrien    XFREE(wire_buf);
13638494Sobrien  }
13738494Sobrien
13838494Sobrien  return vers;
13938494Sobrien}
14038494Sobrien
14138494Sobrien
142174313Sobrienstatic void
143174313Sobrienshow_usage(void)
144174313Sobrien{
145174313Sobrien  fprintf(stderr,
146174313Sobrien	  "Usage: %s [-nprvHS] [-a mount_point] [-c cache_time] [-d domain]\n\
147174313Sobrien\t[-k kernel_arch] [-l logfile%s\n\
148174313Sobrien\t[-t timeout.retrans] [-w wait_timeout] [-A arch] [-C cluster_name]\n\
149174313Sobrien\t[-o op_sys_ver] [-O op_sys_name]\n\
150174313Sobrien\t[-F conf_file] [-T conf_tag]", am_get_progname(),
151174313Sobrien#ifdef HAVE_SYSLOG
152174313Sobrien# ifdef LOG_DAEMON
153174313Sobrien	  "|\"syslog[:facility]\"]"
154174313Sobrien# else /* not LOG_DAEMON */
155174313Sobrien	  "|\"syslog\"]"
156174313Sobrien# endif /* not LOG_DAEMON */
157174313Sobrien#else /* not HAVE_SYSLOG */
158174313Sobrien	  "]"
159174313Sobrien#endif /* not HAVE_SYSLOG */
160174313Sobrien	  );
161174313Sobrien
162174313Sobrien#ifdef HAVE_MAP_NIS
163174313Sobrien  fputs(" [-y nis-domain]\n", stderr);
164174313Sobrien#else /* not HAVE_MAP_NIS */
165174313Sobrien  fputc('\n', stderr);
166174313Sobrien#endif /* HAVE_MAP_NIS */
167174313Sobrien
168174313Sobrien  show_opts('x', xlog_opt);
169174313Sobrien#ifdef DEBUG
170174313Sobrien  show_opts('D', dbg_opt);
171174313Sobrien#endif /* DEBUG */
172174313Sobrien  fprintf(stderr, "\t[directory mapname [-map_options]] ...\n");
173174313Sobrien}
174174313Sobrien
175174313Sobrien
17638494Sobrienvoid
17738494Sobrienget_args(int argc, char *argv[])
17838494Sobrien{
179174313Sobrien  int opt_ch, i;
18038494Sobrien  FILE *fp = stdin;
181174313Sobrien  char getopt_arguments[] = "+nprvSa:c:d:k:l:o:t:w:x:y:C:D:F:T:O:HA:";
182119682Smbr  char *getopt_args;
183174313Sobrien  int print_version = 0;	/* 1 means we should print version info */
18438494Sobrien
185119682Smbr#ifdef HAVE_GNU_GETOPT
186119682Smbr  getopt_args = getopt_arguments;
187119682Smbr#else /* ! HAVE_GNU_GETOPT */
188119682Smbr  getopt_args = &getopt_arguments[1];
189119682Smbr#endif /* HAVE_GNU_GETOPT */
190119682Smbr
19138494Sobrien  /* if no arguments were passed, try to use /etc/amd.conf file */
19238494Sobrien  if (argc <= 1)
19338494Sobrien    use_conf_file = 1;
19438494Sobrien
195119682Smbr  while ((opt_ch = getopt(argc, argv, getopt_args)) != -1)
19638494Sobrien    switch (opt_ch) {
19738494Sobrien
19838494Sobrien    case 'a':
19938494Sobrien      if (*optarg != '/') {
20038494Sobrien	fprintf(stderr, "%s: -a option must begin with a '/'\n",
20142633Sobrien		am_get_progname());
20238494Sobrien	exit(1);
20338494Sobrien      }
20438494Sobrien      gopt.auto_dir = optarg;
20538494Sobrien      break;
20638494Sobrien
20738494Sobrien    case 'c':
20838494Sobrien      gopt.am_timeo = atoi(optarg);
20938494Sobrien      if (gopt.am_timeo <= 0)
21038494Sobrien	gopt.am_timeo = AM_TTL;
21138494Sobrien      break;
21238494Sobrien
21338494Sobrien    case 'd':
21438494Sobrien      gopt.sub_domain = optarg;
21538494Sobrien      break;
21638494Sobrien
21738494Sobrien    case 'k':
21838494Sobrien      gopt.karch = optarg;
21938494Sobrien      break;
22038494Sobrien
22138494Sobrien    case 'l':
22238494Sobrien      gopt.logfile = optarg;
22338494Sobrien      break;
22438494Sobrien
22538494Sobrien    case 'n':
22638494Sobrien      gopt.flags |= CFM_NORMALIZE_HOSTNAMES;
22738494Sobrien      break;
22838494Sobrien
22938494Sobrien    case 'o':
23038494Sobrien      gopt.op_sys_ver = optarg;
23138494Sobrien      break;
23238494Sobrien
23338494Sobrien    case 'p':
23438494Sobrien     gopt.flags |= CFM_PRINT_PID;
23538494Sobrien      break;
23638494Sobrien
23738494Sobrien    case 'r':
23838494Sobrien      gopt.flags |= CFM_RESTART_EXISTING_MOUNTS;
23938494Sobrien      break;
24038494Sobrien
24138494Sobrien    case 't':
242174313Sobrien      /* timeo.retrans (also affects toplvl mounts) */
24338494Sobrien      {
24438494Sobrien	char *dot = strchr(optarg, '.');
245174313Sobrien	int i;
24638494Sobrien	if (dot)
24738494Sobrien	  *dot = '\0';
24838494Sobrien	if (*optarg) {
249174313Sobrien	  for (i=0; i<AMU_TYPE_MAX; ++i)
250174313Sobrien	    gopt.amfs_auto_timeo[i] = atoi(optarg);
25138494Sobrien	}
25238494Sobrien	if (dot) {
253174313Sobrien	  for (i=0; i<AMU_TYPE_MAX; ++i)
254174313Sobrien	    gopt.amfs_auto_retrans[i] = atoi(dot + 1);
25538494Sobrien	  *dot = '.';
25638494Sobrien	}
25738494Sobrien      }
25838494Sobrien      break;
25938494Sobrien
26038494Sobrien    case 'v':
261174313Sobrien      /*
262174313Sobrien       * defer to print version info after every variable had been
263174313Sobrien       * initialized.
264174313Sobrien       */
265174313Sobrien      print_version++;
26638494Sobrien      break;
26738494Sobrien
26838494Sobrien    case 'w':
26938494Sobrien      gopt.am_timeo_w = atoi(optarg);
27038494Sobrien      if (gopt.am_timeo_w <= 0)
27138494Sobrien	gopt.am_timeo_w = AM_TTL_W;
27238494Sobrien      break;
27338494Sobrien
27438494Sobrien    case 'x':
27538494Sobrien      usage += switch_option(optarg);
27638494Sobrien      break;
27738494Sobrien
27838494Sobrien    case 'y':
27938494Sobrien#ifdef HAVE_MAP_NIS
28038494Sobrien      gopt.nis_domain = optarg;
28138494Sobrien#else /* not HAVE_MAP_NIS */
28238494Sobrien      plog(XLOG_USER, "-y: option ignored.  No NIS support available.");
28338494Sobrien#endif /* not HAVE_MAP_NIS */
28438494Sobrien      break;
28538494Sobrien
286174313Sobrien    case 'A':
287174313Sobrien      gopt.arch = optarg;
288174313Sobrien      break;
289174313Sobrien
29038494Sobrien    case 'C':
29138494Sobrien      gopt.cluster = optarg;
29238494Sobrien      break;
29338494Sobrien
29438494Sobrien    case 'D':
29538494Sobrien#ifdef DEBUG
29638494Sobrien      usage += debug_option(optarg);
29738494Sobrien#else /* not DEBUG */
29842633Sobrien      fprintf(stderr, "%s: not compiled with DEBUG option -- sorry.\n",
29942633Sobrien	      am_get_progname());
30038494Sobrien#endif /* not DEBUG */
30138494Sobrien      break;
30238494Sobrien
30338494Sobrien    case 'F':
304174313Sobrien      amu_conf_file = optarg;
30538494Sobrien      use_conf_file = 1;
30638494Sobrien      break;
30738494Sobrien
30838494Sobrien    case 'H':
309174313Sobrien      show_usage();
310174313Sobrien      exit(1);
31138494Sobrien      break;
31238494Sobrien
31338494Sobrien    case 'O':
31438494Sobrien      gopt.op_sys = optarg;
31538494Sobrien      break;
31638494Sobrien
31738494Sobrien    case 'S':
31838494Sobrien      gopt.flags &= ~CFM_PROCESS_LOCK; /* turn process locking off */
31938494Sobrien      break;
32038494Sobrien
32138494Sobrien    case 'T':
32238494Sobrien      conf_tag = optarg;
32338494Sobrien      break;
32438494Sobrien
32538494Sobrien    default:
32638494Sobrien      usage = 1;
32738494Sobrien      break;
32838494Sobrien    }
32938494Sobrien
33038494Sobrien  /*
33138494Sobrien   * amd.conf file: if not command-line arguments were used, or if -F was
33238494Sobrien   * specified, then use that amd.conf file.  If the file cannot be opened,
33338494Sobrien   * abort amd.  If it can be found, open it, parse it, and then close it.
33438494Sobrien   */
335174313Sobrien  if (use_conf_file && amu_conf_file) {
336174313Sobrien    fp = fopen(amu_conf_file, "r");
33738494Sobrien    if (!fp) {
33838494Sobrien      char buf[128];
339174313Sobrien      xsnprintf(buf, sizeof(buf), "Amd configuration file (%s)",
340174313Sobrien		amu_conf_file);
34138494Sobrien      perror(buf);
34238494Sobrien      exit(1);
34338494Sobrien    }
344310490Scy    conf_in = fp;
345310490Scy    conf_parse();
34638494Sobrien    fclose(fp);
347174313Sobrien    if (process_all_regular_maps() != 0)
34838494Sobrien      exit(1);
34938494Sobrien  }
35038494Sobrien
35138494Sobrien#ifdef DEBUG
35238494Sobrien  usage += switch_option("debug");
353310490Scy  /* initialize debug options */
354310490Scy  if (!debug_flags)
355310490Scy    debug_flags = D_CONTROL;	/* CONTROL = "daemon,amq,fork" */
35638494Sobrien#endif /* DEBUG */
35738494Sobrien
35838494Sobrien  /* log information regarding amd.conf file */
359174313Sobrien  if (use_conf_file && amu_conf_file)
360174313Sobrien    plog(XLOG_INFO, "using configuration file %s", amu_conf_file);
36138494Sobrien
36238494Sobrien#ifdef HAVE_MAP_LDAP
36338494Sobrien  /* ensure that if ldap_base is specified, that also ldap_hostports is */
36438494Sobrien  if (gopt.ldap_hostports && !gopt.ldap_base) {
36538494Sobrien    fprintf(stderr, "must specify both ldap_hostports and ldap_base\n");
36638494Sobrien    exit(1);
36738494Sobrien  }
36838494Sobrien#endif /* HAVE_MAP_LDAP */
36938494Sobrien
370174313Sobrien  if (usage) {
371174313Sobrien    show_usage();
372174313Sobrien    exit(1);
373174313Sobrien  }
37438494Sobrien
37538494Sobrien  while (optind <= argc - 2) {
37638494Sobrien    char *dir = argv[optind++];
37738494Sobrien    char *map = argv[optind++];
37838494Sobrien    char *opts = "";
37938494Sobrien    if (argv[optind] && *argv[optind] == '-')
38038494Sobrien      opts = &argv[optind++][1];
38138494Sobrien
38238494Sobrien    root_newmap(dir, opts, map, NULL);
38338494Sobrien  }
38438494Sobrien
38538494Sobrien  if (optind == argc) {
38638494Sobrien    /*
38738494Sobrien     * Append domain name to hostname.
38838494Sobrien     * sub_domain overrides hostdomain
38938494Sobrien     * if given.
39038494Sobrien     */
39138494Sobrien    if (gopt.sub_domain)
39238494Sobrien      hostdomain = gopt.sub_domain;
39338494Sobrien    if (*hostdomain == '.')
39438494Sobrien      hostdomain++;
395174313Sobrien    xstrlcat(hostd, ".", sizeof(hostd));
396174313Sobrien    xstrlcat(hostd, hostdomain, sizeof(hostd));
39738494Sobrien
39838494Sobrien#ifdef MOUNT_TABLE_ON_FILE
399174313Sobrien    if (amuDebug(D_MTAB))
400174313Sobrien      if (gopt.debug_mtab_file)
401174313Sobrien        mnttab_file_name = gopt.debug_mtab_file; /* user supplied debug mtab path */
402174313Sobrien      else
403174313Sobrien	mnttab_file_name = DEBUG_MNTTAB_FILE; /* default debug mtab path */
40438494Sobrien    else
40538494Sobrien      mnttab_file_name = MNTTAB_FILE_NAME;
40638494Sobrien#else /* not MOUNT_TABLE_ON_FILE */
407174313Sobrien    if (amuDebug(D_MTAB))
40838494Sobrien      dlog("-D mtab option ignored");
40982799Sobrien# ifdef MNTTAB_FILE_NAME
41082799Sobrien    mnttab_file_name = MNTTAB_FILE_NAME;
41182799Sobrien# endif /* MNTTAB_FILE_NAME */
41238494Sobrien#endif /* not MOUNT_TABLE_ON_FILE */
41338494Sobrien
41438494Sobrien    /*
41538494Sobrien     * If the kernel architecture was not specified
41638494Sobrien     * then use the machine architecture.
41738494Sobrien     */
418174313Sobrien    if (gopt.karch == NULL)
41938494Sobrien      gopt.karch = gopt.arch;
42038494Sobrien
421174313Sobrien    if (gopt.cluster == NULL)
42238494Sobrien      gopt.cluster = hostdomain;
42338494Sobrien
424174313Sobrien    /* sanity checking, normalize values just in case (toplvl too) */
425174313Sobrien    for (i=0; i<AMU_TYPE_MAX; ++i) {
426174313Sobrien      if (gopt.amfs_auto_timeo[i] == 0)
427174313Sobrien	gopt.amfs_auto_timeo[i] = AMFS_AUTO_TIMEO;
428174313Sobrien      if (gopt.amfs_auto_retrans[i] == 0)
429174313Sobrien	gopt.amfs_auto_retrans[i] = AMFS_AUTO_RETRANS(i);
430174313Sobrien      if (gopt.amfs_auto_retrans[i] == 0)
431174313Sobrien	gopt.amfs_auto_retrans[i] = 3;	/* under very unusual circumstances, could be zero */
432174313Sobrien    }
43338494Sobrien  }
43438494Sobrien
435174313Sobrien  /* finally print version string and exit, if asked for */
436174313Sobrien  if (print_version) {
437174313Sobrien    fputs(get_version_string(), stderr);
438174313Sobrien    exit(0);
439174313Sobrien  }
44038494Sobrien
441174313Sobrien  if (switch_to_logfile(gopt.logfile, orig_umask,
442174313Sobrien			(gopt.flags & CFM_TRUNCATE_LOG)) != 0)
443174313Sobrien    plog(XLOG_USER, "Cannot switch logfile");
44438494Sobrien
445174313Sobrien  return;
44638494Sobrien}
447