]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/amd/amd/conf.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / amd / amd / conf.c
1 /*
2  * Copyright (c) 1997-2006 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  *
40  * File: am-utils/amd/conf.c
41  *
42  */
43
44 /*
45  * Functions to handle the configuration file.
46  */
47
48 #ifdef HAVE_CONFIG_H
49 # include <config.h>
50 #endif /* HAVE_CONFIG_H */
51 #include <am_defs.h>
52 #include <amd.h>
53
54
55 /*
56  * MACROS:
57  */
58 /* Turn on to show some info about maps being configured */
59 /* #define DEBUG_CONF */
60
61 /*
62  * TYPEDEFS:
63  */
64 typedef int (*OptFuncPtr)(const char *);
65
66 /*
67  * STRUCTURES:
68  */
69 struct _func_map {
70   char *name;
71   OptFuncPtr func;
72 };
73
74 /*
75  * FORWARD DECLARATIONS:
76  */
77 static int gopt_arch(const char *val);
78 static int gopt_auto_attrcache(const char *val);
79 static int gopt_auto_dir(const char *val);
80 static int gopt_autofs_use_lofs(const char *val);
81 static int gopt_browsable_dirs(const char *val);
82 static int gopt_cache_duration(const char *val);
83 static int gopt_cluster(const char *val);
84 static int gopt_debug_mtab_file(const char *val);
85 static int gopt_debug_options(const char *val);
86 static int gopt_dismount_interval(const char *val);
87 static int gopt_domain_strip(const char *val);
88 static int gopt_exec_map_timeout(const char *val);
89 static int gopt_forced_unmounts(const char *val);
90 static int gopt_full_os(const char *val);
91 static int gopt_fully_qualified_hosts(const char *val);
92 static int gopt_hesiod_base(const char *val);
93 static int gopt_karch(const char *val);
94 static int gopt_ldap_base(const char *val);
95 static int gopt_ldap_cache_maxmem(const char *val);
96 static int gopt_ldap_cache_seconds(const char *val);
97 static int gopt_ldap_hostports(const char *val);
98 static int gopt_ldap_proto_version(const char *val);
99 static int gopt_local_domain(const char *val);
100 static int gopt_localhost_address(const char *val);
101 static int gopt_log_file(const char *val);
102 static int gopt_log_options(const char *val);
103 static int gopt_map_defaults(const char *val);
104 static int gopt_map_options(const char *val);
105 static int gopt_map_reload_interval(const char *val);
106 static int gopt_map_type(const char *val);
107 static int gopt_mount_type(const char *val);
108 static int gopt_pid_file(const char *val);
109 static int gopt_portmap_program(const char *val);
110 static int gopt_preferred_amq_port(const char *val);
111 static int gopt_nfs_allow_any_interface(const char *val);
112 static int gopt_nfs_allow_insecure_port(const char *val);
113 static int gopt_nfs_proto(const char *val);
114 static int gopt_nfs_retransmit_counter(const char *val);
115 static int gopt_nfs_retransmit_counter_udp(const char *val);
116 static int gopt_nfs_retransmit_counter_tcp(const char *val);
117 static int gopt_nfs_retransmit_counter_toplvl(const char *val);
118 static int gopt_nfs_retry_interval(const char *val);
119 static int gopt_nfs_retry_interval_udp(const char *val);
120 static int gopt_nfs_retry_interval_tcp(const char *val);
121 static int gopt_nfs_retry_interval_toplvl(const char *val);
122 static int gopt_nfs_vers(const char *val);
123 static int gopt_nis_domain(const char *val);
124 static int gopt_normalize_hostnames(const char *val);
125 static int gopt_normalize_slashes(const char *val);
126 static int gopt_os(const char *val);
127 static int gopt_osver(const char *val);
128 static int gopt_plock(const char *val);
129 static int gopt_print_pid(const char *val);
130 static int gopt_print_version(const char *val);
131 static int gopt_restart_mounts(const char *val);
132 static int gopt_search_path(const char *val);
133 static int gopt_selectors_in_defaults(const char *val);
134 static int gopt_show_statfs_entries(const char *val);
135 static int gopt_truncate_log(const char *val);
136 static int gopt_unmount_on_exit(const char *val);
137 static int gopt_use_tcpwrappers(const char *val);
138 static int gopt_vendor(const char *val);
139 static int process_global_option(const char *key, const char *val);
140 static int process_one_regular_map(const cf_map_t *cfm);
141 static int process_regular_option(const char *section, const char *key, const char *val, cf_map_t *cfm);
142 static int ropt_browsable_dirs(const char *val, cf_map_t *cfm);
143 static int ropt_map_name(const char *val, cf_map_t *cfm);
144 static int ropt_map_defaults(const char *val, cf_map_t *cfm);
145 static int ropt_map_options(const char *val, cf_map_t *cfm);
146 static int ropt_map_type(const char *val, cf_map_t *cfm);
147 static int ropt_mount_type(const char *val, cf_map_t *cfm);
148 static int ropt_search_path(const char *val, cf_map_t *cfm);
149 static int ropt_tag(const char *val, cf_map_t *cfm);
150 static void init_cf_map(cf_map_t *cfm);
151
152
153 /*
154  * STATIC VARIABLES:
155  */
156 static cf_map_t *head_map, *cur_map;
157
158 static struct _func_map glob_functable[] = {
159   {"arch",                      gopt_arch},
160   {"auto_attrcache",            gopt_auto_attrcache},
161   {"auto_dir",                  gopt_auto_dir},
162   {"autofs_use_lofs",           gopt_autofs_use_lofs},
163   {"browsable_dirs",            gopt_browsable_dirs},
164   {"cache_duration",            gopt_cache_duration},
165   {"cluster",                   gopt_cluster},
166   {"debug_mtab_file",           gopt_debug_mtab_file},
167   {"debug_options",             gopt_debug_options},
168   {"dismount_interval",         gopt_dismount_interval},
169   {"domain_strip",              gopt_domain_strip},
170   {"exec_map_timeout",          gopt_exec_map_timeout},
171   {"forced_unmounts",           gopt_forced_unmounts},
172   {"fully_qualified_hosts",     gopt_fully_qualified_hosts},
173   {"full_os",                   gopt_full_os},
174   {"hesiod_base",               gopt_hesiod_base},
175   {"karch",                     gopt_karch},
176   {"ldap_base",                 gopt_ldap_base},
177   {"ldap_cache_maxmem",         gopt_ldap_cache_maxmem},
178   {"ldap_cache_seconds",        gopt_ldap_cache_seconds},
179   {"ldap_hostports",            gopt_ldap_hostports},
180   {"ldap_proto_version",        gopt_ldap_proto_version},
181   {"local_domain",              gopt_local_domain},
182   {"localhost_address",         gopt_localhost_address},
183   {"log_file",                  gopt_log_file},
184   {"log_options",               gopt_log_options},
185   {"map_defaults",              gopt_map_defaults},
186   {"map_options",               gopt_map_options},
187   {"map_reload_interval",       gopt_map_reload_interval},
188   {"map_type",                  gopt_map_type},
189   {"mount_type",                gopt_mount_type},
190   {"pid_file",                  gopt_pid_file},
191   {"portmap_program",           gopt_portmap_program},
192   {"preferred_amq_port",        gopt_preferred_amq_port},
193   {"nfs_allow_any_interface",   gopt_nfs_allow_any_interface},
194   {"nfs_allow_insecure_port",   gopt_nfs_allow_insecure_port},
195   {"nfs_proto",                 gopt_nfs_proto},
196   {"nfs_retransmit_counter",    gopt_nfs_retransmit_counter},
197   {"nfs_retransmit_counter_udp",        gopt_nfs_retransmit_counter_udp},
198   {"nfs_retransmit_counter_tcp",        gopt_nfs_retransmit_counter_tcp},
199   {"nfs_retransmit_counter_toplvl",     gopt_nfs_retransmit_counter_toplvl},
200   {"nfs_retry_interval",        gopt_nfs_retry_interval},
201   {"nfs_retry_interval_udp",    gopt_nfs_retry_interval_udp},
202   {"nfs_retry_interval_tcp",    gopt_nfs_retry_interval_tcp},
203   {"nfs_retry_interval_toplvl", gopt_nfs_retry_interval_toplvl},
204   {"nfs_vers",                  gopt_nfs_vers},
205   {"nis_domain",                gopt_nis_domain},
206   {"normalize_hostnames",       gopt_normalize_hostnames},
207   {"normalize_slashes",         gopt_normalize_slashes},
208   {"os",                        gopt_os},
209   {"osver",                     gopt_osver},
210   {"plock",                     gopt_plock},
211   {"print_pid",                 gopt_print_pid},
212   {"print_version",             gopt_print_version},
213   {"restart_mounts",            gopt_restart_mounts},
214   {"search_path",               gopt_search_path},
215   {"selectors_on_default",      gopt_selectors_in_defaults},
216   {"selectors_in_defaults",     gopt_selectors_in_defaults},
217   {"show_statfs_entries",       gopt_show_statfs_entries},
218   {"truncate_log",              gopt_truncate_log},
219   {"unmount_on_exit",           gopt_unmount_on_exit},
220   {"use_tcpwrappers",           gopt_use_tcpwrappers},
221   {"vendor",                    gopt_vendor},
222   {NULL, NULL}
223 };
224
225
226 /*
227  * Initialize a map from [global] defaults.
228  */
229 static void
230 init_cf_map(cf_map_t *cfm)
231 {
232   if (!cfm)
233     return;
234
235   /*
236    * Initialize a regular map's flags and other variables from the
237    * global ones, so that they are applied to all maps.  Of course, each map
238    * can then override the flags individually.
239    *
240    * NOTES:
241    * (1): Will only work for maps that appear after [global].
242    * (2): I'm assigning pointers directly from the global map.
243    */
244
245   /* initialize map_type from [global] */
246   cfm->cfm_type = gopt.map_type;
247
248   /* initialize map_defaults from [global] */
249   cfm->cfm_defaults = gopt.map_defaults;
250
251   /* initialize map_opts from [global] */
252   cfm->cfm_opts = gopt.map_options;
253
254   /* initialize search_path from [global] */
255   cfm->cfm_search_path = gopt.search_path;
256
257   /*
258    * Initialize flags that are common both to [global] and a local map.
259    */
260   cfm->cfm_flags = gopt.flags & (CFM_BROWSABLE_DIRS |
261                                  CFM_BROWSABLE_DIRS_FULL |
262                                  CFM_MOUNT_TYPE_AUTOFS |
263                                  CFM_SELECTORS_IN_DEFAULTS);
264 }
265
266
267 /*
268  * Process configuration file options (called from YACC parser).
269  * Return 0 if OK, 1 otherwise.
270  */
271 int
272 set_conf_kv(const char *section, const char *key, const char *val)
273 {
274   int ret;
275
276 #ifdef DEBUG_CONF
277   fprintf(stderr, "set_conf_kv: section=%s, key=%s, val=%s\n",
278           section, key, val);
279 #endif /* DEBUG_CONF */
280
281   /*
282    * If global section, process kv pairs one at a time.
283    */
284   if (STREQ(section, "global")) {
285     /*
286      * Check if a regular map was configured before "global",
287      * and warn about it.
288      */
289     if (cur_map && cur_map->cfm_dir) {
290       static short printed_this_error;
291       if (!printed_this_error) {
292         fprintf(stderr, "found regular map \"%s\" before global one.\n",
293                 cur_map->cfm_dir);
294         printed_this_error = 1;
295       }
296     }
297
298     /* process the global option first */
299     ret = process_global_option(key, val);
300
301     /* return status from the processing of the global option */
302     return ret;
303   }
304
305   /*
306    * Otherwise we found a non-global option: store it after some testing.
307    */
308
309   /* initialize (static) global list head and current map pointer */
310   if (!head_map && !cur_map) {
311     cur_map = CALLOC(cf_map_t);
312     if (!cur_map) {
313       perror("calloc");
314       exit(1);
315     }
316     /* initialize first head map from global defaults */
317     init_cf_map(cur_map);
318     head_map = cur_map;
319   }
320
321   /* check if we found a new map, then allocate and initialize it */
322   if (cur_map->cfm_dir && !STREQ(cur_map->cfm_dir, section)) {
323     /* allocate new map struct */
324     cf_map_t *tmp_map = CALLOC(cf_map_t);
325     if (!tmp_map) {
326       perror("calloc");
327       exit(1);
328     }
329     /* initialize it from global defaults */
330     init_cf_map(tmp_map);
331     /* append it to end of linked list */
332     cur_map->cfm_next = tmp_map;
333     cur_map = tmp_map;
334   }
335
336   /* now process a single entry of a regular map */
337   return process_regular_option(section, key, val, cur_map);
338 }
339
340
341 /*
342  * Process global section of configuration file options.
343  * Return 0 upon success, 1 otherwise.
344  */
345 static int
346 process_global_option(const char *key, const char *val)
347 {
348   struct _func_map *gfp;
349
350   /* ensure that val is valid */
351   if (!val || val[0] == '\0')
352     return 1;
353
354   /*
355    * search for global function.
356    */
357   for (gfp = glob_functable; gfp->name; gfp++)
358     if (FSTREQ(gfp->name, key))
359       return (gfp->func)(val);
360
361   fprintf(stderr, "conf: unknown global key: \"%s\"\n", key);
362   return 1;                     /* failed to match any command */
363 }
364
365
366 static int
367 gopt_arch(const char *val)
368 {
369   gopt.arch = strdup((char *)val);
370   return 0;
371 }
372
373
374 static int
375 gopt_auto_attrcache(const char *val)
376 {
377   gopt.auto_attrcache = atoi(val);
378   if (gopt.auto_attrcache < 0) {
379     fprintf(stderr, "conf: bad attrcache value: \"%s\"\n", val);
380     return 1;
381   }
382   return 0;
383 }
384
385
386 static int
387 gopt_auto_dir(const char *val)
388 {
389   gopt.auto_dir = strdup((char *)val);
390   return 0;
391 }
392
393
394 static int
395 gopt_autofs_use_lofs(const char *val)
396 {
397   if (STREQ(val, "yes")) {
398     gopt.flags |= CFM_AUTOFS_USE_LOFS;
399     return 0;
400   } else if (STREQ(val, "no")) {
401     gopt.flags &= ~CFM_AUTOFS_USE_LOFS;
402     return 0;
403   }
404
405   fprintf(stderr, "conf: unknown value to autofs_use_lofs \"%s\"\n", val);
406   return 1;                     /* unknown value */
407 }
408
409
410 static int
411 gopt_browsable_dirs(const char *val)
412 {
413   if (STREQ(val, "full")) {
414     gopt.flags |= CFM_BROWSABLE_DIRS_FULL;
415     return 0;
416   } else if (STREQ(val, "yes")) {
417     gopt.flags |= CFM_BROWSABLE_DIRS;
418     return 0;
419   } else if (STREQ(val, "no")) {
420     gopt.flags &= ~CFM_BROWSABLE_DIRS;
421     return 0;
422   }
423
424   fprintf(stderr, "conf: unknown value to browsable_dirs \"%s\"\n", val);
425   return 1;                     /* unknown value */
426 }
427
428
429 static int
430 gopt_cache_duration(const char *val)
431 {
432   gopt.am_timeo = atoi(val);
433   if (gopt.am_timeo <= 0)
434     gopt.am_timeo = AM_TTL;
435   return 0;
436 }
437
438
439 static int
440 gopt_cluster(const char *val)
441 {
442   gopt.cluster = strdup((char *)val);
443   return 0;
444 }
445
446
447 static int
448 gopt_debug_mtab_file(const char *val)
449 {
450   gopt.debug_mtab_file = strdup((char*)val);
451   return 0;
452 }
453
454
455 static int
456 gopt_debug_options(const char *val)
457 {
458 #ifdef DEBUG
459   usage += debug_option((char *)val);
460   return 0;
461 #else /* not DEBUG */
462   fprintf(stderr, "%s: not compiled with DEBUG option -- sorry.\n",
463           am_get_progname());
464   return 1;
465 #endif /* not DEBUG */
466 }
467
468
469 static int
470 gopt_dismount_interval(const char *val)
471 {
472   gopt.am_timeo_w = atoi(val);
473   if (gopt.am_timeo_w <= 0)
474     gopt.am_timeo_w = AM_TTL_W;
475   return 0;
476 }
477
478
479 static int
480 gopt_domain_strip(const char *val)
481 {
482   if (STREQ(val, "yes")) {
483     gopt.flags |= CFM_DOMAIN_STRIP;
484     return 0;
485   } else if (STREQ(val, "no")) {
486     gopt.flags &= ~CFM_DOMAIN_STRIP;
487     return 0;
488   }
489
490   fprintf(stderr, "conf: unknown value to domain_strip \"%s\"\n", val);
491   return 1;                     /* unknown value */
492 }
493
494
495 static int
496 gopt_exec_map_timeout(const char *val)
497 {
498   gopt.exec_map_timeout = atoi(val);
499   if (gopt.exec_map_timeout <= 0)
500     gopt.exec_map_timeout = AMFS_EXEC_MAP_TIMEOUT; /* default exec map timeout */
501   return 0;
502 }
503
504
505 static int
506 gopt_forced_unmounts(const char *val)
507 {
508   if (STREQ(val, "yes")) {
509 #if !defined(MNT2_GEN_OPT_DETACH) && !defined(MNT2_GEN_OPT_FORCE)
510     fprintf(stderr, "conf: forced_unmounts unsupported on this system.\n");
511     return 1;
512 #else /* defined(MNT2_GEN_OPT_DETACH) || defined(MNT2_GEN_OPT_FORCE) */
513 # ifdef __linux__
514     /*
515      * HACK ALERT: Linux has had MNT_FORCE since 2.2, but it hasn't gotten
516      * stable until 2.4.  And it had MNT_DETACH since 2.4, but it hasn't
517      * gotten stable since 2.6.  So alert users if they're trying to use a
518      * feature that may not work well on their older kernel.
519      */
520     {
521       struct utsname un;
522       if (uname(&un) >= 0) {
523 #  ifdef MNT2_GEN_OPT_FORCE
524         if (strcmp(un.release, "2.4.0") < 0)
525           fprintf(stderr, "warning: forced-unmounts (MNT_FORCE) may not work well before 2.4.0\n");
526 #  endif /* MNT2_GEN_OPT_FORCE */
527 #  ifdef MNT2_GEN_OPT_DETACH
528         if (strcmp(un.release, "2.6.0") < 0)
529           fprintf(stderr, "warning: lazy-unmounts (MNT_DETACH) may not work well before 2.6.0\n");
530 #  endif /* MNT2_GEN_OPT_DETACH */
531       }
532     }
533 # endif /* __linux__ */
534     gopt.flags |= CFM_FORCED_UNMOUNTS;
535     return 0;
536 #endif /* defined(MNT2_GEN_OPT_DETACH) || defined(MNT2_GEN_OPT_FORCE) */
537   } else if (STREQ(val, "no")) {
538     gopt.flags &= ~CFM_FORCED_UNMOUNTS;
539     return 0;
540   }
541
542   fprintf(stderr, "conf: unknown value to unmount_on_exit \"%s\"\n", val);
543   return 1;                     /* unknown value */
544 }
545
546
547 static int
548 gopt_full_os(const char *val)
549 {
550   gopt.op_sys_full = strdup((char *)val);
551   return 0;
552 }
553
554
555 static int
556 gopt_fully_qualified_hosts(const char *val)
557 {
558   if (STREQ(val, "yes")) {
559     gopt.flags |= CFM_FULLY_QUALIFIED_HOSTS;
560     return 0;
561   } else if (STREQ(val, "no")) {
562     gopt.flags &= ~CFM_FULLY_QUALIFIED_HOSTS;
563     return 0;
564   }
565
566   fprintf(stderr, "conf: unknown value to fully_qualified_hosts \"%s\"\n", val);
567   return 1;                     /* unknown value */
568 }
569
570
571 static int
572 gopt_hesiod_base(const char *val)
573 {
574 #ifdef HAVE_MAP_HESIOD
575   gopt.hesiod_base = strdup((char *)val);
576   return 0;
577 #else /* not HAVE_MAP_HESIOD */
578   fprintf(stderr, "conf: hesiod_base option ignored.  No Hesiod support available.\n");
579   return 1;
580 #endif /* not HAVE_MAP_HESIOD */
581 }
582
583
584 static int
585 gopt_karch(const char *val)
586 {
587   gopt.karch = strdup((char *)val);
588   return 0;
589 }
590
591
592 static int
593 gopt_pid_file(const char *val)
594 {
595   gopt.pid_file = strdup((char *)val);
596   return 0;
597 }
598
599
600 static int
601 gopt_local_domain(const char *val)
602 {
603   gopt.sub_domain = strdup((char *)val);
604   return 0;
605 }
606
607
608 static int
609 gopt_localhost_address(const char *val)
610 {
611   gopt.localhost_address = strdup((char *)val);
612   return 0;
613 }
614
615
616 static int
617 gopt_ldap_base(const char *val)
618 {
619 #ifdef HAVE_MAP_LDAP
620   gopt.ldap_base = strdup((char *)val);
621   return 0;
622 #else /* not HAVE_MAP_LDAP */
623   fprintf(stderr, "conf: ldap_base option ignored.  No LDAP support available.\n");
624   return 1;
625 #endif /* not HAVE_MAP_LDAP */
626 }
627
628
629 static int
630 gopt_ldap_cache_seconds(const char *val)
631 {
632 #ifdef HAVE_MAP_LDAP
633   char *end;
634
635   gopt.ldap_cache_seconds = strtol((char *)val, &end, 10);
636   if (end == val) {
637     fprintf(stderr, "conf: bad LDAP cache (seconds) option: %s\n",val);
638     return 1;
639   }
640   return 0;
641 #else /* not HAVE_MAP_LDAP */
642   fprintf(stderr, "conf: ldap_cache_seconds option ignored.  No LDAP support available.\n");
643   return 1;
644 #endif /* not HAVE_MAP_LDAP */
645 }
646
647
648 static int
649 gopt_ldap_cache_maxmem(const char *val)
650 {
651 #ifdef HAVE_MAP_LDAP
652   char *end;
653
654   gopt.ldap_cache_maxmem = strtol((char *)val, &end, 10);
655   if (end == val) {
656     fprintf(stderr, "conf: bad LDAP cache (maxmem) option: %s\n",val);
657     return 1;
658   }
659   return 0;
660 #else /* not HAVE_MAP_LDAP */
661   fprintf(stderr, "conf: ldap_cache_maxmem option ignored.  No LDAP support available.\n");
662   return 1;
663 #endif /* not HAVE_MAP_LDAP */
664 }
665
666
667 static int
668 gopt_ldap_hostports(const char *val)
669 {
670 #ifdef HAVE_MAP_LDAP
671   gopt.ldap_hostports = strdup((char *)val);
672   return 0;
673 #else /* not HAVE_MAP_LDAP */
674   fprintf(stderr, "conf: ldap_hostports option ignored.  No LDAP support available.\n");
675   return 1;
676 #endif /* not HAVE_MAP_LDAP */
677
678 }
679
680
681 static int
682 gopt_ldap_proto_version(const char *val)
683 {
684 #ifdef HAVE_MAP_LDAP
685   char *end;
686
687   gopt.ldap_proto_version = strtol((char *)val, &end, 10);
688   if (end == val) {
689     fprintf(stderr, "conf: bad ldap_proto_version option: %s\n",val);
690     return 1;
691   }
692
693   if (gopt.ldap_proto_version < 0 || gopt.ldap_proto_version > LDAP_VERSION_MAX) {
694     fprintf(stderr, "conf: bad ldap_proto_version option value: %s\n",val);
695     return 1;
696   }
697   switch (gopt.ldap_proto_version) {
698     /* XXX: what about LDAP_VERSION1? */
699   case LDAP_VERSION2:
700 #ifdef LDAP_VERSION3
701   case LDAP_VERSION3:
702 #endif /* LDAP_VERSION3 */
703 #ifdef LDAP_VERSION4
704   case LDAP_VERSION4:
705 #endif /* LDAP_VERSION4 */
706     break;
707   default:
708     fprintf(stderr, "conf: unsupported ldap_proto_version option value: %s\n",val);
709     return 1;
710   }
711   return 0;
712 #else /* not HAVE_MAP_LDAP */
713   fprintf(stderr, "conf: ldap_proto_version option ignored.  No LDAP support available.\n");
714   return 1;
715 #endif /* not HAVE_MAP_LDAP */
716 }
717
718
719 static int
720 gopt_log_file(const char *val)
721 {
722   gopt.logfile = strdup((char *)val);
723   return 0;
724 }
725
726
727 static int
728 gopt_log_options(const char *val)
729 {
730   usage += switch_option((char *)val);
731   return 0;
732 }
733
734
735 static int
736 gopt_map_defaults(const char *val)
737 {
738   gopt.map_defaults = strdup((char *)val);
739   return 0;
740 }
741
742
743 static int
744 gopt_map_options(const char *val)
745 {
746   gopt.map_options = strdup((char *)val);
747   return 0;
748 }
749
750
751 static int
752 gopt_map_reload_interval(const char *val)
753 {
754   gopt.map_reload_interval = atoi(val);
755   if (gopt.map_reload_interval <= 0)
756     gopt.map_reload_interval = ONE_HOUR;
757   return 0;
758 }
759
760
761 static int
762 gopt_map_type(const char *val)
763 {
764   /* check if map type exist */
765   if (!mapc_type_exists(val)) {
766     fprintf(stderr, "conf: no such map type \"%s\"\n", val);
767     return 1;
768   }
769   gopt.map_type = strdup((char *)val);
770   return 0;
771 }
772
773
774 static int
775 gopt_mount_type(const char *val)
776 {
777   if (STREQ(val, "autofs")) {
778 #ifdef HAVE_FS_AUTOFS
779     gopt.flags |= CFM_MOUNT_TYPE_AUTOFS;
780     amd_use_autofs++;
781     return 0;
782 #else /* not HAVE_FS_AUTOFS */
783     fprintf(stderr, "conf: no autofs support available\n");
784     return 1;
785 #endif /* not HAVE_FS_AUTOFS */
786   } else if (STREQ(val, "nfs")) {
787     gopt.flags &= ~CFM_MOUNT_TYPE_AUTOFS;
788     return 0;
789   }
790
791   fprintf(stderr, "conf: unknown value to mount_type \"%s\"\n", val);
792   return 1;                     /* unknown value */
793 }
794
795
796 static int
797 gopt_portmap_program(const char *val)
798 {
799   gopt.portmap_program = atol(val);
800   /*
801    * allow alternate program numbers to be no more than 10 offset from
802    * official amd program number (300019).
803    */
804   if (gopt.portmap_program < AMQ_PROGRAM ||
805       gopt.portmap_program > AMQ_PROGRAM + 10) {
806     gopt.portmap_program = AMQ_PROGRAM;
807     set_amd_program_number(gopt.portmap_program);
808     fprintf(stderr, "conf: illegal amd program number \"%s\"\n", val);
809     return 1;
810   }
811
812   set_amd_program_number(gopt.portmap_program);
813   return 0;                     /* all is OK */
814 }
815
816
817 static int
818 gopt_preferred_amq_port(const char *val)
819 {
820   gopt.preferred_amq_port = atoi(val);
821
822   /*
823    * No need to check value: preferred_amq_port is an unsigned short and 0
824    * is a valid number, meaning "any port".
825    */
826   return 0;                     /* all is OK */
827 }
828
829
830 static int
831 gopt_nfs_allow_any_interface(const char *val)
832 {
833   if (STREQ(val, "yes")) {
834     gopt.flags |= CFM_NFS_ANY_INTERFACE;
835     return 0;
836   } else if (STREQ(val, "no")) {
837     gopt.flags &= ~CFM_NFS_ANY_INTERFACE;
838     return 0;
839   }
840
841   fprintf(stderr, "conf: unknown value to nfs_allow_insecure_port \"%s\"\n", val);
842   return 1;                     /* unknown value */
843 }
844
845
846 static int
847 gopt_nfs_allow_insecure_port(const char *val)
848 {
849   if (STREQ(val, "yes")) {
850     gopt.flags |= CFM_NFS_INSECURE_PORT;
851     return 0;
852   } else if (STREQ(val, "no")) {
853     gopt.flags &= ~CFM_NFS_INSECURE_PORT;
854     return 0;
855   }
856
857   fprintf(stderr, "conf: unknown value to nfs_allow_insecure_port \"%s\"\n", val);
858   return 1;                     /* unknown value */
859 }
860
861
862 static int
863 gopt_nfs_proto(const char *val)
864 {
865   if (STREQ(val, "udp") || STREQ(val, "tcp")) {
866     gopt.nfs_proto = strdup((char *)val);
867     return 0;
868   }
869   fprintf(stderr, "conf: illegal nfs_proto \"%s\"\n", val);
870   return 1;
871 }
872
873
874 static int
875 gopt_nfs_retransmit_counter(const char *val)
876 {
877   int i;
878
879   for (i=0; i<AMU_TYPE_MAX; ++i)
880     gopt.amfs_auto_retrans[i] = atoi(val);
881   return 0;
882 }
883
884
885 static int
886 gopt_nfs_retransmit_counter_udp(const char *val)
887 {
888   gopt.amfs_auto_retrans[AMU_TYPE_UDP] = atoi(val);
889   return 0;
890 }
891
892
893 static int
894 gopt_nfs_retransmit_counter_tcp(const char *val)
895 {
896   gopt.amfs_auto_retrans[AMU_TYPE_TCP] = atoi(val);
897   return 0;
898 }
899
900
901 static int
902 gopt_nfs_retransmit_counter_toplvl(const char *val)
903 {
904   gopt.amfs_auto_retrans[AMU_TYPE_TOPLVL] = atoi(val);
905   return 0;
906 }
907
908
909 static int
910 gopt_nfs_retry_interval(const char *val)
911 {
912   int i;
913
914   for (i=0; i<AMU_TYPE_MAX; ++i)
915     gopt.amfs_auto_timeo[i] = atoi(val);
916   return 0;
917 }
918
919
920 static int
921 gopt_nfs_retry_interval_udp(const char *val)
922 {
923   gopt.amfs_auto_timeo[AMU_TYPE_UDP] = atoi(val);
924   return 0;
925 }
926
927
928 static int
929 gopt_nfs_retry_interval_tcp(const char *val)
930 {
931   gopt.amfs_auto_timeo[AMU_TYPE_TCP] = atoi(val);
932   return 0;
933 }
934
935
936 static int
937 gopt_nfs_retry_interval_toplvl(const char *val)
938 {
939   gopt.amfs_auto_timeo[AMU_TYPE_TOPLVL] = atoi(val);
940   return 0;
941 }
942
943
944 static int
945 gopt_nfs_vers(const char *val)
946 {
947   int i = atoi(val);
948
949   if (i == 2 || i == 3) {
950     gopt.nfs_vers = i;
951     return 0;
952   }
953   fprintf(stderr, "conf: illegal nfs_vers \"%s\"\n", val);
954   return 1;
955 }
956
957
958 static int
959 gopt_nis_domain(const char *val)
960 {
961 #ifdef HAVE_MAP_NIS
962   gopt.nis_domain = strdup((char *)val);
963   return 0;
964 #else /* not HAVE_MAP_NIS */
965   fprintf(stderr, "conf: nis_domain option ignored.  No NIS support available.\n");
966   return 1;
967 #endif /* not HAVE_MAP_NIS */
968 }
969
970
971 static int
972 gopt_normalize_hostnames(const char *val)
973 {
974   if (STREQ(val, "yes")) {
975     gopt.flags |= CFM_NORMALIZE_HOSTNAMES;
976     return 0;
977   } else if (STREQ(val, "no")) {
978     gopt.flags &= ~CFM_NORMALIZE_HOSTNAMES;
979     return 0;
980   }
981
982   fprintf(stderr, "conf: unknown value to normalize_hostnames \"%s\"\n", val);
983   return 1;                     /* unknown value */
984 }
985
986
987 static int
988 gopt_normalize_slashes(const char *val)
989 {
990   if (STREQ(val, "yes")) {
991     gopt.flags |= CFM_NORMALIZE_SLASHES;
992     return 0;
993   } else if (STREQ(val, "no")) {
994     gopt.flags &= ~CFM_NORMALIZE_SLASHES;
995     return 0;
996   }
997
998   fprintf(stderr, "conf: unknown value to normalize_slashes \"%s\"\n", val);
999   return 1;                     /* unknown value */
1000 }
1001
1002
1003 static int
1004 gopt_os(const char *val)
1005 {
1006   gopt.op_sys = strdup((char *)val);
1007   return 0;
1008 }
1009
1010
1011 static int
1012 gopt_osver(const char *val)
1013 {
1014   gopt.op_sys_ver = strdup((char *)val);
1015   return 0;
1016 }
1017
1018
1019 static int
1020 gopt_plock(const char *val)
1021 {
1022   if (STREQ(val, "yes")) {
1023     gopt.flags |= CFM_PROCESS_LOCK;
1024     return 0;
1025   } else if (STREQ(val, "no")) {
1026     gopt.flags &= ~CFM_PROCESS_LOCK;
1027     return 0;
1028   }
1029
1030   fprintf(stderr, "conf: unknown value to plock \"%s\"\n", val);
1031   return 1;                     /* unknown value */
1032 }
1033
1034
1035 static int
1036 gopt_print_pid(const char *val)
1037 {
1038   if (STREQ(val, "yes")) {
1039     gopt.flags |= CFM_PRINT_PID;
1040     return 0;
1041   } else if (STREQ(val, "no")) {
1042     gopt.flags &= ~CFM_PRINT_PID;
1043     return 0;
1044   }
1045
1046   fprintf(stderr, "conf: unknown value to print_pid \"%s\"\n", val);
1047   return 1;                     /* unknown value */
1048 }
1049
1050
1051 static int
1052 gopt_print_version(const char *val)
1053 {
1054   if (STREQ(val, "yes")) {
1055     char *vers = get_version_string();
1056     fputs(vers, stderr);
1057     XFREE(vers);
1058     return 0;
1059   } else if (STREQ(val, "no")) {
1060     return 0;
1061   }
1062
1063   fprintf(stderr, "conf: unknown value to print_version \"%s\"\n", val);
1064   return 1;                     /* unknown value */
1065 }
1066
1067
1068 static int
1069 gopt_restart_mounts(const char *val)
1070 {
1071   if (STREQ(val, "yes")) {
1072     gopt.flags |= CFM_RESTART_EXISTING_MOUNTS;
1073     return 0;
1074   } else if (STREQ(val, "no")) {
1075     gopt.flags &= ~CFM_RESTART_EXISTING_MOUNTS;
1076     return 0;
1077   }
1078
1079   fprintf(stderr, "conf: unknown value to restart_mounts \"%s\"\n", val);
1080   return 1;                     /* unknown value */
1081 }
1082
1083
1084 static int
1085 gopt_search_path(const char *val)
1086 {
1087   gopt.search_path = strdup((char *)val);
1088   return 0;
1089 }
1090
1091
1092 static int
1093 gopt_selectors_in_defaults(const char *val)
1094 {
1095   if (STREQ(val, "yes")) {
1096     gopt.flags |= CFM_SELECTORS_IN_DEFAULTS;
1097     return 0;
1098   } else if (STREQ(val, "no")) {
1099     gopt.flags &= ~CFM_SELECTORS_IN_DEFAULTS;
1100     return 0;
1101   }
1102
1103   fprintf(stderr, "conf: unknown value to enable_default_selectors \"%s\"\n", val);
1104   return 1;                     /* unknown value */
1105 }
1106
1107
1108 static int
1109 gopt_show_statfs_entries(const char *val)
1110 {
1111   if (STREQ(val, "yes")) {
1112     gopt.flags |= CFM_SHOW_STATFS_ENTRIES;
1113     return 0;
1114   } else if (STREQ(val, "no")) {
1115     gopt.flags &= ~CFM_SHOW_STATFS_ENTRIES;
1116     return 0;
1117   }
1118
1119   fprintf(stderr, "conf: unknown value to show_statfs_entries \"%s\"\n", val);
1120   return 1;                     /* unknown value */
1121 }
1122
1123
1124 static int
1125 gopt_truncate_log(const char *val)
1126 {
1127   if (STREQ(val, "yes")) {
1128     gopt.flags |= CFM_TRUNCATE_LOG;
1129     return 0;
1130   } else if (STREQ(val, "no")) {
1131     gopt.flags &= ~CFM_TRUNCATE_LOG;
1132     return 0;
1133   }
1134
1135   fprintf(stderr, "conf: unknown value to truncate_log \"%s\"\n", val);
1136   return 1;                     /* unknown value */
1137 }
1138
1139
1140 static int
1141 gopt_unmount_on_exit(const char *val)
1142 {
1143   if (STREQ(val, "yes")) {
1144     gopt.flags |= CFM_UNMOUNT_ON_EXIT;
1145     return 0;
1146   } else if (STREQ(val, "no")) {
1147     gopt.flags &= ~CFM_UNMOUNT_ON_EXIT;
1148     return 0;
1149   }
1150
1151   fprintf(stderr, "conf: unknown value to unmount_on_exit \"%s\"\n", val);
1152   return 1;                     /* unknown value */
1153 }
1154
1155
1156 static int
1157 gopt_use_tcpwrappers(const char *val)
1158 {
1159 #if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
1160   if (STREQ(val, "yes")) {
1161     gopt.flags |= CFM_USE_TCPWRAPPERS;
1162     return 0;
1163   } else if (STREQ(val, "no")) {
1164     gopt.flags &= ~CFM_USE_TCPWRAPPERS;
1165     return 0;
1166   }
1167 #else /* not defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
1168     fprintf(stderr, "conf: no tcpd/libwrap support available\n");
1169     return 1;
1170 #endif /* not defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
1171
1172   fprintf(stderr, "conf: unknown value to use_tcpwrappers \"%s\"\n", val);
1173   return 1;                     /* unknown value */
1174 }
1175
1176
1177 static int
1178 gopt_vendor(const char *val)
1179 {
1180   gopt.op_sys_vendor = strdup((char *)val);
1181   return 0;
1182 }
1183
1184
1185 /*
1186  * Collect one entry for a regular map
1187  */
1188 static int
1189 process_regular_option(const char *section, const char *key, const char *val, cf_map_t *cfm)
1190 {
1191   /* ensure that val is valid */
1192   if (!section || section[0] == '\0' ||
1193       !key || key[0] == '\0' ||
1194       !val || val[0] == '\0' ||
1195       !cfm) {
1196     fprintf(stderr, "conf: process_regular_option: null entries\n");
1197     return 1;
1198   }
1199
1200   /* check if initializing a new map */
1201   if (!cfm->cfm_dir)
1202     cfm->cfm_dir = strdup((char *)section);
1203
1204   /* check for each possible field */
1205   if (STREQ(key, "browsable_dirs"))
1206     return ropt_browsable_dirs(val, cfm);
1207
1208   if (STREQ(key, "map_name"))
1209     return ropt_map_name(val, cfm);
1210
1211   if (STREQ(key, "map_defaults"))
1212     return ropt_map_defaults(val, cfm);
1213
1214   if (STREQ(key, "map_options"))
1215     return ropt_map_options(val, cfm);
1216
1217   if (STREQ(key, "map_type"))
1218     return ropt_map_type(val, cfm);
1219
1220   if (STREQ(key, "mount_type"))
1221     return ropt_mount_type(val, cfm);
1222
1223   if (STREQ(key, "search_path"))
1224     return ropt_search_path(val, cfm);
1225
1226   if (STREQ(key, "tag"))
1227     return ropt_tag(val, cfm);
1228
1229   fprintf(stderr, "conf: unknown regular key \"%s\" for section \"%s\"\n",
1230           key, section);
1231   return 1;                     /* failed to match any command */
1232 }
1233
1234
1235 static int
1236 ropt_browsable_dirs(const char *val, cf_map_t *cfm)
1237 {
1238   if (STREQ(val, "full")) {
1239     cfm->cfm_flags |= CFM_BROWSABLE_DIRS_FULL;
1240     return 0;
1241   } else if (STREQ(val, "yes")) {
1242     cfm->cfm_flags |= CFM_BROWSABLE_DIRS;
1243     return 0;
1244   } else if (STREQ(val, "no")) {
1245     cfm->cfm_flags &= ~CFM_BROWSABLE_DIRS;
1246     return 0;
1247   }
1248
1249   fprintf(stderr, "conf: unknown value to browsable_dirs \"%s\"\n", val);
1250   return 1;                     /* unknown value */
1251 }
1252
1253
1254 static int
1255 ropt_map_name(const char *val, cf_map_t *cfm)
1256 {
1257   cfm->cfm_name = strdup((char *)val);
1258   return 0;
1259 }
1260
1261
1262 static int
1263 ropt_map_defaults(const char *val, cf_map_t *cfm)
1264 {
1265   cfm->cfm_defaults = strdup((char *)val);
1266   return 0;
1267 }
1268
1269
1270 static int
1271 ropt_map_options(const char *val, cf_map_t *cfm)
1272 {
1273   cfm->cfm_opts = strdup((char *)val);
1274   return 0;
1275 }
1276
1277
1278 static int
1279 ropt_map_type(const char *val, cf_map_t *cfm)
1280 {
1281   /* check if map type exist */
1282   if (!mapc_type_exists(val)) {
1283     fprintf(stderr, "conf: no such map type \"%s\"\n", val);
1284     return 1;
1285   }
1286   cfm->cfm_type = strdup((char *)val);
1287   return 0;
1288 }
1289
1290
1291 static int
1292 ropt_mount_type(const char *val, cf_map_t *cfm)
1293 {
1294   if (STREQ(val, "autofs")) {
1295 #ifdef HAVE_FS_AUTOFS
1296     cfm->cfm_flags |= CFM_MOUNT_TYPE_AUTOFS;
1297     amd_use_autofs++;
1298     return 0;
1299 #else /* not HAVE_FS_AUTOFS */
1300     fprintf(stderr, "conf: no autofs support available\n");
1301     return 1;
1302 #endif /* not HAVE_FS_AUTOFS */
1303   } else if (STREQ(val, "nfs")) {
1304     cfm->cfm_flags &= ~CFM_MOUNT_TYPE_AUTOFS;
1305     return 0;
1306   }
1307
1308   fprintf(stderr, "conf: unknown value to mount_type \"%s\"\n", val);
1309   return 1;                     /* unknown value */
1310 }
1311
1312
1313 static int
1314 ropt_search_path(const char *val, cf_map_t *cfm)
1315 {
1316   cfm->cfm_search_path = strdup((char *)val);
1317   return 0;
1318 }
1319
1320
1321 static int
1322 ropt_tag(const char *val, cf_map_t *cfm)
1323 {
1324   cfm->cfm_tag = strdup((char *)val);
1325   return 0;
1326 }
1327
1328
1329 /*
1330  * Process one collected map.
1331  */
1332 static int
1333 process_one_regular_map(const cf_map_t *cfm)
1334 {
1335   if (!cfm->cfm_name) {
1336     fprintf(stderr, "conf: map_name must be defined for map \"%s\"\n", cfm->cfm_dir);
1337     return 1;
1338   }
1339   /*
1340    * If map has no tag defined, process the map.
1341    * If no conf_tag was set in amd -T, process all untagged entries.
1342    * If a tag is defined, then process it only if it matches the map tag.
1343    */
1344   if (!cfm->cfm_tag ||
1345       (conf_tag && STREQ(cfm->cfm_tag, conf_tag))) {
1346 #ifdef DEBUG_CONF
1347     fprintf(stderr, "processing map %s (flags=0x%x)...\n",
1348             cfm->cfm_dir, cfm->cfm_flags);
1349 #endif /* DEBUG_CONF */
1350     root_newmap(cfm->cfm_dir,
1351                 cfm->cfm_opts ? cfm->cfm_opts : "",
1352                 cfm->cfm_name,
1353                 cfm);
1354   } else {
1355     fprintf(stderr, "skipping map %s...\n", cfm->cfm_dir);
1356   }
1357
1358   return 0;
1359 }
1360
1361
1362 /*
1363  * Process all regular maps in conf file (if any)
1364  */
1365 int
1366 process_all_regular_maps(void)
1367 {
1368   cf_map_t *tmp_map = head_map;
1369
1370   /*
1371    * If the amd.conf file only has a [global] section (pretty useless
1372    * IMHO), there's nothing to process
1373    */
1374   if (!tmp_map)
1375     return 0;
1376
1377   while (tmp_map) {
1378     if (process_one_regular_map(tmp_map) != 0)
1379       return 1;
1380     tmp_map = tmp_map->cfm_next;
1381   }
1382   return 0;
1383 }
1384
1385
1386 /*
1387  * Find a cf_map_t for a given map name.
1388  * Return NULL if not found.
1389  */
1390 cf_map_t *
1391 find_cf_map(const char *name)
1392 {
1393
1394   cf_map_t *tmp_map = head_map;
1395
1396   if (!tmp_map || !name)
1397     return NULL;
1398
1399   while (tmp_map) {
1400     if (STREQ(tmp_map->cfm_dir,name)) {
1401       return tmp_map;
1402     }
1403     tmp_map = tmp_map->cfm_next;
1404   }
1405   return NULL;
1406 }