Home | History | Annotate | Line # | Download | only in amd
      1 /*	$NetBSD: conf.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/conf.c
     39  *
     40  */
     41 
     42 /*
     43  * Functions to handle the configuration file.
     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 
     53 /*
     54  * MACROS:
     55  */
     56 /* Turn on to show some info about maps being configured */
     57 /* #define DEBUG_CONF */
     58 
     59 /*
     60  * TYPEDEFS:
     61  */
     62 typedef int (*OptFuncPtr)(const char *);
     63 
     64 /*
     65  * STRUCTURES:
     66  */
     67 struct _func_map {
     68   char *name;
     69   OptFuncPtr func;
     70 };
     71 
     72 /*
     73  * FORWARD DECLARATIONS:
     74  */
     75 static int gopt_arch(const char *val);
     76 static int gopt_auto_attrcache(const char *val);
     77 static int gopt_auto_dir(const char *val);
     78 static int gopt_auto_nfs_version(const char *val);
     79 static int gopt_autofs_use_lofs(const char *val);
     80 static int gopt_browsable_dirs(const char *val);
     81 static int gopt_cache_duration(const char *val);
     82 static int gopt_cluster(const char *val);
     83 static int gopt_debug_mtab_file(const char *val);
     84 static int gopt_debug_options(const char *val);
     85 static int gopt_dismount_interval(const char *val);
     86 static int gopt_domain_strip(const char *val);
     87 static int gopt_exec_map_timeout(const char *val);
     88 static int gopt_forced_unmounts(const char *val);
     89 static int gopt_full_os(const char *val);
     90 static int gopt_fully_qualified_hosts(const char *val);
     91 static int gopt_hesiod_base(const char *val);
     92 static int gopt_karch(const char *val);
     93 static int gopt_ldap_base(const char *val);
     94 static int gopt_ldap_cache_maxmem(const char *val);
     95 static int gopt_ldap_cache_seconds(const char *val);
     96 static int gopt_ldap_hostports(const char *val);
     97 static int gopt_ldap_proto_version(const char *val);
     98 static int gopt_local_domain(const char *val);
     99 static int gopt_localhost_address(const char *val);
    100 static int gopt_log_file(const char *val);
    101 static int gopt_log_options(const char *val);
    102 static int gopt_map_defaults(const char *val);
    103 static int gopt_map_options(const char *val);
    104 static int gopt_map_reload_interval(const char *val);
    105 static int gopt_map_type(const char *val);
    106 static int gopt_mount_type(const char *val);
    107 static int gopt_pid_file(const char *val);
    108 static int gopt_portmap_program(const char *val);
    109 static int gopt_preferred_amq_port(const char *val);
    110 static int gopt_nfs_allow_any_interface(const char *val);
    111 static int gopt_nfs_allow_insecure_port(const char *val);
    112 static int gopt_nfs_proto(const char *val);
    113 static int gopt_nfs_retransmit_counter(const char *val);
    114 static int gopt_nfs_retransmit_counter_udp(const char *val);
    115 static int gopt_nfs_retransmit_counter_tcp(const char *val);
    116 static int gopt_nfs_retransmit_counter_toplvl(const char *val);
    117 static int gopt_nfs_retry_interval(const char *val);
    118 static int gopt_nfs_retry_interval_udp(const char *val);
    119 static int gopt_nfs_retry_interval_tcp(const char *val);
    120 static int gopt_nfs_retry_interval_toplvl(const char *val);
    121 static int gopt_nfs_vers(const char *val);
    122 static int gopt_nfs_vers_ping(const char *val);
    123 static int gopt_nis_domain(const char *val);
    124 static int gopt_normalize_hostnames(const char *val);
    125 static int gopt_normalize_slashes(const char *val);
    126 static int gopt_os(const char *val);
    127 static int gopt_osver(const char *val);
    128 static int gopt_plock(const char *val);
    129 static int gopt_print_pid(const char *val);
    130 static int gopt_print_version(const char *val);
    131 static int gopt_restart_mounts(const char *val);
    132 static int gopt_search_path(const char *val);
    133 static int gopt_selectors_in_defaults(const char *val);
    134 static int gopt_show_statfs_entries(const char *val);
    135 static int gopt_sun_map_syntax(const char *val);
    136 static int gopt_truncate_log(const char *val);
    137 static int gopt_unmount_on_exit(const char *val);
    138 static int gopt_use_tcpwrappers(const char *val);
    139 static int gopt_vendor(const char *val);
    140 static int process_global_option(const char *key, const char *val);
    141 static int process_one_regular_map(const cf_map_t *cfm);
    142 static int process_regular_option(const char *section, const char *key, const char *val, cf_map_t *cfm);
    143 static int ropt_browsable_dirs(const char *val, cf_map_t *cfm);
    144 static int ropt_map_name(const char *val, cf_map_t *cfm);
    145 static int ropt_map_defaults(const char *val, cf_map_t *cfm);
    146 static int ropt_map_options(const char *val, cf_map_t *cfm);
    147 static int ropt_map_type(const char *val, cf_map_t *cfm);
    148 static int ropt_mount_type(const char *val, cf_map_t *cfm);
    149 static int ropt_search_path(const char *val, cf_map_t *cfm);
    150 static int ropt_sun_map_syntax(const char *val, cf_map_t *cfm);
    151 static int ropt_tag(const char *val, cf_map_t *cfm);
    152 static void init_cf_map(cf_map_t *cfm);
    153 
    154 
    155 /*
    156  * STATIC VARIABLES:
    157  */
    158 static cf_map_t *head_map, *cur_map;
    159 
    160 static struct _func_map glob_functable[] = {
    161   {"arch",			gopt_arch},
    162   {"auto_attrcache",		gopt_auto_attrcache},
    163   {"auto_dir",			gopt_auto_dir},
    164   {"auto_nfs_version",		gopt_auto_nfs_version},
    165   {"autofs_use_lofs",		gopt_autofs_use_lofs},
    166   {"browsable_dirs",		gopt_browsable_dirs},
    167   {"cache_duration",		gopt_cache_duration},
    168   {"cluster",			gopt_cluster},
    169   {"debug_mtab_file",           gopt_debug_mtab_file},
    170   {"debug_options",		gopt_debug_options},
    171   {"dismount_interval",		gopt_dismount_interval},
    172   {"domain_strip",		gopt_domain_strip},
    173   {"exec_map_timeout",		gopt_exec_map_timeout},
    174   {"forced_unmounts",		gopt_forced_unmounts},
    175   {"fully_qualified_hosts",	gopt_fully_qualified_hosts},
    176   {"full_os",			gopt_full_os},
    177   {"hesiod_base",		gopt_hesiod_base},
    178   {"karch",			gopt_karch},
    179   {"ldap_base",			gopt_ldap_base},
    180   {"ldap_cache_maxmem",		gopt_ldap_cache_maxmem},
    181   {"ldap_cache_seconds",	gopt_ldap_cache_seconds},
    182   {"ldap_hostports",		gopt_ldap_hostports},
    183   {"ldap_proto_version",	gopt_ldap_proto_version},
    184   {"local_domain",		gopt_local_domain},
    185   {"localhost_address",		gopt_localhost_address},
    186   {"log_file",			gopt_log_file},
    187   {"log_options",		gopt_log_options},
    188   {"map_defaults",		gopt_map_defaults},
    189   {"map_options",		gopt_map_options},
    190   {"map_reload_interval",	gopt_map_reload_interval},
    191   {"map_type",			gopt_map_type},
    192   {"mount_type",		gopt_mount_type},
    193   {"pid_file",			gopt_pid_file},
    194   {"portmap_program",		gopt_portmap_program},
    195   {"preferred_amq_port",	gopt_preferred_amq_port},
    196   {"nfs_allow_any_interface",	gopt_nfs_allow_any_interface},
    197   {"nfs_allow_insecure_port",	gopt_nfs_allow_insecure_port},
    198   {"nfs_proto",			gopt_nfs_proto},
    199   {"nfs_retransmit_counter",	gopt_nfs_retransmit_counter},
    200   {"nfs_retransmit_counter_udp",	gopt_nfs_retransmit_counter_udp},
    201   {"nfs_retransmit_counter_tcp",	gopt_nfs_retransmit_counter_tcp},
    202   {"nfs_retransmit_counter_toplvl",	gopt_nfs_retransmit_counter_toplvl},
    203   {"nfs_retry_interval",	gopt_nfs_retry_interval},
    204   {"nfs_retry_interval_udp",	gopt_nfs_retry_interval_udp},
    205   {"nfs_retry_interval_tcp",	gopt_nfs_retry_interval_tcp},
    206   {"nfs_retry_interval_toplvl",	gopt_nfs_retry_interval_toplvl},
    207   {"nfs_vers",			gopt_nfs_vers},
    208   {"nfs_vers_ping",		gopt_nfs_vers_ping},
    209   {"nis_domain",		gopt_nis_domain},
    210   {"normalize_hostnames",	gopt_normalize_hostnames},
    211   {"normalize_slashes",		gopt_normalize_slashes},
    212   {"os",			gopt_os},
    213   {"osver",			gopt_osver},
    214   {"plock",			gopt_plock},
    215   {"print_pid",			gopt_print_pid},
    216   {"print_version",		gopt_print_version},
    217   {"restart_mounts",		gopt_restart_mounts},
    218   {"search_path",		gopt_search_path},
    219   {"selectors_on_default",	gopt_selectors_in_defaults},
    220   {"selectors_in_defaults",	gopt_selectors_in_defaults},
    221   {"show_statfs_entries",	gopt_show_statfs_entries},
    222   {"sun_map_syntax",		gopt_sun_map_syntax},
    223   {"truncate_log",		gopt_truncate_log},
    224   {"unmount_on_exit",		gopt_unmount_on_exit},
    225   {"use_tcpwrappers",		gopt_use_tcpwrappers},
    226   {"vendor",			gopt_vendor},
    227   {NULL, NULL}
    228 };
    229 
    230 
    231 /*
    232  * Initialize a map from [global] defaults.
    233  */
    234 static void
    235 init_cf_map(cf_map_t *cfm)
    236 {
    237   if (!cfm)
    238     return;
    239 
    240   /*
    241    * Initialize a regular map's flags and other variables from the
    242    * global ones, so that they are applied to all maps.  Of course, each map
    243    * can then override the flags individually.
    244    *
    245    * NOTES:
    246    * (1): Will only work for maps that appear after [global].
    247    * (2): I'm assigning pointers directly from the global map.
    248    */
    249 
    250   /* initialize map_type from [global] */
    251   cfm->cfm_type = gopt.map_type;
    252 
    253   /* initialize map_defaults from [global] */
    254   cfm->cfm_defaults = gopt.map_defaults;
    255 
    256   /* initialize map_opts from [global] */
    257   cfm->cfm_opts = gopt.map_options;
    258 
    259   /* initialize search_path from [global] */
    260   cfm->cfm_search_path = gopt.search_path;
    261 
    262   /*
    263    * Initialize flags that are common both to [global] and a local map
    264    * (that is, they could be inherited from the global section).
    265    */
    266   cfm->cfm_flags = gopt.flags & (CFM_BROWSABLE_DIRS |
    267 				 CFM_BROWSABLE_DIRS_FULL |
    268 				 CFM_MOUNT_TYPE_AUTOFS |
    269 				 CFM_SELECTORS_IN_DEFAULTS |
    270 				 CFM_SUN_MAP_SYNTAX );
    271 }
    272 
    273 
    274 /*
    275  * Process configuration file options (called from YACC parser).
    276  * Return 0 if OK, 1 otherwise.
    277  */
    278 int
    279 set_conf_kv(const char *section, const char *key, const char *val)
    280 {
    281   int ret;
    282 
    283 #ifdef DEBUG_CONF
    284   fprintf(stderr, "set_conf_kv: section=%s, key=%s, val=%s\n",
    285 	  section, key, val);
    286 #endif /* DEBUG_CONF */
    287 
    288   /*
    289    * If global section, process kv pairs one at a time.
    290    */
    291   if (STREQ(section, "global")) {
    292     /*
    293      * Check if a regular map was configured before "global",
    294      * and warn about it.
    295      */
    296     if (cur_map && cur_map->cfm_dir) {
    297       static short printed_this_error;
    298       if (!printed_this_error) {
    299 	fprintf(stderr, "found regular map \"%s\" before global one.\n",
    300 		cur_map->cfm_dir);
    301 	printed_this_error = 1;
    302       }
    303     }
    304 
    305     /* process the global option first */
    306     ret = process_global_option(key, val);
    307 
    308     /* return status from the processing of the global option */
    309     return ret;
    310   }
    311 
    312   /*
    313    * Otherwise we found a non-global option: store it after some testing.
    314    */
    315 
    316   /* initialize (static) global list head and current map pointer */
    317   if (!head_map && !cur_map) {
    318     cur_map = CALLOC(cf_map_t);
    319     if (!cur_map) {
    320       perror("calloc");
    321       exit(1);
    322     }
    323     /* initialize first head map from global defaults */
    324     init_cf_map(cur_map);
    325     head_map = cur_map;
    326   }
    327 
    328   /* check if we found a new map, then allocate and initialize it */
    329   if (cur_map->cfm_dir && !STREQ(cur_map->cfm_dir, section)) {
    330     /* allocate new map struct */
    331     cf_map_t *tmp_map = CALLOC(cf_map_t);
    332     if (!tmp_map) {
    333       perror("calloc");
    334       exit(1);
    335     }
    336     /* initialize it from global defaults */
    337     init_cf_map(tmp_map);
    338     /* append it to end of linked list */
    339     cur_map->cfm_next = tmp_map;
    340     cur_map = tmp_map;
    341   }
    342 
    343   /* now process a single entry of a regular map */
    344   return process_regular_option(section, key, val, cur_map);
    345 }
    346 
    347 
    348 /*
    349  * Process global section of configuration file options.
    350  * Return 0 upon success, 1 otherwise.
    351  */
    352 static int
    353 process_global_option(const char *key, const char *val)
    354 {
    355   struct _func_map *gfp;
    356 
    357   /* ensure that val is valid */
    358   if (!val || val[0] == '\0')
    359     return 1;
    360 
    361   /*
    362    * search for global function.
    363    */
    364   for (gfp = glob_functable; gfp->name; gfp++)
    365     if (FSTREQ(gfp->name, key))
    366       return (gfp->func)(val);
    367 
    368   fprintf(stderr, "conf: unknown global key: \"%s\"\n", key);
    369   return 1;			/* failed to match any command */
    370 }
    371 
    372 
    373 static int
    374 gopt_arch(const char *val)
    375 {
    376   gopt.arch = xstrdup(val);
    377   return 0;
    378 }
    379 
    380 
    381 static int
    382 gopt_auto_attrcache(const char *val)
    383 {
    384   gopt.auto_attrcache = atoi(val);
    385   if (gopt.auto_attrcache < 0) {
    386     fprintf(stderr, "conf: bad attrcache value: \"%s\"\n", val);
    387     return 1;
    388   }
    389   return 0;
    390 }
    391 
    392 
    393 static int
    394 gopt_auto_dir(const char *val)
    395 {
    396   gopt.auto_dir = xstrdup(val);
    397   return 0;
    398 }
    399 
    400 static int
    401 gopt_auto_nfs_version(const char *val)
    402 {
    403   if (strcmp(val, "2") == 0)
    404     nfs_dispatcher = nfs_program_2;
    405   else if (strcmp(val, "3") == 0)
    406     nfs_dispatcher = nfs_program_3;
    407   else {
    408     fprintf(stderr, "conf: bad auto nfs version : \"%s\"\n", val);
    409     return 1;
    410   }
    411   return 0;
    412 }
    413 
    414 static int
    415 gopt_autofs_use_lofs(const char *val)
    416 {
    417   if (STREQ(val, "yes")) {
    418     gopt.flags |= CFM_AUTOFS_USE_LOFS;
    419     return 0;
    420   } else if (STREQ(val, "no")) {
    421     gopt.flags &= ~CFM_AUTOFS_USE_LOFS;
    422     return 0;
    423   }
    424 
    425   fprintf(stderr, "conf: unknown value to autofs_use_lofs \"%s\"\n", val);
    426   return 1;			/* unknown value */
    427 }
    428 
    429 
    430 static int
    431 gopt_browsable_dirs(const char *val)
    432 {
    433   if (STREQ(val, "full")) {
    434     gopt.flags |= CFM_BROWSABLE_DIRS_FULL;
    435     return 0;
    436   } else if (STREQ(val, "yes")) {
    437     gopt.flags |= CFM_BROWSABLE_DIRS;
    438     return 0;
    439   } else if (STREQ(val, "no")) {
    440     gopt.flags &= ~CFM_BROWSABLE_DIRS;
    441     return 0;
    442   }
    443 
    444   fprintf(stderr, "conf: unknown value to browsable_dirs \"%s\"\n", val);
    445   return 1;			/* unknown value */
    446 }
    447 
    448 
    449 static int
    450 gopt_cache_duration(const char *val)
    451 {
    452   gopt.am_timeo = atoi(val);
    453   if (gopt.am_timeo <= 0)
    454     gopt.am_timeo = AM_TTL;
    455   return 0;
    456 }
    457 
    458 
    459 static int
    460 gopt_cluster(const char *val)
    461 {
    462   gopt.cluster = xstrdup(val);
    463   return 0;
    464 }
    465 
    466 
    467 static int
    468 gopt_debug_mtab_file(const char *val)
    469 {
    470   gopt.debug_mtab_file = xstrdup(val);
    471   return 0;
    472 }
    473 
    474 
    475 static int
    476 gopt_debug_options(const char *val)
    477 {
    478 #ifdef DEBUG
    479   usage += debug_option((char *)val);
    480   return 0;
    481 #else /* not DEBUG */
    482   fprintf(stderr, "%s: not compiled with DEBUG option -- sorry.\n",
    483 	  am_get_progname());
    484   return 1;
    485 #endif /* not DEBUG */
    486 }
    487 
    488 
    489 static int
    490 gopt_dismount_interval(const char *val)
    491 {
    492   gopt.am_timeo_w = atoi(val);
    493   if (gopt.am_timeo_w <= 0)
    494     gopt.am_timeo_w = AM_TTL_W;
    495   return 0;
    496 }
    497 
    498 
    499 static int
    500 gopt_domain_strip(const char *val)
    501 {
    502   if (STREQ(val, "yes")) {
    503     gopt.flags |= CFM_DOMAIN_STRIP;
    504     return 0;
    505   } else if (STREQ(val, "no")) {
    506     gopt.flags &= ~CFM_DOMAIN_STRIP;
    507     return 0;
    508   }
    509 
    510   fprintf(stderr, "conf: unknown value to domain_strip \"%s\"\n", val);
    511   return 1;                     /* unknown value */
    512 }
    513 
    514 
    515 static int
    516 gopt_exec_map_timeout(const char *val)
    517 {
    518   gopt.exec_map_timeout = atoi(val);
    519   if (gopt.exec_map_timeout <= 0)
    520     gopt.exec_map_timeout = AMFS_EXEC_MAP_TIMEOUT; /* default exec map timeout */
    521   return 0;
    522 }
    523 
    524 
    525 static int
    526 gopt_forced_unmounts(const char *val)
    527 {
    528   if (STREQ(val, "yes")) {
    529 #if !defined(MNT2_GEN_OPT_DETACH) && !defined(MNT2_GEN_OPT_FORCE)
    530     fprintf(stderr, "conf: forced_unmounts unsupported on this system.\n");
    531     return 1;
    532 #else /* defined(MNT2_GEN_OPT_DETACH) || defined(MNT2_GEN_OPT_FORCE) */
    533 # ifdef __linux__
    534     /*
    535      * HACK ALERT: Linux has had MNT_FORCE since 2.2, but it hasn't gotten
    536      * stable until 2.4.  And it had MNT_DETACH since 2.4, but it hasn't
    537      * gotten stable since 2.6.  So alert users if they're trying to use a
    538      * feature that may not work well on their older kernel.
    539      */
    540     {
    541       struct utsname un;
    542       if (uname(&un) >= 0) {
    543 #  ifdef MNT2_GEN_OPT_FORCE
    544 	if (strcmp(un.release, "2.4.0") < 0)
    545 	  fprintf(stderr, "warning: forced-unmounts (MNT_FORCE) may not work well before 2.4.0\n");
    546 #  endif /* MNT2_GEN_OPT_FORCE */
    547 #  ifdef MNT2_GEN_OPT_DETACH
    548 	if (strcmp(un.release, "2.6.0") < 0)
    549 	  fprintf(stderr, "warning: lazy-unmounts (MNT_DETACH) may not work well before 2.6.0\n");
    550 #  endif /* MNT2_GEN_OPT_DETACH */
    551       }
    552     }
    553 # endif /* __linux__ */
    554     gopt.flags |= CFM_FORCED_UNMOUNTS;
    555     return 0;
    556 #endif /* defined(MNT2_GEN_OPT_DETACH) || defined(MNT2_GEN_OPT_FORCE) */
    557   } else if (STREQ(val, "no")) {
    558     gopt.flags &= ~CFM_FORCED_UNMOUNTS;
    559     return 0;
    560   }
    561 
    562   fprintf(stderr, "conf: unknown value to unmount_on_exit \"%s\"\n", val);
    563   return 1;			/* unknown value */
    564 }
    565 
    566 
    567 static int
    568 gopt_full_os(const char *val)
    569 {
    570   gopt.op_sys_full = xstrdup(val);
    571   return 0;
    572 }
    573 
    574 
    575 static int
    576 gopt_fully_qualified_hosts(const char *val)
    577 {
    578   if (STREQ(val, "yes")) {
    579     gopt.flags |= CFM_FULLY_QUALIFIED_HOSTS;
    580     return 0;
    581   } else if (STREQ(val, "no")) {
    582     gopt.flags &= ~CFM_FULLY_QUALIFIED_HOSTS;
    583     return 0;
    584   }
    585 
    586   fprintf(stderr, "conf: unknown value to fully_qualified_hosts \"%s\"\n", val);
    587   return 1;			/* unknown value */
    588 }
    589 
    590 
    591 static int
    592 gopt_hesiod_base(const char *val)
    593 {
    594 #ifdef HAVE_MAP_HESIOD
    595   gopt.hesiod_base = xstrdup(val);
    596   return 0;
    597 #else /* not HAVE_MAP_HESIOD */
    598   fprintf(stderr, "conf: hesiod_base option ignored.  No Hesiod support available.\n");
    599   return 1;
    600 #endif /* not HAVE_MAP_HESIOD */
    601 }
    602 
    603 
    604 static int
    605 gopt_karch(const char *val)
    606 {
    607   gopt.karch = xstrdup(val);
    608   return 0;
    609 }
    610 
    611 
    612 static int
    613 gopt_pid_file(const char *val)
    614 {
    615   gopt.pid_file = xstrdup(val);
    616   return 0;
    617 }
    618 
    619 
    620 static int
    621 gopt_local_domain(const char *val)
    622 {
    623   gopt.sub_domain = xstrdup(val);
    624   return 0;
    625 }
    626 
    627 
    628 static int
    629 gopt_localhost_address(const char *val)
    630 {
    631   gopt.localhost_address = xstrdup(val);
    632   return 0;
    633 }
    634 
    635 
    636 static int
    637 gopt_ldap_base(const char *val)
    638 {
    639 #ifdef HAVE_MAP_LDAP
    640   gopt.ldap_base = xstrdup(val);
    641   return 0;
    642 #else /* not HAVE_MAP_LDAP */
    643   fprintf(stderr, "conf: ldap_base option ignored.  No LDAP support available.\n");
    644   return 1;
    645 #endif /* not HAVE_MAP_LDAP */
    646 }
    647 
    648 
    649 static int
    650 gopt_ldap_cache_seconds(const char *val)
    651 {
    652 #ifdef HAVE_MAP_LDAP
    653   char *end;
    654 
    655   gopt.ldap_cache_seconds = strtol((char *)val, &end, 10);
    656   if (end == val) {
    657     fprintf(stderr, "conf: bad LDAP cache (seconds) option: %s\n",val);
    658     return 1;
    659   }
    660   return 0;
    661 #else /* not HAVE_MAP_LDAP */
    662   fprintf(stderr, "conf: ldap_cache_seconds option ignored.  No LDAP support available.\n");
    663   return 1;
    664 #endif /* not HAVE_MAP_LDAP */
    665 }
    666 
    667 
    668 static int
    669 gopt_ldap_cache_maxmem(const char *val)
    670 {
    671 #ifdef HAVE_MAP_LDAP
    672   char *end;
    673 
    674   gopt.ldap_cache_maxmem = strtol((char *)val, &end, 10);
    675   if (end == val) {
    676     fprintf(stderr, "conf: bad LDAP cache (maxmem) option: %s\n",val);
    677     return 1;
    678   }
    679   return 0;
    680 #else /* not HAVE_MAP_LDAP */
    681   fprintf(stderr, "conf: ldap_cache_maxmem option ignored.  No LDAP support available.\n");
    682   return 1;
    683 #endif /* not HAVE_MAP_LDAP */
    684 }
    685 
    686 
    687 static int
    688 gopt_ldap_hostports(const char *val)
    689 {
    690 #ifdef HAVE_MAP_LDAP
    691   gopt.ldap_hostports = xstrdup(val);
    692   return 0;
    693 #else /* not HAVE_MAP_LDAP */
    694   fprintf(stderr, "conf: ldap_hostports option ignored.  No LDAP support available.\n");
    695   return 1;
    696 #endif /* not HAVE_MAP_LDAP */
    697 
    698 }
    699 
    700 
    701 static int
    702 gopt_ldap_proto_version(const char *val)
    703 {
    704 #ifdef HAVE_MAP_LDAP
    705   char *end;
    706 
    707   gopt.ldap_proto_version = strtol((char *)val, &end, 10);
    708   if (end == val) {
    709     fprintf(stderr, "conf: bad ldap_proto_version option: %s\n",val);
    710     return 1;
    711   }
    712 
    713   if (gopt.ldap_proto_version < 0 || gopt.ldap_proto_version > LDAP_VERSION_MAX) {
    714     fprintf(stderr, "conf: bad ldap_proto_version option value: %s\n",val);
    715     return 1;
    716   }
    717   switch (gopt.ldap_proto_version) {
    718     /* XXX: what about LDAP_VERSION1? */
    719   case LDAP_VERSION2:
    720 #ifdef LDAP_VERSION3
    721   case LDAP_VERSION3:
    722 #endif /* LDAP_VERSION3 */
    723 #ifdef LDAP_VERSION4
    724   case LDAP_VERSION4:
    725 #endif /* LDAP_VERSION4 */
    726     break;
    727   default:
    728     fprintf(stderr, "conf: unsupported ldap_proto_version option value: %s\n",val);
    729     return 1;
    730   }
    731   return 0;
    732 #else /* not HAVE_MAP_LDAP */
    733   fprintf(stderr, "conf: ldap_proto_version option ignored.  No LDAP support available.\n");
    734   return 1;
    735 #endif /* not HAVE_MAP_LDAP */
    736 }
    737 
    738 
    739 static int
    740 gopt_log_file(const char *val)
    741 {
    742   gopt.logfile = xstrdup(val);
    743   return 0;
    744 }
    745 
    746 
    747 static int
    748 gopt_log_options(const char *val)
    749 {
    750   usage += switch_option((char *)val);
    751   return 0;
    752 }
    753 
    754 
    755 static int
    756 gopt_map_defaults(const char *val)
    757 {
    758   gopt.map_defaults = xstrdup(val);
    759   return 0;
    760 }
    761 
    762 
    763 static int
    764 gopt_map_options(const char *val)
    765 {
    766   gopt.map_options = xstrdup(val);
    767   return 0;
    768 }
    769 
    770 
    771 static int
    772 gopt_map_reload_interval(const char *val)
    773 {
    774   gopt.map_reload_interval = atoi(val);
    775   if (gopt.map_reload_interval <= 0)
    776     gopt.map_reload_interval = ONE_HOUR;
    777   return 0;
    778 }
    779 
    780 
    781 static int
    782 gopt_map_type(const char *val)
    783 {
    784   /* check if map type exist */
    785   if (!mapc_type_exists(val)) {
    786     fprintf(stderr, "conf: no such map type \"%s\"\n", val);
    787     return 1;
    788   }
    789   gopt.map_type = xstrdup(val);
    790   return 0;
    791 }
    792 
    793 
    794 static int
    795 gopt_mount_type(const char *val)
    796 {
    797   if (STREQ(val, "autofs")) {
    798 #ifdef HAVE_FS_AUTOFS
    799     gopt.flags |= CFM_MOUNT_TYPE_AUTOFS;
    800     amd_use_autofs++;
    801     return 0;
    802 #else /* not HAVE_FS_AUTOFS */
    803     fprintf(stderr, "conf: no autofs support available\n");
    804     return 1;
    805 #endif /* not HAVE_FS_AUTOFS */
    806   } else if (STREQ(val, "nfs")) {
    807     gopt.flags &= ~CFM_MOUNT_TYPE_AUTOFS;
    808     return 0;
    809   }
    810 
    811   fprintf(stderr, "conf: unknown value to mount_type \"%s\"\n", val);
    812   return 1;			/* unknown value */
    813 }
    814 
    815 
    816 static int
    817 gopt_portmap_program(const char *val)
    818 {
    819   gopt.portmap_program = atol(val);
    820   /*
    821    * allow alternate program numbers to be no more than 10 offset from
    822    * official amd program number (300019).
    823    */
    824   if (gopt.portmap_program < AMQ_PROGRAM ||
    825       gopt.portmap_program > AMQ_PROGRAM + 10) {
    826     gopt.portmap_program = AMQ_PROGRAM;
    827     set_amd_program_number(gopt.portmap_program);
    828     fprintf(stderr, "conf: illegal amd program number \"%s\"\n", val);
    829     return 1;
    830   }
    831 
    832   set_amd_program_number(gopt.portmap_program);
    833   return 0;			/* all is OK */
    834 }
    835 
    836 
    837 static int
    838 gopt_preferred_amq_port(const char *val)
    839 {
    840   gopt.preferred_amq_port = atoi(val);
    841 
    842   /*
    843    * No need to check value: preferred_amq_port is an unsigned short and 0
    844    * is a valid number, meaning "any port".
    845    */
    846   return 0;			/* all is OK */
    847 }
    848 
    849 
    850 static int
    851 gopt_nfs_allow_any_interface(const char *val)
    852 {
    853   if (STREQ(val, "yes")) {
    854     gopt.flags |= CFM_NFS_ANY_INTERFACE;
    855     return 0;
    856   } else if (STREQ(val, "no")) {
    857     gopt.flags &= ~CFM_NFS_ANY_INTERFACE;
    858     return 0;
    859   }
    860 
    861   fprintf(stderr, "conf: unknown value to nfs_allow_insecure_port \"%s\"\n", val);
    862   return 1;			/* unknown value */
    863 }
    864 
    865 
    866 static int
    867 gopt_nfs_allow_insecure_port(const char *val)
    868 {
    869   if (STREQ(val, "yes")) {
    870     gopt.flags |= CFM_NFS_INSECURE_PORT;
    871     return 0;
    872   } else if (STREQ(val, "no")) {
    873     gopt.flags &= ~CFM_NFS_INSECURE_PORT;
    874     return 0;
    875   }
    876 
    877   fprintf(stderr, "conf: unknown value to nfs_allow_insecure_port \"%s\"\n", val);
    878   return 1;			/* unknown value */
    879 }
    880 
    881 
    882 static int
    883 gopt_nfs_proto(const char *val)
    884 {
    885   if (STREQ(val, "udp") || STREQ(val, "tcp")) {
    886     gopt.nfs_proto = xstrdup(val);
    887     return 0;
    888   }
    889   fprintf(stderr, "conf: illegal nfs_proto \"%s\"\n", val);
    890   return 1;
    891 }
    892 
    893 
    894 static int
    895 gopt_nfs_retransmit_counter(const char *val)
    896 {
    897   int i;
    898 
    899   for (i=0; i<AMU_TYPE_MAX; ++i)
    900     gopt.amfs_auto_retrans[i] = atoi(val);
    901   return 0;
    902 }
    903 
    904 
    905 static int
    906 gopt_nfs_retransmit_counter_udp(const char *val)
    907 {
    908   gopt.amfs_auto_retrans[AMU_TYPE_UDP] = atoi(val);
    909   return 0;
    910 }
    911 
    912 
    913 static int
    914 gopt_nfs_retransmit_counter_tcp(const char *val)
    915 {
    916   gopt.amfs_auto_retrans[AMU_TYPE_TCP] = atoi(val);
    917   return 0;
    918 }
    919 
    920 
    921 static int
    922 gopt_nfs_retransmit_counter_toplvl(const char *val)
    923 {
    924   gopt.amfs_auto_retrans[AMU_TYPE_TOPLVL] = atoi(val);
    925   return 0;
    926 }
    927 
    928 
    929 static int
    930 gopt_nfs_retry_interval(const char *val)
    931 {
    932   int i;
    933 
    934   for (i=0; i<AMU_TYPE_MAX; ++i)
    935     gopt.amfs_auto_timeo[i] = atoi(val);
    936   return 0;
    937 }
    938 
    939 
    940 static int
    941 gopt_nfs_retry_interval_udp(const char *val)
    942 {
    943   gopt.amfs_auto_timeo[AMU_TYPE_UDP] = atoi(val);
    944   return 0;
    945 }
    946 
    947 
    948 static int
    949 gopt_nfs_retry_interval_tcp(const char *val)
    950 {
    951   gopt.amfs_auto_timeo[AMU_TYPE_TCP] = atoi(val);
    952   return 0;
    953 }
    954 
    955 
    956 static int
    957 gopt_nfs_retry_interval_toplvl(const char *val)
    958 {
    959   gopt.amfs_auto_timeo[AMU_TYPE_TOPLVL] = atoi(val);
    960   return 0;
    961 }
    962 
    963 
    964 static int
    965 gopt_nfs_vers(const char *val)
    966 {
    967   int i = atoi(val);
    968 
    969   if (i == 2 || i == 3 || i == 4) {
    970     gopt.nfs_vers = i;
    971     return 0;
    972   }
    973   fprintf(stderr, "conf: illegal nfs_vers \"%s\"\n", val);
    974   return 1;
    975 }
    976 
    977 
    978 static int
    979 gopt_nfs_vers_ping(const char *val)
    980 {
    981   int i = atoi(val);
    982 
    983   if (i == 2 || i == 3 || i == 4) {
    984     gopt.nfs_vers_ping = i;
    985     return 0;
    986   }
    987   fprintf(stderr, "conf: illegal nfs_vers_ping \"%s\"\n", val);
    988   return 1;
    989 }
    990 
    991 static int
    992 gopt_nis_domain(const char *val)
    993 {
    994 #ifdef HAVE_MAP_NIS
    995   gopt.nis_domain = xstrdup(val);
    996   return 0;
    997 #else /* not HAVE_MAP_NIS */
    998   fprintf(stderr, "conf: nis_domain option ignored.  No NIS support available.\n");
    999   return 1;
   1000 #endif /* not HAVE_MAP_NIS */
   1001 }
   1002 
   1003 
   1004 static int
   1005 gopt_normalize_hostnames(const char *val)
   1006 {
   1007   if (STREQ(val, "yes")) {
   1008     gopt.flags |= CFM_NORMALIZE_HOSTNAMES;
   1009     return 0;
   1010   } else if (STREQ(val, "no")) {
   1011     gopt.flags &= ~CFM_NORMALIZE_HOSTNAMES;
   1012     return 0;
   1013   }
   1014 
   1015   fprintf(stderr, "conf: unknown value to normalize_hostnames \"%s\"\n", val);
   1016   return 1;			/* unknown value */
   1017 }
   1018 
   1019 
   1020 static int
   1021 gopt_normalize_slashes(const char *val)
   1022 {
   1023   if (STREQ(val, "yes")) {
   1024     gopt.flags |= CFM_NORMALIZE_SLASHES;
   1025     return 0;
   1026   } else if (STREQ(val, "no")) {
   1027     gopt.flags &= ~CFM_NORMALIZE_SLASHES;
   1028     return 0;
   1029   }
   1030 
   1031   fprintf(stderr, "conf: unknown value to normalize_slashes \"%s\"\n", val);
   1032   return 1;			/* unknown value */
   1033 }
   1034 
   1035 
   1036 static int
   1037 gopt_os(const char *val)
   1038 {
   1039   gopt.op_sys = xstrdup(val);
   1040   return 0;
   1041 }
   1042 
   1043 
   1044 static int
   1045 gopt_osver(const char *val)
   1046 {
   1047   gopt.op_sys_ver = xstrdup(val);
   1048   return 0;
   1049 }
   1050 
   1051 
   1052 static int
   1053 gopt_plock(const char *val)
   1054 {
   1055   if (STREQ(val, "yes")) {
   1056     gopt.flags |= CFM_PROCESS_LOCK;
   1057     return 0;
   1058   } else if (STREQ(val, "no")) {
   1059     gopt.flags &= ~CFM_PROCESS_LOCK;
   1060     return 0;
   1061   }
   1062 
   1063   fprintf(stderr, "conf: unknown value to plock \"%s\"\n", val);
   1064   return 1;			/* unknown value */
   1065 }
   1066 
   1067 
   1068 static int
   1069 gopt_print_pid(const char *val)
   1070 {
   1071   if (STREQ(val, "yes")) {
   1072     gopt.flags |= CFM_PRINT_PID;
   1073     return 0;
   1074   } else if (STREQ(val, "no")) {
   1075     gopt.flags &= ~CFM_PRINT_PID;
   1076     return 0;
   1077   }
   1078 
   1079   fprintf(stderr, "conf: unknown value to print_pid \"%s\"\n", val);
   1080   return 1;			/* unknown value */
   1081 }
   1082 
   1083 
   1084 static int
   1085 gopt_print_version(const char *val)
   1086 {
   1087   if (STREQ(val, "yes")) {
   1088     char *vers = get_version_string();
   1089     fputs(vers, stderr);
   1090     XFREE(vers);
   1091     return 0;
   1092   } else if (STREQ(val, "no")) {
   1093     return 0;
   1094   }
   1095 
   1096   fprintf(stderr, "conf: unknown value to print_version \"%s\"\n", val);
   1097   return 1;			/* unknown value */
   1098 }
   1099 
   1100 
   1101 static int
   1102 gopt_restart_mounts(const char *val)
   1103 {
   1104   if (STREQ(val, "yes")) {
   1105     gopt.flags |= CFM_RESTART_EXISTING_MOUNTS;
   1106     return 0;
   1107   } else if (STREQ(val, "no")) {
   1108     gopt.flags &= ~CFM_RESTART_EXISTING_MOUNTS;
   1109     return 0;
   1110   }
   1111 
   1112   fprintf(stderr, "conf: unknown value to restart_mounts \"%s\"\n", val);
   1113   return 1;			/* unknown value */
   1114 }
   1115 
   1116 
   1117 static int
   1118 gopt_search_path(const char *val)
   1119 {
   1120   gopt.search_path = xstrdup(val);
   1121   return 0;
   1122 }
   1123 
   1124 
   1125 static int
   1126 gopt_selectors_in_defaults(const char *val)
   1127 {
   1128   if (STREQ(val, "yes")) {
   1129     gopt.flags |= CFM_SELECTORS_IN_DEFAULTS;
   1130     return 0;
   1131   } else if (STREQ(val, "no")) {
   1132     gopt.flags &= ~CFM_SELECTORS_IN_DEFAULTS;
   1133     return 0;
   1134   }
   1135 
   1136   fprintf(stderr, "conf: unknown value to enable_default_selectors \"%s\"\n", val);
   1137   return 1;			/* unknown value */
   1138 }
   1139 
   1140 
   1141 static int
   1142 gopt_show_statfs_entries(const char *val)
   1143 {
   1144   if (STREQ(val, "yes")) {
   1145     gopt.flags |= CFM_SHOW_STATFS_ENTRIES;
   1146     return 0;
   1147   } else if (STREQ(val, "no")) {
   1148     gopt.flags &= ~CFM_SHOW_STATFS_ENTRIES;
   1149     return 0;
   1150   }
   1151 
   1152   fprintf(stderr, "conf: unknown value to show_statfs_entries \"%s\"\n", val);
   1153   return 1;			/* unknown value */
   1154 }
   1155 
   1156 
   1157 static int
   1158 gopt_sun_map_syntax(const char *val)
   1159 {
   1160   if (STREQ(val, "yes")) {
   1161     gopt.flags |= CFM_SUN_MAP_SYNTAX;
   1162     return 0;
   1163   } else if (STREQ(val, "no")) {
   1164     gopt.flags &= ~CFM_SUN_MAP_SYNTAX;
   1165     return 0;
   1166   }
   1167 
   1168   fprintf(stderr, "conf: unknown value to sun_map_syntax \"%s\"\n", val);
   1169   return 1;			/* unknown value */
   1170 }
   1171 
   1172 
   1173 static int
   1174 gopt_truncate_log(const char *val)
   1175 {
   1176   if (STREQ(val, "yes")) {
   1177     gopt.flags |= CFM_TRUNCATE_LOG;
   1178     return 0;
   1179   } else if (STREQ(val, "no")) {
   1180     gopt.flags &= ~CFM_TRUNCATE_LOG;
   1181     return 0;
   1182   }
   1183 
   1184   fprintf(stderr, "conf: unknown value to truncate_log \"%s\"\n", val);
   1185   return 1;			/* unknown value */
   1186 }
   1187 
   1188 
   1189 static int
   1190 gopt_unmount_on_exit(const char *val)
   1191 {
   1192   if (STREQ(val, "yes")) {
   1193     gopt.flags |= CFM_UNMOUNT_ON_EXIT;
   1194     return 0;
   1195   } else if (STREQ(val, "no")) {
   1196     gopt.flags &= ~CFM_UNMOUNT_ON_EXIT;
   1197     return 0;
   1198   }
   1199 
   1200   fprintf(stderr, "conf: unknown value to unmount_on_exit \"%s\"\n", val);
   1201   return 1;			/* unknown value */
   1202 }
   1203 
   1204 
   1205 static int
   1206 gopt_use_tcpwrappers(const char *val)
   1207 {
   1208 #if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
   1209   if (STREQ(val, "yes")) {
   1210     gopt.flags |= CFM_USE_TCPWRAPPERS;
   1211     return 0;
   1212   } else if (STREQ(val, "no")) {
   1213     gopt.flags &= ~CFM_USE_TCPWRAPPERS;
   1214     return 0;
   1215   }
   1216 #else /* not defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
   1217     fprintf(stderr, "conf: no tcpd/libwrap support available\n");
   1218     return 1;
   1219 #endif /* not defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
   1220 
   1221   fprintf(stderr, "conf: unknown value to use_tcpwrappers \"%s\"\n", val);
   1222   return 1;			/* unknown value */
   1223 }
   1224 
   1225 
   1226 static int
   1227 gopt_vendor(const char *val)
   1228 {
   1229   gopt.op_sys_vendor = xstrdup(val);
   1230   return 0;
   1231 }
   1232 
   1233 
   1234 /*
   1235  * Collect one entry for a regular map
   1236  */
   1237 static int
   1238 process_regular_option(const char *section, const char *key, const char *val, cf_map_t *cfm)
   1239 {
   1240   /* ensure that val is valid */
   1241   if (!section || section[0] == '\0' ||
   1242       !key || key[0] == '\0' ||
   1243       !val || val[0] == '\0' ||
   1244       !cfm) {
   1245     fprintf(stderr, "conf: process_regular_option: null entries\n");
   1246     return 1;
   1247   }
   1248 
   1249   /* check if initializing a new map */
   1250   if (!cfm->cfm_dir)
   1251     cfm->cfm_dir = xstrdup(section);
   1252 
   1253   /* check for each possible field */
   1254   if (STREQ(key, "browsable_dirs"))
   1255     return ropt_browsable_dirs(val, cfm);
   1256 
   1257   if (STREQ(key, "map_name"))
   1258     return ropt_map_name(val, cfm);
   1259 
   1260   if (STREQ(key, "map_defaults"))
   1261     return ropt_map_defaults(val, cfm);
   1262 
   1263   if (STREQ(key, "map_options"))
   1264     return ropt_map_options(val, cfm);
   1265 
   1266   if (STREQ(key, "map_type"))
   1267     return ropt_map_type(val, cfm);
   1268 
   1269   if (STREQ(key, "mount_type"))
   1270     return ropt_mount_type(val, cfm);
   1271 
   1272   if (STREQ(key, "search_path"))
   1273     return ropt_search_path(val, cfm);
   1274 
   1275   if (STREQ(key, "sun_map_syntax"))
   1276     return ropt_sun_map_syntax(val, cfm);
   1277 
   1278   if (STREQ(key, "tag"))
   1279     return ropt_tag(val, cfm);
   1280 
   1281   fprintf(stderr, "conf: unknown regular key \"%s\" for section \"%s\"\n",
   1282 	  key, section);
   1283   return 1;			/* failed to match any command */
   1284 }
   1285 
   1286 
   1287 static int
   1288 ropt_browsable_dirs(const char *val, cf_map_t *cfm)
   1289 {
   1290   if (STREQ(val, "full")) {
   1291     cfm->cfm_flags |= CFM_BROWSABLE_DIRS_FULL;
   1292     return 0;
   1293   } else if (STREQ(val, "yes")) {
   1294     cfm->cfm_flags |= CFM_BROWSABLE_DIRS;
   1295     return 0;
   1296   } else if (STREQ(val, "no")) {
   1297     cfm->cfm_flags &= ~CFM_BROWSABLE_DIRS;
   1298     return 0;
   1299   }
   1300 
   1301   fprintf(stderr, "conf: unknown value to browsable_dirs \"%s\"\n", val);
   1302   return 1;			/* unknown value */
   1303 }
   1304 
   1305 
   1306 static int
   1307 ropt_map_name(const char *val, cf_map_t *cfm)
   1308 {
   1309   cfm->cfm_name = xstrdup(val);
   1310   return 0;
   1311 }
   1312 
   1313 
   1314 static int
   1315 ropt_map_defaults(const char *val, cf_map_t *cfm)
   1316 {
   1317   cfm->cfm_defaults = xstrdup(val);
   1318   return 0;
   1319 }
   1320 
   1321 
   1322 static int
   1323 ropt_map_options(const char *val, cf_map_t *cfm)
   1324 {
   1325   cfm->cfm_opts = xstrdup(val);
   1326   return 0;
   1327 }
   1328 
   1329 
   1330 static int
   1331 ropt_map_type(const char *val, cf_map_t *cfm)
   1332 {
   1333   /* check if map type exist */
   1334   if (!mapc_type_exists(val)) {
   1335     fprintf(stderr, "conf: no such map type \"%s\"\n", val);
   1336     return 1;
   1337   }
   1338   cfm->cfm_type = xstrdup(val);
   1339   return 0;
   1340 }
   1341 
   1342 
   1343 static int
   1344 ropt_mount_type(const char *val, cf_map_t *cfm)
   1345 {
   1346   if (STREQ(val, "autofs")) {
   1347 #ifdef HAVE_FS_AUTOFS
   1348     cfm->cfm_flags |= CFM_MOUNT_TYPE_AUTOFS;
   1349     amd_use_autofs++;
   1350     return 0;
   1351 #else /* not HAVE_FS_AUTOFS */
   1352     fprintf(stderr, "conf: no autofs support available\n");
   1353     return 1;
   1354 #endif /* not HAVE_FS_AUTOFS */
   1355   } else if (STREQ(val, "nfs")) {
   1356     cfm->cfm_flags &= ~CFM_MOUNT_TYPE_AUTOFS;
   1357     return 0;
   1358   }
   1359 
   1360   fprintf(stderr, "conf: unknown value to mount_type \"%s\"\n", val);
   1361   return 1;			/* unknown value */
   1362 }
   1363 
   1364 
   1365 static int
   1366 ropt_search_path(const char *val, cf_map_t *cfm)
   1367 {
   1368   cfm->cfm_search_path = xstrdup(val);
   1369   return 0;
   1370 }
   1371 
   1372 
   1373 static int
   1374 ropt_sun_map_syntax(const char *val, cf_map_t *cfm)
   1375 {
   1376   if (STREQ(val, "yes")) {
   1377     cfm->cfm_flags |= CFM_SUN_MAP_SYNTAX;
   1378     return 0;
   1379 
   1380   } else if (STREQ(val, "no")) {
   1381     cfm->cfm_flags &= ~CFM_SUN_MAP_SYNTAX;
   1382     return 0;
   1383   }
   1384 
   1385   fprintf(stderr, "conf: unknown value to sun_map_syntax \"%s\"\n", val);
   1386   return 1;			/* unknown value */
   1387 }
   1388 
   1389 
   1390 static int
   1391 ropt_tag(const char *val, cf_map_t *cfm)
   1392 {
   1393   cfm->cfm_tag = xstrdup(val);
   1394   return 0;
   1395 }
   1396 
   1397 
   1398 /*
   1399  * Process one collected map.
   1400  */
   1401 static int
   1402 process_one_regular_map(const cf_map_t *cfm)
   1403 {
   1404   if (!cfm->cfm_name) {
   1405     fprintf(stderr, "conf: map_name must be defined for map \"%s\"\n", cfm->cfm_dir);
   1406     return 1;
   1407   }
   1408   /*
   1409    * If map has no tag defined, process the map.
   1410    * If no conf_tag was set in amd -T, process all untagged entries.
   1411    * If a tag is defined, then process it only if it matches the map tag.
   1412    */
   1413   if (!cfm->cfm_tag ||
   1414       (conf_tag && STREQ(cfm->cfm_tag, conf_tag))) {
   1415 #ifdef DEBUG_CONF
   1416     fprintf(stderr, "processing map %s (flags=0x%x)...\n",
   1417 	    cfm->cfm_dir, cfm->cfm_flags);
   1418 #endif /* DEBUG_CONF */
   1419     root_newmap(cfm->cfm_dir,
   1420 		cfm->cfm_opts ? cfm->cfm_opts : "",
   1421 		cfm->cfm_name,
   1422 		cfm);
   1423   } else {
   1424     fprintf(stderr, "skipping map %s...\n", cfm->cfm_dir);
   1425   }
   1426 
   1427   return 0;
   1428 }
   1429 
   1430 
   1431 /*
   1432  * Process all regular maps in conf file (if any)
   1433  */
   1434 int
   1435 process_all_regular_maps(void)
   1436 {
   1437   cf_map_t *tmp_map = head_map;
   1438 
   1439   /*
   1440    * If the amd.conf file only has a [global] section (pretty useless
   1441    * IMHO), there's nothing to process
   1442    */
   1443   if (!tmp_map)
   1444     return 0;
   1445 
   1446   while (tmp_map) {
   1447     if (process_one_regular_map(tmp_map) != 0)
   1448       return 1;
   1449     tmp_map = tmp_map->cfm_next;
   1450   }
   1451   return 0;
   1452 }
   1453 
   1454 
   1455 /*
   1456  * Find a cf_map_t for a given map name.
   1457  * Return NULL if not found.
   1458  */
   1459 cf_map_t *
   1460 find_cf_map(const char *name)
   1461 {
   1462 
   1463   cf_map_t *tmp_map = head_map;
   1464 
   1465   if (!tmp_map || !name)
   1466     return NULL;
   1467 
   1468   while (tmp_map) {
   1469     if (STREQ(tmp_map->cfm_dir, name)) {
   1470       return tmp_map;
   1471     }
   1472     tmp_map = tmp_map->cfm_next;
   1473   }
   1474   return NULL;
   1475 }
   1476