conf.c revision 41142
1/*
2 * Copyright (c) 1997-1998 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 acknowledgement:
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 5.2.2.1 1992/02/09 15:08:23 jsp beta $
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_fully_qualified_hosts(const char *val);
86static int gopt_hesiod_base(const char *val);
87static int gopt_karch(const char *val);
88static int gopt_ldap_base(const char *val);
89static int gopt_ldap_cache_maxmem(const char *val);
90static int gopt_ldap_cache_seconds(const char *val);
91static int gopt_ldap_hostports(const char *val);
92static int gopt_local_domain(const char *val);
93static int gopt_log_file(const char *val);
94static int gopt_log_options(const char *val);
95static 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  /* check if map type exist */
538  if (!mapc_type_exists(val)) {
539    fprintf(stderr, "conf: no such map type \"%s\"\n", val);
540    return 1;
541  }
542  gopt.map_type = strdup((char *)val);
543  return 0;
544}
545
546
547static int
548gopt_mount_type(const char *val)
549{
550  if (STREQ(val, "autofs")) {
551#ifdef HAVE_FS_AUTOFS
552    gopt.flags |= CFM_MOUNT_TYPE_AUTOFS;
553    return 0;
554#else /* not HAVE_FS_AUTOFS */
555    fprintf(stderr, "conf: no autofs support available\n");
556    return 1;
557#endif /* not HAVE_FS_AUTOFS */
558  } else if (STREQ(val, "nfs")) {
559    gopt.flags &= ~CFM_MOUNT_TYPE_AUTOFS;
560    return 0;
561  }
562
563  fprintf(stderr, "conf: unknown value to mount_type \"%s\"\n", val);
564  return 1;			/* unknown value */
565}
566
567
568static int
569gopt_portmap_program(const char *val)
570{
571  gopt.portmap_program = atoi(val);
572  /*
573   * allow alternate program numbers to be no more than 10 offset from
574   * official amd program number (300019).
575   */
576  if (gopt.portmap_program < AMQ_PROGRAM ||
577      gopt.portmap_program > AMQ_PROGRAM + 10) {
578    gopt.portmap_program = AMQ_PROGRAM;
579    set_amd_program_number(gopt.portmap_program);
580    fprintf(stderr, "conf: illegal amd program numver \"%s\"\n", val);
581    return 1;
582  }
583
584  set_amd_program_number(gopt.portmap_program);
585  return 0;			/* all is OK */
586}
587
588
589static int
590gopt_nfs_retransmit_counter(const char *val)
591{
592  gopt.amfs_auto_retrans = atoi(val);
593  return 0;
594}
595
596
597static int
598gopt_nfs_retry_interval(const char *val)
599{
600  gopt.amfs_auto_timeo = atoi(val);
601  return 0;
602}
603
604
605static int
606gopt_nis_domain(const char *val)
607{
608#ifdef HAVE_MAP_NIS
609  gopt.nis_domain = strdup((char *)val);
610  return 0;
611#else /* not HAVE_MAP_NIS */
612  fprintf(stderr, "conf: nis_domain option ignored.  No NIS support available.\n");
613  return 1;
614#endif /* not HAVE_MAP_NIS */
615}
616
617
618static int
619gopt_normalize_hostnames(const char *val)
620{
621  if (STREQ(val, "yes")) {
622    gopt.flags |= CFM_NORMALIZE_HOSTNAMES;
623    return 0;
624  } else if (STREQ(val, "no")) {
625    gopt.flags &= ~CFM_NORMALIZE_HOSTNAMES;
626    return 0;
627  }
628
629  fprintf(stderr, "conf: unknown value to normalize_hostnames \"%s\"\n", val);
630  return 1;			/* unknown value */
631}
632
633
634static int
635gopt_os(const char *val)
636{
637  gopt.op_sys = strdup((char *)val);
638  return 0;
639}
640
641
642static int
643gopt_osver(const char *val)
644{
645  gopt.op_sys_ver = strdup((char *)val);
646  return 0;
647}
648
649
650static int
651gopt_plock(const char *val)
652{
653  if (STREQ(val, "yes")) {
654    gopt.flags |= CFM_PROCESS_LOCK;
655    return 0;
656  } else if (STREQ(val, "no")) {
657    gopt.flags &= ~CFM_PROCESS_LOCK;
658    return 0;
659  }
660
661  fprintf(stderr, "conf: unknown value to plock \"%s\"\n", val);
662  return 1;			/* unknown value */
663}
664
665
666static int
667gopt_print_pid(const char *val)
668{
669  if (STREQ(val, "yes")) {
670    gopt.flags |= CFM_PRINT_PID;
671    return 0;
672  } else if (STREQ(val, "no")) {
673    gopt.flags &= ~CFM_PRINT_PID;
674    return 0;
675  }
676
677  fprintf(stderr, "conf: unknown value to print_pid \"%s\"\n", val);
678  return 1;			/* unknown value */
679}
680
681
682static int
683gopt_print_version(const char *val)
684{
685  if (STREQ(val, "yes")) {
686    fputs(get_version_string(), stderr);
687    return 0;
688  } else if (STREQ(val, "no")) {
689    return 0;
690  }
691
692  fprintf(stderr, "conf: unknown value to print_version \"%s\"\n", val);
693  return 1;			/* unknown value */
694}
695
696
697static int
698gopt_restart_mounts(const char *val)
699{
700  if (STREQ(val, "yes")) {
701    gopt.flags |= CFM_RESTART_EXISTING_MOUNTS;
702    return 0;
703  } else if (STREQ(val, "no")) {
704    gopt.flags &= ~CFM_RESTART_EXISTING_MOUNTS;
705    return 0;
706  }
707
708  fprintf(stderr, "conf: unknown value to restart_mounts \"%s\"\n", val);
709  return 1;			/* unknown value */
710}
711
712
713static int
714gopt_search_path(const char *val)
715{
716  gopt.search_path = strdup((char *)val);
717  return 0;
718}
719
720
721static int
722gopt_selectors_on_default(const char *val)
723{
724  if (STREQ(val, "yes")) {
725    gopt.flags |= CFM_ENABLE_DEFAULT_SELECTORS;
726    return 0;
727  } else if (STREQ(val, "no")) {
728    gopt.flags &= ~CFM_ENABLE_DEFAULT_SELECTORS;
729    return 0;
730  }
731
732  fprintf(stderr, "conf: unknown value to enable_default_selectors \"%s\"\n", val);
733  return 1;			/* unknown value */
734}
735
736
737static int
738gopt_show_statfs_entries(const char *val)
739{
740  if (STREQ(val, "yes")) {
741    gopt.flags |= CFM_SHOW_STATFS_ENTRIES;
742    return 0;
743  } else if (STREQ(val, "no")) {
744    gopt.flags &= ~CFM_SHOW_STATFS_ENTRIES;
745    return 0;
746  }
747
748  fprintf(stderr, "conf: unknown value to show_statfs_entries \"%s\"\n", val);
749  return 1;			/* unknown value */
750}
751
752
753static int
754gopt_unmount_on_exit(const char *val)
755{
756  if (STREQ(val, "yes")) {
757    gopt.flags |= CFM_UNMOUNT_ON_EXIT;
758    return 0;
759  } else if (STREQ(val, "no")) {
760    gopt.flags &= ~CFM_UNMOUNT_ON_EXIT;
761    return 0;
762  }
763
764  fprintf(stderr, "conf: unknown value to unmount_on_exit \"%s\"\n", val);
765  return 1;			/* unknown value */
766}
767
768
769/*
770 * Collect one entry for a regular map
771 */
772static int
773process_regular_option(const char *section, const char *key, const char *val, cf_map_t *cfm)
774{
775  /* ensure that val is valid */
776  if (!section || section[0] == '\0' ||
777      !key || key[0] == '\0' ||
778      !val || val[0] == '\0' ||
779      !cfm) {
780    fprintf(stderr, "conf: process_regular_option: null entries\n");
781    return 1;
782  }
783
784  /* check if initializing a new map */
785  if (!cfm->cfm_dir)
786    cfm->cfm_dir = strdup((char *)section);
787
788  /* check for each possible field */
789  if (STREQ(key, "browsable_dirs"))
790    return ropt_browsable_dirs(val, cfm);
791
792  if (STREQ(key, "map_name"))
793    return ropt_map_name(val, cfm);
794
795  if (STREQ(key, "map_options"))
796    return ropt_map_options(val, cfm);
797
798  if (STREQ(key, "map_type"))
799    return ropt_map_type(val, cfm);
800
801  if (STREQ(key, "mount_type"))
802    return ropt_mount_type(val, cfm);
803
804  if (STREQ(key, "search_path"))
805    return ropt_search_path(val, cfm);
806
807  if (STREQ(key, "tag"))
808    return ropt_tag(val, cfm);
809
810  fprintf(stderr, "conf: unknown regular key \"%s\" for section \"%s\"\n",
811	  key, section);
812  return 1;			/* failed to match any command */
813}
814
815
816static int
817ropt_browsable_dirs(const char *val, cf_map_t *cfm)
818{
819  if (STREQ(val, "full")) {
820    cfm->cfm_flags |= CFM_BROWSABLE_DIRS_FULL;
821    return 0;
822  } else if (STREQ(val, "yes")) {
823    cfm->cfm_flags |= CFM_BROWSABLE_DIRS;
824    return 0;
825  } else if (STREQ(val, "no")) {
826    cfm->cfm_flags &= ~CFM_BROWSABLE_DIRS;
827    return 0;
828  }
829
830  fprintf(stderr, "conf: unknown value to browsable_dirs \"%s\"\n", val);
831  return 1;			/* unknown value */
832}
833
834
835static int
836ropt_map_name(const char *val, cf_map_t *cfm)
837{
838  cfm->cfm_name = strdup((char *)val);
839  return 0;
840}
841
842
843static int
844ropt_map_options(const char *val, cf_map_t *cfm)
845{
846  cfm->cfm_opts = strdup((char *)val);
847  return 0;
848}
849
850
851static int
852ropt_map_type(const char *val, cf_map_t *cfm)
853{
854  /* check if map type exist */
855  if (!mapc_type_exists(val)) {
856    fprintf(stderr, "conf: no such map type \"%s\"\n", val);
857    return 1;
858  }
859  cfm->cfm_type = strdup((char *)val);
860  return 0;
861}
862
863
864static int
865ropt_mount_type(const char *val, cf_map_t *cfm)
866{
867  if (STREQ(val, "autofs")) {
868#ifdef HAVE_FS_AUTOFS
869    cfm->cfm_flags |= CFM_MOUNT_TYPE_AUTOFS;
870    return 0;
871#else /* not HAVE_FS_AUTOFS */
872    fprintf(stderr, "conf: no autofs support available\n");
873    return 1;
874#endif /* not HAVE_FS_AUTOFS */
875  } else if (STREQ(val, "nfs")) {
876    cfm->cfm_flags &= ~CFM_MOUNT_TYPE_AUTOFS;
877    return 0;
878  }
879
880  fprintf(stderr, "conf: unknown value to mount_type \"%s\"\n", val);
881  return 1;			/* unknown value */
882}
883
884
885static int
886ropt_search_path(const char *val, cf_map_t *cfm)
887{
888  cfm->cfm_search_path = strdup((char *)val);
889  return 0;
890}
891
892
893static int
894ropt_tag(const char *val, cf_map_t *cfm)
895{
896  cfm->cfm_tag = strdup((char *)val);
897  return 0;
898}
899
900
901/*
902 * Process one collected map.
903 */
904static int
905process_regular_map(cf_map_t *cfm)
906{
907
908  if (!cfm->cfm_name) {
909    fprintf(stderr, "conf: map_name must be defined for map \"%s\"\n", cfm->cfm_dir);
910    return 1;
911  }
912  /*
913   * If map has no tag defined, process the map.
914   * If no conf_tag was set in amd -T, process all untagged entries.
915   * If a tag is defined, then process it only if it matches the map tag.
916   */
917  if (!cfm->cfm_tag ||
918      (conf_tag && STREQ(cfm->cfm_tag, conf_tag))) {
919#ifdef DEBUG_CONF
920    fprintf(stderr, "processing map %s (flags=0x%x)...\n",
921	    cfm->cfm_dir, cfm->cfm_flags);
922#endif /* DEBUG_CONF */
923    root_newmap(cfm->cfm_dir,
924		cfm->cfm_opts ? cfm->cfm_opts : "",
925		cfm->cfm_name,
926		cfm);
927  } else {
928    fprintf(stderr, "skipping map %s...\n", cfm->cfm_dir);
929  }
930
931  reset_cf_map(cfm);
932  return 0;
933}
934
935
936/*
937 * Process last map in conf file (if any)
938 */
939int
940process_last_regular_map(void)
941{
942  /*
943   * If the amd.conf file only has a [global] section (pretty useless
944   * IMHO), do not try to process a map that does not exist.
945   */
946  if (!cur_map.cfm_dir)
947    return 0;
948  return process_regular_map(&cur_map);
949}
950