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