-/*
- Get variable from a section in a configfile. returns -1 on failure.
-*/
-int
-readconfig(const char *fname, FILE *fp)
-{
- char *line, *temp_buf;
- char *p, *q;
- int i, lineno = 0;
- config_t *cfg;
-
- line = (char *)xmalloc(80 * sizeof(char));
- temp_buf = (char *)xmalloc(80 * sizeof(char));
-
- for(;;)
- {
- if(fgets(line, 80, fp) == NULL)
- return 0;
-
- while(!index(line, '\n'))
- {
- fgets(temp_buf, (strlen(line)+1) * 80, fp);
- if(!temp_buf)
- break;
- strcat(line, temp_buf);
- line = (char *)xrealloc(line, (strlen(line)+1) * sizeof(char));
- }
- lineno++;
-
- if((p = strtok(line, "\t\n\r =")) == NULL)
- continue; /* no tokens on this line */
-
- if(p[0] == '#')
- continue; /* comment: ignore */
-
- for(i = 0; hazahaza[i].name != NULL; i++)
- if(!strcasecmp(hazahaza[i].name, p))
- break;
-
- if(!hazahaza[i].name)
- {
- fprintf(stderr, _("%s: %d: Invalid variable name `%s'.\n"),
- fname, lineno, p);
- return -1;
+void init_configuration(splay_tree_t ** config_tree) {
+ *config_tree = splay_alloc_tree((splay_compare_t) config_compare, (splay_action_t) free_config);
+}
+
+void exit_configuration(splay_tree_t ** config_tree) {
+ splay_delete_tree(*config_tree);
+ *config_tree = NULL;
+}
+
+config_t *new_config(void) {
+ return xmalloc_and_zero(sizeof(config_t));
+}
+
+void free_config(config_t *cfg) {
+ if(cfg->variable)
+ free(cfg->variable);
+
+ if(cfg->value)
+ free(cfg->value);
+
+ if(cfg->file)
+ free(cfg->file);
+
+ free(cfg);
+}
+
+void config_add(splay_tree_t *config_tree, config_t *cfg) {
+ splay_insert(config_tree, cfg);
+}
+
+config_t *lookup_config(splay_tree_t *config_tree, char *variable) {
+ config_t cfg, *found;
+
+ cfg.variable = variable;
+ cfg.file = NULL;
+ cfg.line = 0;
+
+ found = splay_search_closest_greater(config_tree, &cfg);
+
+ if(!found)
+ return NULL;
+
+ if(strcasecmp(found->variable, variable))
+ return NULL;
+
+ return found;
+}
+
+config_t *lookup_config_next(splay_tree_t *config_tree, const config_t *cfg) {
+ splay_node_t *node;
+ config_t *found;
+
+ node = splay_search_node(config_tree, cfg);
+
+ if(node) {
+ if(node->next) {
+ found = node->next->data;
+
+ if(!strcasecmp(found->variable, cfg->variable))
+ return found;
+ }
+ }
+
+ return NULL;
+}
+
+bool get_config_bool(const config_t *cfg, bool *result) {
+ if(!cfg)
+ return false;
+
+ if(!strcasecmp(cfg->value, "yes")) {
+ *result = true;
+ return true;
+ } else if(!strcasecmp(cfg->value, "no")) {
+ *result = false;
+ return true;
+ }
+
+ logger(LOG_ERR, "\"yes\" or \"no\" expected for configuration variable %s in %s line %d",
+ cfg->variable, cfg->file, cfg->line);
+
+ return false;
+}
+
+bool get_config_int(const config_t *cfg, int *result) {
+ if(!cfg)
+ return false;
+
+ if(sscanf(cfg->value, "%d", result) == 1)
+ return true;
+
+ logger(LOG_ERR, "Integer expected for configuration variable %s in %s line %d",
+ cfg->variable, cfg->file, cfg->line);
+
+ return false;
+}
+
+bool get_config_string(const config_t *cfg, char **result) {
+ if(!cfg)
+ return false;
+
+ *result = xstrdup(cfg->value);
+
+ return true;
+}
+
+bool get_config_address(const config_t *cfg, struct addrinfo **result) {
+ struct addrinfo *ai;
+
+ if(!cfg)
+ return false;
+
+ ai = str2addrinfo(cfg->value, NULL, 0);
+
+ if(ai) {
+ *result = ai;
+ return true;