From 6d5b096d2756ae625e2d7c28c7a9d8466539ebfa Mon Sep 17 00:00:00 2001
From: Kubat <mael.martin31@gmail.com>
Date: Sun, 13 Sep 2020 18:02:02 +0200
Subject: [PATCH] CONF: Write default config file if it doesn't exists

---
 inc/lektor/config.h |  3 +++
 src/base/config.c   | 19 ++++++++++++++++
 src/main/server.c   | 55 +++++++++++++++++++++++++++++++++++++++------
 3 files changed, 70 insertions(+), 7 deletions(-)

diff --git a/inc/lektor/config.h b/inc/lektor/config.h
index 074fb50b..4515f0e3 100644
--- a/inc/lektor/config.h
+++ b/inc/lektor/config.h
@@ -37,6 +37,9 @@ int config_new(volatile sqlite3 *db, const char *conf);
 /* Prints the default config file. */
 void config_default(FILE *output);
 
+/* Get the default user config file, the ~/.config/lektor/lektor.ini file. */
+void config_default_file(char *dest, size_t len);
+
 /* Manipulate Environment Variables */
 #define env_set(var, val)   setenv(var, val, 1)
 #define env_get             getenv
diff --git a/src/base/config.c b/src/base/config.c
index 711df535..4d5d7d50 100644
--- a/src/base/config.c
+++ b/src/base/config.c
@@ -164,6 +164,25 @@ ini_parse(const char *path, volatile sqlite3 *db)
     return error;
 }
 
+void
+config_default_file(char *dest, size_t len)
+{
+    /* TODO: Use ~/.config/baka and not ~/.config/lektor. */
+    /* First try the XDG_CONFIG_HOME variable, else the default location HOME/.config. */
+    memset(dest, 0, len * sizeof(char));
+    char *home = getenv("XDG_CONFIG_HOME");
+    if (NULL == home || strlen(home) >= len) {
+        home = getenv("HOME");
+        if (NULL == home) {
+            LOG_ERROR("FATAL", "Failed to get home folder for user, will now exit");
+            exit(EXIT_FAILURE);
+        }
+        strncat(dest, "/.config/lektor/lektor.ini", len - 1);
+    } else {
+        strncat(dest, "/lektor/lektor.ini", len - 1);
+    }
+}
+
 int
 config_detect_file(char *conf, size_t conf_len)
 {
diff --git a/src/main/server.c b/src/main/server.c
index fb1c4cba..12515efe 100644
--- a/src/main/server.c
+++ b/src/main/server.c
@@ -16,12 +16,36 @@
 #include <string.h>
 #include <strings.h>
 #include <pthread.h>
+#include <sys/stat.h>
 
 #if defined (LKT_STATIC_MODULE)
-    REG_DECLARE(sdl2_reg)
-    REG_DECLARE(repo_reg)
+REG_DECLARE(sdl2_reg)
+REG_DECLARE(repo_reg)
 #endif
 
+/* Recursive mkdir, where the last word of the string is a file, not a folder. */
+static inline void
+__mkdir(const char *dir)
+{
+    char tmp[PATH_MAX];
+    char *p = NULL;
+    safe_snprintf(tmp, sizeof(tmp), "%s", dir);
+    size_t len = strlen(tmp);
+    /* In our case, the final word is always a file, not a folder. */
+    if (tmp[len - 1] == '/')
+        tmp[len - 1] = 0;
+    for (p = tmp + 1; *p; p++) {
+        if(*p == '/') {
+            *p = 0;
+            mkdir(tmp, 00700);
+            *p = '/';
+        }
+    }
+    /* Don't do final mkdir here, because in our case the final word in the string
+     * is a file, not a folder.
+     * mkdir(tmp, S_IRWXU); */
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -62,9 +86,7 @@ main(int argc, char *argv[])
     /* Init the server */
     char *db_path   = safe_malloc(PATH_MAX * sizeof(char));
     char *kara_dir  = safe_malloc(PATH_MAX * sizeof(char));
-    struct lkt_state srv = {
-        .kara_prefix = kara_dir,
-    };
+    struct lkt_state srv = { .kara_prefix = kara_dir };
     if (lkt_queue_new(&srv.queue)) {
         LOG_ERROR("INIT", "Faield to create server queue");
         exit(EXIT_FAILURE);
@@ -76,9 +98,28 @@ main(int argc, char *argv[])
         exit(EXIT_FAILURE);
     }
 
+    /* Read or create default config file. */
+    int retry_config_once = 0;
+retry_config:
     if (conf_file[0] == '\0' && config_detect_file(conf_file, PATH_MAX)) {
-        LOG_ERROR("INIT", "Failed to find a config file");
-        exit(EXIT_FAILURE);
+        if (retry_config_once) {
+            LOG_ERROR("INIT", "Failed to find a config file");
+            exit(EXIT_FAILURE);
+        } else {
+            LOG_INFO("INIT", "Creating default config file");
+            config_default_file(conf_file, PATH_MAX);
+            __mkdir(conf_file); /* Create the folder for the file. */
+            FILE *file_desc = fopen(conf_file, "w+");
+            if (NULL == file_desc) {
+                LOG_ERROR("FATAL", "Failed to open default config fiel for initializing it");
+                exit(EXIT_FAILURE);
+            }
+            config_default(file_desc);
+            fclose(file_desc);
+            LOG_INFO("INIT", "Default configuration file has been writen to %s", conf_file);
+            retry_config_once = 1;
+            goto retry_config;
+        }
     }
 
     if (config_new(srv.db, conf_file)) {
-- 
GitLab