]> mj.ucw.cz Git - libucw.git/blob - ucw/conf-getopt.c
Conf: Split off everything related to cf_getopt()
[libucw.git] / ucw / conf-getopt.c
1 /*
2  *      UCW Library -- Configuration files: getopt wrapper
3  *
4  *      (c) 2001--2006 Robert Spalek <robert@ucw.cz>
5  *      (c) 2003--2012 Martin Mares <mj@ucw.cz>
6  *
7  *      This software may be freely distributed and used according to the terms
8  *      of the GNU Lesser General Public License.
9  */
10
11 #include <ucw/lib.h>
12 #include <ucw/conf.h>
13 #include <ucw/conf-internal.h>
14 #include <ucw/getopt.h>
15 #include <ucw/fastbuf.h>
16
17 #include <stdlib.h>
18
19 #ifndef CONFIG_UCW_DEFAULT_CONFIG
20 #define CONFIG_UCW_DEFAULT_CONFIG NULL
21 #endif
22 char *cf_def_file = CONFIG_UCW_DEFAULT_CONFIG;
23
24 #ifndef CONFIG_UCW_ENV_VAR_CONFIG
25 #define CONFIG_UCW_ENV_VAR_CONFIG NULL
26 #endif
27 char *cf_env_file = CONFIG_UCW_ENV_VAR_CONFIG;
28
29 static void
30 load_default(struct cf_context *cc)
31 {
32   if (cc->config_loaded++)
33     return;
34   if (cf_def_file)
35     {
36       char *env;
37       if (cf_env_file && (env = getenv(cf_env_file)))
38         {
39           if (cf_load(env))
40             die("Cannot load config file %s", env);
41         }
42       else if (cf_load(cf_def_file))
43         die("Cannot load default config %s", cf_def_file);
44     }
45   else
46     {
47       // We need to create an empty pool and initialize all configuration items
48       struct cf_journal_item *oldj = cf_journal_new_transaction(1);
49       cf_init_stack(cc);
50       cf_done_stack(cc);
51       cf_journal_commit_transaction(1, oldj);
52     }
53 }
54
55 static void
56 final_commit(struct cf_context *cc)
57 {
58   if (cc->postpone_commit)
59     {
60       cc->postpone_commit = 0;
61       if (cf_done_stack(cc))
62         die("Cannot commit after the initialization");
63     }
64 }
65
66 int
67 cf_getopt(int argc, char *const argv[], const char *short_opts, const struct option *long_opts, int *long_index)
68 {
69   struct cf_context *cc = cf_get_context();
70   cc->postpone_commit = 1;
71
72   while (1)
73     {
74       int res = getopt_long(argc, argv, short_opts, long_opts, long_index);
75       if (res == 'S' || res == 'C' || res == 0x64436667)
76         {
77           if (cc->other_options)
78             die("The -S and -C options must precede all other arguments");
79           if (res == 'S')
80             {
81               load_default(cc);
82               if (cf_set(optarg))
83                 die("Cannot set %s", optarg);
84             }
85           else if (res == 'C')
86             {
87               if (cf_load(optarg))
88                 die("Cannot load config file %s", optarg);
89             }
90 #ifdef CONFIG_UCW_DEBUG
91           else
92             {                   /* --dumpconfig */
93               load_default(cc);
94               final_commit(cc);
95               struct fastbuf *b = bfdopen(1, 4096);
96               cf_dump_sections(b);
97               bclose(b);
98               exit(0);
99             }
100 #endif
101         }
102       else
103         {
104           /* unhandled option or end of options */
105           if (res != ':' && res != '?')
106             {
107               load_default(cc);
108               final_commit(cc);
109             }
110           cc->other_options++;
111           return res;
112         }
113     }
114 }