2 * Copyright (C) 2013 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include <common/defaults.h>
27 #include <common/error.h>
28 #include <common/macros.h>
29 #include <common/utils.h>
32 #include "config-internal.h"
34 struct handler_filter_args
{
36 config_entry_handler_cb handler
;
40 const char * const config_str_yes
= "yes";
41 const char * const config_str_true
= "true";
42 const char * const config_str_on
= "on";
43 const char * const config_str_no
= "no";
44 const char * const config_str_false
= "false";
45 const char * const config_str_off
= "off";
46 const char * const config_xml_encoding
= "UTF-8";
47 /* Size of the encoding's largest character */
48 const size_t config_xml_encoding_bytes_per_char
= 2;
49 const char * const config_xml_indent_string
= "\t";
50 const char * const config_xml_true
= "true";
51 const char * const config_xml_false
= "false";
53 static int config_entry_handler_filter(struct handler_filter_args
*args
,
54 const char *section
, const char *name
, const char *value
)
57 struct config_entry entry
= { section
, name
, value
};
61 if (!section
|| !name
|| !value
) {
67 if (strcmp(args
->section
, section
)) {
72 ret
= args
->handler(&entry
, args
->user_data
);
78 int config_get_section_entries(const char *override_path
, const char *section
,
79 config_entry_handler_cb handler
, void *user_data
)
82 FILE *config_file
= NULL
;
83 struct handler_filter_args filter
= { section
, handler
, user_data
};
86 config_file
= fopen(override_path
, "r");
88 DBG("Loaded daemon configuration file at %s",
91 ERR("Failed to open daemon configuration file at %s",
97 char *path
= utils_get_home_dir();
99 /* Try to open the user's daemon configuration file */
101 ret
= asprintf(&path
, DEFAULT_DAEMON_HOME_CONFIGPATH
, path
);
107 config_file
= fopen(path
, "r");
109 DBG("Loaded daemon configuration file at %s", path
);
115 /* Try to open the system daemon configuration file */
117 config_file
= fopen(DEFAULT_DAEMON_HOME_CONFIGPATH
, "r");
122 DBG("No daemon configuration file found.");
126 ret
= ini_parse_file(config_file
,
127 (ini_entry_handler
) config_entry_handler_filter
, (void *) &filter
);
134 int config_parse_value(const char *value
)
137 char *endptr
, *lower_str
;
147 v
= strtoul(value
, &endptr
, 10);
148 if (endptr
!= value
) {
153 lower_str
= zmalloc(len
+ 1);
160 for (i
= 0; i
< len
; i
++) {
161 lower_str
[i
] = tolower(value
[i
]);
164 if (!strcmp(lower_str
, config_str_yes
) ||
165 !strcmp(lower_str
, config_str_true
) ||
166 !strcmp(lower_str
, config_str_on
)) {
168 } else if (!strcmp(lower_str
, config_str_no
) ||
169 !strcmp(lower_str
, config_str_false
) ||
170 !strcmp(lower_str
, config_str_off
)) {
182 * Returns a xmlChar string which must be released using xmlFree().
184 static xmlChar
*encode_string(const char *in_str
)
186 xmlChar
*out_str
= NULL
;
187 xmlCharEncodingHandlerPtr handler
;
188 int out_len
, ret
, in_len
;
192 handler
= xmlFindCharEncodingHandler(config_xml_encoding
);
194 ERR("xmlFindCharEncodingHandler return NULL!. Configure issue!");
198 in_len
= strlen(in_str
);
200 * Add 1 byte for the NULL terminted character. The factor 2 here is
201 * because UTF-8 can be on two bytes so this fits the worst case for each
204 out_len
= (in_len
* 2) + 1;
205 out_str
= xmlMalloc(out_len
);
210 ret
= handler
->input(out_str
, &out_len
, (const xmlChar
*) in_str
, &in_len
);
217 /* out_len is now the size of out_str */
218 out_str
[out_len
] = '\0';
224 struct config_writer
*config_writer_create(int fd_output
)
227 struct config_writer
*writer
;
228 xmlOutputBufferPtr buffer
;
230 writer
= zmalloc(sizeof(struct config_writer
));
232 PERROR("zmalloc config_writer_create");
236 buffer
= xmlOutputBufferCreateFd(fd_output
, NULL
);
241 writer
->writer
= xmlNewTextWriter(buffer
);
242 ret
= xmlTextWriterStartDocument(writer
->writer
, NULL
,
243 config_xml_encoding
, NULL
);
248 ret
= xmlTextWriterSetIndentString(writer
->writer
,
249 BAD_CAST config_xml_indent_string
);
254 ret
= xmlTextWriterSetIndent(writer
->writer
, 1);
262 config_writer_destroy(writer
);
267 int config_writer_destroy(struct config_writer
*writer
)
276 if (xmlTextWriterEndDocument(writer
->writer
) < 0) {
277 WARN("Could not close XML document");
281 if (writer
->writer
) {
282 xmlFreeTextWriter(writer
->writer
);
291 int config_writer_open_element(struct config_writer
*writer
,
292 const char *element_name
)
295 xmlChar
*encoded_element_name
;
297 if (!writer
|| !writer
->writer
|| !element_name
|| !element_name
[0]) {
302 encoded_element_name
= encode_string(element_name
);
303 if (!encoded_element_name
) {
308 ret
= xmlTextWriterStartElement(writer
->writer
, encoded_element_name
);
309 xmlFree(encoded_element_name
);
311 return ret
> 0 ? 0 : ret
;
315 int config_writer_close_element(struct config_writer
*writer
)
319 if (!writer
|| !writer
->writer
) {
324 ret
= xmlTextWriterEndElement(writer
->writer
);
326 return ret
> 0 ? 0 : ret
;
330 int config_writer_write_element_unsigned_int(struct config_writer
*writer
,
331 const char *element_name
, uint64_t value
)
334 xmlChar
*encoded_element_name
;
336 if (!writer
|| !writer
->writer
|| !element_name
|| !element_name
[0]) {
341 encoded_element_name
= encode_string(element_name
);
342 if (!encoded_element_name
) {
347 ret
= xmlTextWriterWriteFormatElement(writer
->writer
,
348 encoded_element_name
, "%" PRIu64
, value
);
349 xmlFree(encoded_element_name
);
351 return ret
> 0 ? 0 : ret
;
355 int config_writer_write_element_signed_int(struct config_writer
*writer
,
356 const char *element_name
, int64_t value
)
359 xmlChar
*encoded_element_name
;
361 if (!writer
|| !writer
->writer
|| !element_name
|| !element_name
[0]) {
366 encoded_element_name
= encode_string(element_name
);
367 if (!encoded_element_name
) {
372 ret
= xmlTextWriterWriteFormatElement(writer
->writer
,
373 encoded_element_name
, "%" PRIi64
, value
);
374 xmlFree(encoded_element_name
);
376 return ret
> 0 ? 0 : ret
;
380 int config_writer_write_element_bool(struct config_writer
*writer
,
381 const char *element_name
, int value
)
383 return config_writer_write_element_string(writer
, element_name
,
384 value
? config_xml_true
: config_xml_false
);
388 int config_writer_write_element_string(struct config_writer
*writer
,
389 const char *element_name
, const char *value
)
392 xmlChar
*encoded_element_name
= NULL
;
393 xmlChar
*encoded_value
= NULL
;
395 if (!writer
|| !writer
->writer
|| !element_name
|| !element_name
[0] ||
401 encoded_element_name
= encode_string(element_name
);
402 if (!encoded_element_name
) {
407 encoded_value
= encode_string(value
);
408 if (!encoded_value
) {
413 ret
= xmlTextWriterWriteElement(writer
->writer
, encoded_element_name
,
416 xmlFree(encoded_element_name
);
417 xmlFree(encoded_value
);
418 return ret
> 0 ? 0 : ret
;