get_args.c revision 310490
1/*
2 * Copyright (c) 1997-2014 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.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Jan-Simon Pendry at Imperial College, London.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
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. Neither the name of the University nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 *
36 * File: am-utils/amd/get_args.c
37 *
38 */
39
40/*
41 * Argument decode
42 */
43
44#ifdef HAVE_CONFIG_H
45# include <config.h>
46#endif /* HAVE_CONFIG_H */
47#include <am_defs.h>
48#include <amd.h>
49
50/* include auto-generated version file */
51#include <build_version.h>
52
53char *amu_conf_file = "/etc/amd.conf"; /* default amd configuration file */
54char *conf_tag = NULL;		/* default conf file tags to use */
55int usage = 0;
56int use_conf_file = 0;		/* default don't use amd.conf file */
57char *mnttab_file_name = NULL;	/* symbol must be available always */
58
59
60/*
61 * Return the version string (dynamic buffer)
62 */
63char *
64get_version_string(void)
65{
66  char *vers = NULL;
67  char tmpbuf[1024];
68  char *wire_buf;
69  int wire_buf_len = 0;
70  size_t len;		  /* max allocated length (to avoid buf overflow) */
71
72  /*
73   * First get dynamic string listing all known networks.
74   * This could be a long list, if host has lots of interfaces.
75   */
76  wire_buf = print_wires();
77  if (wire_buf)
78    wire_buf_len = strlen(wire_buf);
79
80  len = 2048 + wire_buf_len;
81  vers = xmalloc(len);
82  xsnprintf(vers, len, "%s\n%s\n%s\n%s\n",
83	    "Copyright (c) 1997-2014 Erez Zadok",
84	    "Copyright (c) 1990 Jan-Simon Pendry",
85	    "Copyright (c) 1990 Imperial College of Science, Technology & Medicine",
86	    "Copyright (c) 1990 The Regents of the University of California.");
87  xsnprintf(tmpbuf, sizeof(tmpbuf), "%s version %s (build %d).\n",
88	    PACKAGE_NAME, PACKAGE_VERSION, AMU_BUILD_VERSION);
89  xstrlcat(vers, tmpbuf, len);
90  xsnprintf(tmpbuf, sizeof(tmpbuf), "Report bugs to %s.\n", PACKAGE_BUGREPORT);
91  xstrlcat(vers, tmpbuf, len);
92#if 0
93  /*
94   * XXX  This block (between from the #if 0 to #endif was in the
95   * XXX  original was in the original merge however in the interest
96   * XXX  of reproduceable builds and the fact that this is redundant
97   * XXX  information, it is effectively removed.
98   */
99  xsnprintf(tmpbuf, sizeof(tmpbuf), "Configured by %s@%s on date %s.\n",
100	    USER_NAME, HOST_NAME, CONFIG_DATE);
101  xstrlcat(vers, tmpbuf, len);
102  xsnprintf(tmpbuf, sizeof(tmpbuf), "Built by %s@%s on date %s.\n",
103	    BUILD_USER, BUILD_HOST, BUILD_DATE);
104  xstrlcat(vers, tmpbuf, len);
105#endif
106  xsnprintf(tmpbuf, sizeof(tmpbuf), "Configured by %s@%s on date %s.\n",
107	    USER_NAME, HOST_NAME, CONFIG_DATE);
108  strlcat(vers, tmpbuf, len);
109  xsnprintf(tmpbuf, sizeof(tmpbuf), "Built by %s@%s.\n",
110	    BUILD_USER, BUILD_HOST);
111  strlcat(vers, tmpbuf, len);
112  xsnprintf(tmpbuf, sizeof(tmpbuf), "cpu=%s (%s-endian), arch=%s, karch=%s.\n",
113	    cpu, endian, gopt.arch, gopt.karch);
114  xstrlcat(vers, tmpbuf, len);
115  xsnprintf(tmpbuf, sizeof(tmpbuf), "full_os=%s, os=%s, osver=%s, vendor=%s, distro=%s.\n",
116	    gopt.op_sys_full, gopt.op_sys, gopt.op_sys_ver, gopt.op_sys_vendor, DISTRO_NAME);
117  xstrlcat(vers, tmpbuf, len);
118  xsnprintf(tmpbuf, sizeof(tmpbuf), "domain=%s, host=%s, hostd=%s.\n",
119	    hostdomain, am_get_hostname(), hostd);
120  xstrlcat(vers, tmpbuf, len);
121
122  xstrlcat(vers, "Map support for: ", len);
123  mapc_showtypes(tmpbuf, sizeof(tmpbuf));
124  xstrlcat(vers, tmpbuf, len);
125  xstrlcat(vers, ".\nAMFS: ", len);
126  ops_showamfstypes(tmpbuf, sizeof(tmpbuf));
127  xstrlcat(vers, tmpbuf, len);
128  xstrlcat(vers, ", inherit.\nFS: ", len); /* hack: "show" that we support type:=inherit */
129  ops_showfstypes(tmpbuf, sizeof(tmpbuf));
130  xstrlcat(vers, tmpbuf, len);
131
132  /* append list of networks if available */
133  if (wire_buf) {
134    xstrlcat(vers, wire_buf, len);
135    XFREE(wire_buf);
136  }
137
138  return vers;
139}
140
141
142static void
143show_usage(void)
144{
145  fprintf(stderr,
146	  "Usage: %s [-nprvHS] [-a mount_point] [-c cache_time] [-d domain]\n\
147\t[-k kernel_arch] [-l logfile%s\n\
148\t[-t timeout.retrans] [-w wait_timeout] [-A arch] [-C cluster_name]\n\
149\t[-o op_sys_ver] [-O op_sys_name]\n\
150\t[-F conf_file] [-T conf_tag]", am_get_progname(),
151#ifdef HAVE_SYSLOG
152# ifdef LOG_DAEMON
153	  "|\"syslog[:facility]\"]"
154# else /* not LOG_DAEMON */
155	  "|\"syslog\"]"
156# endif /* not LOG_DAEMON */
157#else /* not HAVE_SYSLOG */
158	  "]"
159#endif /* not HAVE_SYSLOG */
160	  );
161
162#ifdef HAVE_MAP_NIS
163  fputs(" [-y nis-domain]\n", stderr);
164#else /* not HAVE_MAP_NIS */
165  fputc('\n', stderr);
166#endif /* HAVE_MAP_NIS */
167
168  show_opts('x', xlog_opt);
169#ifdef DEBUG
170  show_opts('D', dbg_opt);
171#endif /* DEBUG */
172  fprintf(stderr, "\t[directory mapname [-map_options]] ...\n");
173}
174
175
176void
177get_args(int argc, char *argv[])
178{
179  int opt_ch, i;
180  FILE *fp = stdin;
181  char getopt_arguments[] = "+nprvSa:c:d:k:l:o:t:w:x:y:C:D:F:T:O:HA:";
182  char *getopt_args;
183  int print_version = 0;	/* 1 means we should print version info */
184
185#ifdef HAVE_GNU_GETOPT
186  getopt_args = getopt_arguments;
187#else /* ! HAVE_GNU_GETOPT */
188  getopt_args = &getopt_arguments[1];
189#endif /* HAVE_GNU_GETOPT */
190
191  /* if no arguments were passed, try to use /etc/amd.conf file */
192  if (argc <= 1)
193    use_conf_file = 1;
194
195  while ((opt_ch = getopt(argc, argv, getopt_args)) != -1)
196    switch (opt_ch) {
197
198    case 'a':
199      if (*optarg != '/') {
200	fprintf(stderr, "%s: -a option must begin with a '/'\n",
201		am_get_progname());
202	exit(1);
203      }
204      gopt.auto_dir = optarg;
205      break;
206
207    case 'c':
208      gopt.am_timeo = atoi(optarg);
209      if (gopt.am_timeo <= 0)
210	gopt.am_timeo = AM_TTL;
211      break;
212
213    case 'd':
214      gopt.sub_domain = optarg;
215      break;
216
217    case 'k':
218      gopt.karch = optarg;
219      break;
220
221    case 'l':
222      gopt.logfile = optarg;
223      break;
224
225    case 'n':
226      gopt.flags |= CFM_NORMALIZE_HOSTNAMES;
227      break;
228
229    case 'o':
230      gopt.op_sys_ver = optarg;
231      break;
232
233    case 'p':
234     gopt.flags |= CFM_PRINT_PID;
235      break;
236
237    case 'r':
238      gopt.flags |= CFM_RESTART_EXISTING_MOUNTS;
239      break;
240
241    case 't':
242      /* timeo.retrans (also affects toplvl mounts) */
243      {
244	char *dot = strchr(optarg, '.');
245	int i;
246	if (dot)
247	  *dot = '\0';
248	if (*optarg) {
249	  for (i=0; i<AMU_TYPE_MAX; ++i)
250	    gopt.amfs_auto_timeo[i] = atoi(optarg);
251	}
252	if (dot) {
253	  for (i=0; i<AMU_TYPE_MAX; ++i)
254	    gopt.amfs_auto_retrans[i] = atoi(dot + 1);
255	  *dot = '.';
256	}
257      }
258      break;
259
260    case 'v':
261      /*
262       * defer to print version info after every variable had been
263       * initialized.
264       */
265      print_version++;
266      break;
267
268    case 'w':
269      gopt.am_timeo_w = atoi(optarg);
270      if (gopt.am_timeo_w <= 0)
271	gopt.am_timeo_w = AM_TTL_W;
272      break;
273
274    case 'x':
275      usage += switch_option(optarg);
276      break;
277
278    case 'y':
279#ifdef HAVE_MAP_NIS
280      gopt.nis_domain = optarg;
281#else /* not HAVE_MAP_NIS */
282      plog(XLOG_USER, "-y: option ignored.  No NIS support available.");
283#endif /* not HAVE_MAP_NIS */
284      break;
285
286    case 'A':
287      gopt.arch = optarg;
288      break;
289
290    case 'C':
291      gopt.cluster = optarg;
292      break;
293
294    case 'D':
295#ifdef DEBUG
296      usage += debug_option(optarg);
297#else /* not DEBUG */
298      fprintf(stderr, "%s: not compiled with DEBUG option -- sorry.\n",
299	      am_get_progname());
300#endif /* not DEBUG */
301      break;
302
303    case 'F':
304      amu_conf_file = optarg;
305      use_conf_file = 1;
306      break;
307
308    case 'H':
309      show_usage();
310      exit(1);
311      break;
312
313    case 'O':
314      gopt.op_sys = optarg;
315      break;
316
317    case 'S':
318      gopt.flags &= ~CFM_PROCESS_LOCK; /* turn process locking off */
319      break;
320
321    case 'T':
322      conf_tag = optarg;
323      break;
324
325    default:
326      usage = 1;
327      break;
328    }
329
330  /*
331   * amd.conf file: if not command-line arguments were used, or if -F was
332   * specified, then use that amd.conf file.  If the file cannot be opened,
333   * abort amd.  If it can be found, open it, parse it, and then close it.
334   */
335  if (use_conf_file && amu_conf_file) {
336    fp = fopen(amu_conf_file, "r");
337    if (!fp) {
338      char buf[128];
339      xsnprintf(buf, sizeof(buf), "Amd configuration file (%s)",
340		amu_conf_file);
341      perror(buf);
342      exit(1);
343    }
344    conf_in = fp;
345    conf_parse();
346    fclose(fp);
347    if (process_all_regular_maps() != 0)
348      exit(1);
349  }
350
351#ifdef DEBUG
352  usage += switch_option("debug");
353  /* initialize debug options */
354  if (!debug_flags)
355    debug_flags = D_CONTROL;	/* CONTROL = "daemon,amq,fork" */
356#endif /* DEBUG */
357
358  /* log information regarding amd.conf file */
359  if (use_conf_file && amu_conf_file)
360    plog(XLOG_INFO, "using configuration file %s", amu_conf_file);
361
362#ifdef HAVE_MAP_LDAP
363  /* ensure that if ldap_base is specified, that also ldap_hostports is */
364  if (gopt.ldap_hostports && !gopt.ldap_base) {
365    fprintf(stderr, "must specify both ldap_hostports and ldap_base\n");
366    exit(1);
367  }
368#endif /* HAVE_MAP_LDAP */
369
370  if (usage) {
371    show_usage();
372    exit(1);
373  }
374
375  while (optind <= argc - 2) {
376    char *dir = argv[optind++];
377    char *map = argv[optind++];
378    char *opts = "";
379    if (argv[optind] && *argv[optind] == '-')
380      opts = &argv[optind++][1];
381
382    root_newmap(dir, opts, map, NULL);
383  }
384
385  if (optind == argc) {
386    /*
387     * Append domain name to hostname.
388     * sub_domain overrides hostdomain
389     * if given.
390     */
391    if (gopt.sub_domain)
392      hostdomain = gopt.sub_domain;
393    if (*hostdomain == '.')
394      hostdomain++;
395    xstrlcat(hostd, ".", sizeof(hostd));
396    xstrlcat(hostd, hostdomain, sizeof(hostd));
397
398#ifdef MOUNT_TABLE_ON_FILE
399    if (amuDebug(D_MTAB))
400      if (gopt.debug_mtab_file)
401        mnttab_file_name = gopt.debug_mtab_file; /* user supplied debug mtab path */
402      else
403	mnttab_file_name = DEBUG_MNTTAB_FILE; /* default debug mtab path */
404    else
405      mnttab_file_name = MNTTAB_FILE_NAME;
406#else /* not MOUNT_TABLE_ON_FILE */
407    if (amuDebug(D_MTAB))
408      dlog("-D mtab option ignored");
409# ifdef MNTTAB_FILE_NAME
410    mnttab_file_name = MNTTAB_FILE_NAME;
411# endif /* MNTTAB_FILE_NAME */
412#endif /* not MOUNT_TABLE_ON_FILE */
413
414    /*
415     * If the kernel architecture was not specified
416     * then use the machine architecture.
417     */
418    if (gopt.karch == NULL)
419      gopt.karch = gopt.arch;
420
421    if (gopt.cluster == NULL)
422      gopt.cluster = hostdomain;
423
424    /* sanity checking, normalize values just in case (toplvl too) */
425    for (i=0; i<AMU_TYPE_MAX; ++i) {
426      if (gopt.amfs_auto_timeo[i] == 0)
427	gopt.amfs_auto_timeo[i] = AMFS_AUTO_TIMEO;
428      if (gopt.amfs_auto_retrans[i] == 0)
429	gopt.amfs_auto_retrans[i] = AMFS_AUTO_RETRANS(i);
430      if (gopt.amfs_auto_retrans[i] == 0)
431	gopt.amfs_auto_retrans[i] = 3;	/* under very unusual circumstances, could be zero */
432    }
433  }
434
435  /* finally print version string and exit, if asked for */
436  if (print_version) {
437    fputs(get_version_string(), stderr);
438    exit(0);
439  }
440
441  if (switch_to_logfile(gopt.logfile, orig_umask,
442			(gopt.flags & CFM_TRUNCATE_LOG)) != 0)
443    plog(XLOG_USER, "Cannot switch logfile");
444
445  return;
446}
447