From a089bc43c32a064ca94a94dc3bf2c037cc7307fc Mon Sep 17 00:00:00 2001 From: lisk77 Date: Fri, 29 Aug 2025 20:15:19 +0200 Subject: [PATCH] feat(config): added a simple user config --- include/config.h | 20 +++++++ src/config.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 include/config.h create mode 100644 src/config.c diff --git a/include/config.h b/include/config.h new file mode 100644 index 0000000..2c34058 --- /dev/null +++ b/include/config.h @@ -0,0 +1,20 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#include "tomlc17.h" +#include "utilities.h" + +typedef struct { + char *name; + char *email; +} UserTable; + +typedef struct { + UserTable user; +} Config; + +int load_config(Config*); +void free_config(Config*); +int validate_config(Config*); + +#endif // CONFIG_H diff --git a/src/config.c b/src/config.c new file mode 100644 index 0000000..374f218 --- /dev/null +++ b/src/config.c @@ -0,0 +1,150 @@ +#include "config.h" + +// Initialize config with defaults +static void init_default_config(Config* config) { + config->user.name = NULL; + config->user.email = NULL; +} + +// Free config memory +void free_config(Config* config) { + if (!config) return; + + free(config->user.name); + free(config->user.email); + + memset(config, 0, sizeof(*config)); +} + +// Get XDG config directory +static char* get_xdg_config_dir() { + char *xdg_config = getenv("XDG_CONFIG_HOME"); + if (xdg_config && strlen(xdg_config) > 0) { + return strdup(xdg_config); + } + + char *home = getenv("HOME"); + if (!home) { + fprintf(stderr, "Error: HOME environment variable not set\n"); + return NULL; + } + + size_t len = strlen(home) + strlen("/.config") + 1; + char *config_dir = malloc(len); + if (!config_dir) { + perror("malloc"); + return NULL; + } + + snprintf(config_dir, len, "%s/.config", home); + return config_dir; +} + +// Get config file path +static char* get_config_path() { + char *config_dir = get_xdg_config_dir(); + if (!config_dir) return NULL; + + size_t len = strlen(config_dir) + strlen("/merk/config.toml") + 1; + char *config_path = malloc(len); + if (!config_path) { + free(config_dir); + return NULL; + } + + snprintf(config_path, len, "%s/merk/config.toml", config_dir); + free(config_dir); + + return config_path; +} + +// Parse TOML config into Config +static int parse_toml_config(toml_result_t result, Config* config) { + if (!result.ok) { + fprintf(stderr, "TOML parse error: %s\n", result.errmsg); + return -1; + } + + toml_datum_t root = result.toptab; + if (root.type != TOML_TABLE) { + fprintf(stderr, "Root element is not a table\n"); + return -1; + } + + toml_datum_t user_table = toml_get(root, "user"); + if (user_table.type != TOML_TABLE) { + fprintf(stderr, "Warning: 'user' table not found or invalid\n"); + return 0; + } + + toml_datum_t name = toml_get(user_table, "name"); + if (name.type == TOML_STRING) { + config->user.name = strdup(name.u.s); + if (!config->user.name) { + perror("strdup"); + return -1; + } + } + + toml_datum_t email = toml_get(user_table, "email"); + if (email.type == TOML_STRING) { + config->user.email = strdup(email.u.s); + if (!config->user.email) { + perror("strdup"); + return -1; + } + } + + return 0; +} + +// Load configuration from file +int load_config(Config* config) { + if (!config) return -1; + + init_default_config(config); + + char *config_path = get_config_path(); + + if (!config_path) { + fprintf(stderr, "Failed to get config path\n"); + return -1; + } + + if (access(config_path, F_OK) != 0) { + if (create_default_config_file(config_path) < 0) { + free(config_path); + return -1; + } + } + + toml_result_t result = toml_parse_file_ex(config_path); + free(config_path); + + int ret = parse_toml_config(result, config); + toml_free(result); + + return ret; +} + +// Validate configuration +int validate_config(Config* config) { + if (!config) return -1; + + if (!config->user.name || strlen(config->user.name) == 0) { + fprintf(stderr, "Error: User name is required\n"); + return -1; + } + + if (!config->user.email || strlen(config->user.email) == 0) { + fprintf(stderr, "Error: User email is required\n"); + return -1; + } + + if (!strchr(config->user.email, '@') || !strchr(config->user.email, '.')) { + fprintf(stderr, "Error: Invalid email format\n"); + return -1; + } + + return 0; +}