conf.c revision 119679
190075Sobrien/*
290075Sobrien * Copyright (c) 1997-2003 Erez Zadok
390075Sobrien * Copyright (c) 1990 Jan-Simon Pendry
490075Sobrien * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
590075Sobrien * Copyright (c) 1990 The Regents of the University of California.
690075Sobrien * All rights reserved.
790075Sobrien *
890075Sobrien * This code is derived from software contributed to Berkeley by
990075Sobrien * Jan-Simon Pendry at Imperial College, London.
1090075Sobrien *
1190075Sobrien * Redistribution and use in source and binary forms, with or without
1290075Sobrien * modification, are permitted provided that the following conditions
1390075Sobrien * are met:
1490075Sobrien * 1. Redistributions of source code must retain the above copyright
1590075Sobrien *    notice, this list of conditions and the following disclaimer.
1690075Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1790075Sobrien *    notice, this list of conditions and the following disclaimer in the
18169689Skan *    documentation and/or other materials provided with the distribution.
19169689Skan * 3. All advertising materials mentioning features or use of this software
2090075Sobrien *    must display the following acknowledgment:
2190075Sobrien *      This product includes software developed by the University of
2290075Sobrien *      California, Berkeley and its contributors.
23117395Skan * 4. Neither the name of the University nor the names of its contributors
24169689Skan *    may be used to endorse or promote products derived from this software
25169689Skan *    without specific prior written permission.
26169689Skan *
27169689Skan * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2890075Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2990075Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3090075Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3190075Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3290075Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3390075Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3490075Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3590075Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3690075Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3790075Sobrien * SUCH DAMAGE.
3890075Sobrien *
3990075Sobrien *      %W% (Berkeley) %G%
4090075Sobrien *
4190075Sobrien * $Id: conf.c,v 1.7.2.6 2002/12/27 22:44:34 ezk Exp $
4290075Sobrien *
4390075Sobrien */
4490075Sobrien
4590075Sobrien/*
4690075Sobrien * Functions to handle the configuration file.
4790075Sobrien */
4890075Sobrien
4990075Sobrien#ifdef HAVE_CONFIG_H
50117395Skan# include <config.h>
5190075Sobrien#endif /* HAVE_CONFIG_H */
5290075Sobrien#include <am_defs.h>
5390075Sobrien#include <amd.h>
5490075Sobrien
5590075Sobrien
5690075Sobrien/*
5790075Sobrien * MACROS:
5890075Sobrien */
5990075Sobrien/* Turn on to show some info about maps being configured */
6090075Sobrien/* #define DEBUG_CONF */
6190075Sobrien
6290075Sobrien/*
63169689Skan * TYPEDEFS:
64169689Skan */
6590075Sobrientypedef int (*OptFuncPtr)(const char *);
6690075Sobrien
6790075Sobrien/*
6890075Sobrien * STRUCTURES:
6990075Sobrien */
7090075Sobrienstruct _func_map {
7190075Sobrien  char *name;
72169689Skan  OptFuncPtr func;
73169689Skan};
7490075Sobrien
7590075Sobrien/*
7690075Sobrien * FORWARD DECLARATIONS:
7790075Sobrien */
7890075Sobrienstatic int gopt_arch(const char *val);
7990075Sobrienstatic int gopt_auto_dir(const char *val);
8090075Sobrienstatic int gopt_browsable_dirs(const char *val);
8190075Sobrienstatic int gopt_cache_duration(const char *val);
8290075Sobrienstatic int gopt_cluster(const char *val);
8390075Sobrienstatic int gopt_debug_options(const char *val);
84169689Skanstatic int gopt_dismount_interval(const char *val);
85169689Skanstatic int gopt_full_os(const char *val);
86169689Skanstatic int gopt_fully_qualified_hosts(const char *val);
87169689Skanstatic int gopt_hesiod_base(const char *val);
88169689Skanstatic int gopt_karch(const char *val);
8990075Sobrienstatic int gopt_ldap_base(const char *val);
9090075Sobrienstatic int gopt_ldap_cache_maxmem(const char *val);
9190075Sobrienstatic int gopt_ldap_cache_seconds(const char *val);
9290075Sobrienstatic int gopt_ldap_hostports(const char *val);
93117395Skanstatic int gopt_local_domain(const char *val);
94117395Skanstatic int gopt_log_file(const char *val);
95117395Skanstatic int gopt_log_options(const char *val);
96117395Skanstatic int gopt_map_options(const char *val);
97117395Skanstatic int gopt_map_type(const char *val);
9890075Sobrienstatic int gopt_mount_type(const char *val);
9990075Sobrienstatic int gopt_pid_file(const char *val);
10090075Sobrienstatic int gopt_portmap_program(const char *val);
10190075Sobrienstatic int gopt_nfs_proto(const char *val);
10290075Sobrienstatic int gopt_nfs_retransmit_counter(const char *val);
10390075Sobrienstatic int gopt_nfs_retry_interval(const char *val);
10490075Sobrienstatic int gopt_nfs_vers(const char *val);
10590075Sobrienstatic int gopt_nis_domain(const char *val);
10690075Sobrienstatic int gopt_normalize_hostnames(const char *val);
10790075Sobrienstatic int gopt_os(const char *val);
10890075Sobrienstatic int gopt_osver(const char *val);
109122180Skanstatic int gopt_plock(const char *val);
11090075Sobrienstatic int gopt_print_pid(const char *val);
11190075Sobrienstatic int gopt_print_version(const char *val);
11296263Sobrienstatic int gopt_restart_mounts(const char *val);
113122180Skanstatic int gopt_search_path(const char *val);
114117395Skanstatic int gopt_selectors_in_defaults(const char *val);
115122180Skanstatic int gopt_show_statfs_entries(const char *val);
116117395Skanstatic int gopt_unmount_on_exit(const char *val);
117122180Skanstatic int gopt_vendor(const char *val);
118117395Skanstatic int process_global_option(const char *key, const char *val);
11996263Sobrienstatic int process_regular_map(cf_map_t *cfm);
12096263Sobrienstatic int process_regular_option(const char *section, const char *key, const char *val, cf_map_t *cfm);
12190075Sobrienstatic int ropt_browsable_dirs(const char *val, cf_map_t *cfm);
122122180Skanstatic int ropt_map_name(const char *val, cf_map_t *cfm);
123122180Skanstatic int ropt_map_options(const char *val, cf_map_t *cfm);
124122180Skanstatic int ropt_map_type(const char *val, cf_map_t *cfm);
125122180Skanstatic int ropt_mount_type(const char *val, cf_map_t *cfm);
126122180Skanstatic int ropt_search_path(const char *val, cf_map_t *cfm);
127122180Skanstatic int ropt_tag(const char *val, cf_map_t *cfm);
128122180Skanstatic void reset_cf_map(cf_map_t *cfm);
12990075Sobrien
13090075Sobrien
13190075Sobrien/*
13290075Sobrien * STATIC VARIABLES:
133 */
134static cf_map_t cur_map;
135static struct _func_map glob_functable[] = {
136  {"arch",			gopt_arch},
137  {"auto_dir",			gopt_auto_dir},
138  {"browsable_dirs",		gopt_browsable_dirs},
139  {"cache_duration",		gopt_cache_duration},
140  {"cluster",			gopt_cluster},
141  {"debug_options",		gopt_debug_options},
142  {"dismount_interval",		gopt_dismount_interval},
143  {"fully_qualified_hosts",	gopt_fully_qualified_hosts},
144  {"full_os",			gopt_full_os},
145  {"hesiod_base",		gopt_hesiod_base},
146  {"karch",			gopt_karch},
147  {"ldap_base",			gopt_ldap_base},
148  {"ldap_cache_maxmem",		gopt_ldap_cache_maxmem},
149  {"ldap_cache_seconds",	gopt_ldap_cache_seconds},
150  {"ldap_hostports",		gopt_ldap_hostports},
151  {"local_domain",		gopt_local_domain},
152  {"log_file",			gopt_log_file},
153  {"log_options",		gopt_log_options},
154  {"map_options",		gopt_map_options},
155  {"map_type",			gopt_map_type},
156  {"mount_type",		gopt_mount_type},
157  {"pid_file",			gopt_pid_file},
158  {"portmap_program",		gopt_portmap_program},
159  {"nfs_proto",			gopt_nfs_proto},
160  {"nfs_retransmit_counter",	gopt_nfs_retransmit_counter},
161  {"nfs_retry_interval",	gopt_nfs_retry_interval},
162  {"nfs_vers",			gopt_nfs_vers},
163  {"nis_domain",		gopt_nis_domain},
164  {"normalize_hostnames",	gopt_normalize_hostnames},
165  {"os",			gopt_os},
166  {"osver",			gopt_osver},
167  {"plock",			gopt_plock},
168  {"print_pid",			gopt_print_pid},
169  {"print_version",		gopt_print_version},
170  {"restart_mounts",		gopt_restart_mounts},
171  {"search_path",		gopt_search_path},
172  {"selectors_on_default",	gopt_selectors_in_defaults},
173  {"selectors_in_defaults",	gopt_selectors_in_defaults},
174  {"show_statfs_entries",	gopt_show_statfs_entries},
175  {"unmount_on_exit",		gopt_unmount_on_exit},
176  {"vendor",			gopt_vendor},
177  {NULL, NULL}
178};
179
180
181/*
182 * Reset a map.
183 */
184static void
185reset_cf_map(cf_map_t *cfm)
186{
187  if (!cfm)
188    return;
189
190  if (cfm->cfm_dir) {
191    XFREE(cfm->cfm_dir);
192    cfm->cfm_dir = NULL;
193  }
194
195  if (cfm->cfm_name) {
196    XFREE(cfm->cfm_name);
197    cfm->cfm_name = NULL;
198  }
199
200  if (cfm->cfm_tag) {
201    XFREE(cfm->cfm_tag);
202    cfm->cfm_tag = NULL;
203  }
204
205  /*
206   * reset/initialize a regular map's flags and other variables from the
207   * global ones, so that they are applied to all maps.  Of course, each map
208   * can then override the flags individually.
209   *
210   * NOTES:
211   * (1): Will only work for maps that appear after [global].
212   * (2): Also be careful not to free() a global option.
213   * (3): I'm doing direct char* pointer comparison, and not strcmp().  This
214   *      is correct!
215   */
216
217  /* initialize map_type from [global] */
218  if (cfm->cfm_type && cfm->cfm_type != gopt.map_type)
219    XFREE(cfm->cfm_type);
220  cfm->cfm_type = gopt.map_type;
221
222  /* initialize map_opts from [global] */
223  if (cfm->cfm_opts && cfm->cfm_opts != gopt.map_options)
224    XFREE(cfm->cfm_opts);
225  cfm->cfm_opts = gopt.map_options;
226
227  /* initialize search_path from [global] */
228  if (cfm->cfm_search_path && cfm->cfm_search_path != gopt.search_path)
229    XFREE(cfm->cfm_search_path);
230  cfm->cfm_search_path = gopt.search_path;
231
232  /*
233   * Initialize flags that are common both to [global] and a local map.
234   */
235  cfm->cfm_flags = gopt.flags & (CFM_BROWSABLE_DIRS |
236				 CFM_BROWSABLE_DIRS_FULL |
237				 CFM_MOUNT_TYPE_AUTOFS |
238				 CFM_SELECTORS_IN_DEFAULTS);
239}
240
241
242/*
243 * Process configuration file options.
244 * Return 0 if OK, 1 otherwise.
245 */
246int
247set_conf_kv(const char *section, const char *key, const char *val)
248{
249  int ret;
250
251#ifdef DEBUG_CONF
252  fprintf(stderr,"set_conf_kv: section=%s, key=%s, val=%s\n",
253	  section, key, val);
254#endif /* DEBUG_CONF */
255
256  /*
257   * If global section, process them one at a time.
258   */
259  if (STREQ(section, "global")) {
260    /*
261     * Check if a regular map was configured before "global",
262     * and process it as needed.
263     */
264    if (cur_map.cfm_dir) {
265      fprintf(stderr,"processing regular map \"%s\" before global one.\n",
266	      section);
267      ret = process_regular_map(&cur_map); /* will reset map */
268      if (ret != 0)
269	return ret;
270    }
271
272    /* process the global option first */
273    ret = process_global_option(key, val);
274
275    /* reset default options for regular maps from just updated globals */
276    if (ret == 0)
277      reset_cf_map(&cur_map);
278
279    /* return status from the processing of the global option */
280    return ret;
281  }
282
283  /*
284   * otherwise save options and process a single map all at once.
285   */
286
287  /* check if we found a new map, so process one already collected */
288  if (cur_map.cfm_dir && !STREQ(cur_map.cfm_dir, section)) {
289    ret = process_regular_map(&cur_map); /* will reset map */
290    if (ret != 0)
291      return ret;
292  }
293
294  /* now process a single entry of a regular map */
295  return process_regular_option(section, key, val, &cur_map);
296}
297
298
299/*
300 * Process global section of configuration file options.
301 * Return 0 upon success, 1 otherwise.
302 */
303static int
304process_global_option(const char *key, const char *val)
305{
306  struct _func_map *gfp;
307
308  /* ensure that val is valid */
309  if (!val || val[0] == '\0')
310    return 1;
311
312  /*
313   * search for global function.
314   */
315  for (gfp = glob_functable; gfp->name; gfp++)
316    if (FSTREQ(gfp->name, key))
317      return (gfp->func)(val);
318
319  fprintf(stderr, "conf: unknown global key: \"%s\"\n", key);
320  return 1;			/* failed to match any command */
321}
322
323
324static int
325gopt_arch(const char *val)
326{
327  gopt.arch = strdup((char *)val);
328  return 0;
329}
330
331
332static int
333gopt_auto_dir(const char *val)
334{
335  gopt.auto_dir = strdup((char *)val);
336  return 0;
337}
338
339
340static int
341gopt_browsable_dirs(const char *val)
342{
343  if (STREQ(val, "full")) {
344    gopt.flags |= CFM_BROWSABLE_DIRS_FULL;
345    return 0;
346  } else if (STREQ(val, "yes")) {
347    gopt.flags |= CFM_BROWSABLE_DIRS;
348    return 0;
349  } else if (STREQ(val, "no")) {
350    gopt.flags &= ~CFM_BROWSABLE_DIRS;
351    return 0;
352  }
353
354  fprintf(stderr, "conf: unknown value to browsable_dirs \"%s\"\n", val);
355  return 1;			/* unknown value */
356}
357
358
359static int
360gopt_cache_duration(const char *val)
361{
362  gopt.am_timeo = atoi(val);
363  if (gopt.am_timeo <= 0)
364    gopt.am_timeo = AM_TTL;
365  return 0;
366}
367
368
369static int
370gopt_cluster(const char *val)
371{
372  gopt.cluster = strdup((char *)val);
373  return 0;
374}
375
376
377static int
378gopt_debug_options(const char *val)
379{
380#ifdef DEBUG
381  usage += debug_option(strdup((char *)val));
382  return 0;
383#else /* not DEBUG */
384  fprintf(stderr, "%s: not compiled with DEBUG option -- sorry.\n",
385	  am_get_progname());
386  return 1;
387#endif /* not DEBUG */
388}
389
390
391static int
392gopt_dismount_interval(const char *val)
393{
394  gopt.am_timeo_w = atoi(val);
395  if (gopt.am_timeo_w <= 0)
396    gopt.am_timeo_w = AM_TTL_W;
397  return 0;
398}
399
400
401static int
402gopt_full_os(const char *val)
403{
404  gopt.op_sys_full = strdup((char *)val);
405  return 0;
406}
407
408
409static int
410gopt_fully_qualified_hosts(const char *val)
411{
412  if (STREQ(val, "yes")) {
413    gopt.flags |= CFM_FULLY_QUALIFIED_HOSTS;
414    return 0;
415  } else if (STREQ(val, "no")) {
416    gopt.flags &= ~CFM_FULLY_QUALIFIED_HOSTS;
417    return 0;
418  }
419
420  fprintf(stderr, "conf: unknown value to fully_qualified_hosts \"%s\"\n", val);
421  return 1;			/* unknown value */
422}
423
424
425static int
426gopt_hesiod_base(const char *val)
427{
428#ifdef HAVE_MAP_HESIOD
429  gopt.hesiod_base = strdup((char *)val);
430  return 0;
431#else /* not HAVE_MAP_HESIOD */
432  fprintf(stderr, "conf: hesiod_base option ignored.  No Hesiod support available.\n");
433  return 1;
434#endif /* not HAVE_MAP_HESIOD */
435}
436
437
438static int
439gopt_karch(const char *val)
440{
441  gopt.karch = strdup((char *)val);
442  return 0;
443}
444
445
446static int
447gopt_pid_file(const char *val)
448{
449  gopt.pid_file = strdup((char *)val);
450  return 0;
451}
452
453
454static int
455gopt_local_domain(const char *val)
456{
457  gopt.sub_domain = strdup((char *)val);
458  return 0;
459}
460
461
462static int
463gopt_ldap_base(const char *val)
464{
465#ifdef HAVE_MAP_LDAP
466  gopt.ldap_base = strdup((char *)val);
467  return 0;
468#else /* not HAVE_MAP_LDAP */
469  fprintf(stderr, "conf: ldap_base option ignored.  No LDAP support available.\n");
470  return 1;
471#endif /* not HAVE_MAP_LDAP */
472}
473
474
475static int
476gopt_ldap_cache_seconds(const char *val)
477{
478#ifdef HAVE_MAP_LDAP
479  char *end;
480
481  gopt.ldap_cache_seconds = strtol((char *)val, &end, 10);
482  if (end == val) {
483    fprintf(stderr, "conf: bad LDAP cache (seconds) option: %s\n",val);
484    return 1;
485  }
486  return 0;
487#else /* not HAVE_MAP_LDAP */
488  fprintf(stderr, "conf: ldap_cache_seconds option ignored.  No LDAP support available.\n");
489  return 1;
490#endif /* not HAVE_MAP_LDAP */
491}
492
493
494static int
495gopt_ldap_cache_maxmem(const char *val)
496{
497#ifdef HAVE_MAP_LDAP
498  char *end;
499
500  gopt.ldap_cache_maxmem = strtol((char *)val, &end, 10);
501  if (end == val) {
502    fprintf(stderr, "conf: bad LDAP cache (maxmem) option: %s\n",val);
503    return 1;
504  }
505  return 0;
506#else /* not HAVE_MAP_LDAP */
507  fprintf(stderr, "conf: ldap_cache_maxmem option ignored.  No LDAP support available.\n");
508  return 1;
509#endif /* not HAVE_MAP_LDAP */
510}
511
512
513static int
514gopt_ldap_hostports(const char *val)
515{
516#ifdef HAVE_MAP_LDAP
517  gopt.ldap_hostports = strdup((char *)val);
518  return 0;
519#else /* not HAVE_MAP_LDAP */
520  fprintf(stderr, "conf: ldap_hostports option ignored.  No LDAP support available.\n");
521  return 1;
522#endif /* not HAVE_MAP_LDAP */
523
524}
525
526
527static int
528gopt_log_file(const char *val)
529{
530  gopt.logfile = strdup((char *)val);
531  return 0;
532}
533
534
535static int
536gopt_log_options(const char *val)
537{
538  usage += switch_option(strdup((char *)val));
539  return 0;
540}
541
542
543static int
544gopt_map_options(const char *val)
545{
546  gopt.map_options = strdup((char *)val);
547  return 0;
548}
549
550
551static int
552gopt_map_type(const char *val)
553{
554  /* check if map type exist */
555  if (!mapc_type_exists(val)) {
556    fprintf(stderr, "conf: no such map type \"%s\"\n", val);
557    return 1;
558  }
559  gopt.map_type = strdup((char *)val);
560  return 0;
561}
562
563
564static int
565gopt_mount_type(const char *val)
566{
567  if (STREQ(val, "autofs")) {
568    fprintf(stderr, "conf: no autofs support available, turning it off\n");
569    gopt.flags &= ~CFM_MOUNT_TYPE_AUTOFS;
570    return 0;
571  } else if (STREQ(val, "nfs")) {
572    gopt.flags &= ~CFM_MOUNT_TYPE_AUTOFS;
573    return 0;
574  }
575
576  fprintf(stderr, "conf: unknown value to mount_type \"%s\"\n", val);
577  return 1;			/* unknown value */
578}
579
580
581static int
582gopt_portmap_program(const char *val)
583{
584  gopt.portmap_program = atoi(val);
585  /*
586   * allow alternate program numbers to be no more than 10 offset from
587   * official amd program number (300019).
588   */
589  if (gopt.portmap_program < AMQ_PROGRAM ||
590      gopt.portmap_program > AMQ_PROGRAM + 10) {
591    gopt.portmap_program = AMQ_PROGRAM;
592    set_amd_program_number(gopt.portmap_program);
593    fprintf(stderr, "conf: illegal amd program number \"%s\"\n", val);
594    return 1;
595  }
596
597  set_amd_program_number(gopt.portmap_program);
598  return 0;			/* all is OK */
599}
600
601
602static int
603gopt_nfs_proto(const char *val)
604{
605  if (STREQ(val, "udp") || STREQ(val, "tcp")) {
606    gopt.nfs_proto = strdup((char *)val);
607    return 0;
608  }
609  fprintf(stderr, "conf: illegal nfs_proto \"%s\"\n", val);
610  return 1;
611}
612
613
614static int
615gopt_nfs_retransmit_counter(const char *val)
616{
617  gopt.amfs_auto_retrans = atoi(val);
618  return 0;
619}
620
621
622static int
623gopt_nfs_retry_interval(const char *val)
624{
625  gopt.amfs_auto_timeo = atoi(val);
626  return 0;
627}
628
629
630static int
631gopt_nfs_vers(const char *val)
632{
633  int i = atoi(val);
634
635  if (i == 2 || i == 3) {
636    gopt.nfs_vers = i;
637    return 0;
638  }
639  fprintf(stderr, "conf: illegal nfs_vers \"%s\"\n", val);
640  return 1;
641}
642
643
644static int
645gopt_nis_domain(const char *val)
646{
647#ifdef HAVE_MAP_NIS
648  gopt.nis_domain = strdup((char *)val);
649  return 0;
650#else /* not HAVE_MAP_NIS */
651  fprintf(stderr, "conf: nis_domain option ignored.  No NIS support available.\n");
652  return 1;
653#endif /* not HAVE_MAP_NIS */
654}
655
656
657static int
658gopt_normalize_hostnames(const char *val)
659{
660  if (STREQ(val, "yes")) {
661    gopt.flags |= CFM_NORMALIZE_HOSTNAMES;
662    return 0;
663  } else if (STREQ(val, "no")) {
664    gopt.flags &= ~CFM_NORMALIZE_HOSTNAMES;
665    return 0;
666  }
667
668  fprintf(stderr, "conf: unknown value to normalize_hostnames \"%s\"\n", val);
669  return 1;			/* unknown value */
670}
671
672
673static int
674gopt_os(const char *val)
675{
676  gopt.op_sys = strdup((char *)val);
677  return 0;
678}
679
680
681static int
682gopt_osver(const char *val)
683{
684  gopt.op_sys_ver = strdup((char *)val);
685  return 0;
686}
687
688
689static int
690gopt_plock(const char *val)
691{
692  if (STREQ(val, "yes")) {
693    gopt.flags |= CFM_PROCESS_LOCK;
694    return 0;
695  } else if (STREQ(val, "no")) {
696    gopt.flags &= ~CFM_PROCESS_LOCK;
697    return 0;
698  }
699
700  fprintf(stderr, "conf: unknown value to plock \"%s\"\n", val);
701  return 1;			/* unknown value */
702}
703
704
705static int
706gopt_print_pid(const char *val)
707{
708  if (STREQ(val, "yes")) {
709    gopt.flags |= CFM_PRINT_PID;
710    return 0;
711  } else if (STREQ(val, "no")) {
712    gopt.flags &= ~CFM_PRINT_PID;
713    return 0;
714  }
715
716  fprintf(stderr, "conf: unknown value to print_pid \"%s\"\n", val);
717  return 1;			/* unknown value */
718}
719
720
721static int
722gopt_print_version(const char *val)
723{
724  if (STREQ(val, "yes")) {
725    fputs(get_version_string(), stderr);
726    return 0;
727  } else if (STREQ(val, "no")) {
728    return 0;
729  }
730
731  fprintf(stderr, "conf: unknown value to print_version \"%s\"\n", val);
732  return 1;			/* unknown value */
733}
734
735
736static int
737gopt_restart_mounts(const char *val)
738{
739  if (STREQ(val, "yes")) {
740    gopt.flags |= CFM_RESTART_EXISTING_MOUNTS;
741    return 0;
742  } else if (STREQ(val, "no")) {
743    gopt.flags &= ~CFM_RESTART_EXISTING_MOUNTS;
744    return 0;
745  }
746
747  fprintf(stderr, "conf: unknown value to restart_mounts \"%s\"\n", val);
748  return 1;			/* unknown value */
749}
750
751
752static int
753gopt_search_path(const char *val)
754{
755  gopt.search_path = strdup((char *)val);
756  return 0;
757}
758
759
760static int
761gopt_selectors_in_defaults(const char *val)
762{
763  if (STREQ(val, "yes")) {
764    gopt.flags |= CFM_SELECTORS_IN_DEFAULTS;
765    return 0;
766  } else if (STREQ(val, "no")) {
767    gopt.flags &= ~CFM_SELECTORS_IN_DEFAULTS;
768    return 0;
769  }
770
771  fprintf(stderr, "conf: unknown value to enable_default_selectors \"%s\"\n", val);
772  return 1;			/* unknown value */
773}
774
775
776static int
777gopt_show_statfs_entries(const char *val)
778{
779  if (STREQ(val, "yes")) {
780    gopt.flags |= CFM_SHOW_STATFS_ENTRIES;
781    return 0;
782  } else if (STREQ(val, "no")) {
783    gopt.flags &= ~CFM_SHOW_STATFS_ENTRIES;
784    return 0;
785  }
786
787  fprintf(stderr, "conf: unknown value to show_statfs_entries \"%s\"\n", val);
788  return 1;			/* unknown value */
789}
790
791
792static int
793gopt_unmount_on_exit(const char *val)
794{
795  if (STREQ(val, "yes")) {
796    gopt.flags |= CFM_UNMOUNT_ON_EXIT;
797    return 0;
798  } else if (STREQ(val, "no")) {
799    gopt.flags &= ~CFM_UNMOUNT_ON_EXIT;
800    return 0;
801  }
802
803  fprintf(stderr, "conf: unknown value to unmount_on_exit \"%s\"\n", val);
804  return 1;			/* unknown value */
805}
806
807
808static int
809gopt_vendor(const char *val)
810{
811  gopt.op_sys_vendor = strdup((char *)val);
812  return 0;
813}
814
815
816/*
817 * Collect one entry for a regular map
818 */
819static int
820process_regular_option(const char *section, const char *key, const char *val, cf_map_t *cfm)
821{
822  /* ensure that val is valid */
823  if (!section || section[0] == '\0' ||
824      !key || key[0] == '\0' ||
825      !val || val[0] == '\0' ||
826      !cfm) {
827    fprintf(stderr, "conf: process_regular_option: null entries\n");
828    return 1;
829  }
830
831  /* check if initializing a new map */
832  if (!cfm->cfm_dir)
833    cfm->cfm_dir = strdup((char *)section);
834
835  /* check for each possible field */
836  if (STREQ(key, "browsable_dirs"))
837    return ropt_browsable_dirs(val, cfm);
838
839  if (STREQ(key, "map_name"))
840    return ropt_map_name(val, cfm);
841
842  if (STREQ(key, "map_options"))
843    return ropt_map_options(val, cfm);
844
845  if (STREQ(key, "map_type"))
846    return ropt_map_type(val, cfm);
847
848  if (STREQ(key, "mount_type"))
849    return ropt_mount_type(val, cfm);
850
851  if (STREQ(key, "search_path"))
852    return ropt_search_path(val, cfm);
853
854  if (STREQ(key, "tag"))
855    return ropt_tag(val, cfm);
856
857  fprintf(stderr, "conf: unknown regular key \"%s\" for section \"%s\"\n",
858	  key, section);
859  return 1;			/* failed to match any command */
860}
861
862
863static int
864ropt_browsable_dirs(const char *val, cf_map_t *cfm)
865{
866  if (STREQ(val, "full")) {
867    cfm->cfm_flags |= CFM_BROWSABLE_DIRS_FULL;
868    return 0;
869  } else if (STREQ(val, "yes")) {
870    cfm->cfm_flags |= CFM_BROWSABLE_DIRS;
871    return 0;
872  } else if (STREQ(val, "no")) {
873    cfm->cfm_flags &= ~CFM_BROWSABLE_DIRS;
874    return 0;
875  }
876
877  fprintf(stderr, "conf: unknown value to browsable_dirs \"%s\"\n", val);
878  return 1;			/* unknown value */
879}
880
881
882static int
883ropt_map_name(const char *val, cf_map_t *cfm)
884{
885  cfm->cfm_name = strdup((char *)val);
886  return 0;
887}
888
889
890static int
891ropt_map_options(const char *val, cf_map_t *cfm)
892{
893  cfm->cfm_opts = strdup((char *)val);
894  return 0;
895}
896
897
898static int
899ropt_map_type(const char *val, cf_map_t *cfm)
900{
901  /* check if map type exist */
902  if (!mapc_type_exists(val)) {
903    fprintf(stderr, "conf: no such map type \"%s\"\n", val);
904    return 1;
905  }
906  cfm->cfm_type = strdup((char *)val);
907  return 0;
908}
909
910
911static int
912ropt_mount_type(const char *val, cf_map_t *cfm)
913{
914  if (STREQ(val, "autofs")) {
915    fprintf(stderr, "conf: no autofs support available, turning it off\n");
916    cfm->cfm_flags &= ~CFM_MOUNT_TYPE_AUTOFS;
917    return 0;
918  } else if (STREQ(val, "nfs")) {
919    cfm->cfm_flags &= ~CFM_MOUNT_TYPE_AUTOFS;
920    return 0;
921  }
922
923  fprintf(stderr, "conf: unknown value to mount_type \"%s\"\n", val);
924  return 1;			/* unknown value */
925}
926
927
928static int
929ropt_search_path(const char *val, cf_map_t *cfm)
930{
931  cfm->cfm_search_path = strdup((char *)val);
932  return 0;
933}
934
935
936static int
937ropt_tag(const char *val, cf_map_t *cfm)
938{
939  cfm->cfm_tag = strdup((char *)val);
940  return 0;
941}
942
943
944/*
945 * Process one collected map.
946 */
947static int
948process_regular_map(cf_map_t *cfm)
949{
950
951  if (!cfm->cfm_name) {
952    fprintf(stderr, "conf: map_name must be defined for map \"%s\"\n", cfm->cfm_dir);
953    return 1;
954  }
955  /*
956   * If map has no tag defined, process the map.
957   * If no conf_tag was set in amd -T, process all untagged entries.
958   * If a tag is defined, then process it only if it matches the map tag.
959   */
960  if (!cfm->cfm_tag ||
961      (conf_tag && STREQ(cfm->cfm_tag, conf_tag))) {
962#ifdef DEBUG_CONF
963    fprintf(stderr, "processing map %s (flags=0x%x)...\n",
964	    cfm->cfm_dir, cfm->cfm_flags);
965#endif /* DEBUG_CONF */
966    root_newmap(cfm->cfm_dir,
967		cfm->cfm_opts ? cfm->cfm_opts : "",
968		cfm->cfm_name,
969		cfm);
970  } else {
971    fprintf(stderr, "skipping map %s...\n", cfm->cfm_dir);
972  }
973
974  reset_cf_map(cfm);
975  return 0;
976}
977
978
979/*
980 * Process last map in conf file (if any)
981 */
982int
983process_last_regular_map(void)
984{
985  /*
986   * If the amd.conf file only has a [global] section (pretty useless
987   * IMHO), do not try to process a map that does not exist.
988   */
989  if (!cur_map.cfm_dir)
990    return 0;
991  return process_regular_map(&cur_map);
992}
993