Files
pooler/src/config.c

216 lines
4.5 KiB
C

#include <errno.h>
#include <ini.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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;
}