91746b10267cab4e304f0f1eb3a98b64a6c8eb0d
1 /*
2 * SysDB - src/daemon/config.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 #include "sysdb.h"
29 #include "core/plugin.h"
30 #include "core/error.h"
31 #include "core/time.h"
33 #include "daemon/config.h"
35 #include "liboconfig/oconfig.h"
36 #include "liboconfig/utils.h"
38 #include <assert.h>
39 #include <strings.h>
41 /*
42 * Parser error values:
43 * - Values less than zero indicate an error in the daemon or libsysdb.
44 * - Zero indicates success.
45 * - Any other values indicate parsing errors.
46 */
48 enum {
49 ERR_UNKNOWN_OPTION = 1,
50 ERR_UNKNOWN_ARG = 2,
51 ERR_INVALID_ARG = 3,
52 ERR_PARSE_FAILED = 4,
53 };
55 /*
56 * private variables
57 */
59 static sdb_time_t default_interval = 0;
61 /*
62 * private helper functions
63 */
65 static int
66 config_get_interval(oconfig_item_t *ci, sdb_time_t *interval)
67 {
68 double interval_dbl = 0.0;
70 assert(ci && interval);
72 if (oconfig_get_number(ci, &interval_dbl)) {
73 sdb_log(SDB_LOG_ERR, "config: Interval requires "
74 "a single numeric argument\n"
75 "\tUsage: Interval SECONDS");
76 return ERR_INVALID_ARG;
77 }
79 if (interval_dbl <= 0.0) {
80 sdb_log(SDB_LOG_ERR, "config: Invalid interval: %f\n"
81 "\tInterval may not be less than or equal to zero.",
82 interval_dbl);
83 return ERR_INVALID_ARG;
84 }
86 *interval = DOUBLE_TO_SDB_TIME(interval_dbl);
87 return 0;
88 } /* config_get_interval */
90 /*
91 * token parser
92 */
94 typedef struct {
95 char *name;
96 int (*dispatcher)(oconfig_item_t *);
97 } token_parser_t;
99 static int
100 daemon_set_interval(oconfig_item_t *ci)
101 {
102 return config_get_interval(ci, &default_interval);
103 } /* daemon_set_interval */
105 static int
106 daemon_load_plugin(oconfig_item_t *ci)
107 {
108 char *name;
109 int i;
111 if (oconfig_get_string(ci, &name)) {
112 sdb_log(SDB_LOG_ERR, "config: LoadPlugin requires a single "
113 "string argument\n"
114 "\tUsage: LoadPlugin PLUGIN");
115 return ERR_INVALID_ARG;
116 }
118 for (i = 0; i < ci->children_num; ++i) {
119 oconfig_item_t *child = ci->children + i;
121 /* we don't currently support any options */
122 sdb_log(SDB_LOG_WARNING, "config: Unknown option '%s' "
123 "inside 'LoadPlugin' -- see the documentation for "
124 "details.", child->key);
125 continue;
126 }
128 /* returns a negative value on error */
129 return sdb_plugin_load(name, NULL);
130 } /* daemon_load_plugin */
132 static int
133 daemon_load_backend(oconfig_item_t *ci)
134 {
135 sdb_plugin_ctx_t ctx = SDB_PLUGIN_CTX_INIT;
137 char plugin_name[1024];
138 char *name;
140 int i;
142 ctx.interval = default_interval;
144 if (oconfig_get_string(ci, &name)) {
145 sdb_log(SDB_LOG_ERR, "config: LoadBackend requires a single "
146 "string argument\n"
147 "\tUsage: LoadBackend BACKEND");
148 return ERR_INVALID_ARG;
149 }
151 snprintf(plugin_name, sizeof(plugin_name), "backend::%s", name);
153 for (i = 0; i < ci->children_num; ++i) {
154 oconfig_item_t *child = ci->children + i;
156 if (! strcasecmp(child->key, "Interval")) {
157 if (config_get_interval(child, &ctx.interval))
158 return ERR_INVALID_ARG;
159 }
160 else {
161 sdb_log(SDB_LOG_WARNING, "config: Unknown option '%s' "
162 "inside 'LoadBackend' -- see the documentation for "
163 "details.", child->key);
164 continue;
165 }
166 }
168 return sdb_plugin_load(plugin_name, &ctx);
169 } /* daemon_load_backend */
171 static int
172 daemon_configure_plugin(oconfig_item_t *ci)
173 {
174 char *name;
176 assert(ci);
178 if (oconfig_get_string(ci, &name)) {
179 sdb_log(SDB_LOG_ERR, "config: %s requires a single "
180 "string argument\n"
181 "\tUsage: LoadBackend BACKEND",
182 ci->key);
183 return ERR_INVALID_ARG;
184 }
186 return sdb_plugin_configure(name, ci);
187 } /* daemon_configure_backend */
189 static token_parser_t token_parser_list[] = {
190 { "Interval", daemon_set_interval },
191 { "LoadPlugin", daemon_load_plugin },
192 { "LoadBackend", daemon_load_backend },
193 { "Backend", daemon_configure_plugin },
194 { "Plugin", daemon_configure_plugin },
195 { NULL, NULL },
196 };
198 /*
199 * public API
200 */
202 int
203 daemon_parse_config(const char *filename)
204 {
205 oconfig_item_t *ci;
206 int retval = 0, i;
208 ci = oconfig_parse_file(filename);
209 if (! ci)
210 return ERR_PARSE_FAILED;
212 for (i = 0; i < ci->children_num; ++i) {
213 oconfig_item_t *child = ci->children + i;
214 int status = ERR_UNKNOWN_OPTION, j;
216 for (j = 0; token_parser_list[j].name; ++j) {
217 if (! strcasecmp(token_parser_list[j].name, child->key))
218 status = token_parser_list[j].dispatcher(child);
219 }
221 if (status) {
222 sdb_error_set("config: Failed to parse option '%s'\n",
223 child->key);
224 if (status == ERR_UNKNOWN_OPTION)
225 sdb_error_append("\tUnknown option '%s' -- "
226 "see the documentation for details\n",
227 child->key);
228 sdb_error_chomp();
229 sdb_error_log(SDB_LOG_ERR);
230 retval = status;
231 }
232 }
233 return retval;
234 } /* daemon_parse_config */
236 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */