Code

Include config.h in source files.
[sysdb.git] / src / tools / sysdbd / configfile.c
1 /*
2  * SysDB - src/tools/sysdbd/configfile.c
3  * Copyright (C) 2012 Sebastian 'tokkee' Harl <sh@tokkee.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
28 #if HAVE_CONFIG_H
29 #       include "config.h"
30 #endif /* HAVE_CONFIG_H */
32 #include "tools/sysdbd/configfile.h"
34 #include "sysdb.h"
35 #include "core/plugin.h"
36 #include "core/time.h"
37 #include "utils/error.h"
39 #include "liboconfig/oconfig.h"
40 #include "liboconfig/utils.h"
42 #include <assert.h>
43 #include <errno.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <strings.h>
49 /*
50  * Parser error values:
51  *  - Values less than zero indicate an error in the daemon or libsysdb.
52  *  - Zero indicates success.
53  *  - Any other values indicate parsing errors.
54  */
56 enum {
57         ERR_UNKNOWN_OPTION = 1,
58         ERR_UNKNOWN_ARG    = 2,
59         ERR_INVALID_ARG    = 3,
60         ERR_PARSE_FAILED   = 4,
61 };
63 /*
64  * private variables
65  */
67 static sdb_time_t default_interval = 0;
69 /*
70  * private helper functions
71  */
73 static int
74 config_get_interval(oconfig_item_t *ci, sdb_time_t *interval)
75 {
76         double interval_dbl = 0.0;
78         assert(ci && interval);
80         if (oconfig_get_number(ci, &interval_dbl)) {
81                 sdb_log(SDB_LOG_ERR, "config: Interval requires "
82                                 "a single numeric argument\n"
83                                 "\tUsage: Interval SECONDS");
84                 return ERR_INVALID_ARG;
85         }
87         if (interval_dbl <= 0.0) {
88                 sdb_log(SDB_LOG_ERR, "config: Invalid interval: %f\n"
89                                 "\tInterval may not be less than or equal to zero.",
90                                 interval_dbl);
91                 return ERR_INVALID_ARG;
92         }
94         *interval = DOUBLE_TO_SDB_TIME(interval_dbl);
95         return 0;
96 } /* config_get_interval */
98 /*
99  * public parse results
100  */
102 char **listen_addresses = NULL;
103 size_t listen_addresses_num = 0;
105 /*
106  * token parser
107  */
109 typedef struct {
110         char *name;
111         int (*dispatcher)(oconfig_item_t *);
112 } token_parser_t;
114 static int
115 daemon_add_listener(oconfig_item_t *ci)
117         char **tmp;
118         char *address;
120         if (oconfig_get_string(ci, &address)) {
121                 sdb_log(SDB_LOG_ERR, "config: Listen requires a single "
122                                 "string argument\n"
123                                 "\tUsage: Listen ADDRESS");
124                 return ERR_INVALID_ARG;
125         }
127         tmp = realloc(listen_addresses,
128                         (listen_addresses_num + 1) * sizeof(*listen_addresses));
129         if (! tmp) {
130                 char buf[1024];
131                 sdb_log(SDB_LOG_ERR, "config: Failed to allocate memory: %s",
132                                 sdb_strerror(errno, buf, sizeof(buf)));
133                 return -1;
134         }
136         listen_addresses = tmp;
137         listen_addresses[listen_addresses_num] = strdup(address);
138         if (! listen_addresses[listen_addresses_num]) {
139                 char buf[1024];
140                 sdb_log(SDB_LOG_ERR, "config: Failed to allocate memory: %s",
141                                 sdb_strerror(errno, buf, sizeof(buf)));
142                 return -1;
143         }
145         ++listen_addresses_num;
146         return 0;
147 } /* daemon_add_listener */
149 static int
150 daemon_set_interval(oconfig_item_t *ci)
152         return config_get_interval(ci, &default_interval);
153 } /* daemon_set_interval */
155 static int
156 daemon_load_plugin(oconfig_item_t *ci)
158         char *name;
159         int i;
161         if (oconfig_get_string(ci, &name)) {
162                 sdb_log(SDB_LOG_ERR, "config: LoadPlugin requires a single "
163                                 "string argument\n"
164                                 "\tUsage: LoadPlugin PLUGIN");
165                 return ERR_INVALID_ARG;
166         }
168         for (i = 0; i < ci->children_num; ++i) {
169                 oconfig_item_t *child = ci->children + i;
171                 /* we don't currently support any options */
172                 sdb_log(SDB_LOG_WARNING, "config: Unknown option '%s' "
173                                 "inside 'LoadPlugin' -- see the documentation for "
174                                 "details.", child->key);
175                 continue;
176         }
178         /* returns a negative value on error */
179         return sdb_plugin_load(name, NULL);
180 } /* daemon_load_plugin */
182 static int
183 daemon_load_backend(oconfig_item_t *ci)
185         sdb_plugin_ctx_t ctx = SDB_PLUGIN_CTX_INIT;
187         char  plugin_name[1024];
188         char *name;
190         int i;
192         ctx.interval = default_interval;
194         if (oconfig_get_string(ci, &name)) {
195                 sdb_log(SDB_LOG_ERR, "config: LoadBackend requires a single "
196                                 "string argument\n"
197                                 "\tUsage: LoadBackend BACKEND");
198                 return ERR_INVALID_ARG;
199         }
201         snprintf(plugin_name, sizeof(plugin_name), "backend::%s", name);
203         for (i = 0; i < ci->children_num; ++i) {
204                 oconfig_item_t *child = ci->children + i;
206                 if (! strcasecmp(child->key, "Interval")) {
207                         if (config_get_interval(child, &ctx.interval))
208                                 return ERR_INVALID_ARG;
209                 }
210                 else {
211                         sdb_log(SDB_LOG_WARNING, "config: Unknown option '%s' "
212                                         "inside 'LoadBackend' -- see the documentation for "
213                                         "details.", child->key);
214                         continue;
215                 }
216         }
218         return sdb_plugin_load(plugin_name, &ctx);
219 } /* daemon_load_backend */
221 static int
222 daemon_configure_plugin(oconfig_item_t *ci)
224         char *name;
226         assert(ci);
228         if (oconfig_get_string(ci, &name)) {
229                 sdb_log(SDB_LOG_ERR, "config: %s requires a single "
230                                 "string argument\n"
231                                 "\tUsage: LoadBackend BACKEND",
232                                 ci->key);
233                 return ERR_INVALID_ARG;
234         }
236         return sdb_plugin_configure(name, ci);
237 } /* daemon_configure_backend */
239 static token_parser_t token_parser_list[] = {
240         { "Listen", daemon_add_listener },
241         { "Interval", daemon_set_interval },
242         { "LoadPlugin", daemon_load_plugin },
243         { "LoadBackend", daemon_load_backend },
244         { "Backend", daemon_configure_plugin },
245         { "Plugin", daemon_configure_plugin },
246         { NULL, NULL },
247 };
249 /*
250  * public API
251  */
253 int
254 daemon_parse_config(const char *filename)
256         oconfig_item_t *ci;
257         int retval = 0, i;
259         ci = oconfig_parse_file(filename);
260         if (! ci)
261                 return ERR_PARSE_FAILED;
263         for (i = 0; i < ci->children_num; ++i) {
264                 oconfig_item_t *child = ci->children + i;
265                 int status = ERR_UNKNOWN_OPTION, j;
267                 for (j = 0; token_parser_list[j].name; ++j) {
268                         if (! strcasecmp(token_parser_list[j].name, child->key))
269                                 status = token_parser_list[j].dispatcher(child);
270                 }
272                 if (status) {
273                         sdb_error_set("config: Failed to parse option '%s'\n",
274                                         child->key);
275                         if (status == ERR_UNKNOWN_OPTION)
276                                 sdb_error_append("\tUnknown option '%s' -- "
277                                                 "see the documentation for details\n",
278                                                 child->key);
279                         sdb_error_chomp();
280                         sdb_error_log(SDB_LOG_ERR);
281                         retval = status;
282                 }
283         }
284         return retval;
285 } /* daemon_parse_config */
287 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */