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