You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

223 lines
5.5 KiB

#include "common.h"
#include "config.h"
9 years ago
#include "log.h"
#define CONFIGLINE_MAX 256
f2b_config_param_t *
9 years ago
f2b_config_parse_kv_pair(const char *src) {
f2b_config_param_t *param = NULL;
9 years ago
char line[CONFIGLINE_MAX] = "";
char *p, *key, *value;
9 years ago
size_t len;
strncpy(line, src, sizeof(line));
line[CONFIGLINE_MAX] = '\0';
9 years ago
/* strip spaces before key */
key = line;
9 years ago
while (isblank(*key))
key++;
if ((value = strchr(key, '=')) == NULL)
return NULL;
/* strip spaces after key */
p = value - 1;
while (p > line && isblank(*p))
p--;
p++, *p = '\0';
value++; /* move to next char after '=' */
while (isblank(*value))
value++;
/* strip trailing comment */
if ((p = strstr(value, " #")) != NULL) *p = '\0';
if ((p = strstr(value, "\t#")) != NULL) *p = '\0';
if ((p = strstr(value, " ;")) != NULL) *p = '\0';
if ((p = strstr(value, "\t;")) != NULL) *p = '\0';
/* strip trailing spaces */
p = value + strlen(value);
if (p > value)
p--; /* step back at char before '\0' */
9 years ago
while (p > value && isspace(*p))
p--;
p++, *p = '\0';
9 years ago
len = strlen(key);
if (len < 1 || len > CONFIG_KEY_MAX)
return NULL;
len = strlen(value);
if (len < 1 || len > CONFIG_VAL_MAX)
return NULL;
9 years ago
if ((param = calloc(1, sizeof(f2b_config_param_t))) != NULL) {
strncpy(param->name, key, sizeof(param->name));
strncpy(param->value, value, sizeof(param->value));
param->name[CONFIG_KEY_MAX] = '\0';
param->name[CONFIG_VAL_MAX] = '\0';
return param;
}
return NULL;
}
f2b_config_section_t *
9 years ago
f2b_config_parse_section(const char *src) {
f2b_config_section_t *section = NULL;
9 years ago
char line[CONFIGLINE_MAX] = "";
char *name, *end;
9 years ago
strncpy(line, src, sizeof(line));
line[CONFIGLINE_MAX] = '\0';
if ((end = strchr(line, ']')) == NULL)
return NULL;
*end = '\0';
if ((section = calloc(1, sizeof(f2b_config_section_t))) == NULL)
return NULL;
name = "[defaults]";
if (strncmp(line, name, strlen(name)) == 0) {
section->type = t_defaults;
return section;
}
name = "[backend:";
if (strncmp(line, name, strlen(name)) == 0) {
section->type = t_backend;
strncpy(section->name, line + strlen(name), sizeof(section->name));
return section;
}
name = "[jail:";
if (strncmp(line, name, strlen(name)) == 0) {
section->type = t_jail;
strncpy(section->name, line + strlen(name), sizeof(section->name));
return section;
}
free(section);
return NULL;
}
f2b_config_section_t *
9 years ago
f2b_config_find_section(f2b_config_section_t *section, f2b_section_type type, const char *name) {
for (; section != NULL; section = section->next) {
if (section->type == type && strcmp(section->name, name) == 0)
return section;
}
return NULL;
}
f2b_config_param_t *
f2b_config_find_param(f2b_config_param_t *param, const char *name) {
for (; param != NULL; param = param->next) {
if (strcmp(name, param->name) == 0)
return param;
}
return NULL;
}
9 years ago
f2b_config_section_t *
f2b_config_append_param(f2b_config_section_t *section, f2b_config_param_t *param) {
if (section->param) {
section->last->next = param;
section->last = section->last->next;
} else {
section->param = param;
section->last = param;
}
return section;
}
f2b_config_section_t *
f2b_config_load(const char *path) {
f2b_config_section_t *config = NULL; /* always points to current section */
f2b_config_section_t *section = NULL; /* temp pointer */
f2b_config_param_t *param = NULL; /* temp pointer */
FILE *f = NULL; /* config file fd */
char *p; /* temp pointer */
char line[CONFIGLINE_MAX] = ""; /* last read line */
bool skip_section = false; /* if set - skip parameters unless next section */
size_t linenum = 0; /* current line number in config */
if ((f = fopen(path, "r")) == NULL) {
9 years ago
f2b_log_msg(log_error, "can't open config file '%s': %s", path, strerror(errno));
9 years ago
return NULL;
}
if ((config = calloc(1, sizeof(f2b_config_section_t))) == NULL)
return NULL;
config->type = t_main;
while (1) {
p = fgets(line, sizeof(line), f);
if (!p && (feof(f) || ferror(f)))
break;
while (isblank(*p))
p++;
linenum++;
switch(*p) {
case '\0':
case '\r':
case '\n':
/* empty line */
break;
case ';':
case '#':
/* comment line */
break;
case '[':
/* section header */
section = f2b_config_parse_section(p);
if (section) {
skip_section = false;
section->next = config;
config = section;
} else {
skip_section = true;
f2b_log_msg(log_error, "unknown section at line %d: %s", linenum, p);
}
break;
default:
if (skip_section) {
f2b_log_msg(log_warn, "skipping line in unknown section: %s", p);
continue;
}
/* key/value pair */
param = f2b_config_parse_kv_pair(p);
if (param) {
f2b_config_append_param(config, param);
} else {
f2b_log_msg(log_error, "can't parse key/value at line %d: %s", linenum, p);
}
break;
} /* switch */
} /* while */
fclose(f);
return config;
}
void
f2b_config_free(f2b_config_section_t *config) {
f2b_config_section_t *next_section = NULL;
f2b_config_param_t *next_param = NULL;
for (; config != NULL; config = next_section) {
next_section = config->next;
for (; config->param != NULL; config->param = next_param) {
next_param = config->param->next;
FREE(config->param);
}
FREE(next_section);
}
}