192 lines
4.1 KiB
C
192 lines
4.1 KiB
C
#include <errno.h>
|
|
#include <ini.h>
|
|
#include <libmp/all.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include "config.h"
|
|
#include "intl.h"
|
|
#include "log.h"
|
|
|
|
#define option_count() sizeof(config.options) / sizeof(config.options[0])
|
|
|
|
config_t config = {
|
|
.options =
|
|
{
|
|
{.key = "threads", .type = TYPE_INTEGER, .def.integer = 10},
|
|
{.key = "addr", .type = TYPE_STRING, .def.string = "0.0.0.0:5858"},
|
|
{.key = "dir", .type = TYPE_STRING, .def.string = NULL},
|
|
{.key = "log", .type = TYPE_STRING, .def.string = NULL},
|
|
},
|
|
.pools = NULL,
|
|
};
|
|
|
|
pool_config_t *config_pool_add(char *name) {
|
|
pool_config_t *pool = malloc(sizeof(pool_config_t));
|
|
bzero(pool, sizeof(pool_config_t));
|
|
|
|
pool->name = strdup(name);
|
|
pool->next = config.pools;
|
|
config.pools = pool;
|
|
|
|
return pool;
|
|
}
|
|
|
|
bool config_pool_contains(char *name) {
|
|
pool_config_t *cur = config.pools;
|
|
while (NULL != cur) {
|
|
if (eq(cur->name, name))
|
|
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, "host")) {
|
|
free(config.pools->host);
|
|
config.pools->host = strdup(value);
|
|
}
|
|
|
|
else
|
|
goto unknown;
|
|
|
|
return 1;
|
|
|
|
unknown:
|
|
log_error("Unknown configuration option: %s/%s", section, key);
|
|
return 0;
|
|
}
|
|
|
|
bool config_load(char *file) {
|
|
config_options_clear();
|
|
|
|
if (!exists(file) || !can_read(file)) {
|
|
log_error("Failed to access the configuration file: %s", file);
|
|
return false;
|
|
}
|
|
|
|
if (ini_parse(file, config_load_handler, NULL) < 0) {
|
|
log_error("Failed to parse the configuration");
|
|
return false;
|
|
}
|
|
|
|
pool_config_t *pool = config.pools;
|
|
while (NULL != pool) {
|
|
if (NULL == pool->host) {
|
|
log_error("Hostname not specified for the pool: %s", pool->name);
|
|
return false;
|
|
}
|
|
pool = pool->next;
|
|
}
|
|
|
|
log_info("Loaded the configuration");
|
|
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->host);
|
|
free(old->name);
|
|
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;
|
|
}
|