xref: /original-bsd/usr.sbin/amd/amd/get_args.c (revision 92ab646d)
1 /*
2  * $Id: get_args.c,v 5.2 90/06/23 22:19:24 jsp Rel $
3  *
4  * Copyright (c) 1990 Jan-Simon Pendry
5  * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
6  * Copyright (c) 1990 The Regents of the University of California.
7  * All rights reserved.
8  *
9  * This code is derived from software contributed to Berkeley by
10  * Jan-Simon Pendry at Imperial College, London.
11  *
12  * %sccs.include.redist.c%
13  *
14  *	@(#)get_args.c	5.1 (Berkeley) 06/29/90
15  */
16 
17 /*
18  * Argument decode
19  */
20 
21 #include "am.h"
22 #ifdef HAS_SYSLOG
23 #include <syslog.h>
24 #endif /* HAS_SYSLOG */
25 #include <sys/stat.h>
26 
27 extern int optind;
28 extern char *optarg;
29 
30 #if defined(DEBUG) && defined(PARANOID)
31 char **gargv;
32 #endif /* defined(DEBUG) && defined(PARANOID) */
33 int restart_existing_mounts;
34 int print_pid;
35 int normalize_hosts;
36 char *karch;			/* Kernel architecture */
37 char *cluster;			/* Cluster name */
38 #ifdef HAS_NIS_MAPS
39 char *domain;			/* YP domain */
40 #endif /* HAS_NIS_MAPS */
41 #ifdef UPDATE_MTAB
42 char *mtab;
43 #endif /* UPDATE_MTAB */
44 FILE *logfp = stderr;		/* Log errors to stderr initially */
45 #ifdef HAS_SYSLOG
46 int syslogging;
47 #endif /* HAS_SYSLOG */
48 int afs_timeo = -1;
49 int afs_retrans = -1;
50 int am_timeo = AM_TTL;
51 int am_timeo_w = AM_TTL_W;
52 int xlog_level = 0;
53 int xlog_level_init = ~0;
54 
55 /*
56  * List of log options
57  */
58 static struct opt_tab xlog_opt[] = {
59 	{ "all", XLOG_ALL },		/* All messages */
60 #ifdef DEBUG
61 	{ "debug", XLOG_DEBUG },	/* Debug messages */
62 #endif /* DEBUG */
63 	{ "error", XLOG_ERROR },	/* Non-fatal system errors */
64 	{ "fatal", XLOG_FATAL },	/* Fatal errors */
65 	{ "info", XLOG_INFO },		/* Information */
66 	{ "map", XLOG_MAP },		/* Map errors */
67 	{ "stats", XLOG_STATS },	/* Additional statistical information */
68 	{ "user", XLOG_USER },		/* Non-fatal user errors */
69 	{ "warn", XLOG_WARNING },	/* Warnings */
70 	{ "warning", XLOG_WARNING },	/* Warnings */
71 	{ 0, 0 }
72 };
73 
74 #ifdef DEBUG
75 /*
76  * List of debug options.
77  */
78 static struct opt_tab dbg_opt[] = {
79 	{ "all", D_ALL },		/* All */
80 	{ "amq", D_AMQ },		/* Register for AMQ program */
81 	{ "daemon", D_DAEMON },		/* Enter daemon mode */
82 	{ "full", D_FULL },		/* Program trace */
83 	{ "mem", D_MEM },		/* Trace memory allocations */
84 	{ "mtab", D_MTAB },		/* Use local mtab file */
85 	{ "str", D_STR },		/* Debug string munging */
86 	{ "test", D_TEST },		/* Full debug - but no daemon */
87 	{ "trace", D_TRACE },		/* Protocol trace */
88 	{ 0, 0 }
89 };
90 
91 int debug_flags = D_AMQ			/* Register AMQ */
92 		 |D_DAEMON		/* Enter daemon mode */
93 		 ;
94 #endif /* DEBUG */
95 
96 void show_opts(ch, opts)
97 int ch;
98 struct opt_tab *opts;
99 {
100 	/*
101 	 * Display current debug options
102 	 */
103 	int i;
104 	int s = '{';
105 	fprintf(stderr, "\t[-%c {no}", ch);
106 	for (i = 0; opts[i].opt; i++) {
107 		fprintf(stderr, "%c%s", s, opts[i].opt);
108 		s = ',';
109 	}
110 	fputs("}]\n", stderr);
111 }
112 
113 static int option(s, optb, flags)
114 char *s;
115 struct opt_tab *optb;
116 int *flags;
117 {
118 	char *p = s;
119 	int errs = 0;
120 
121 	while (p && *p) {
122 		int neg;
123 		char *opt;
124 		struct opt_tab *dp;
125 
126 		s = p;
127 		p = strchr(p, ',');
128 		if (p)
129 			*p = '\0';
130 
131 		if (s[0] == 'n' && s[1] == 'o') {
132 			opt = s + 2;
133 			neg = 1;
134 		} else {
135 			opt = s;
136 			neg = 0;
137 		}
138 
139 		/*
140 		 * Scan the array of debug options to find the
141 		 * corresponding flag value.  If it is found
142 		 * then set (or clear) the flag (depending on
143 		 * whether the option was prefixed with "no").
144 		 */
145 		for (dp = optb; dp->opt; dp++) {
146 			if (strcmp(opt, dp->opt) == 0) {
147 				if (neg)
148 					*flags &= ~dp->flag;
149 				else
150 					*flags |= dp->flag;
151 				break;
152 			}
153 		}
154 
155 		if (dp->opt == 0) {
156 			/*
157 			 * This will log to stderr when parsing the command line
158 			 * since any -l option will not yet have taken effect.
159 			 */
160 			plog(XLOG_USER, "option \"%s\" not recognised", s);
161 			errs++;
162 		}
163 		/*
164 		 * Put the comma back
165 		 */
166 		if (p)
167 			*p++ = ',';
168 	}
169 
170 	return errs;
171 }
172 
173 /*
174  * Switch on/off logging options
175  */
176 int switch_option(opt)
177 char *opt;
178 {
179 	int xl = xlog_level;
180 	int rc = option(opt, xlog_opt, &xl);
181 	if (rc) {
182 		rc = EINVAL;
183 	} else {
184 		/*
185 		 * Keep track of initial log level, and
186 		 * don't allow options to be turned off.
187 		 */
188 		if (xlog_level_init == ~0)
189 			xlog_level_init = xl;
190 		else
191 			xl |= xlog_level_init;
192 		xlog_level = xl;
193 	}
194 	return rc;
195 }
196 
197 #ifdef DEBUG
198 /*
199  * Switch on/off debug options
200  */
201 int debug_option(opt)
202 char *opt;
203 {
204 	return option(opt, dbg_opt, &debug_flags);
205 }
206 #endif /* DEBUG */
207 
208 /*
209  * Change current logfile
210  */
211 int switch_to_logfile(logfile)
212 char *logfile;
213 {
214 	FILE *new_logfp = stderr;
215 
216 	if (logfile) {
217 #ifdef HAS_SYSLOG
218 		syslogging = 0;
219 #endif /* HAS_SYSLOG */
220 		if (strcmp(logfile, "/dev/stderr") == 0)
221 			new_logfp = stderr;
222 		else if (strcmp(logfile, "syslog") == 0) {
223 #ifdef HAS_SYSLOG
224 			syslogging = 1;
225 			new_logfp = stderr;
226 #ifdef LOG_CONS
227 			openlog(progname, LOG_PID|LOG_CONS|LOG_NOWAIT,
228 				LOG_DAEMON);
229 #else
230 			/* 4.2 compat mode - XXX */
231 			openlog(progname, LOG_PID);
232 #endif /* LOG_CONS */
233 #else
234 			plog(XLOG_WARNING, "syslog option not supported, logging unchanged");
235 #endif /* HAS_SYSLOG */
236 		} else {
237 			(void) umask(orig_umask);
238 			new_logfp = fopen(logfile, "a");
239 			umask(0);
240 		}
241 	}
242 
243 	/*
244 	 * If we couldn't open a new file, then continue using the old.
245 	 */
246 	if (!new_logfp && logfile) {
247 		plog(XLOG_USER, "%s: Can't open logfile: %m", logfile);
248 		return 1;
249 	}
250 	/*
251 	 * Close the previous file
252 	 */
253 	if (logfp && logfp != stderr)
254 		(void) fclose(logfp);
255 	logfp = new_logfp;
256 	return 0;
257 }
258 
259 void get_args(c, v)
260 int c;
261 char *v[];
262 {
263 	int opt_ch;
264 	int usage = 0;
265 	char *logfile = 0;
266 	char *sub_domain = 0;
267 
268 #if defined(DEBUG) && defined(PARANOID)
269 	gargv = v;
270 	progname = v[0];		/* Use argv[0] to try to solve Piete's problem */
271 #else
272 	if (v[0]) {
273 		progname = strrchr(v[0], '/');
274 		if (progname && progname[1])
275 			progname++;
276 		else
277 			progname = v[0];
278 	}
279 #endif /* defined(DEBUG) && defined(PARANOID) */
280 	if (!progname)
281 		progname = "amd";
282 
283 	while ((opt_ch = getopt(c, v, "mnprva:c:d:h:k:l:t:w:x:y:C:D:")) != EOF)
284 	switch (opt_ch) {
285 	case 'a':
286 		if (*optarg != '/') {
287 			fprintf(stderr, "%s: -a option must begin with a '/'\n",
288 					progname);
289 			exit(1);
290 		}
291 		auto_dir = optarg;
292 		break;
293 
294 	case 'c':
295 		am_timeo = atoi(optarg);
296 		if (am_timeo <= 0)
297 			am_timeo = AM_TTL;
298 		break;
299 
300 	case 'd':
301 		sub_domain = optarg;
302 		break;
303 
304 	case 'h':
305 #if defined(HAS_HOST) && defined(HOST_EXEC)
306 		host_helper = optarg;
307 #else
308 		plog(XLOG_USER, "-h: option ignored.  HOST_EXEC is not enabled.");
309 		break;
310 #endif /* defined(HAS_HOST) && defined(HOST_EXEC) */
311 
312 	case 'k':
313 		karch = optarg;
314 		break;
315 
316 	case 'l':
317 		logfile = optarg;
318 		break;
319 
320 	case 'm':
321 		plog(XLOG_USER, "The -m option is no longer supported.");
322 		plog(XLOG_USER, "... Use `ypcat -k am.master` on the command line instead");
323 		break;
324 
325 	case 'n':
326 		normalize_hosts = 1;
327 		break;
328 
329 	case 'p':
330 		print_pid = 1;
331 		break;
332 
333 	case 'r':
334 		restart_existing_mounts = 1;
335 		break;
336 
337 	case 't':
338 		/* timeo.retrans */
339 		{ char *dot = strchr(optarg, '.');
340 		  if (dot) *dot = '\0';
341 		  if (*optarg) {
342 			afs_timeo = atoi(optarg);
343 		  }
344 		  if (dot) {
345 		  	afs_retrans = atoi(dot+1);
346 			*dot = '.';
347 		  }
348 		}
349 		break;
350 
351 	case 'v':
352 		{ char buf[256];
353 		  show_rcs_info(version, buf);
354 		  fputs(buf, stderr);
355 		}
356 		fprintf(stderr,
357 			" for a%s %s running %s (%s-endian)\n",
358 					strchr("aeiou", arch[0]) ? "n" : "",
359 					arch, op_sys, endian);
360 		fputs("Map support for: ", stderr);
361 		mapc_showtypes(stderr);
362 		fputs(".\n", stderr);
363 		exit(0);
364 		break;
365 
366 	case 'w':
367 		am_timeo_w = atoi(optarg);
368 		if (am_timeo_w <= 0)
369 			am_timeo_w = AM_TTL_W;
370 		break;
371 
372 	case 'x':
373 		usage += switch_option(optarg);
374 		break;
375 
376 	case 'y':
377 #ifdef HAS_NIS_MAPS
378 		domain = optarg;
379 #else
380 		plog(XLOG_USER, "-y: option ignored.  No NIS support available.");
381 #endif /* HAS_NIS_MAPS */
382 		break;
383 
384 	case 'C':
385 		cluster = optarg;
386 		break;
387 
388 	case 'D':
389 #ifdef DEBUG
390 		usage += debug_option(optarg);
391 #else
392 		fprintf(stderr, "%s: not compiled with DEBUG option -- sorry.\n", progname);
393 #endif /* DEBUG */
394 		break;
395 
396 	default:
397 		usage = 1;
398 		break;
399 	}
400 
401 	if (xlog_level == 0) {
402 		/* Take copy to avoid writable-strings problem */
403 		char *dfstr = strdup(XLOG_DEFSTR);
404 		usage += switch_option(dfstr);
405 		free((voidp) dfstr);
406 #ifdef DEBUG
407 		usage += switch_option("debug");
408 #endif /* DEBUG */
409 	} else {
410 #ifdef DEBUG
411 		usage += switch_option("debug");
412 #endif /* DEBUG */
413 	}
414 
415 	if (usage)
416 		goto show_usage;
417 
418 	while (optind <= c-2) {
419 		char *dir = v[optind++];
420 		char *map = v[optind++];
421 		char *opts = "";
422 		if (v[optind] && *v[optind] == '-')
423 			opts = &v[optind++][1];
424 
425 		root_newmap(dir, opts, map);
426 	}
427 
428 	if (optind == c) {
429 #ifdef hpux
430 		/*
431 		 * HP-UX can't handle ./mtab
432 		 * That system is sick - really.
433 		 */
434 #ifdef	DEBUG
435 		debug_option("nomtab");
436 #endif	/* DEBUG */
437 #endif	/* hpux */
438 
439 		/*
440 		 * Append domain name to hostname.
441 		 * sub_domain overrides hostdomain
442 		 * if given.
443 		 */
444 		if (sub_domain)
445 			hostdomain = sub_domain;
446 		if (*hostdomain == '.')
447 			hostdomain++;
448 		strcat(hostd,  ".");
449 		strcat(hostd, hostdomain);
450 
451 #ifdef UPDATE_MTAB
452 #ifdef DEBUG
453 		if (debug_flags & D_MTAB)
454 			mtab = DEBUG_MTAB;
455 		else
456 #endif /* DEBUG */
457 		mtab = MOUNTED;
458 #else
459 #ifdef DEBUG
460 		{ if (debug_flags & D_MTAB) {
461 			dlog("-D mtab option ignored");
462 		} }
463 #endif /* DEBUG */
464 #endif /* UPDATE_MTAB */
465 
466 		if (switch_to_logfile(logfile) != 0)
467 			plog(XLOG_USER, "Cannot switch logfile");
468 
469 		/*
470 		 * If the kernel architecture was not specified
471 		 * then use the machine architecture.
472 		 */
473 		if (karch == 0)
474 			karch = arch;
475 
476 		if (cluster == 0)
477 			cluster = hostdomain;
478 
479 		if (afs_timeo <= 0)
480 			afs_timeo = AFS_TIMEO;
481 		if (afs_retrans <= 0)
482 			afs_retrans = AFS_RETRANS;
483 		if (afs_retrans <= 0)
484 			afs_retrans = 3;	/* XXX */
485 		return;
486 	}
487 
488 show_usage:
489 	fprintf(stderr,
490 "Usage: %s [-mnprv] [-a mnt_point] [-c cache_time] [-d domain]\n\
491 \t[-k kernel_arch] [-l logfile|\"syslog\"] [-t afs_timeout]\n\
492 \t[-w wait_timeout] [-C cluster_name]", progname);
493 
494 #if defined(HAS_HOST) && defined(HOST_EXEC)
495 	fputs(" [-h host_helper]\n", stderr);
496 #endif /* defined(HAS_HOST) && defined(HOST_EXEC) */
497 
498 #ifdef HAS_NIS_MAPS
499 	fputs(" [-y nis-domain]\n", stderr);
500 #else
501 	fputc('\n', stderr);
502 #endif /* HAS_NIS_MAPS */
503 
504 	show_opts('x', xlog_opt);
505 #ifdef DEBUG
506 	show_opts('D', dbg_opt);
507 #endif /* DEBUG */
508 	fprintf(stderr, "\t{directory mapname [-map_options]} ...\n");
509 	exit(1);
510 }
511