conf.c revision 82794
1/* 2 * Copyright (c) 1997-2001 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. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgment: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * %W% (Berkeley) %G% 40 * 41 * $Id: conf.c,v 1.7.2.3 2001/04/14 21:08:21 ezk Exp $ 42 * 43 */ 44 45/* 46 * Functions to handle the configuration file. 47 */ 48 49#ifdef HAVE_CONFIG_H 50# include <config.h> 51#endif /* HAVE_CONFIG_H */ 52#include <am_defs.h> 53#include <amd.h> 54 55 56/* 57 * MACROS: 58 */ 59/* Turn on to show some info about maps being configured */ 60/* #define DEBUG_CONF */ 61 62/* 63 * TYPEDEFS: 64 */ 65typedef int (*OptFuncPtr)(const char *); 66 67/* 68 * STRUCTURES: 69 */ 70struct _func_map { 71 char *name; 72 OptFuncPtr func; 73}; 74 75/* 76 * FORWARD DECLARATIONS: 77 */ 78static int gopt_arch(const char *val); 79static int gopt_auto_dir(const char *val); 80static int gopt_browsable_dirs(const char *val); 81static int gopt_cache_duration(const char *val); 82static int gopt_cluster(const char *val); 83static int gopt_debug_options(const char *val); 84static int gopt_dismount_interval(const char *val); 85static int gopt_full_os(const char *val); 86static int gopt_fully_qualified_hosts(const char *val); 87static int gopt_hesiod_base(const char *val); 88static int gopt_karch(const char *val); 89static int gopt_ldap_base(const char *val); 90static int gopt_ldap_cache_maxmem(const char *val); 91static int gopt_ldap_cache_seconds(const char *val); 92static int gopt_ldap_hostports(const char *val); 93static int gopt_local_domain(const char *val); 94static int gopt_log_file(const char *val); 95static int gopt_log_options(const char *val); 96static int gopt_map_options(const char *val); 97static int gopt_map_type(const char *val); 98static int gopt_mount_type(const char *val); 99static int gopt_pid_file(const char *val); 100static int gopt_portmap_program(const char *val); 101static int gopt_nfs_proto(const char *val); 102static int gopt_nfs_retransmit_counter(const char *val); 103static int gopt_nfs_retry_interval(const char *val); 104static int gopt_nfs_vers(const char *val); 105static int gopt_nis_domain(const char *val); 106static int gopt_normalize_hostnames(const char *val); 107static int gopt_os(const char *val); 108static int gopt_osver(const char *val); 109static int gopt_plock(const char *val); 110static int gopt_print_pid(const char *val); 111static int gopt_print_version(const char *val); 112static int gopt_restart_mounts(const char *val); 113static int gopt_search_path(const char *val); 114static int gopt_selectors_in_defaults(const char *val); 115static int gopt_show_statfs_entries(const char *val); 116static int gopt_unmount_on_exit(const char *val); 117static int gopt_vendor(const char *val); 118static int process_global_option(const char *key, const char *val); 119static int process_regular_map(cf_map_t *cfm); 120static int process_regular_option(const char *section, const char *key, const char *val, cf_map_t *cfm); 121static int ropt_browsable_dirs(const char *val, cf_map_t *cfm); 122static int ropt_map_name(const char *val, cf_map_t *cfm); 123static int ropt_map_options(const char *val, cf_map_t *cfm); 124static int ropt_map_type(const char *val, cf_map_t *cfm); 125static int ropt_mount_type(const char *val, cf_map_t *cfm); 126static int ropt_search_path(const char *val, cf_map_t *cfm); 127static int ropt_tag(const char *val, cf_map_t *cfm); 128static void reset_cf_map(cf_map_t *cfm); 129 130 131/* 132 * STATIC VARIABLES: 133 */ 134static cf_map_t cur_map; 135static struct _func_map glob_functable[] = { 136 {"arch", gopt_arch}, 137 {"auto_dir", gopt_auto_dir}, 138 {"browsable_dirs", gopt_browsable_dirs}, 139 {"cache_duration", gopt_cache_duration}, 140 {"cluster", gopt_cluster}, 141 {"debug_options", gopt_debug_options}, 142 {"dismount_interval", gopt_dismount_interval}, 143 {"fully_qualified_hosts", gopt_fully_qualified_hosts}, 144 {"full_os", gopt_full_os}, 145 {"hesiod_base", gopt_hesiod_base}, 146 {"karch", gopt_karch}, 147 {"ldap_base", gopt_ldap_base}, 148 {"ldap_cache_maxmem", gopt_ldap_cache_maxmem}, 149 {"ldap_cache_seconds", gopt_ldap_cache_seconds}, 150 {"ldap_hostports", gopt_ldap_hostports}, 151 {"local_domain", gopt_local_domain}, 152 {"log_file", gopt_log_file}, 153 {"log_options", gopt_log_options}, 154 {"map_options", gopt_map_options}, 155 {"map_type", gopt_map_type}, 156 {"mount_type", gopt_mount_type}, 157 {"pid_file", gopt_pid_file}, 158 {"portmap_program", gopt_portmap_program}, 159 {"nfs_proto", gopt_nfs_proto}, 160 {"nfs_retransmit_counter", gopt_nfs_retransmit_counter}, 161 {"nfs_retry_interval", gopt_nfs_retry_interval}, 162 {"nfs_vers", gopt_nfs_vers}, 163 {"nis_domain", gopt_nis_domain}, 164 {"normalize_hostnames", gopt_normalize_hostnames}, 165 {"os", gopt_os}, 166 {"osver", gopt_osver}, 167 {"plock", gopt_plock}, 168 {"print_pid", gopt_print_pid}, 169 {"print_version", gopt_print_version}, 170 {"restart_mounts", gopt_restart_mounts}, 171 {"search_path", gopt_search_path}, 172 {"selectors_on_default", gopt_selectors_in_defaults}, 173 {"selectors_in_defaults", gopt_selectors_in_defaults}, 174 {"show_statfs_entries", gopt_show_statfs_entries}, 175 {"unmount_on_exit", gopt_unmount_on_exit}, 176 {"vendor", gopt_vendor}, 177 {NULL, NULL} 178}; 179 180 181/* 182 * Reset a map. 183 */ 184static void 185reset_cf_map(cf_map_t *cfm) 186{ 187 if (!cfm) 188 return; 189 190 if (cfm->cfm_dir) { 191 XFREE(cfm->cfm_dir); 192 cfm->cfm_dir = NULL; 193 } 194 195 if (cfm->cfm_name) { 196 XFREE(cfm->cfm_name); 197 cfm->cfm_name = NULL; 198 } 199 200 if (cfm->cfm_tag) { 201 XFREE(cfm->cfm_tag); 202 cfm->cfm_tag = NULL; 203 } 204 205 /* 206 * reset/initialize a regular map's flags and other variables from the 207 * global ones, so that they are applied to all maps. Of course, each map 208 * can then override the flags individually. 209 * 210 * NOTES: 211 * (1): Will only work for maps that appear after [global]. 212 * (2): Also be careful not to free() a global option. 213 * (3): I'm doing direct char* pointer comparison, and not strcmp(). This 214 * is correct! 215 */ 216 217 /* initialize map_type from [global] */ 218 if (cfm->cfm_type && cfm->cfm_type != gopt.map_type) 219 XFREE(cfm->cfm_type); 220 cfm->cfm_type = gopt.map_type; 221 222 /* initialize map_opts from [global] */ 223 if (cfm->cfm_opts && cfm->cfm_opts != gopt.map_options) 224 XFREE(cfm->cfm_opts); 225 cfm->cfm_opts = gopt.map_options; 226 227 /* initialize search_path from [global] */ 228 if (cfm->cfm_search_path && cfm->cfm_search_path != gopt.search_path) 229 XFREE(cfm->cfm_search_path); 230 cfm->cfm_search_path = gopt.search_path; 231 232 /* 233 * Initialize flags that are common both to [global] and a local map. 234 */ 235 cfm->cfm_flags = gopt.flags & (CFM_BROWSABLE_DIRS | 236 CFM_BROWSABLE_DIRS_FULL | 237 CFM_MOUNT_TYPE_AUTOFS | 238 CFM_SELECTORS_IN_DEFAULTS); 239} 240 241 242/* 243 * Process configuration file options. 244 * Return 0 if OK, 1 otherwise. 245 */ 246int 247set_conf_kv(const char *section, const char *key, const char *val) 248{ 249 int ret; 250 251#ifdef DEBUG_CONF 252 fprintf(stderr,"set_conf_kv: section=%s, key=%s, val=%s\n", 253 section, key, val); 254#endif /* DEBUG_CONF */ 255 256 /* 257 * If global section, process them one at a time. 258 */ 259 if (STREQ(section, "global")) { 260 /* 261 * Check if a regular map was configured before "global", 262 * and process it as needed. 263 */ 264 if (cur_map.cfm_dir) { 265 fprintf(stderr,"processing regular map \"%s\" before global one.\n", 266 section); 267 ret = process_regular_map(&cur_map); /* will reset map */ 268 if (ret != 0) 269 return ret; 270 } 271 272 /* process the global option first */ 273 ret = process_global_option(key, val); 274 275 /* reset default options for regular maps from just updated globals */ 276 if (ret == 0) 277 reset_cf_map(&cur_map); 278 279 /* return status from the processing of the global option */ 280 return ret; 281 } 282 283 /* 284 * otherwise save options and process a single map all at once. 285 */ 286 287 /* check if we found a new map, so process one already collected */ 288 if (cur_map.cfm_dir && !STREQ(cur_map.cfm_dir, section)) { 289 ret = process_regular_map(&cur_map); /* will reset map */ 290 if (ret != 0) 291 return ret; 292 } 293 294 /* now process a single entry of a regular map */ 295 return process_regular_option(section, key, val, &cur_map); 296} 297 298 299/* 300 * Process global section of configuration file options. 301 * Return 0 upon success, 1 otherwise. 302 */ 303static int 304process_global_option(const char *key, const char *val) 305{ 306 struct _func_map *gfp; 307 308 /* ensure that val is valid */ 309 if (!val || val[0] == '\0') 310 return 1; 311 312 /* 313 * search for global function. 314 */ 315 for (gfp = glob_functable; gfp->name; gfp++) 316 if (FSTREQ(gfp->name, key)) 317 return (gfp->func)(val); 318 319 fprintf(stderr, "conf: unknown global key: \"%s\"\n", key); 320 return 1; /* failed to match any command */ 321} 322 323 324static int 325gopt_arch(const char *val) 326{ 327 gopt.arch = strdup((char *)val); 328 return 0; 329} 330 331 332static int 333gopt_auto_dir(const char *val) 334{ 335 gopt.auto_dir = strdup((char *)val); 336 return 0; 337} 338 339 340static int 341gopt_browsable_dirs(const char *val) 342{ 343 if (STREQ(val, "full")) { 344 gopt.flags |= CFM_BROWSABLE_DIRS_FULL; 345 return 0; 346 } else if (STREQ(val, "yes")) { 347 gopt.flags |= CFM_BROWSABLE_DIRS; 348 return 0; 349 } else if (STREQ(val, "no")) { 350 gopt.flags &= ~CFM_BROWSABLE_DIRS; 351 return 0; 352 } 353 354 fprintf(stderr, "conf: unknown value to browsable_dirs \"%s\"\n", val); 355 return 1; /* unknown value */ 356} 357 358 359static int 360gopt_cache_duration(const char *val) 361{ 362 gopt.am_timeo = atoi(val); 363 if (gopt.am_timeo <= 0) 364 gopt.am_timeo = AM_TTL; 365 return 0; 366} 367 368 369static int 370gopt_cluster(const char *val) 371{ 372 gopt.cluster = strdup((char *)val); 373 return 0; 374} 375 376 377static int 378gopt_debug_options(const char *val) 379{ 380#ifdef DEBUG 381 usage += debug_option(strdup((char *)val)); 382 return 0; 383#else /* not DEBUG */ 384 fprintf(stderr, "%s: not compiled with DEBUG option -- sorry.\n", 385 am_get_progname()); 386 return 1; 387#endif /* not DEBUG */ 388} 389 390 391static int 392gopt_dismount_interval(const char *val) 393{ 394 gopt.am_timeo_w = atoi(val); 395 if (gopt.am_timeo_w <= 0) 396 gopt.am_timeo_w = AM_TTL_W; 397 return 0; 398} 399 400 401static int 402gopt_full_os(const char *val) 403{ 404 gopt.op_sys_full = strdup((char *)val); 405 return 0; 406} 407 408 409static int 410gopt_fully_qualified_hosts(const char *val) 411{ 412 if (STREQ(val, "yes")) { 413 gopt.flags |= CFM_FULLY_QUALIFIED_HOSTS; 414 return 0; 415 } else if (STREQ(val, "no")) { 416 gopt.flags &= ~CFM_FULLY_QUALIFIED_HOSTS; 417 return 0; 418 } 419 420 fprintf(stderr, "conf: unknown value to fully_qualified_hosts \"%s\"\n", val); 421 return 1; /* unknown value */ 422} 423 424 425static int 426gopt_hesiod_base(const char *val) 427{ 428#ifdef HAVE_MAP_HESIOD 429 gopt.hesiod_base = strdup((char *)val); 430 return 0; 431#else /* not HAVE_MAP_HESIOD */ 432 fprintf(stderr, "conf: hesiod_base option ignored. No Hesiod support available.\n"); 433 return 1; 434#endif /* not HAVE_MAP_HESIOD */ 435} 436 437 438static int 439gopt_karch(const char *val) 440{ 441 gopt.karch = strdup((char *)val); 442 return 0; 443} 444 445 446static int 447gopt_pid_file(const char *val) 448{ 449 gopt.pid_file = strdup((char *)val); 450 return 0; 451} 452 453 454static int 455gopt_local_domain(const char *val) 456{ 457 gopt.sub_domain = strdup((char *)val); 458 return 0; 459} 460 461 462static int 463gopt_ldap_base(const char *val) 464{ 465#ifdef HAVE_MAP_LDAP 466 gopt.ldap_base = strdup((char *)val); 467 return 0; 468#else /* not HAVE_MAP_LDAP */ 469 fprintf(stderr, "conf: ldap_base option ignored. No LDAP support available.\n"); 470 return 1; 471#endif /* not HAVE_MAP_LDAP */ 472} 473 474 475static int 476gopt_ldap_cache_seconds(const char *val) 477{ 478#ifdef HAVE_MAP_LDAP 479 char *end; 480 481 gopt.ldap_cache_seconds = strtol((char *)val, &end, 10); 482 if (end == val) { 483 fprintf(stderr, "conf: bad LDAP cache (seconds) option: %s\n",val); 484 return 1; 485 } 486 return 0; 487#else /* not HAVE_MAP_LDAP */ 488 fprintf(stderr, "conf: ldap_cache_seconds option ignored. No LDAP support available.\n"); 489 return 1; 490#endif /* not HAVE_MAP_LDAP */ 491} 492 493 494static int 495gopt_ldap_cache_maxmem(const char *val) 496{ 497#ifdef HAVE_MAP_LDAP 498 char *end; 499 500 gopt.ldap_cache_maxmem = strtol((char *)val, &end, 10); 501 if (end == val) { 502 fprintf(stderr, "conf: bad LDAP cache (maxmem) option: %s\n",val); 503 return 1; 504 } 505 return 0; 506#else /* not HAVE_MAP_LDAP */ 507 fprintf(stderr, "conf: ldap_cache_maxmem option ignored. No LDAP support available.\n"); 508 return 1; 509#endif /* not HAVE_MAP_LDAP */ 510} 511 512 513static int 514gopt_ldap_hostports(const char *val) 515{ 516#ifdef HAVE_MAP_LDAP 517 gopt.ldap_hostports = strdup((char *)val); 518 return 0; 519#else /* not HAVE_MAP_LDAP */ 520 fprintf(stderr, "conf: ldap_hostports option ignored. No LDAP support available.\n"); 521 return 1; 522#endif /* not HAVE_MAP_LDAP */ 523 524} 525 526 527static int 528gopt_log_file(const char *val) 529{ 530 gopt.logfile = strdup((char *)val); 531 return 0; 532} 533 534 535static int 536gopt_log_options(const char *val) 537{ 538 usage += switch_option(strdup((char *)val)); 539 return 0; 540} 541 542 543static int 544gopt_map_options(const char *val) 545{ 546 gopt.map_options = strdup((char *)val); 547 return 0; 548} 549 550 551static int 552gopt_map_type(const char *val) 553{ 554 /* check if map type exist */ 555 if (!mapc_type_exists(val)) { 556 fprintf(stderr, "conf: no such map type \"%s\"\n", val); 557 return 1; 558 } 559 gopt.map_type = strdup((char *)val); 560 return 0; 561} 562 563 564static int 565gopt_mount_type(const char *val) 566{ 567 if (STREQ(val, "autofs")) { 568#ifdef HAVE_FS_AUTOFS 569 gopt.flags |= CFM_MOUNT_TYPE_AUTOFS; 570 amd_use_autofs++; 571 return 0; 572#else /* not HAVE_FS_AUTOFS */ 573 fprintf(stderr, "conf: no autofs support available\n"); 574 return 1; 575#endif /* not HAVE_FS_AUTOFS */ 576 } else if (STREQ(val, "nfs")) { 577 gopt.flags &= ~CFM_MOUNT_TYPE_AUTOFS; 578 return 0; 579 } 580 581 fprintf(stderr, "conf: unknown value to mount_type \"%s\"\n", val); 582 return 1; /* unknown value */ 583} 584 585 586static int 587gopt_portmap_program(const char *val) 588{ 589 gopt.portmap_program = atoi(val); 590 /* 591 * allow alternate program numbers to be no more than 10 offset from 592 * official amd program number (300019). 593 */ 594 if (gopt.portmap_program < AMQ_PROGRAM || 595 gopt.portmap_program > AMQ_PROGRAM + 10) { 596 gopt.portmap_program = AMQ_PROGRAM; 597 set_amd_program_number(gopt.portmap_program); 598 fprintf(stderr, "conf: illegal amd program number \"%s\"\n", val); 599 return 1; 600 } 601 602 set_amd_program_number(gopt.portmap_program); 603 return 0; /* all is OK */ 604} 605 606 607static int 608gopt_nfs_proto(const char *val) 609{ 610 if (STREQ(val, "udp") || STREQ(val, "tcp")) { 611 gopt.nfs_proto = strdup((char *)val); 612 return 0; 613 } 614 fprintf(stderr, "conf: illegal nfs_proto \"%s\"\n", val); 615 return 1; 616} 617 618 619static int 620gopt_nfs_retransmit_counter(const char *val) 621{ 622 gopt.amfs_auto_retrans = atoi(val); 623 return 0; 624} 625 626 627static int 628gopt_nfs_retry_interval(const char *val) 629{ 630 gopt.amfs_auto_timeo = atoi(val); 631 return 0; 632} 633 634 635static int 636gopt_nfs_vers(const char *val) 637{ 638 int i = atoi(val); 639 640 if (i == 2 || i == 3) { 641 gopt.nfs_vers = i; 642 return 0; 643 } 644 fprintf(stderr, "conf: illegal nfs_vers \"%s\"\n", val); 645 return 1; 646} 647 648 649static int 650gopt_nis_domain(const char *val) 651{ 652#ifdef HAVE_MAP_NIS 653 gopt.nis_domain = strdup((char *)val); 654 return 0; 655#else /* not HAVE_MAP_NIS */ 656 fprintf(stderr, "conf: nis_domain option ignored. No NIS support available.\n"); 657 return 1; 658#endif /* not HAVE_MAP_NIS */ 659} 660 661 662static int 663gopt_normalize_hostnames(const char *val) 664{ 665 if (STREQ(val, "yes")) { 666 gopt.flags |= CFM_NORMALIZE_HOSTNAMES; 667 return 0; 668 } else if (STREQ(val, "no")) { 669 gopt.flags &= ~CFM_NORMALIZE_HOSTNAMES; 670 return 0; 671 } 672 673 fprintf(stderr, "conf: unknown value to normalize_hostnames \"%s\"\n", val); 674 return 1; /* unknown value */ 675} 676 677 678static int 679gopt_os(const char *val) 680{ 681 gopt.op_sys = strdup((char *)val); 682 return 0; 683} 684 685 686static int 687gopt_osver(const char *val) 688{ 689 gopt.op_sys_ver = strdup((char *)val); 690 return 0; 691} 692 693 694static int 695gopt_plock(const char *val) 696{ 697 if (STREQ(val, "yes")) { 698 gopt.flags |= CFM_PROCESS_LOCK; 699 return 0; 700 } else if (STREQ(val, "no")) { 701 gopt.flags &= ~CFM_PROCESS_LOCK; 702 return 0; 703 } 704 705 fprintf(stderr, "conf: unknown value to plock \"%s\"\n", val); 706 return 1; /* unknown value */ 707} 708 709 710static int 711gopt_print_pid(const char *val) 712{ 713 if (STREQ(val, "yes")) { 714 gopt.flags |= CFM_PRINT_PID; 715 return 0; 716 } else if (STREQ(val, "no")) { 717 gopt.flags &= ~CFM_PRINT_PID; 718 return 0; 719 } 720 721 fprintf(stderr, "conf: unknown value to print_pid \"%s\"\n", val); 722 return 1; /* unknown value */ 723} 724 725 726static int 727gopt_print_version(const char *val) 728{ 729 if (STREQ(val, "yes")) { 730 fputs(get_version_string(), stderr); 731 return 0; 732 } else if (STREQ(val, "no")) { 733 return 0; 734 } 735 736 fprintf(stderr, "conf: unknown value to print_version \"%s\"\n", val); 737 return 1; /* unknown value */ 738} 739 740 741static int 742gopt_restart_mounts(const char *val) 743{ 744 if (STREQ(val, "yes")) { 745 gopt.flags |= CFM_RESTART_EXISTING_MOUNTS; 746 return 0; 747 } else if (STREQ(val, "no")) { 748 gopt.flags &= ~CFM_RESTART_EXISTING_MOUNTS; 749 return 0; 750 } 751 752 fprintf(stderr, "conf: unknown value to restart_mounts \"%s\"\n", val); 753 return 1; /* unknown value */ 754} 755 756 757static int 758gopt_search_path(const char *val) 759{ 760 gopt.search_path = strdup((char *)val); 761 return 0; 762} 763 764 765static int 766gopt_selectors_in_defaults(const char *val) 767{ 768 if (STREQ(val, "yes")) { 769 gopt.flags |= CFM_SELECTORS_IN_DEFAULTS; 770 return 0; 771 } else if (STREQ(val, "no")) { 772 gopt.flags &= ~CFM_SELECTORS_IN_DEFAULTS; 773 return 0; 774 } 775 776 fprintf(stderr, "conf: unknown value to enable_default_selectors \"%s\"\n", val); 777 return 1; /* unknown value */ 778} 779 780 781static int 782gopt_show_statfs_entries(const char *val) 783{ 784 if (STREQ(val, "yes")) { 785 gopt.flags |= CFM_SHOW_STATFS_ENTRIES; 786 return 0; 787 } else if (STREQ(val, "no")) { 788 gopt.flags &= ~CFM_SHOW_STATFS_ENTRIES; 789 return 0; 790 } 791 792 fprintf(stderr, "conf: unknown value to show_statfs_entries \"%s\"\n", val); 793 return 1; /* unknown value */ 794} 795 796 797static int 798gopt_unmount_on_exit(const char *val) 799{ 800 if (STREQ(val, "yes")) { 801 gopt.flags |= CFM_UNMOUNT_ON_EXIT; 802 return 0; 803 } else if (STREQ(val, "no")) { 804 gopt.flags &= ~CFM_UNMOUNT_ON_EXIT; 805 return 0; 806 } 807 808 fprintf(stderr, "conf: unknown value to unmount_on_exit \"%s\"\n", val); 809 return 1; /* unknown value */ 810} 811 812 813static int 814gopt_vendor(const char *val) 815{ 816 gopt.op_sys_vendor = strdup((char *)val); 817 return 0; 818} 819 820 821/* 822 * Collect one entry for a regular map 823 */ 824static int 825process_regular_option(const char *section, const char *key, const char *val, cf_map_t *cfm) 826{ 827 /* ensure that val is valid */ 828 if (!section || section[0] == '\0' || 829 !key || key[0] == '\0' || 830 !val || val[0] == '\0' || 831 !cfm) { 832 fprintf(stderr, "conf: process_regular_option: null entries\n"); 833 return 1; 834 } 835 836 /* check if initializing a new map */ 837 if (!cfm->cfm_dir) 838 cfm->cfm_dir = strdup((char *)section); 839 840 /* check for each possible field */ 841 if (STREQ(key, "browsable_dirs")) 842 return ropt_browsable_dirs(val, cfm); 843 844 if (STREQ(key, "map_name")) 845 return ropt_map_name(val, cfm); 846 847 if (STREQ(key, "map_options")) 848 return ropt_map_options(val, cfm); 849 850 if (STREQ(key, "map_type")) 851 return ropt_map_type(val, cfm); 852 853 if (STREQ(key, "mount_type")) 854 return ropt_mount_type(val, cfm); 855 856 if (STREQ(key, "search_path")) 857 return ropt_search_path(val, cfm); 858 859 if (STREQ(key, "tag")) 860 return ropt_tag(val, cfm); 861 862 fprintf(stderr, "conf: unknown regular key \"%s\" for section \"%s\"\n", 863 key, section); 864 return 1; /* failed to match any command */ 865} 866 867 868static int 869ropt_browsable_dirs(const char *val, cf_map_t *cfm) 870{ 871 if (STREQ(val, "full")) { 872 cfm->cfm_flags |= CFM_BROWSABLE_DIRS_FULL; 873 return 0; 874 } else if (STREQ(val, "yes")) { 875 cfm->cfm_flags |= CFM_BROWSABLE_DIRS; 876 return 0; 877 } else if (STREQ(val, "no")) { 878 cfm->cfm_flags &= ~CFM_BROWSABLE_DIRS; 879 return 0; 880 } 881 882 fprintf(stderr, "conf: unknown value to browsable_dirs \"%s\"\n", val); 883 return 1; /* unknown value */ 884} 885 886 887static int 888ropt_map_name(const char *val, cf_map_t *cfm) 889{ 890 cfm->cfm_name = strdup((char *)val); 891 return 0; 892} 893 894 895static int 896ropt_map_options(const char *val, cf_map_t *cfm) 897{ 898 cfm->cfm_opts = strdup((char *)val); 899 return 0; 900} 901 902 903static int 904ropt_map_type(const char *val, cf_map_t *cfm) 905{ 906 /* check if map type exist */ 907 if (!mapc_type_exists(val)) { 908 fprintf(stderr, "conf: no such map type \"%s\"\n", val); 909 return 1; 910 } 911 cfm->cfm_type = strdup((char *)val); 912 return 0; 913} 914 915 916static int 917ropt_mount_type(const char *val, cf_map_t *cfm) 918{ 919 if (STREQ(val, "autofs")) { 920#ifdef HAVE_FS_AUTOFS 921 cfm->cfm_flags |= CFM_MOUNT_TYPE_AUTOFS; 922 amd_use_autofs++; 923 return 0; 924#else /* not HAVE_FS_AUTOFS */ 925 fprintf(stderr, "conf: no autofs support available\n"); 926 return 1; 927#endif /* not HAVE_FS_AUTOFS */ 928 } else if (STREQ(val, "nfs")) { 929 cfm->cfm_flags &= ~CFM_MOUNT_TYPE_AUTOFS; 930 return 0; 931 } 932 933 fprintf(stderr, "conf: unknown value to mount_type \"%s\"\n", val); 934 return 1; /* unknown value */ 935} 936 937 938static int 939ropt_search_path(const char *val, cf_map_t *cfm) 940{ 941 cfm->cfm_search_path = strdup((char *)val); 942 return 0; 943} 944 945 946static int 947ropt_tag(const char *val, cf_map_t *cfm) 948{ 949 cfm->cfm_tag = strdup((char *)val); 950 return 0; 951} 952 953 954/* 955 * Process one collected map. 956 */ 957static int 958process_regular_map(cf_map_t *cfm) 959{ 960 961 if (!cfm->cfm_name) { 962 fprintf(stderr, "conf: map_name must be defined for map \"%s\"\n", cfm->cfm_dir); 963 return 1; 964 } 965 /* 966 * If map has no tag defined, process the map. 967 * If no conf_tag was set in amd -T, process all untagged entries. 968 * If a tag is defined, then process it only if it matches the map tag. 969 */ 970 if (!cfm->cfm_tag || 971 (conf_tag && STREQ(cfm->cfm_tag, conf_tag))) { 972#ifdef DEBUG_CONF 973 fprintf(stderr, "processing map %s (flags=0x%x)...\n", 974 cfm->cfm_dir, cfm->cfm_flags); 975#endif /* DEBUG_CONF */ 976 root_newmap(cfm->cfm_dir, 977 cfm->cfm_opts ? cfm->cfm_opts : "", 978 cfm->cfm_name, 979 cfm); 980 } else { 981 fprintf(stderr, "skipping map %s...\n", cfm->cfm_dir); 982 } 983 984 reset_cf_map(cfm); 985 return 0; 986} 987 988 989/* 990 * Process last map in conf file (if any) 991 */ 992int 993process_last_regular_map(void) 994{ 995 /* 996 * If the amd.conf file only has a [global] section (pretty useless 997 * IMHO), do not try to process a map that does not exist. 998 */ 999 if (!cur_map.cfm_dir) 1000 return 0; 1001 return process_regular_map(&cur_map); 1002} 1003