summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stapelberg <michael@stapelberg.de>2010-01-03 16:58:41 +0100
committerMichael Stapelberg <michael@stapelberg.de>2010-01-03 16:58:41 +0100
commit7c130fb540da378c4ba3744d2ff39983df3ad705 (patch)
tree72607e7d9a9a6b6bc89f0c00c26ce7fc5c19a34e
parentba2dd3a3ebef790b0f342027476238ef8bfc9d8e (diff)
Obey the XDG Base Directory Specification for config file paths
This means you can now put your i3 config into $XDG_CONFIG_HOME/i3/config, which probably is ~/.config/i3/config if not set otherwise.
-rw-r--r--src/config.c83
1 files changed, 70 insertions, 13 deletions
diff --git a/src/config.c b/src/config.c
index 930b09c..4babce1 100644
--- a/src/config.c
+++ b/src/config.c
@@ -15,8 +15,10 @@
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
+#include <sys/types.h>
#include <stdlib.h>
#include <glob.h>
+#include <unistd.h>
/* We need Xlib for XStringToKeysym */
#include <X11/Xlib.h>
@@ -47,6 +49,15 @@ static char *glob_path(const char *path) {
return result;
}
+/*
+ * Checks if the given path exists by calling stat().
+ *
+ */
+static bool path_exists(const char *path) {
+ struct stat buf;
+ return (stat(path, &buf) == 0);
+}
+
/**
* Ungrabs all keys, to be called before re-grabbing the keys because of a
* mapping_notify event or a configuration file reload
@@ -149,6 +160,61 @@ void switch_mode(xcb_connection_t *conn, const char *new_mode) {
}
/*
+ * Get the path of the first configuration file found. Checks the XDG folders
+ * first ($XDG_CONFIG_HOME, $XDG_CONFIG_DIRS), then the traditional paths.
+ *
+ */
+static char *get_config_path() {
+ /* 1: check for $XDG_CONFIG_HOME/i3/config */
+ char *xdg_config_home, *xdg_config_dirs, *config_path;
+
+ if ((xdg_config_home = getenv("XDG_CONFIG_HOME")) == NULL)
+ xdg_config_home = "~/.config";
+
+ xdg_config_home = glob_path(xdg_config_home);
+ if (asprintf(&config_path, "%s/i3/config", xdg_config_home) == -1)
+ die("asprintf() failed");
+ free(xdg_config_home);
+
+ if (path_exists(config_path))
+ return config_path;
+ free(config_path);
+
+ /* 2: check for $XDG_CONFIG_DIRS/i3/config */
+ if ((xdg_config_dirs = getenv("XDG_CONFIG_DIRS")) == NULL)
+ xdg_config_dirs = "/etc/xdg";
+
+ char *buf = strdup(xdg_config_dirs);
+ char *tok = strtok(buf, ":");
+ while (tok != NULL) {
+ tok = glob_path(tok);
+ if (asprintf(&config_path, "%s/i3/config", tok) == -1)
+ die("asprintf() failed");
+ free(tok);
+ if (path_exists(config_path)) {
+ free(buf);
+ return config_path;
+ }
+ free(config_path);
+ tok = strtok(NULL, ":");
+ }
+ free(buf);
+
+ /* 3: check traditional paths */
+ config_path = glob_path("~/.i3/config");
+ if (path_exists(config_path))
+ return config_path;
+
+ config_path = strdup("/etc/i3/config");
+ if (!path_exists(config_path))
+ die("Neither $XDG_CONFIG_HOME/i3/config, nor "
+ "$XDG_CONFIG_DIRS/i3/config, nor ~/.i3/config nor "
+ "/etc/i3/config exist.");
+
+ return config_path;
+}
+
+/*
* Finds the configuration file to use (either the one specified by
* override_configpath), the user’s one or the system default) and calls
* parse_file().
@@ -160,19 +226,10 @@ static void parse_configuration(const char *override_configpath) {
return;
}
- FILE *handle;
- char *globbed = glob_path("~/.i3/config");
- if ((handle = fopen(globbed, "r")) == NULL) {
- if ((handle = fopen("/etc/i3/config", "r")) == NULL)
- die("Neither \"%s\" nor /etc/i3/config could be opened\n", globbed);
-
- parse_file("/etc/i3/config");
- fclose(handle);
- return;
- }
-
- parse_file(globbed);
- fclose(handle);
+ char *path = get_config_path();
+ DLOG("Parsing configfile %s\n", path);
+ parse_file(path);
+ free(path);
}
/*