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