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.
8 * This code is derived from software contributed to Berkeley by
9 * Jan-Simon Pendry at Imperial College, London.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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
41 * $Id: conf.c,v 1.5 1999/09/30 21:01:30 ezk Exp $
46 * Functions to handle the configuration file.
51 #endif /* HAVE_CONFIG_H */
59 /* Turn on to show some info about maps being configured */
60 /* #define DEBUG_CONF */
65 typedef int (*OptFuncPtr)(const char *);
76 * FORWARD DECLARATIONS:
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);
132 static cf_map_t cur_map;
133 static struct _func_map glob_functable[] = {
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},
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},
180 reset_cf_map(cf_map_t *cfm)
191 XFREE(cfm->cfm_name);
192 cfm->cfm_name = NULL;
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.
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
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;
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;
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;
228 * Initialize flags that are common both to [global] and a local map.
230 cfm->cfm_flags = gopt.flags & (CFM_BROWSABLE_DIRS |
231 CFM_BROWSABLE_DIRS_FULL |
232 CFM_MOUNT_TYPE_AUTOFS |
233 CFM_ENABLE_DEFAULT_SELECTORS);
238 * Process configuration file options.
239 * Return 0 if OK, 1 otherwise.
242 set_conf_kv(const char *section, const char *key, const char *val)
247 fprintf(stderr,"set_conf_kv: section=%s, key=%s, val=%s\n",
249 #endif /* DEBUG_CONF */
252 * If global section, process them one at a time.
254 if (STREQ(section, "global")) {
256 * Check if a regular map was configured before "global",
257 * and process it as needed.
259 if (cur_map.cfm_dir) {
260 fprintf(stderr,"processing regular map \"%s\" before global one.\n",
262 ret = process_regular_map(&cur_map); /* will reset map */
267 /* process the global option first */
268 ret = process_global_option(key, val);
270 /* reset default options for regular maps from just updated globals */
272 reset_cf_map(&cur_map);
274 /* return status from the processing of the global option */
279 * otherwise save options and process a single map all at once.
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 */
289 /* now process a single entry of a regular map */
290 return process_regular_option(section, key, val, &cur_map);
295 * Process global section of configuration file options.
296 * Return 0 upon success, 1 otherwise.
299 process_global_option(const char *key, const char *val)
301 struct _func_map *gfp;
303 /* ensure that val is valid */
304 if (!val || val[0] == '\0')
308 * search for global function.
310 for (gfp = glob_functable; gfp->name; gfp++)
311 if (FSTREQ(gfp->name, key))
312 return (gfp->func)(val);
314 fprintf(stderr, "conf: unknown global key: \"%s\"\n", key);
315 return 1; /* failed to match any command */
320 gopt_arch(const char *val)
322 gopt.arch = strdup((char *)val);
328 gopt_auto_dir(const char *val)
330 gopt.auto_dir = strdup((char *)val);
336 gopt_browsable_dirs(const char *val)
338 if (STREQ(val, "full")) {
339 gopt.flags |= CFM_BROWSABLE_DIRS_FULL;
341 } else if (STREQ(val, "yes")) {
342 gopt.flags |= CFM_BROWSABLE_DIRS;
344 } else if (STREQ(val, "no")) {
345 gopt.flags &= ~CFM_BROWSABLE_DIRS;
349 fprintf(stderr, "conf: unknown value to browsable_dirs \"%s\"\n", val);
350 return 1; /* unknown value */
355 gopt_cache_duration(const char *val)
357 gopt.am_timeo = atoi(val);
358 if (gopt.am_timeo <= 0)
359 gopt.am_timeo = AM_TTL;
365 gopt_cluster(const char *val)
367 gopt.cluster = strdup((char *)val);
373 gopt_debug_options(const char *val)
376 usage += debug_option(strdup((char *)val));
378 #else /* not DEBUG */
379 fprintf(stderr, "%s: not compiled with DEBUG option -- sorry.\n",
382 #endif /* not DEBUG */
387 gopt_dismount_interval(const char *val)
389 gopt.am_timeo_w = atoi(val);
390 if (gopt.am_timeo_w <= 0)
391 gopt.am_timeo_w = AM_TTL_W;
397 gopt_full_os(const char *val)
399 gopt.op_sys_full = strdup((char *)val);
405 gopt_fully_qualified_hosts(const char *val)
407 if (STREQ(val, "yes")) {
408 gopt.flags |= CFM_FULLY_QUALIFIED_HOSTS;
410 } else if (STREQ(val, "no")) {
411 gopt.flags &= ~CFM_FULLY_QUALIFIED_HOSTS;
415 fprintf(stderr, "conf: unknown value to fully_qualified_hosts \"%s\"\n", val);
416 return 1; /* unknown value */
421 gopt_hesiod_base(const char *val)
423 #ifdef HAVE_MAP_HESIOD
424 gopt.hesiod_base = strdup((char *)val);
426 #else /* not HAVE_MAP_HESIOD */
427 fprintf(stderr, "conf: hesiod_base option ignored. No Hesiod support available.\n");
429 #endif /* not HAVE_MAP_HESIOD */
434 gopt_karch(const char *val)
436 gopt.karch = strdup((char *)val);
442 gopt_pid_file(const char *val)
444 gopt.pid_file = strdup((char *)val);
450 gopt_local_domain(const char *val)
452 gopt.sub_domain = strdup((char *)val);
458 gopt_ldap_base(const char *val)
461 gopt.ldap_base = strdup((char *)val);
463 #else /* not HAVE_MAP_LDAP */
464 fprintf(stderr, "conf: ldap_base option ignored. No LDAP support available.\n");
466 #endif /* not HAVE_MAP_LDAP */
471 gopt_ldap_cache_seconds(const char *val)
476 gopt.ldap_cache_seconds = strtol((char *)val, &end, 10);
478 fprintf(stderr, "conf: bad LDAP cache (seconds) option: %s\n",val);
482 #else /* not HAVE_MAP_LDAP */
483 fprintf(stderr, "conf: ldap_cache option ignored. No LDAP support available.\n");
485 #endif /* not HAVE_MAP_LDAP */
490 gopt_ldap_cache_maxmem(const char *val)
495 gopt.ldap_cache_maxmem = strtol((char *)val, &end, 10);
497 fprintf(stderr, "conf: bad LDAP cache (maxmem) option: %s\n",val);
501 #else /* not HAVE_MAP_LDAP */
502 fprintf(stderr, "conf: ldap_cache option ignored. No LDAP support available.\n");
504 #endif /* not HAVE_MAP_LDAP */
509 gopt_ldap_hostports(const char *val)
512 gopt.ldap_hostports = strdup((char *)val);
514 #else /* not HAVE_MAP_LDAP */
515 fprintf(stderr, "conf: ldap_hostports option ignored. No LDAP support available.\n");
517 #endif /* not HAVE_MAP_LDAP */
523 gopt_log_file(const char *val)
525 gopt.logfile = strdup((char *)val);
531 gopt_log_options(const char *val)
533 usage += switch_option(strdup((char *)val));
539 gopt_map_options(const char *val)
541 gopt.map_options = strdup((char *)val);
547 gopt_map_type(const char *val)
549 /* check if map type exist */
550 if (!mapc_type_exists(val)) {
551 fprintf(stderr, "conf: no such map type \"%s\"\n", val);
554 gopt.map_type = strdup((char *)val);
560 gopt_mount_type(const char *val)
562 if (STREQ(val, "autofs")) {
563 #ifdef HAVE_FS_AUTOFS
564 gopt.flags |= CFM_MOUNT_TYPE_AUTOFS;
567 #else /* not HAVE_FS_AUTOFS */
568 fprintf(stderr, "conf: no autofs support available\n");
570 #endif /* not HAVE_FS_AUTOFS */
571 } else if (STREQ(val, "nfs")) {
572 gopt.flags &= ~CFM_MOUNT_TYPE_AUTOFS;
576 fprintf(stderr, "conf: unknown value to mount_type \"%s\"\n", val);
577 return 1; /* unknown value */
582 gopt_portmap_program(const char *val)
584 gopt.portmap_program = atoi(val);
586 * allow alternate program numbers to be no more than 10 offset from
587 * official amd program number (300019).
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);
597 set_amd_program_number(gopt.portmap_program);
598 return 0; /* all is OK */
603 gopt_nfs_retransmit_counter(const char *val)
605 gopt.amfs_auto_retrans = atoi(val);
611 gopt_nfs_retry_interval(const char *val)
613 gopt.amfs_auto_timeo = atoi(val);
619 gopt_nis_domain(const char *val)
622 gopt.nis_domain = strdup((char *)val);
624 #else /* not HAVE_MAP_NIS */
625 fprintf(stderr, "conf: nis_domain option ignored. No NIS support available.\n");
627 #endif /* not HAVE_MAP_NIS */
632 gopt_normalize_hostnames(const char *val)
634 if (STREQ(val, "yes")) {
635 gopt.flags |= CFM_NORMALIZE_HOSTNAMES;
637 } else if (STREQ(val, "no")) {
638 gopt.flags &= ~CFM_NORMALIZE_HOSTNAMES;
642 fprintf(stderr, "conf: unknown value to normalize_hostnames \"%s\"\n", val);
643 return 1; /* unknown value */
648 gopt_os(const char *val)
650 gopt.op_sys = strdup((char *)val);
656 gopt_osver(const char *val)
658 gopt.op_sys_ver = strdup((char *)val);
664 gopt_plock(const char *val)
666 if (STREQ(val, "yes")) {
667 gopt.flags |= CFM_PROCESS_LOCK;
669 } else if (STREQ(val, "no")) {
670 gopt.flags &= ~CFM_PROCESS_LOCK;
674 fprintf(stderr, "conf: unknown value to plock \"%s\"\n", val);
675 return 1; /* unknown value */
680 gopt_print_pid(const char *val)
682 if (STREQ(val, "yes")) {
683 gopt.flags |= CFM_PRINT_PID;
685 } else if (STREQ(val, "no")) {
686 gopt.flags &= ~CFM_PRINT_PID;
690 fprintf(stderr, "conf: unknown value to print_pid \"%s\"\n", val);
691 return 1; /* unknown value */
696 gopt_print_version(const char *val)
698 if (STREQ(val, "yes")) {
699 fputs(get_version_string(), stderr);
701 } else if (STREQ(val, "no")) {
705 fprintf(stderr, "conf: unknown value to print_version \"%s\"\n", val);
706 return 1; /* unknown value */
711 gopt_restart_mounts(const char *val)
713 if (STREQ(val, "yes")) {
714 gopt.flags |= CFM_RESTART_EXISTING_MOUNTS;
716 } else if (STREQ(val, "no")) {
717 gopt.flags &= ~CFM_RESTART_EXISTING_MOUNTS;
721 fprintf(stderr, "conf: unknown value to restart_mounts \"%s\"\n", val);
722 return 1; /* unknown value */
727 gopt_search_path(const char *val)
729 gopt.search_path = strdup((char *)val);
735 gopt_selectors_on_default(const char *val)
737 if (STREQ(val, "yes")) {
738 gopt.flags |= CFM_ENABLE_DEFAULT_SELECTORS;
740 } else if (STREQ(val, "no")) {
741 gopt.flags &= ~CFM_ENABLE_DEFAULT_SELECTORS;
745 fprintf(stderr, "conf: unknown value to enable_default_selectors \"%s\"\n", val);
746 return 1; /* unknown value */
751 gopt_show_statfs_entries(const char *val)
753 if (STREQ(val, "yes")) {
754 gopt.flags |= CFM_SHOW_STATFS_ENTRIES;
756 } else if (STREQ(val, "no")) {
757 gopt.flags &= ~CFM_SHOW_STATFS_ENTRIES;
761 fprintf(stderr, "conf: unknown value to show_statfs_entries \"%s\"\n", val);
762 return 1; /* unknown value */
767 gopt_unmount_on_exit(const char *val)
769 if (STREQ(val, "yes")) {
770 gopt.flags |= CFM_UNMOUNT_ON_EXIT;
772 } else if (STREQ(val, "no")) {
773 gopt.flags &= ~CFM_UNMOUNT_ON_EXIT;
777 fprintf(stderr, "conf: unknown value to unmount_on_exit \"%s\"\n", val);
778 return 1; /* unknown value */
783 gopt_vendor(const char *val)
785 gopt.op_sys_vendor = strdup((char *)val);
791 * Collect one entry for a regular map
794 process_regular_option(const char *section, const char *key, const char *val, cf_map_t *cfm)
796 /* ensure that val is valid */
797 if (!section || section[0] == '\0' ||
798 !key || key[0] == '\0' ||
799 !val || val[0] == '\0' ||
801 fprintf(stderr, "conf: process_regular_option: null entries\n");
805 /* check if initializing a new map */
807 cfm->cfm_dir = strdup((char *)section);
809 /* check for each possible field */
810 if (STREQ(key, "browsable_dirs"))
811 return ropt_browsable_dirs(val, cfm);
813 if (STREQ(key, "map_name"))
814 return ropt_map_name(val, cfm);
816 if (STREQ(key, "map_options"))
817 return ropt_map_options(val, cfm);
819 if (STREQ(key, "map_type"))
820 return ropt_map_type(val, cfm);
822 if (STREQ(key, "mount_type"))
823 return ropt_mount_type(val, cfm);
825 if (STREQ(key, "search_path"))
826 return ropt_search_path(val, cfm);
828 if (STREQ(key, "tag"))
829 return ropt_tag(val, cfm);
831 fprintf(stderr, "conf: unknown regular key \"%s\" for section \"%s\"\n",
833 return 1; /* failed to match any command */
838 ropt_browsable_dirs(const char *val, cf_map_t *cfm)
840 if (STREQ(val, "full")) {
841 cfm->cfm_flags |= CFM_BROWSABLE_DIRS_FULL;
843 } else if (STREQ(val, "yes")) {
844 cfm->cfm_flags |= CFM_BROWSABLE_DIRS;
846 } else if (STREQ(val, "no")) {
847 cfm->cfm_flags &= ~CFM_BROWSABLE_DIRS;
851 fprintf(stderr, "conf: unknown value to browsable_dirs \"%s\"\n", val);
852 return 1; /* unknown value */
857 ropt_map_name(const char *val, cf_map_t *cfm)
859 cfm->cfm_name = strdup((char *)val);
865 ropt_map_options(const char *val, cf_map_t *cfm)
867 cfm->cfm_opts = strdup((char *)val);
873 ropt_map_type(const char *val, cf_map_t *cfm)
875 /* check if map type exist */
876 if (!mapc_type_exists(val)) {
877 fprintf(stderr, "conf: no such map type \"%s\"\n", val);
880 cfm->cfm_type = strdup((char *)val);
886 ropt_mount_type(const char *val, cf_map_t *cfm)
888 if (STREQ(val, "autofs")) {
889 #ifdef HAVE_FS_AUTOFS
890 cfm->cfm_flags |= CFM_MOUNT_TYPE_AUTOFS;
893 #else /* not HAVE_FS_AUTOFS */
894 fprintf(stderr, "conf: no autofs support available\n");
896 #endif /* not HAVE_FS_AUTOFS */
897 } else if (STREQ(val, "nfs")) {
898 cfm->cfm_flags &= ~CFM_MOUNT_TYPE_AUTOFS;
902 fprintf(stderr, "conf: unknown value to mount_type \"%s\"\n", val);
903 return 1; /* unknown value */
908 ropt_search_path(const char *val, cf_map_t *cfm)
910 cfm->cfm_search_path = strdup((char *)val);
916 ropt_tag(const char *val, cf_map_t *cfm)
918 cfm->cfm_tag = strdup((char *)val);
924 * Process one collected map.
927 process_regular_map(cf_map_t *cfm)
930 if (!cfm->cfm_name) {
931 fprintf(stderr, "conf: map_name must be defined for map \"%s\"\n", cfm->cfm_dir);
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.
940 (conf_tag && STREQ(cfm->cfm_tag, conf_tag))) {
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 : "",
950 fprintf(stderr, "skipping map %s...\n", cfm->cfm_dir);
959 * Process last map in conf file (if any)
962 process_last_regular_map(void)
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.
968 if (!cur_map.cfm_dir)
970 return process_regular_map(&cur_map);