From ccc818fda58646bd34318ab53d7cef2c50dbbf4e Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Sat, 18 Jul 2020 11:28:39 +0100 Subject: [PATCH] Add src/config/config-dir.c --- include/config/config-dir.h | 6 ++++ src/config/config-dir.c | 70 +++++++++++++++++++++++++++++++++++++ src/config/meson.build | 1 + src/config/rcxml.c | 21 +++++++++-- src/main.c | 10 ++++-- 5 files changed, 102 insertions(+), 6 deletions(-) create mode 100644 include/config/config-dir.h create mode 100644 src/config/config-dir.c diff --git a/include/config/config-dir.h b/include/config/config-dir.h new file mode 100644 index 00000000..bf74960f --- /dev/null +++ b/include/config/config-dir.h @@ -0,0 +1,6 @@ +#ifndef CONFIG_DIR_H +#define CONFIG_DIR_H + +char *config_dir(void); + +#endif /* CONFIG_DIR_H */ diff --git a/src/config/config-dir.c b/src/config/config-dir.c new file mode 100644 index 00000000..f506b960 --- /dev/null +++ b/src/config/config-dir.c @@ -0,0 +1,70 @@ +/* + * Find the labwc configuration directory + * + * Copyright Johan Malm 2020 + */ + +#include +#include +#include +#include +#include + +#include "config/config-dir.h" + +struct dir { + const char *prefix; + const char *path; +}; + +/* clang-format off */ +static struct dir config_dirs[] = { + { "XDG_CONFIG_HOME", "labwc" }, + { "HOME", ".config/labwc" }, + { "XDG_CONFIG_DIRS", "labwc" }, + { NULL, "/etc/xdg/labwc" }, + { "XDG_CONFIG_HOME", "openbox" }, + { "HOME", ".config/openbox" }, + { "XDG_CONFIG_DIRS", "openbox" }, + { NULL, "/etc/xdg/openbox" }, + { NULL, NULL } +}; +/* clang-format on */ + +static bool isdir(const char *path) +{ + struct stat st; + return (!stat(path, &st) && S_ISDIR(st.st_mode)); +} + +char *config_dir(void) +{ + static char buf[4096] = { 0 }; + if (buf[0] != '\0') + return buf; + + for (int i = 0; config_dirs[i].path; i++) { + struct dir d = config_dirs[i]; + if (!d.prefix) { + /* handle /etc/xdg... */ + snprintf(buf, sizeof(buf), "%s", d.path); + if (isdir(buf)) + return buf; + } else { + /* handle $HOME/.config/... and $XDG_* */ + char *prefix = getenv(d.prefix); + if (!prefix) + continue; + gchar **prefixes = g_strsplit(prefix, ":", -1); + for (gchar **p = prefixes; *p; p++) { + snprintf(buf, sizeof(buf), "%s/%s", *p, d.path); + if (isdir(buf)) + return buf; + } + } + } + /* no config directory was found */ + buf[0] = '.'; + buf[1] = '\0'; + return buf; +} diff --git a/src/config/meson.build b/src/config/meson.build index ac8e6012..97a67693 100644 --- a/src/config/meson.build +++ b/src/config/meson.build @@ -1,4 +1,5 @@ labwc_sources += files( + 'config-dir.c', 'rcxml.c', 'keybind.c', ) diff --git a/src/config/rcxml.c b/src/config/rcxml.c index 460e9a0c..b6381a76 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -11,6 +11,7 @@ #include #include "rcxml.h" +#include "config/config-dir.h" static bool in_keybind = false; static bool is_attribute = false; @@ -192,20 +193,34 @@ static void post_processing(void) } } +static void rcxml_path(char *buf, size_t len, const char *filename) +{ + if (filename) + snprintf(buf, len, "%s", filename); + else + snprintf(buf, len, "%s/rc.xml", config_dir()); +} + void rcxml_read(const char *filename) { FILE *stream; char *line = NULL; size_t len = 0; struct buf b; + char rcxml[4096]; rcxml_init(); wl_list_init(&rc.keybinds); - /* Read into buffer and then call rcxml_parse_xml() */ - stream = fopen(filename, "r"); + /* + * Reading file into buffer before parsing makes it easier to write + * unit tests. + */ + rcxml_path(rcxml, sizeof(rcxml), filename); + fprintf(stderr, "info: read config file (%s)\n", rcxml); + stream = fopen(rcxml, "r"); if (!stream) { - fprintf(stderr, "warn: cannot read '%s'\n", filename); + fprintf(stderr, "warn: cannot read '%s'\n", rcxml); goto out; } buf_init(&b); diff --git a/src/main.c b/src/main.c index fe3f1753..7a3f67e4 100644 --- a/src/main.c +++ b/src/main.c @@ -8,7 +8,7 @@ struct rcxml rc = { 0 }; struct theme theme = { 0 }; static const char labwc_usage[] = -"Usage: labwc [-h] [-s ]\n"; +"Usage: labwc [-h] [-s ] [-c ]\n"; static void usage(void) { @@ -19,14 +19,18 @@ static void usage(void) int main(int argc, char *argv[]) { char *startup_cmd = NULL; + char *config_file = NULL; wlr_log_init(WLR_ERROR, NULL); int c; - while ((c = getopt(argc, argv, "s:h")) != -1) { + while ((c = getopt(argc, argv, "s:c:h")) != -1) { switch (c) { case 's': startup_cmd = optarg; break; + case 'c': + config_file = optarg; + break; default: usage(); } @@ -34,7 +38,7 @@ int main(int argc, char *argv[]) if (optind < argc) usage(); - rcxml_read("data/rc.xml"); + rcxml_read(config_file); /* Wayland requires XDG_RUNTIME_DIR to be set */ if (!getenv("XDG_RUNTIME_DIR")) { -- 2.52.0