Merge from vendor branch FILE:
[dragonfly.git] / contrib / amd / amd / conf.c
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  */
65 typedef int (*OptFuncPtr)(const char *);
66
67 /*
68  * STRUCTURES:
69  */
70 struct _func_map {
71   char *name;
72   OptFuncPtr func;
73 };
74
75 /*
76  * FORWARD DECLARATIONS:
77  */
78 static int gopt_arch(const char *val);
79 static int gopt_auto_dir(const char *val);
80 static int gopt_browsable_dirs(const char *val);
81 static int gopt_cache_duration(const char *val);
82 static int gopt_cluster(const char *val);
83 static int gopt_debug_options(const char *val);
84 static int gopt_dismount_interval(const char *val);
85 static int gopt_full_os(const char *val);
86 static int gopt_fully_qualified_hosts(const char *val);
87 static int gopt_hesiod_base(const char *val);
88 static int gopt_karch(const char *val);
89 static int gopt_ldap_base(const char *val);
90 static int gopt_ldap_cache_maxmem(const char *val);
91 static int gopt_ldap_cache_seconds(const char *val);
92 static int gopt_ldap_hostports(const char *val);
93 static int gopt_local_domain(const char *val);
94 static int gopt_log_file(const char *val);
95 static int gopt_log_options(const char *val);
96 static int gopt_map_options(const char *val);
97 static int gopt_map_type(const char *val);
98 static int gopt_mount_type(const char *val);
99 static int gopt_pid_file(const char *val);
100 static int gopt_portmap_program(const char *val);
101 static int gopt_nfs_retransmit_counter(const char *val);
102 static int gopt_nfs_retry_interval(const char *val);
103 static int gopt_nis_domain(const char *val);
104 static int gopt_normalize_hostnames(const char *val);
105 static int gopt_os(const char *val);
106 static int gopt_osver(const char *val);
107 static int gopt_plock(const char *val);
108 static int gopt_print_pid(const char *val);
109 static int gopt_print_version(const char *val);
110 static int gopt_restart_mounts(const char *val);
111 static int gopt_search_path(const char *val);
112 static int gopt_selectors_on_default(const char *val);
113 static int gopt_show_statfs_entries(const char *val);
114 static int gopt_unmount_on_exit(const char *val);
115 static int gopt_vendor(const char *val);
116 static int process_global_option(const char *key, const char *val);
117 static int process_regular_map(cf_map_t *cfm);
118 static int process_regular_option(const char *section, const char *key, const char *val, cf_map_t *cfm);
119 static int ropt_browsable_dirs(const char *val, cf_map_t *cfm);
120 static int ropt_map_name(const char *val, cf_map_t *cfm);
121 static int ropt_map_options(const char *val, cf_map_t *cfm);
122 static int ropt_map_type(const char *val, cf_map_t *cfm);
123 static int ropt_mount_type(const char *val, cf_map_t *cfm);
124 static int ropt_search_path(const char *val, cf_map_t *cfm);
125 static int ropt_tag(const char *val, cf_map_t *cfm);
126 static void reset_cf_map(cf_map_t *cfm);
127
128
129 /*
130  * STATIC VARIABLES:
131  */
132 static cf_map_t cur_map;
133 static 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  */
179 static void
180 reset_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  */
241 int
242 set_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  */
298 static int
299 process_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
319 static int
320 gopt_arch(const char *val)
321 {
322   gopt.arch = strdup((char *)val);
323   return 0;
324 }
325
326
327 static int
328 gopt_auto_dir(const char *val)
329 {
330   gopt.auto_dir = strdup((char *)val);
331   return 0;
332 }
333
334
335 static int
336 gopt_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
354 static int
355 gopt_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
364 static int
365 gopt_cluster(const char *val)
366 {
367   gopt.cluster = strdup((char *)val);
368   return 0;
369 }
370
371
372 static int
373 gopt_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
386 static int
387 gopt_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
396 static int
397 gopt_full_os(const char *val)
398 {
399   gopt.op_sys_full = strdup((char *)val);
400   return 0;
401 }
402
403
404 static int
405 gopt_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
420 static int
421 gopt_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
433 static int
434 gopt_karch(const char *val)
435 {
436   gopt.karch = strdup((char *)val);
437   return 0;
438 }
439
440
441 static int
442 gopt_pid_file(const char *val)
443 {
444   gopt.pid_file = strdup((char *)val);
445   return 0;
446 }
447
448
449 static int
450 gopt_local_domain(const char *val)
451 {
452   gopt.sub_domain = strdup((char *)val);
453   return 0;
454 }
455
456
457 static int
458 gopt_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
470 static int
471 gopt_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
489 static int
490 gopt_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
508 static int
509 gopt_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
522 static int
523 gopt_log_file(const char *val)
524 {
525   gopt.logfile = strdup((char *)val);
526   return 0;
527 }
528
529
530 static int
531 gopt_log_options(const char *val)
532 {
533   usage += switch_option(strdup((char *)val));
534   return 0;
535 }
536
537
538 static int
539 gopt_map_options(const char *val)
540 {
541   gopt.map_options = strdup((char *)val);
542   return 0;
543 }
544
545
546 static int
547 gopt_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
559 static int
560 gopt_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
581 static int
582 gopt_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
602 static int
603 gopt_nfs_retransmit_counter(const char *val)
604 {
605   gopt.amfs_auto_retrans = atoi(val);
606   return 0;
607 }
608
609
610 static int
611 gopt_nfs_retry_interval(const char *val)
612 {
613   gopt.amfs_auto_timeo = atoi(val);
614   return 0;
615 }
616
617
618 static int
619 gopt_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
631 static int
632 gopt_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
647 static int
648 gopt_os(const char *val)
649 {
650   gopt.op_sys = strdup((char *)val);
651   return 0;
652 }
653
654
655 static int
656 gopt_osver(const char *val)
657 {
658   gopt.op_sys_ver = strdup((char *)val);
659   return 0;
660 }
661
662
663 static int
664 gopt_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
679 static int
680 gopt_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
695 static int
696 gopt_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
710 static int
711 gopt_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
726 static int
727 gopt_search_path(const char *val)
728 {
729   gopt.search_path = strdup((char *)val);
730   return 0;
731 }
732
733
734 static int
735 gopt_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
750 static int
751 gopt_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
766 static int
767 gopt_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
782 static int
783 gopt_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  */
793 static int
794 process_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
837 static int
838 ropt_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
856 static int
857 ropt_map_name(const char *val, cf_map_t *cfm)
858 {
859   cfm->cfm_name = strdup((char *)val);
860   return 0;
861 }
862
863
864 static int
865 ropt_map_options(const char *val, cf_map_t *cfm)
866 {
867   cfm->cfm_opts = strdup((char *)val);
868   return 0;
869 }
870
871
872 static int
873 ropt_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
885 static int
886 ropt_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
907 static int
908 ropt_search_path(const char *val, cf_map_t *cfm)
909 {
910   cfm->cfm_search_path = strdup((char *)val);
911   return 0;
912 }
913
914
915 static int
916 ropt_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  */
926 static int
927 process_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  */
961 int
962 process_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 }