-/*
- Add given value to the list of configs cfg
-*/
-config_t *
-add_config_val(config_t **cfg, int argtype, char *val)
-{
- config_t *p;
- char *q;
-cp
- p = (config_t*)xmalloc(sizeof(*p));
- p->data.val = 0;
-
- switch(argtype)
- {
- case TYPE_INT:
- p->data.val = strtol(val, &q, 0);
- if(q && *q)
- p->data.val = 0;
- break;
- case TYPE_NAME:
- p->data.ptr = xmalloc(strlen(val) + 1);
- strcpy(p->data.ptr, val);
- break;
- case TYPE_IP:
- p->data.ip = strtoip(val);
- break;
- case TYPE_BOOL:
- if(!strcasecmp("yes", val))
- p->data.val = stupid_true;
- else if(!strcasecmp("no", val))
- p->data.val = stupid_false;
- else
- p->data.val = 0;
- }
-
- p->argtype = argtype;
-
- if(p->data.val)
- {
- p->next = *cfg;
- *cfg = p;
-cp
- return p;
- }
- else
- {
- free(p);
-cp
- return NULL;
- }
+splay_tree_t *create_configuration(void) {
+ splay_tree_t *tree = splay_alloc_tree(NULL, NULL);
+ init_configuration(tree);
+ return tree;
+}
+
+void init_configuration(splay_tree_t *tree) {
+ memset(tree, 0, sizeof(*tree));
+ tree->compare = (splay_compare_t) config_compare;
+ tree->delete = (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 xzalloc(sizeof(config_t));
+}
+
+void free_config(config_t *cfg) {
+ free(cfg->variable);
+ free(cfg->value);
+ 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, const char *variable) {
+ const config_t cfg = {
+ .variable = (char *)variable,
+ .file = NULL,
+ .line = 0,
+ };
+
+ config_t *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(DEBUG_ALWAYS, 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(DEBUG_ALWAYS, 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;
+ }
+
+ logger(DEBUG_ALWAYS, LOG_ERR, "Hostname or IP address expected for configuration variable %s in %s line %d",
+ cfg->variable, cfg->file, cfg->line);
+
+ return false;