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