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