1 |
/* |
---|
2 |
* Copyright (c) 2007, OmniTI Computer Consulting, Inc. |
---|
3 |
* All rights reserved. |
---|
4 |
*/ |
---|
5 |
|
---|
6 |
#include "noit_defines.h" |
---|
7 |
|
---|
8 |
#include <stdio.h> |
---|
9 |
#include <unistd.h> |
---|
10 |
#include <fcntl.h> |
---|
11 |
#include <errno.h> |
---|
12 |
#include <assert.h> |
---|
13 |
#include <libxml/parser.h> |
---|
14 |
#include <libxml/tree.h> |
---|
15 |
#include <libxml/xpath.h> |
---|
16 |
|
---|
17 |
#include "noit_conf.h" |
---|
18 |
#include "noit_check.h" |
---|
19 |
#include "noit_console.h" |
---|
20 |
#include "utils/noit_hash.h" |
---|
21 |
#include "utils/noit_log.h" |
---|
22 |
|
---|
23 |
/* tmp hash impl, replace this with something nice */ |
---|
24 |
static noit_hash_table _tmp_config = NOIT_HASH_EMPTY; |
---|
25 |
static xmlDocPtr master_config = NULL; |
---|
26 |
static char master_config_file[PATH_MAX] = ""; |
---|
27 |
static xmlXPathContextPtr xpath_ctxt = NULL; |
---|
28 |
|
---|
29 |
static noit_hash_table _compiled_fallback = NOIT_HASH_EMPTY; |
---|
30 |
static struct { |
---|
31 |
const char *key; |
---|
32 |
const char *val; |
---|
33 |
} config_info[] = { |
---|
34 |
/* |
---|
35 |
* These are compile-time fallbacks to be used in the event |
---|
36 |
* that the current running config does not have values for |
---|
37 |
* these config paths. |
---|
38 |
* |
---|
39 |
* PLEASE: keep them alphabetically sorted. |
---|
40 |
*/ |
---|
41 |
{ "/%s/eventer/@implementation", DEFAULT_EVENTER }, |
---|
42 |
{ "/%s/modules/@directory", MODULES_DIR }, |
---|
43 |
|
---|
44 |
{ NULL, NULL } |
---|
45 |
}; |
---|
46 |
|
---|
47 |
void noit_conf_xml_error_func(void *ctx, const char *format, ...) { |
---|
48 |
struct timeval __now; |
---|
49 |
noit_log_stream_t ls = ctx; |
---|
50 |
va_list arg; |
---|
51 |
if(!ls) return; |
---|
52 |
va_start(arg, format); |
---|
53 |
gettimeofday(&__now, NULL); |
---|
54 |
noit_vlog(ls, &__now, __FILE__, __LINE__, format, arg); |
---|
55 |
va_end(arg); |
---|
56 |
} |
---|
57 |
void noit_conf_xml_error_ext_func(void *ctx, xmlErrorPtr err) { |
---|
58 |
struct timeval __now; |
---|
59 |
noit_log_stream_t ls = ctx; |
---|
60 |
if(!ls) return; |
---|
61 |
gettimeofday(&__now, NULL); |
---|
62 |
if(err->file) |
---|
63 |
noit_log(ls, &__now, err->file, err->line, |
---|
64 |
"XML error [%d/%d] in %s on line %d %s\n", |
---|
65 |
err->domain, err->code, err->file, err->line, err->message); |
---|
66 |
else |
---|
67 |
noit_log(ls, &__now, err->file, err->line, |
---|
68 |
"XML error [%d/%d] %s\n", |
---|
69 |
err->domain, err->code, err->message); |
---|
70 |
} |
---|
71 |
void noit_conf_init(const char *toplevel) { |
---|
72 |
int i; |
---|
73 |
char keystr[256]; |
---|
74 |
xmlSetGenericErrorFunc(noit_error, noit_conf_xml_error_func); |
---|
75 |
xmlSetStructuredErrorFunc(noit_error, noit_conf_xml_error_ext_func); |
---|
76 |
for(i = 0; config_info[i].key != NULL; i++) { |
---|
77 |
snprintf(keystr, sizeof(keystr), config_info[i].key, toplevel); |
---|
78 |
noit_hash_store(&_compiled_fallback, |
---|
79 |
strdup(keystr), strlen(keystr), |
---|
80 |
(void *)strdup(config_info[i].val)); |
---|
81 |
} |
---|
82 |
xmlKeepBlanksDefault(0); |
---|
83 |
xmlInitParser(); |
---|
84 |
xmlXPathInit(); |
---|
85 |
} |
---|
86 |
|
---|
87 |
int noit_conf_load(const char *path) { |
---|
88 |
xmlDocPtr new_config; |
---|
89 |
new_config = xmlParseFile(path); |
---|
90 |
if(new_config) { |
---|
91 |
if(master_config) xmlFreeDoc(master_config); |
---|
92 |
if(xpath_ctxt) xmlXPathFreeContext(xpath_ctxt); |
---|
93 |
|
---|
94 |
master_config = new_config; |
---|
95 |
xpath_ctxt = xmlXPathNewContext(master_config); |
---|
96 |
if(path != master_config_file) realpath(path, master_config_file); |
---|
97 |
return 0; |
---|
98 |
} |
---|
99 |
return -1; |
---|
100 |
} |
---|
101 |
int noit_conf_xml_xpath(xmlDocPtr *mc, xmlXPathContextPtr *xp) { |
---|
102 |
if(mc) *mc = master_config; |
---|
103 |
if(xp) *xp = xpath_ctxt; |
---|
104 |
return 0; |
---|
105 |
} |
---|
106 |
int noit_conf_save(const char *path) { |
---|
107 |
return -1; |
---|
108 |
} |
---|
109 |
|
---|
110 |
void noit_conf_get_elements_into_hash(noit_conf_section_t section, |
---|
111 |
const char *path, |
---|
112 |
noit_hash_table *table) { |
---|
113 |
int i, cnt; |
---|
114 |
xmlXPathObjectPtr pobj = NULL; |
---|
115 |
xmlXPathContextPtr current_ctxt; |
---|
116 |
xmlNodePtr current_node = (xmlNodePtr)section; |
---|
117 |
xmlNodePtr node; |
---|
118 |
|
---|
119 |
current_ctxt = xpath_ctxt; |
---|
120 |
if(current_node) { |
---|
121 |
current_ctxt = xmlXPathNewContext(master_config); |
---|
122 |
current_ctxt->node = current_node; |
---|
123 |
} |
---|
124 |
pobj = xmlXPathEval((xmlChar *)path, current_ctxt); |
---|
125 |
if(!pobj) goto out; |
---|
126 |
if(pobj->type != XPATH_NODESET) goto out; |
---|
127 |
if(xmlXPathNodeSetIsEmpty(pobj->nodesetval)) goto out; |
---|
128 |
cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); |
---|
129 |
for(i=0; i<cnt; i++) { |
---|
130 |
char *value; |
---|
131 |
node = xmlXPathNodeSetItem(pobj->nodesetval, i); |
---|
132 |
value = (char *)xmlXPathCastNodeToString(node); |
---|
133 |
noit_hash_replace(table, |
---|
134 |
strdup((char *)node->name), strlen((char *)node->name), |
---|
135 |
strdup(value), free, free); |
---|
136 |
} |
---|
137 |
out: |
---|
138 |
if(pobj) xmlXPathFreeObject(pobj); |
---|
139 |
if(current_ctxt && current_ctxt != xpath_ctxt) |
---|
140 |
xmlXPathFreeContext(current_ctxt); |
---|
141 |
} |
---|
142 |
void noit_conf_get_into_hash(noit_conf_section_t section, |
---|
143 |
const char *path, |
---|
144 |
noit_hash_table *table) { |
---|
145 |
int cnt; |
---|
146 |
xmlXPathObjectPtr pobj = NULL; |
---|
147 |
xmlXPathContextPtr current_ctxt; |
---|
148 |
xmlNodePtr current_node = (xmlNodePtr)section; |
---|
149 |
xmlNodePtr node, parent_node; |
---|
150 |
char xpath_expr[1024]; |
---|
151 |
char *inheritid; |
---|
152 |
|
---|
153 |
current_ctxt = xpath_ctxt; |
---|
154 |
if(current_node) { |
---|
155 |
current_ctxt = xmlXPathNewContext(master_config); |
---|
156 |
current_ctxt->node = current_node; |
---|
157 |
} |
---|
158 |
if(path[0] == '/') |
---|
159 |
strlcpy(xpath_expr, path, sizeof(xpath_expr)); |
---|
160 |
else |
---|
161 |
snprintf(xpath_expr, sizeof(xpath_expr), |
---|
162 |
"ancestor-or-self::node()/%s", path); |
---|
163 |
pobj = xmlXPathEval((xmlChar *)xpath_expr, current_ctxt); |
---|
164 |
if(!pobj) goto out; |
---|
165 |
if(pobj->type != XPATH_NODESET) goto out; |
---|
166 |
if(xmlXPathNodeSetIsEmpty(pobj->nodesetval)) goto out; |
---|
167 |
cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); |
---|
168 |
/* These are in the order of root to leaf |
---|
169 |
* We want to recurse... apply: |
---|
170 |
* 1. our parent's config |
---|
171 |
* 2. our "inherit" config if it exists. |
---|
172 |
* 3. our config. |
---|
173 |
*/ |
---|
174 |
node = xmlXPathNodeSetItem(pobj->nodesetval, cnt-1); |
---|
175 |
/* 1. */ |
---|
176 |
if(cnt > 1) { |
---|
177 |
parent_node = xmlXPathNodeSetItem(pobj->nodesetval, cnt-2); |
---|
178 |
noit_conf_get_into_hash(parent_node, (const char *)node->name, table); |
---|
179 |
} |
---|
180 |
/* 2. */ |
---|
181 |
inheritid = (char *)xmlGetProp(node, (xmlChar *)"inherit"); |
---|
182 |
if(inheritid) { |
---|
183 |
snprintf(xpath_expr, sizeof(xpath_expr), "//*[@id=\"%s\"]", inheritid); |
---|
184 |
noit_conf_get_into_hash(NULL, xpath_expr, table); |
---|
185 |
} |
---|
186 |
/* 3. */ |
---|
187 |
noit_conf_get_elements_into_hash(node, "*", table); |
---|
188 |
|
---|
189 |
out: |
---|
190 |
if(pobj) xmlXPathFreeObject(pobj); |
---|
191 |
if(current_ctxt && current_ctxt != xpath_ctxt) |
---|
192 |
xmlXPathFreeContext(current_ctxt); |
---|
193 |
} |
---|
194 |
noit_hash_table *noit_conf_get_hash(noit_conf_section_t section, |
---|
195 |
const char *path) { |
---|
196 |
noit_hash_table *table = NULL; |
---|
197 |
|
---|
198 |
table = calloc(1, sizeof(*table)); |
---|
199 |
noit_conf_get_into_hash(section, path, table); |
---|
200 |
return table; |
---|
201 |
} |
---|
202 |
noit_conf_section_t noit_conf_get_section(noit_conf_section_t section, |
---|
203 |
const char *path) { |
---|
204 |
noit_conf_section_t subsection = NULL; |
---|
205 |
xmlXPathObjectPtr pobj = NULL; |
---|
206 |
xmlXPathContextPtr current_ctxt; |
---|
207 |
xmlNodePtr current_node = (xmlNodePtr)section; |
---|
208 |
|
---|
209 |
current_ctxt = xpath_ctxt; |
---|
210 |
if(current_node) { |
---|
211 |
current_ctxt = xmlXPathNewContext(master_config); |
---|
212 |
current_ctxt->node = current_node; |
---|
213 |
} |
---|
214 |
pobj = xmlXPathEval((xmlChar *)path, current_ctxt); |
---|
215 |
if(!pobj) goto out; |
---|
216 |
if(pobj->type != XPATH_NODESET) goto out; |
---|
217 |
if(xmlXPathNodeSetIsEmpty(pobj->nodesetval)) goto out; |
---|
218 |
subsection = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0); |
---|
219 |
out: |
---|
220 |
if(pobj) xmlXPathFreeObject(pobj); |
---|
221 |
if(current_ctxt && current_ctxt != xpath_ctxt) |
---|
222 |
xmlXPathFreeContext(current_ctxt); |
---|
223 |
return subsection; |
---|
224 |
} |
---|
225 |
noit_conf_section_t *noit_conf_get_sections(noit_conf_section_t section, |
---|
226 |
const char *path, |
---|
227 |
int *cnt) { |
---|
228 |
int i; |
---|
229 |
noit_conf_section_t *sections = NULL; |
---|
230 |
xmlXPathObjectPtr pobj = NULL; |
---|
231 |
xmlXPathContextPtr current_ctxt; |
---|
232 |
xmlNodePtr current_node = (xmlNodePtr)section; |
---|
233 |
|
---|
234 |
*cnt = 0; |
---|
235 |
current_ctxt = xpath_ctxt; |
---|
236 |
if(current_node) { |
---|
237 |
current_ctxt = xmlXPathNewContext(master_config); |
---|
238 |
current_ctxt->node = current_node; |
---|
239 |
} |
---|
240 |
pobj = xmlXPathEval((xmlChar *)path, current_ctxt); |
---|
241 |
if(!pobj) goto out; |
---|
242 |
if(pobj->type != XPATH_NODESET) goto out; |
---|
243 |
if(xmlXPathNodeSetIsEmpty(pobj->nodesetval)) goto out; |
---|
244 |
*cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); |
---|
245 |
sections = calloc(*cnt, sizeof(*sections)); |
---|
246 |
for(i=0; i<*cnt; i++) |
---|
247 |
sections[i] = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i); |
---|
248 |
out: |
---|
249 |
if(pobj) xmlXPathFreeObject(pobj); |
---|
250 |
if(current_ctxt && current_ctxt != xpath_ctxt) |
---|
251 |
xmlXPathFreeContext(current_ctxt); |
---|
252 |
return sections; |
---|
253 |
} |
---|
254 |
int _noit_conf_get_string(noit_conf_section_t section, xmlNodePtr *vnode, |
---|
255 |
const char *path, char **value) { |
---|
256 |
char *str; |
---|
257 |
int i; |
---|
258 |
xmlXPathObjectPtr pobj; |
---|
259 |
xmlXPathContextPtr current_ctxt; |
---|
260 |
xmlNodePtr current_node = (xmlNodePtr)section; |
---|
261 |
|
---|
262 |
current_ctxt = xpath_ctxt; |
---|
263 |
if(current_node) { |
---|
264 |
current_ctxt = xmlXPathNewContext(master_config); |
---|
265 |
current_ctxt->node = current_node; |
---|
266 |
} |
---|
267 |
pobj = xmlXPathEval((xmlChar *)path, current_ctxt); |
---|
268 |
if(pobj) { |
---|
269 |
xmlNodePtr node; |
---|
270 |
switch(pobj->type) { |
---|
271 |
case XPATH_NODESET: |
---|
272 |
if(xmlXPathNodeSetIsEmpty(pobj->nodesetval)) goto fallback; |
---|
273 |
i = xmlXPathNodeSetGetLength(pobj->nodesetval); |
---|
274 |
node = xmlXPathNodeSetItem(pobj->nodesetval, i-1); |
---|
275 |
if(vnode) *vnode = node; |
---|
276 |
*value = (char *)xmlXPathCastNodeToString(node); |
---|
277 |
break; |
---|
278 |
default: |
---|
279 |
*value = (char *)xmlXPathCastToString(pobj); |
---|
280 |
} |
---|
281 |
goto found; |
---|
282 |
} |
---|
283 |
fallback: |
---|
284 |
if(noit_hash_retrieve(&_compiled_fallback, |
---|
285 |
path, strlen(path), (void **)&str)) { |
---|
286 |
*value = str; |
---|
287 |
goto found; |
---|
288 |
} |
---|
289 |
return 0; |
---|
290 |
found: |
---|
291 |
if(current_ctxt && current_ctxt != xpath_ctxt) |
---|
292 |
xmlXPathFreeContext(current_ctxt); |
---|
293 |
return 1; |
---|
294 |
} |
---|
295 |
int noit_conf_get_uuid(noit_conf_section_t section, |
---|
296 |
const char *path, uuid_t out) { |
---|
297 |
char *str; |
---|
298 |
if(_noit_conf_get_string(section,NULL,path,&str)) { |
---|
299 |
if(uuid_parse(str, out) == 0) return 1; |
---|
300 |
return 0; |
---|
301 |
} |
---|
302 |
return 0; |
---|
303 |
} |
---|
304 |
int noit_conf_get_string(noit_conf_section_t section, |
---|
305 |
const char *path, char **value) { |
---|
306 |
char *str; |
---|
307 |
if(_noit_conf_get_string(section,NULL,path,&str)) { |
---|
308 |
*value = strdup(str); |
---|
309 |
return 1; |
---|
310 |
} |
---|
311 |
return 0; |
---|
312 |
} |
---|
313 |
int noit_conf_get_stringbuf(noit_conf_section_t section, |
---|
314 |
const char *path, char *buf, int len) { |
---|
315 |
char *str; |
---|
316 |
if(_noit_conf_get_string(section,NULL,path,&str)) { |
---|
317 |
strlcpy(buf, str, len); |
---|
318 |
return 1; |
---|
319 |
} |
---|
320 |
return 0; |
---|
321 |
} |
---|
322 |
int noit_conf_set_string(noit_conf_section_t section, |
---|
323 |
const char *path, const char *value) { |
---|
324 |
noit_hash_replace(&_tmp_config, |
---|
325 |
strdup(path), strlen(path), (void *)strdup(value), |
---|
326 |
free, free); |
---|
327 |
return 1; |
---|
328 |
} |
---|
329 |
int noit_conf_get_int(noit_conf_section_t section, |
---|
330 |
const char *path, int *value) { |
---|
331 |
char *str; |
---|
332 |
long longval; |
---|
333 |
if(_noit_conf_get_string(section,NULL,path,&str)) { |
---|
334 |
int base = 10; |
---|
335 |
if(str[0] == '0') { |
---|
336 |
if(str[1] == 'x') base = 16; |
---|
337 |
else base = 8; |
---|
338 |
} |
---|
339 |
longval = strtol(str, NULL, base); |
---|
340 |
*value = (int)longval; |
---|
341 |
return 1; |
---|
342 |
} |
---|
343 |
return 0; |
---|
344 |
} |
---|
345 |
int noit_conf_set_int(noit_conf_section_t section, |
---|
346 |
const char *path, int value) { |
---|
347 |
char buffer[32]; |
---|
348 |
snprintf(buffer, 32, "%d", value); |
---|
349 |
return noit_conf_set_string(section,path,buffer); |
---|
350 |
} |
---|
351 |
int noit_conf_get_float(noit_conf_section_t section, |
---|
352 |
const char *path, float *value) { |
---|
353 |
char *str; |
---|
354 |
if(_noit_conf_get_string(section,NULL,path,&str)) { |
---|
355 |
*value = atof(str); |
---|
356 |
return 1; |
---|
357 |
} |
---|
358 |
return 0; |
---|
359 |
} |
---|
360 |
int noit_conf_set_float(noit_conf_section_t section, |
---|
361 |
const char *path, float value) { |
---|
362 |
char buffer[32]; |
---|
363 |
snprintf(buffer, 32, "%f", value); |
---|
364 |
return noit_conf_set_string(section,path,buffer); |
---|
365 |
} |
---|
366 |
int noit_conf_get_boolean(noit_conf_section_t section, |
---|
367 |
const char *path, noit_conf_boolean *value) { |
---|
368 |
char *str; |
---|
369 |
if(_noit_conf_get_string(section,NULL,path,&str)) { |
---|
370 |
if(!strcasecmp(str, "true") || |
---|
371 |
!strcasecmp(str, "on")) *value = noit_true; |
---|
372 |
else *value = noit_false; |
---|
373 |
return 1; |
---|
374 |
} |
---|
375 |
return 0; |
---|
376 |
} |
---|
377 |
int noit_conf_set_boolean(noit_conf_section_t section, |
---|
378 |
const char *path, noit_conf_boolean value) { |
---|
379 |
if(value == noit_true) |
---|
380 |
return noit_conf_set_string(section,path,"true"); |
---|
381 |
return noit_conf_set_string(section,path,"false"); |
---|
382 |
} |
---|
383 |
|
---|
384 |
static int |
---|
385 |
noit_console_write_xml(void *vncct, const char *buffer, int len) { |
---|
386 |
noit_console_closure_t ncct = vncct; |
---|
387 |
return nc_write(ncct, buffer, len); |
---|
388 |
} |
---|
389 |
static int |
---|
390 |
noit_console_close_xml(void *vncct) { |
---|
391 |
return 0; |
---|
392 |
} |
---|
393 |
|
---|
394 |
int |
---|
395 |
noit_conf_reload(noit_console_closure_t ncct, |
---|
396 |
int argc, char **argv, |
---|
397 |
noit_console_state_t *state, void *closure) { |
---|
398 |
if(noit_conf_load(master_config_file)) { |
---|
399 |
nc_printf(ncct, "error loading config\n"); |
---|
400 |
return -1; |
---|
401 |
} |
---|
402 |
return 0; |
---|
403 |
} |
---|
404 |
int |
---|
405 |
noit_conf_write_terminal(noit_console_closure_t ncct, |
---|
406 |
int argc, char **argv, |
---|
407 |
noit_console_state_t *state, void *closure) { |
---|
408 |
xmlOutputBufferPtr out; |
---|
409 |
xmlCharEncodingHandlerPtr enc; |
---|
410 |
enc = xmlGetCharEncodingHandler(XML_CHAR_ENCODING_UTF8); |
---|
411 |
out = xmlOutputBufferCreateIO(noit_console_write_xml, |
---|
412 |
noit_console_close_xml, |
---|
413 |
ncct, enc); |
---|
414 |
xmlSaveFormatFileTo(out, master_config, "utf8", 1); |
---|
415 |
return 0; |
---|
416 |
} |
---|
417 |
int |
---|
418 |
noit_conf_write_file(noit_console_closure_t ncct, |
---|
419 |
int argc, char **argv, |
---|
420 |
noit_console_state_t *state, void *closure) { |
---|
421 |
int fd, len; |
---|
422 |
char master_file_tmp[PATH_MAX]; |
---|
423 |
xmlOutputBufferPtr out; |
---|
424 |
xmlCharEncodingHandlerPtr enc; |
---|
425 |
|
---|
426 |
snprintf(master_file_tmp, sizeof(master_file_tmp), |
---|
427 |
"%s.tmp", master_config_file); |
---|
428 |
unlink(master_file_tmp); |
---|
429 |
fd = open(master_file_tmp, O_CREAT|O_EXCL|O_WRONLY, 0640); |
---|
430 |
if(fd < 0) { |
---|
431 |
nc_printf(ncct, "Failed to open tmp file: %s\n", strerror(errno)); |
---|
432 |
return -1; |
---|
433 |
} |
---|
434 |
enc = xmlGetCharEncodingHandler(XML_CHAR_ENCODING_UTF8); |
---|
435 |
out = xmlOutputBufferCreateFd(fd, enc); |
---|
436 |
if(!out) { |
---|
437 |
close(fd); |
---|
438 |
unlink(master_file_tmp); |
---|
439 |
nc_printf(ncct, "internal error: OutputBufferCreate failed\n"); |
---|
440 |
return -1; |
---|
441 |
} |
---|
442 |
len = xmlSaveFormatFileTo(out, master_config, "utf8", 1); |
---|
443 |
close(fd); |
---|
444 |
if(len <= 0) { |
---|
445 |
nc_printf(ncct, "internal error: writing to tmp file failed.\n"); |
---|
446 |
return -1; |
---|
447 |
} |
---|
448 |
if(rename(master_file_tmp, master_config_file) != 0) { |
---|
449 |
nc_printf(ncct, "Failed to replace file: %s\n", strerror(errno)); |
---|
450 |
return -1; |
---|
451 |
} |
---|
452 |
nc_printf(ncct, "%d bytes written.\n", len); |
---|
453 |
return 0; |
---|
454 |
} |
---|
455 |
|
---|
456 |
void |
---|
457 |
noit_conf_log_init(const char *toplevel) { |
---|
458 |
int i, cnt = 0, o, ocnt = 0; |
---|
459 |
noit_conf_section_t *log_configs, *outlets; |
---|
460 |
char path[256]; |
---|
461 |
|
---|
462 |
snprintf(path, sizeof(path), "/%s/logs//log", toplevel); |
---|
463 |
log_configs = noit_conf_get_sections(NULL, path, &cnt); |
---|
464 |
noitL(noit_stderr, "Found %d %s stanzas\n", cnt, path); |
---|
465 |
for(i=0; i<cnt; i++) { |
---|
466 |
noit_log_stream_t ls; |
---|
467 |
char name[256], type[256], path[256]; |
---|
468 |
noit_hash_table *config; |
---|
469 |
noit_conf_boolean disabled; |
---|
470 |
|
---|
471 |
if(!noit_conf_get_stringbuf(log_configs[i], |
---|
472 |
"ancestor-or-self::node()/@name", |
---|
473 |
name, sizeof(name))) { |
---|
474 |
noitL(noit_error, "log section %d does not have a name attribute\n", i+1); |
---|
475 |
exit(-1); |
---|
476 |
} |
---|
477 |
if(!noit_conf_get_stringbuf(log_configs[i], |
---|
478 |
"ancestor-or-self::node()/@type", |
---|
479 |
type, sizeof(type))) { |
---|
480 |
type[0] = '\0'; |
---|
481 |
} |
---|
482 |
if(!noit_conf_get_stringbuf(log_configs[i], |
---|
483 |
"ancestor-or-self::node()/@path", |
---|
484 |
path, sizeof(path))) { |
---|
485 |
path[0] = '\0'; |
---|
486 |
} |
---|
487 |
config = noit_conf_get_hash(log_configs[i], |
---|
488 |
"ancestor-or-self::node()/config/*"); |
---|
489 |
ls = noit_log_stream_new(name, type[0] ? type : NULL, |
---|
490 |
path[0] ? path : NULL, config); |
---|
491 |
if(!ls) { |
---|
492 |
fprintf(stderr, "Error configuring log: %s[%s:%s]\n", name, type, path); |
---|
493 |
exit(-1); |
---|
494 |
} |
---|
495 |
|
---|
496 |
if(noit_conf_get_boolean(log_configs[i], |
---|
497 |
"ancestor-or-self::node()/@disabled", |
---|
498 |
&disabled) && disabled) |
---|
499 |
ls->enabled = 0; |
---|
500 |
|
---|
501 |
outlets = noit_conf_get_sections(log_configs[i], |
---|
502 |
"ancestor-or-self::node()/outlet", &ocnt); |
---|
503 |
noitL(noit_debug, "found %d outlets for log '%s'\n", ocnt, name); |
---|
504 |
|
---|
505 |
for(o=0; o<ocnt; o++) { |
---|
506 |
noit_log_stream_t outlet; |
---|
507 |
char oname[256]; |
---|
508 |
noit_conf_get_stringbuf(outlets[o], "@name", |
---|
509 |
oname, sizeof(oname)); |
---|
510 |
outlet = noit_log_stream_find(oname); |
---|
511 |
if(!outlet) { |
---|
512 |
fprintf(stderr, "Cannot find outlet '%s' for %s[%s:%s]\n", oname, |
---|
513 |
name, type, path); |
---|
514 |
exit(-1); |
---|
515 |
} |
---|
516 |
else |
---|
517 |
noit_log_stream_add_stream(ls, outlet); |
---|
518 |
} |
---|
519 |
if(outlets) free(outlets); |
---|
520 |
} |
---|
521 |
if(log_configs) free(log_configs); |
---|
522 |
} |
---|