Files
dns-keeper/src/config.c
T

120 lines
3.3 KiB
C

#include <errno.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "log.h"
static int load_env_str(const char *env_name, char **out, int unset) {
const char *env_var = getenv(env_name);
if (!env_var || env_var[0] == '\0') {
log_error("Missing required env var %s", env_name);
return -1;
}
*out = strdup(env_var);
if (!*out) { log_error("Memory allocation failed"); return -1; }
if (unset) unsetenv(env_name);
return 0;
}
static int load_env_int(
const char *env_name,
int *out,
int min,
int max,
int fallback
) {
const char *env_var = getenv(env_name);
if (!env_var || env_var[0] == '\0') { *out = fallback; return 0; }
char *end;
errno = 0;
long parsed = strtol(env_var, &end, 10);
if (errno != 0 || *end != '\0') {
log_error("%s needs to be an integer", env_name);
return -1;
}
if (parsed < min || parsed > max) {
log_error("%s needs to be within range (%d-%d)", env_name, min, max);
return -1;
}
*out = (int)parsed;
return 0;
}
static int load_env_strs(
const char *env_name,
char ***out,
int *count,
int max_str_len
) {
char *str = NULL;
if (load_env_str(env_name, &str, 0)) return -1;
*count = 1;
for (char *p = str; *p; p++)
if (*p == ',') (*count)++;
for (char *start = str, *p = str; ; p++) {
if (*p == ',' || *p == '\0') {
if ((int)(p - start) > max_str_len) {
log_error("'%.*s' in %s exceeds max length (%d)",
(int)(p - start), start, env_name, max_str_len);
free(str);
return -1;
}
if (*p == '\0') break;
start = p + 1;
}
}
char **arr = malloc(*count * sizeof(char *));
if (!arr) { log_error("Memory allocation failed"); free(str); return -1; }
int i = 0;
char *token = strtok(str, ",");
while (token) {
arr[i++] = strdup(token);
token = strtok(NULL, ",");
}
free(str);
*out = arr;
return 0;
}
int config_load(Config *cfg) {
if (load_env_str(ENV_GANDI_TOKEN, &cfg->api_token, 1)) return -1;
if (load_env_str(ENV_DNS_KEEPER_DOMAIN, &cfg->dns_keeper_domain, 0)) return -1;
if (load_env_str(ENV_DNS_KEEPER_RECORD, &cfg->dns_keeper_record, 0)) return -1;
if (strlen(cfg->dns_keeper_record) + 1 + strlen(cfg->dns_keeper_domain) > CONFIG_MAX_DOMAIN_LEN) {
log_error("%s.%s exceeds max domain length (%d)",
ENV_DNS_KEEPER_RECORD, ENV_DNS_KEEPER_DOMAIN, CONFIG_MAX_DOMAIN_LEN);
return -1;
}
if (load_env_int(ENV_DNS_KEEPER_PORT, &cfg->dns_keeper_port,
1, 65535, DEFAULT_DNS_KEEPER_PORT)) return -1;
if (load_env_int(ENV_POLL_INTERVAL, &cfg->poll_interval,
1, INT_MAX, DEFAULT_POLL_INTERVAL)) return -1;
if (load_env_strs(ENV_DOMAINS, &cfg->domains, &cfg->domain_count, CONFIG_MAX_DOMAIN_LEN)) return -1;
return 0;
}
void config_free(Config *cfg) {
if (cfg->domains) {
for (int i = 0; i < cfg->domain_count; i++) {
free(cfg->domains[i]);
}
free(cfg->domains);
cfg->domains = NULL;
cfg->domain_count = 0;
}
}