#include "config.h" #include #include #include #include "log.h" #include "util.h" struct config g_cfg; static void set_str(char **dst, const char *val) { free(*dst); *dst = xstrdup(val); } void config_defaults(void) { memset(&g_cfg, 0, sizeof g_cfg); g_cfg.socket_path = xstrdup("/run/bokfd/bokfd.sock"); g_cfg.db_path = xstrdup("/var/lib/bokfd/bokfd.db"); g_cfg.backup_dir = xstrdup("/var/lib/bokfd/backup"); g_cfg.export_dir = xstrdup("/var/lib/bokfd/export"); g_cfg.tcp_addr = NULL; g_cfg.tcp_enabled = 0; g_cfg.tls_addr = NULL; g_cfg.tls_enabled = 0; g_cfg.tls_cert = xstrdup("/var/lib/bokfd/certs/fullchain.pem"); g_cfg.tls_key = xstrdup("/var/lib/bokfd/certs/privkey.pem"); g_cfg.log_level = LOG_INFO; g_cfg.allow_org_create = 1; g_cfg.audit_reads = 0; g_cfg.synchronous = xstrdup("FULL"); g_cfg.chart_k2_file = xstrdup("/usr/local/share/bokf/bas_k2.csv"); g_cfg.chart_k3_file = xstrdup("/usr/local/share/bokf/bas_k3.csv"); g_cfg.session_ttl = 8 * 3600; g_cfg.max_line_bytes = 1024 * 1024; g_cfg.max_attachment_bytes = 10 * 1024 * 1024; } static int apply_kv(const char *key, const char *val, char **err) { if (strcmp(key, "socket") == 0) set_str(&g_cfg.socket_path, val); else if (strcmp(key, "db") == 0) set_str(&g_cfg.db_path, val); else if (strcmp(key, "backup_dir") == 0) set_str(&g_cfg.backup_dir, val); else if (strcmp(key, "export_dir") == 0) set_str(&g_cfg.export_dir, val); else if (strcmp(key, "tcp") == 0) { if (strcmp(val, "off") == 0 || strcmp(val, "") == 0) { g_cfg.tcp_enabled = 0; } else { set_str(&g_cfg.tcp_addr, val); g_cfg.tcp_enabled = 1; } } else if (strcmp(key, "tls") == 0) { if (strcmp(val, "off") == 0 || strcmp(val, "") == 0) { g_cfg.tls_enabled = 0; } else { set_str(&g_cfg.tls_addr, val); g_cfg.tls_enabled = 1; } } else if (strcmp(key, "tls_cert") == 0) { set_str(&g_cfg.tls_cert, val); } else if (strcmp(key, "tls_key") == 0) { set_str(&g_cfg.tls_key, val); } else if (strcmp(key, "log_level") == 0) { g_cfg.log_level = log_level_from_name(val); } else if (strcmp(key, "allow_org_create") == 0) { g_cfg.allow_org_create = strcmp(val, "false") != 0; } else if (strcmp(key, "audit_reads") == 0) { g_cfg.audit_reads = strcmp(val, "true") == 0; } else if (strcmp(key, "synchronous") == 0) { set_str(&g_cfg.synchronous, val); } else if (strcmp(key, "chart_k2") == 0) { set_str(&g_cfg.chart_k2_file, val); } else if (strcmp(key, "chart_k3") == 0) { set_str(&g_cfg.chart_k3_file, val); } else if (strcmp(key, "session_ttl") == 0) { g_cfg.session_ttl = strtol(val, NULL, 10); } else if (strcmp(key, "max_line_bytes") == 0) { g_cfg.max_line_bytes = strtol(val, NULL, 10); } else if (strcmp(key, "max_attachment_bytes") == 0) { g_cfg.max_attachment_bytes = strtol(val, NULL, 10); } else { char buf[256]; snprintf(buf, sizeof buf, "unknown config key: %s", key); if (err) *err = xstrdup(buf); return -1; } return 0; } int config_load_file(const char *path, char **err) { FILE *f = fopen(path, "r"); if (!f) { char buf[512]; snprintf(buf, sizeof buf, "cannot open config file %s", path); if (err) *err = xstrdup(buf); return -1; } char line[1024]; int lineno = 0; int rc = 0; while (fgets(line, sizeof line, f)) { lineno++; char *s = line; char *hash = strchr(s, '#'); if (hash) *hash = '\0'; s = util_str_trim(s); if (!*s) continue; char *eq = strchr(s, '='); if (!eq) { char buf[512]; snprintf(buf, sizeof buf, "%s:%d: expected key = value", path, lineno); if (err) *err = xstrdup(buf); rc = -1; break; } *eq = '\0'; char *key = util_str_trim(s); char *val = util_str_trim(eq + 1); if (apply_kv(key, val, err) != 0) { rc = -1; break; } } fclose(f); return rc; } void config_apply_env(void) { const char *v; if ((v = getenv("BOKFD_SOCKET"))) set_str(&g_cfg.socket_path, v); if ((v = getenv("BOKFD_DB"))) set_str(&g_cfg.db_path, v); if ((v = getenv("BOKFD_BACKUP_DIR"))) set_str(&g_cfg.backup_dir, v); if ((v = getenv("BOKFD_EXPORT_DIR"))) set_str(&g_cfg.export_dir, v); if ((v = getenv("BOKFD_TCP"))) apply_kv("tcp", v, NULL); if ((v = getenv("BOKFD_TLS"))) apply_kv("tls", v, NULL); if ((v = getenv("BOKFD_TLS_CERT"))) set_str(&g_cfg.tls_cert, v); if ((v = getenv("BOKFD_TLS_KEY"))) set_str(&g_cfg.tls_key, v); if ((v = getenv("BOKFD_LOG_LEVEL"))) g_cfg.log_level = log_level_from_name(v); if ((v = getenv("BOKFD_ALLOW_ORG_CREATE"))) g_cfg.allow_org_create = strcmp(v, "false") != 0; if ((v = getenv("BOKFD_AUDIT_READS"))) g_cfg.audit_reads = strcmp(v, "true") == 0; if ((v = getenv("BOKFD_SYNCHRONOUS"))) set_str(&g_cfg.synchronous, v); if ((v = getenv("BOKFD_CHART_K2"))) set_str(&g_cfg.chart_k2_file, v); if ((v = getenv("BOKFD_CHART_K3"))) set_str(&g_cfg.chart_k3_file, v); if ((v = getenv("BOKFD_SESSION_TTL"))) g_cfg.session_ttl = strtol(v, NULL, 10); if ((v = getenv("BOKFD_MAX_LINE_BYTES"))) g_cfg.max_line_bytes = strtol(v, NULL, 10); if ((v = getenv("BOKFD_MAX_ATTACHMENT_BYTES"))) g_cfg.max_attachment_bytes = strtol(v, NULL, 10); } void config_free(void) { free(g_cfg.socket_path); free(g_cfg.db_path); free(g_cfg.backup_dir); free(g_cfg.export_dir); free(g_cfg.tcp_addr); free(g_cfg.tls_addr); free(g_cfg.tls_cert); free(g_cfg.tls_key); free(g_cfg.synchronous); free(g_cfg.chart_k2_file); free(g_cfg.chart_k3_file); memset(&g_cfg, 0, sizeof g_cfg); }