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