#include #include #include #include #include #include "config.h" #include "intl.h" #include "log.h" #include "util.h" #define option_count() sizeof(config.options) / sizeof(config.options[0]) config_t config = { .options = { {.key = "threads", .type = TYPE_INTEGER, .def.integer = 10}, {.key = "tmpdir", .type = TYPE_STRING, .def.string = "/tmp/pooler"}, {.key = "addr", .type = TYPE_STRING, .def.string = "0.0.0.0:5858"}, }, .pools = NULL, }; pool_config_t *config_pool_add(char *section) { pool_config_t *pool = malloc(sizeof(pool_config_t)); bzero(pool, sizeof(pool_config_t)); pool->section = strdup(section); pool->next = config.pools; config.pools = pool; return pool; } bool config_pool_contains(char *section) { pool_config_t *cur = config.pools; while (NULL != cur) { if (eq(cur->section, section)) return true; cur = cur->next; } return false; } void config_option_set(config_option_t *op, char *value) { switch (op->type) { case TYPE_STRING: free(op->val.string); op->val.string = strdup(value); break; case TYPE_INTEGER: op->val.integer = atoi(value); break; } } void config_option_free(config_option_t *op) { switch (op->type) { case TYPE_STRING: free(op->val.string); break; case TYPE_INTEGER: op->val.integer = 0; break; } } bool config_set(char *key, char *value) { for (int i = 0; i < option_count(); i++) { if (eq(config.options[i].key, key)) { config_option_set(&config.options[i], value); return true; } } return false; } void config_options_clear() { for (int i = 0; i < option_count(); i++) { config_option_t *cur = &config.options[i]; switch (cur->type) { case TYPE_STRING: cur->val.string = NULL; break; case TYPE_INTEGER: cur->val.integer = -1; break; } } } int config_load_handler(void *data, const char *_section, const char *_key, const char *_value) { char *section = (char *)_section, *key = (char *)_key, *value = (char *)_value; if (eq("", section)) { if (!config_set(key, value)) goto unknown; return 1; } if (!config_pool_contains(section)) config_pool_add(section); if (eq(key, "name")) { free(config.pools->name); config.pools->name = strdup(value); } else if (eq(key, "host")) { free(config.pools->host); config.pools->host = strdup(value); } else if (eq(key, "path")) { free(config.pools->path); config.pools->path = strdup(value); } else if (eq(key, "dir")) { free(config.pools->dir); config.pools->dir = strdup(value); } else goto unknown; return 1; unknown: if (NULL == section || section[0] == '\0') error(_("Unknown configuration option: %s"), key); else error(_("Unknown configuration option: %s/%s"), section, key); return 0; } bool config_load(char *file) { config_options_clear(); if (!file_canread(file)) { error(_("Failed to access the configuration file: %s"), file); return false; } if (ini_parse(file, config_load_handler, NULL) < 0) { error(_("Failed to parse the configuration")); return false; } pool_config_t *pool = config.pools; while (NULL != pool) { if (NULL == pool->name) pool->name = pool->section; if (NULL == pool->host) { error(_("Hostname not specified for the pool: %s"), pool->name); return false; } pool = pool->next; } return true; } void config_free() { for (int i = 0; i < option_count(); i++) config_option_free(&config.options[i]); pool_config_t *cur = config.pools, *old = NULL; while (NULL != cur) { old = cur; cur = cur->next; free(old->section); if (old->section != old->name) free(old->name); free(old->host); free(old->path); free(old->dir); free(old); } } char *config_get_string(char *key) { for (int i = 0; i < option_count(); i++) { if (!eq(config.options[i].key, key) || config.options[i].type != TYPE_STRING) continue; if (NULL == config.options[i].val.string) return config.options[i].def.string; return config.options[i].val.string; } return NULL; } int config_get_integer(char *key) { for (int i = 0; i < option_count(); i++) { if (!eq(config.options[i].key, key) || config.options[i].type != TYPE_INTEGER) continue; if (config.options[i].val.integer < 0) return config.options[i].def.integer; return config.options[i].val.integer; } return -1; }