feat(config): added a simple user config

This commit is contained in:
lisk77 2025-08-29 20:15:19 +02:00
parent 1e4677bcda
commit a089bc43c3
2 changed files with 170 additions and 0 deletions

20
include/config.h Normal file
View file

@ -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

150
src/config.c Normal file
View file

@ -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;
}