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 59 char *amu_conf_file = "/etc/amd.conf"; /* default amd configuration file */ 60 char *conf_tag = NULL; /* default conf file tags to use */ 61 int usage = 0; 62 int use_conf_file = 0; /* default don't use amd.conf file */ 63 char *mnttab_file_name = NULL; /* symbol must be available always */ 64 65 66 /* 67 * Return the version string (dynamic buffer) 68 */ 69 char * 70 get_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 134 static void 135 show_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 168 void 169 get_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