138494Sobrien/*
2174313Sobrien * Copyright (c) 1997-2006 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.
1938494Sobrien * 3. All advertising materials mentioning features or use of this software
2042633Sobrien *    must display the following acknowledgment:
2138494Sobrien *      This product includes software developed by the University of
2238494Sobrien *      California, Berkeley and its contributors.
2338494Sobrien * 4. Neither the name of the University nor the names of its contributors
2438494Sobrien *    may be used to endorse or promote products derived from this software
2538494Sobrien *    without specific prior written permission.
2638494Sobrien *
2738494Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2838494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2938494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3038494Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3138494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3238494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3338494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3438494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3538494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3638494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3738494Sobrien * SUCH DAMAGE.
3838494Sobrien *
3938494Sobrien *
40174313Sobrien * File: am-utils/amd/get_args.c
4138494Sobrien *
4238494Sobrien */
4338494Sobrien
4438494Sobrien/*
4538494Sobrien * Argument decode
4638494Sobrien */
4738494Sobrien
4838494Sobrien#ifdef HAVE_CONFIG_H
4938494Sobrien# include <config.h>
5038494Sobrien#endif /* HAVE_CONFIG_H */
5138494Sobrien#include <am_defs.h>
5238494Sobrien#include <amd.h>
5338494Sobrien
5438494Sobrien/* include auto-generated version file */
5538494Sobrien#include <build_version.h>
5638494Sobrien
57174313Sobrienchar *amu_conf_file = "/etc/amd.conf"; /* default amd configuration file */
5838494Sobrienchar *conf_tag = NULL;		/* default conf file tags to use */
5938494Sobrienint usage = 0;
6038494Sobrienint use_conf_file = 0;		/* default don't use amd.conf file */
6138494Sobrienchar *mnttab_file_name = NULL;	/* symbol must be available always */
6238494Sobrien
63174313Sobrien
6438494Sobrien/*
6538494Sobrien * Return the version string (dynamic buffer)
6638494Sobrien */
6738494Sobrienchar *
6838494Sobrienget_version_string(void)
6938494Sobrien{
70174313Sobrien  char *vers = NULL;
7138494Sobrien  char tmpbuf[1024];
7238494Sobrien  char *wire_buf;
7338494Sobrien  int wire_buf_len = 0;
74174313Sobrien  size_t len;		  /* max allocated length (to avoid buf overflow) */
7538494Sobrien
76174313Sobrien  /*
77174313Sobrien   * First get dynamic string listing all known networks.
78174313Sobrien   * This could be a long list, if host has lots of interfaces.
79174313Sobrien   */
8038494Sobrien  wire_buf = print_wires();
8138494Sobrien  if (wire_buf)
8238494Sobrien    wire_buf_len = strlen(wire_buf);
8338494Sobrien
84174313Sobrien  len = 2048 + wire_buf_len;
85174313Sobrien  vers = xmalloc(len);
86174313Sobrien  xsnprintf(vers, len, "%s\n%s\n%s\n%s\n",
87174313Sobrien	    "Copyright (c) 1997-2006 Erez Zadok",
88174313Sobrien	    "Copyright (c) 1990 Jan-Simon Pendry",
89174313Sobrien	    "Copyright (c) 1990 Imperial College of Science, Technology & Medicine",
90174313Sobrien	    "Copyright (c) 1990 The Regents of the University of California.");
91174313Sobrien  xsnprintf(tmpbuf, sizeof(tmpbuf), "%s version %s (build %d).\n",
92174313Sobrien	    PACKAGE_NAME, PACKAGE_VERSION, AMU_BUILD_VERSION);
93174313Sobrien  strlcat(vers, tmpbuf, len);
94174313Sobrien  xsnprintf(tmpbuf, sizeof(tmpbuf), "Report bugs to %s.\n", PACKAGE_BUGREPORT);
95174313Sobrien  strlcat(vers, tmpbuf, len);
96174313Sobrien  xsnprintf(tmpbuf, sizeof(tmpbuf), "Configured by %s@%s on date %s.\n",
97174313Sobrien	    USER_NAME, HOST_NAME, CONFIG_DATE);
98174313Sobrien  strlcat(vers, tmpbuf, len);
99195626Scperciva  xsnprintf(tmpbuf, sizeof(tmpbuf), "Built by %s@%s.\n",
100195626Scperciva	    BUILD_USER, BUILD_HOST);
101174313Sobrien  strlcat(vers, tmpbuf, len);
102174313Sobrien  xsnprintf(tmpbuf, sizeof(tmpbuf), "cpu=%s (%s-endian), arch=%s, karch=%s.\n",
103174313Sobrien	    cpu, endian, gopt.arch, gopt.karch);
104174313Sobrien  strlcat(vers, tmpbuf, len);
105174313Sobrien  xsnprintf(tmpbuf, sizeof(tmpbuf), "full_os=%s, os=%s, osver=%s, vendor=%s, distro=%s.\n",
106174313Sobrien	    gopt.op_sys_full, gopt.op_sys, gopt.op_sys_ver, gopt.op_sys_vendor, DISTRO_NAME);
107174313Sobrien  strlcat(vers, tmpbuf, len);
108174313Sobrien  xsnprintf(tmpbuf, sizeof(tmpbuf), "domain=%s, host=%s, hostd=%s.\n",
109174313Sobrien	    hostdomain, am_get_hostname(), hostd);
110174313Sobrien  strlcat(vers, tmpbuf, len);
11138494Sobrien
112174313Sobrien  strlcat(vers, "Map support for: ", len);
113174313Sobrien  mapc_showtypes(tmpbuf, sizeof(tmpbuf));
114174313Sobrien  strlcat(vers, tmpbuf, len);
115174313Sobrien  strlcat(vers, ".\nAMFS: ", len);
116174313Sobrien  ops_showamfstypes(tmpbuf, sizeof(tmpbuf));
117174313Sobrien  strlcat(vers, tmpbuf, len);
118174313Sobrien  strlcat(vers, ", inherit.\nFS: ", len); /* hack: "show" that we support type:=inherit */
119174313Sobrien  ops_showfstypes(tmpbuf, sizeof(tmpbuf));
120174313Sobrien  strlcat(vers, tmpbuf, len);
12138494Sobrien
12238494Sobrien  /* append list of networks if available */
12338494Sobrien  if (wire_buf) {
124174313Sobrien    strlcat(vers, wire_buf, len);
12538494Sobrien    XFREE(wire_buf);
12638494Sobrien  }
12738494Sobrien
12838494Sobrien  return vers;
12938494Sobrien}
13038494Sobrien
13138494Sobrien
132174313Sobrienstatic void
133174313Sobrienshow_usage(void)
134174313Sobrien{
135174313Sobrien  fprintf(stderr,
136174313Sobrien	  "Usage: %s [-nprvHS] [-a mount_point] [-c cache_time] [-d domain]\n\
137174313Sobrien\t[-k kernel_arch] [-l logfile%s\n\
138174313Sobrien\t[-t timeout.retrans] [-w wait_timeout] [-A arch] [-C cluster_name]\n\
139174313Sobrien\t[-o op_sys_ver] [-O op_sys_name]\n\
140174313Sobrien\t[-F conf_file] [-T conf_tag]", am_get_progname(),
141174313Sobrien#ifdef HAVE_SYSLOG
142174313Sobrien# ifdef LOG_DAEMON
143174313Sobrien	  "|\"syslog[:facility]\"]"
144174313Sobrien# else /* not LOG_DAEMON */
145174313Sobrien	  "|\"syslog\"]"
146174313Sobrien# endif /* not LOG_DAEMON */
147174313Sobrien#else /* not HAVE_SYSLOG */
148174313Sobrien	  "]"
149174313Sobrien#endif /* not HAVE_SYSLOG */
150174313Sobrien	  );
151174313Sobrien
152174313Sobrien#ifdef HAVE_MAP_NIS
153174313Sobrien  fputs(" [-y nis-domain]\n", stderr);
154174313Sobrien#else /* not HAVE_MAP_NIS */
155174313Sobrien  fputc('\n', stderr);
156174313Sobrien#endif /* HAVE_MAP_NIS */
157174313Sobrien
158174313Sobrien  show_opts('x', xlog_opt);
159174313Sobrien#ifdef DEBUG
160174313Sobrien  show_opts('D', dbg_opt);
161174313Sobrien#endif /* DEBUG */
162174313Sobrien  fprintf(stderr, "\t[directory mapname [-map_options]] ...\n");
163174313Sobrien}
164174313Sobrien
165174313Sobrien
16638494Sobrienvoid
16738494Sobrienget_args(int argc, char *argv[])
16838494Sobrien{
169174313Sobrien  int opt_ch, i;
17038494Sobrien  FILE *fp = stdin;
171174313Sobrien  char getopt_arguments[] = "+nprvSa:c:d:k:l:o:t:w:x:y:C:D:F:T:O:HA:";
172119682Smbr  char *getopt_args;
173174313Sobrien  int print_version = 0;	/* 1 means we should print version info */
17438494Sobrien
175119682Smbr#ifdef HAVE_GNU_GETOPT
176119682Smbr  getopt_args = getopt_arguments;
177119682Smbr#else /* ! HAVE_GNU_GETOPT */
178119682Smbr  getopt_args = &getopt_arguments[1];
179119682Smbr#endif /* HAVE_GNU_GETOPT */
180119682Smbr
18138494Sobrien  /* if no arguments were passed, try to use /etc/amd.conf file */
18238494Sobrien  if (argc <= 1)
18338494Sobrien    use_conf_file = 1;
18438494Sobrien
185119682Smbr  while ((opt_ch = getopt(argc, argv, getopt_args)) != -1)
18638494Sobrien    switch (opt_ch) {
18738494Sobrien
18838494Sobrien    case 'a':
18938494Sobrien      if (*optarg != '/') {
19038494Sobrien	fprintf(stderr, "%s: -a option must begin with a '/'\n",
19142633Sobrien		am_get_progname());
19238494Sobrien	exit(1);
19338494Sobrien      }
19438494Sobrien      gopt.auto_dir = optarg;
19538494Sobrien      break;
19638494Sobrien
19738494Sobrien    case 'c':
19838494Sobrien      gopt.am_timeo = atoi(optarg);
19938494Sobrien      if (gopt.am_timeo <= 0)
20038494Sobrien	gopt.am_timeo = AM_TTL;
20138494Sobrien      break;
20238494Sobrien
20338494Sobrien    case 'd':
20438494Sobrien      gopt.sub_domain = optarg;
20538494Sobrien      break;
20638494Sobrien
20738494Sobrien    case 'k':
20838494Sobrien      gopt.karch = optarg;
20938494Sobrien      break;
21038494Sobrien
21138494Sobrien    case 'l':
21238494Sobrien      gopt.logfile = optarg;
21338494Sobrien      break;
21438494Sobrien
21538494Sobrien    case 'n':
21638494Sobrien      gopt.flags |= CFM_NORMALIZE_HOSTNAMES;
21738494Sobrien      break;
21838494Sobrien
21938494Sobrien    case 'o':
22038494Sobrien      gopt.op_sys_ver = optarg;
22138494Sobrien      break;
22238494Sobrien
22338494Sobrien    case 'p':
22438494Sobrien     gopt.flags |= CFM_PRINT_PID;
22538494Sobrien      break;
22638494Sobrien
22738494Sobrien    case 'r':
22838494Sobrien      gopt.flags |= CFM_RESTART_EXISTING_MOUNTS;
22938494Sobrien      break;
23038494Sobrien
23138494Sobrien    case 't':
232174313Sobrien      /* timeo.retrans (also affects toplvl mounts) */
23338494Sobrien      {
23438494Sobrien	char *dot = strchr(optarg, '.');
235174313Sobrien	int i;
23638494Sobrien	if (dot)
23738494Sobrien	  *dot = '\0';
23838494Sobrien	if (*optarg) {
239174313Sobrien	  for (i=0; i<AMU_TYPE_MAX; ++i)
240174313Sobrien	    gopt.amfs_auto_timeo[i] = atoi(optarg);
24138494Sobrien	}
24238494Sobrien	if (dot) {
243174313Sobrien	  for (i=0; i<AMU_TYPE_MAX; ++i)
244174313Sobrien	    gopt.amfs_auto_retrans[i] = atoi(dot + 1);
24538494Sobrien	  *dot = '.';
24638494Sobrien	}
24738494Sobrien      }
24838494Sobrien      break;
24938494Sobrien
25038494Sobrien    case 'v':
251174313Sobrien      /*
252174313Sobrien       * defer to print version info after every variable had been
253174313Sobrien       * initialized.
254174313Sobrien       */
255174313Sobrien      print_version++;
25638494Sobrien      break;
25738494Sobrien
25838494Sobrien    case 'w':
25938494Sobrien      gopt.am_timeo_w = atoi(optarg);
26038494Sobrien      if (gopt.am_timeo_w <= 0)
26138494Sobrien	gopt.am_timeo_w = AM_TTL_W;
26238494Sobrien      break;
26338494Sobrien
26438494Sobrien    case 'x':
26538494Sobrien      usage += switch_option(optarg);
26638494Sobrien      break;
26738494Sobrien
26838494Sobrien    case 'y':
26938494Sobrien#ifdef HAVE_MAP_NIS
27038494Sobrien      gopt.nis_domain = optarg;
27138494Sobrien#else /* not HAVE_MAP_NIS */
27238494Sobrien      plog(XLOG_USER, "-y: option ignored.  No NIS support available.");
27338494Sobrien#endif /* not HAVE_MAP_NIS */
27438494Sobrien      break;
27538494Sobrien
276174313Sobrien    case 'A':
277174313Sobrien      gopt.arch = optarg;
278174313Sobrien      break;
279174313Sobrien
28038494Sobrien    case 'C':
28138494Sobrien      gopt.cluster = optarg;
28238494Sobrien      break;
28338494Sobrien
28438494Sobrien    case 'D':
28538494Sobrien#ifdef DEBUG
28638494Sobrien      usage += debug_option(optarg);
28738494Sobrien#else /* not DEBUG */
28842633Sobrien      fprintf(stderr, "%s: not compiled with DEBUG option -- sorry.\n",
28942633Sobrien	      am_get_progname());
29038494Sobrien#endif /* not DEBUG */
29138494Sobrien      break;
29238494Sobrien
29338494Sobrien    case 'F':
294174313Sobrien      amu_conf_file = optarg;
29538494Sobrien      use_conf_file = 1;
29638494Sobrien      break;
29738494Sobrien
29838494Sobrien    case 'H':
299174313Sobrien      show_usage();
300174313Sobrien      exit(1);
30138494Sobrien      break;
30238494Sobrien
30338494Sobrien    case 'O':
30438494Sobrien      gopt.op_sys = optarg;
30538494Sobrien      break;
30638494Sobrien
30738494Sobrien    case 'S':
30838494Sobrien      gopt.flags &= ~CFM_PROCESS_LOCK; /* turn process locking off */
30938494Sobrien      break;
31038494Sobrien
31138494Sobrien    case 'T':
31238494Sobrien      conf_tag = optarg;
31338494Sobrien      break;
31438494Sobrien
31538494Sobrien    default:
31638494Sobrien      usage = 1;
31738494Sobrien      break;
31838494Sobrien    }
31938494Sobrien
32038494Sobrien  /*
32138494Sobrien   * amd.conf file: if not command-line arguments were used, or if -F was
32238494Sobrien   * specified, then use that amd.conf file.  If the file cannot be opened,
32338494Sobrien   * abort amd.  If it can be found, open it, parse it, and then close it.
32438494Sobrien   */
325174313Sobrien  if (use_conf_file && amu_conf_file) {
326174313Sobrien    fp = fopen(amu_conf_file, "r");
32738494Sobrien    if (!fp) {
32838494Sobrien      char buf[128];
329174313Sobrien      xsnprintf(buf, sizeof(buf), "Amd configuration file (%s)",
330174313Sobrien		amu_conf_file);
33138494Sobrien      perror(buf);
33238494Sobrien      exit(1);
33338494Sobrien    }
33438494Sobrien    yyin = fp;
33538494Sobrien    yyparse();
33638494Sobrien    fclose(fp);
337174313Sobrien    if (process_all_regular_maps() != 0)
33838494Sobrien      exit(1);
33938494Sobrien  }
34038494Sobrien
34138494Sobrien  /* make sure there are some default options defined */
34238494Sobrien  if (xlog_level_init == ~0) {
34338494Sobrien    switch_option("");
34438494Sobrien  }
34538494Sobrien#ifdef DEBUG
34638494Sobrien  usage += switch_option("debug");
34738494Sobrien#endif /* DEBUG */
34838494Sobrien
34938494Sobrien  /* log information regarding amd.conf file */
350174313Sobrien  if (use_conf_file && amu_conf_file)
351174313Sobrien    plog(XLOG_INFO, "using configuration file %s", amu_conf_file);
35238494Sobrien
35338494Sobrien#ifdef HAVE_MAP_LDAP
35438494Sobrien  /* ensure that if ldap_base is specified, that also ldap_hostports is */
35538494Sobrien  if (gopt.ldap_hostports && !gopt.ldap_base) {
35638494Sobrien    fprintf(stderr, "must specify both ldap_hostports and ldap_base\n");
35738494Sobrien    exit(1);
35838494Sobrien  }
35938494Sobrien#endif /* HAVE_MAP_LDAP */
36038494Sobrien
361174313Sobrien  if (usage) {
362174313Sobrien    show_usage();
363174313Sobrien    exit(1);
364174313Sobrien  }
36538494Sobrien
36638494Sobrien  while (optind <= argc - 2) {
36738494Sobrien    char *dir = argv[optind++];
36838494Sobrien    char *map = argv[optind++];
36938494Sobrien    char *opts = "";
37038494Sobrien    if (argv[optind] && *argv[optind] == '-')
37138494Sobrien      opts = &argv[optind++][1];
37238494Sobrien
37338494Sobrien    root_newmap(dir, opts, map, NULL);
37438494Sobrien  }
37538494Sobrien
37638494Sobrien  if (optind == argc) {
37738494Sobrien    /*
37838494Sobrien     * Append domain name to hostname.
37938494Sobrien     * sub_domain overrides hostdomain
38038494Sobrien     * if given.
38138494Sobrien     */
38238494Sobrien    if (gopt.sub_domain)
38338494Sobrien      hostdomain = gopt.sub_domain;
38438494Sobrien    if (*hostdomain == '.')
38538494Sobrien      hostdomain++;
386174313Sobrien    xstrlcat(hostd, ".", sizeof(hostd));
387174313Sobrien    xstrlcat(hostd, hostdomain, sizeof(hostd));
38838494Sobrien
38938494Sobrien#ifdef MOUNT_TABLE_ON_FILE
390174313Sobrien    if (amuDebug(D_MTAB))
391174313Sobrien      if (gopt.debug_mtab_file)
392174313Sobrien        mnttab_file_name = gopt.debug_mtab_file; /* user supplied debug mtab path */
393174313Sobrien      else
394174313Sobrien	mnttab_file_name = DEBUG_MNTTAB_FILE; /* default debug mtab path */
39538494Sobrien    else
39638494Sobrien      mnttab_file_name = MNTTAB_FILE_NAME;
39738494Sobrien#else /* not MOUNT_TABLE_ON_FILE */
398174313Sobrien    if (amuDebug(D_MTAB))
39938494Sobrien      dlog("-D mtab option ignored");
40082799Sobrien# ifdef MNTTAB_FILE_NAME
40182799Sobrien    mnttab_file_name = MNTTAB_FILE_NAME;
40282799Sobrien# endif /* MNTTAB_FILE_NAME */
40338494Sobrien#endif /* not MOUNT_TABLE_ON_FILE */
40438494Sobrien
40538494Sobrien    /*
40638494Sobrien     * If the kernel architecture was not specified
40738494Sobrien     * then use the machine architecture.
40838494Sobrien     */
409174313Sobrien    if (gopt.karch == NULL)
41038494Sobrien      gopt.karch = gopt.arch;
41138494Sobrien
412174313Sobrien    if (gopt.cluster == NULL)
41338494Sobrien      gopt.cluster = hostdomain;
41438494Sobrien
415174313Sobrien    /* sanity checking, normalize values just in case (toplvl too) */
416174313Sobrien    for (i=0; i<AMU_TYPE_MAX; ++i) {
417174313Sobrien      if (gopt.amfs_auto_timeo[i] == 0)
418174313Sobrien	gopt.amfs_auto_timeo[i] = AMFS_AUTO_TIMEO;
419174313Sobrien      if (gopt.amfs_auto_retrans[i] == 0)
420174313Sobrien	gopt.amfs_auto_retrans[i] = AMFS_AUTO_RETRANS(i);
421174313Sobrien      if (gopt.amfs_auto_retrans[i] == 0)
422174313Sobrien	gopt.amfs_auto_retrans[i] = 3;	/* under very unusual circumstances, could be zero */
423174313Sobrien    }
42438494Sobrien  }
42538494Sobrien
426174313Sobrien  /* finally print version string and exit, if asked for */
427174313Sobrien  if (print_version) {
428174313Sobrien    fputs(get_version_string(), stderr);
429174313Sobrien    exit(0);
430174313Sobrien  }
43138494Sobrien
432174313Sobrien  if (switch_to_logfile(gopt.logfile, orig_umask,
433174313Sobrien			(gopt.flags & CFM_TRUNCATE_LOG)) != 0)
434174313Sobrien    plog(XLOG_USER, "Cannot switch logfile");
43538494Sobrien
436174313Sobrien  return;
43738494Sobrien}
438