#include #include #include #include #include #include #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; } }