summaryrefslogtreecommitdiff
path: root/src/config.c
diff options
context:
space:
mode:
authorAnders Betts <anders.betts@gmail.com>2026-09-17 19:55:36 +0200
committerAnders Betts <anders.betts@gmail.com>2026-09-17 19:55:36 +0200
commit380195f7cd5e57acf2c1cf2bc41069e6b0b979ed (patch)
tree32a88fb22a7fbe8f1fd5c105156d1f928c93950d /src/config.c
downloadbokf-380195f7cd5e57acf2c1cf2bc41069e6b0b979ed.tar.gz
bokf-380195f7cd5e57acf2c1cf2bc41069e6b0b979ed.zip
Initial commit: daemon, clients, docs, Docker deploy pipelinev0.1.0
Diffstat (limited to 'src/config.c')
-rw-r--r--src/config.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/src/config.c b/src/config.c
new file mode 100644
index 0000000..3bce6e9
--- /dev/null
+++ b/src/config.c
@@ -0,0 +1,171 @@
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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.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, "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_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.synchronous);
+ free(g_cfg.chart_k2_file);
+ free(g_cfg.chart_k3_file);
+ memset(&g_cfg, 0, sizeof g_cfg);
+}