]> git.sur5r.net Git - i3/i3/commitdiff
Port the path resolution and config loading code from -next.
authorFernando Tarlá Cardoso Lemos <fernandotcl@gmail.com>
Mon, 15 Nov 2010 00:54:40 +0000 (22:54 -0200)
committerMichael Stapelberg <michael@stapelberg.de>
Mon, 15 Nov 2010 13:00:46 +0000 (14:00 +0100)
common.mk
include/config.h
src/config.c
src/tree.c
src/util.c

index 00300cf88d71fb2362a1d389e0e08634f94e6b76..492980497b27de3fefb4e5cffdc5f7b6749809e0 100644 (file)
--- a/common.mk
+++ b/common.mk
@@ -20,6 +20,7 @@ CFLAGS += -Wunused-value
 CFLAGS += -Iinclude
 CFLAGS += -I/usr/local/include
 CFLAGS += -DI3_VERSION=\"${GIT_VERSION}\"
+CFLAGS += -DSYSCONFDIR=\"${SYSCONFDIR}\"
 
 LDFLAGS += -lm
 LDFLAGS += -lxcb-event
index ab2dac878b4d973388ed1c77715ce28dca981777..c9e8e1a4f138efa0565b9381b4cd7837d957a0cd 100644 (file)
@@ -127,7 +127,7 @@ struct Config {
         } bar;
 };
 
-char *glob_path(const char *path);
+char *resolve_tilde(const char *path);
 bool path_exists(const char *path);
 
 /**
index b37f013c18d73c6a028c65e254033822b3a9914f..93390b4a69c80d31532f7f2ecbe46a58c6e0537f 100644 (file)
 Config config;
 struct modes_head modes;
 
+
 /*
  * This function resolves ~ in pathnames.
+ * It may resolve wildcards in the first part of the path, but if no match
+ * or multiple matches are found, it just returns a copy of path as given.
  *
  */
-char *glob_path(const char *path) {
+char *resolve_tilde(const char *path) {
         static glob_t globbuf;
-        if (glob(path, GLOB_NOCHECK | GLOB_TILDE, NULL, &globbuf) < 0)
-                die("glob() failed");
-        char *result = sstrdup(globbuf.gl_pathc > 0 ? globbuf.gl_pathv[0] : path);
-        globfree(&globbuf);
+        char *head, *tail, *result;
 
-        /* If the file does not exist yet, we still may need to resolve tilde,
-         * so call wordexp */
-        if (strcmp(result, path) == 0) {
-                wordexp_t we;
-                wordexp(path, &we, WRDE_NOCMD);
-                if (we.we_wordc > 0) {
-                        free(result);
-                        result = sstrdup(we.we_wordv[0]);
-                }
-                wordfree(&we);
+        tail = strchr(path, '/');
+        head = strndup(path, tail ? tail - path : strlen(path));
+
+        int res = glob(head, GLOB_TILDE, NULL, &globbuf);
+        free(head);
+        /* no match, or many wildcard matches are bad */
+        if (res == GLOB_NOMATCH || globbuf.gl_pathc != 1)
+                result = sstrdup(path);
+        else if (res != 0) {
+                die("glob() failed");
+        } else {
+                head = globbuf.gl_pathv[0];
+                result = scalloc(strlen(head) + (tail ? strlen(tail) : 0) + 1);
+                strncpy(result, head, strlen(head));
+                strncat(result, tail, strlen(tail));
         }
+        globfree(&globbuf);
 
         return result;
 }
 
-
 /*
  * Checks if the given path exists by calling stat().
  *
@@ -205,18 +210,24 @@ 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.
+ * Get the path of the first configuration file found. Checks the home directory
+ * first, then the system directory first, always taking into account the XDG
+ * Base Directory Specification ($XDG_CONFIG_HOME, $XDG_CONFIG_DIRS)
  *
  */
 static char *get_config_path() {
-        /* 1: check for $XDG_CONFIG_HOME/i3/config */
         char *xdg_config_home, *xdg_config_dirs, *config_path;
 
+        /* 1: check the traditional path under the home directory */
+        config_path = resolve_tilde("~/.i3/config");
+        if (path_exists(config_path))
+                return config_path;
+
+        /* 2: check for $XDG_CONFIG_HOME/i3/config */
         if ((xdg_config_home = getenv("XDG_CONFIG_HOME")) == NULL)
                 xdg_config_home = "~/.config";
 
-        xdg_config_home = glob_path(xdg_config_home);
+        xdg_config_home = resolve_tilde(xdg_config_home);
         if (asprintf(&config_path, "%s/i3/config", xdg_config_home) == -1)
                 die("asprintf() failed");
         free(xdg_config_home);
@@ -225,14 +236,19 @@ static char *get_config_path() {
                 return config_path;
         free(config_path);
 
-        /* 2: check for $XDG_CONFIG_DIRS/i3/config */
+        /* 3: check the traditional path under /etc */
+        config_path = SYSCONFDIR "/i3/config";
+        if (path_exists(config_path))
+                return sstrdup(config_path);
+
+        /* 4: 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 *buf = sstrdup(xdg_config_dirs);
         char *tok = strtok(buf, ":");
         while (tok != NULL) {
-                tok = glob_path(tok);
+                tok = resolve_tilde(tok);
                 if (asprintf(&config_path, "%s/i3/config", tok) == -1)
                         die("asprintf() failed");
                 free(tok);
@@ -245,18 +261,9 @@ static char *get_config_path() {
         }
         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;
+        die("Unable to find the configuration file (looked at "
+                "~/.i3/config, $XDG_CONFIG_HOME/i3/config, "
+                SYSCONFDIR "i3/config and $XDG_CONFIG_DIRS/i3/config)");
 }
 
 /*
index 6ba83ea701ae3464c91e0b7a1c1bdebc99343e07..7d12cab1799368d89c052e5a5f385b1a66839451 100644 (file)
@@ -14,7 +14,7 @@ struct all_cons_head all_cons = TAILQ_HEAD_INITIALIZER(all_cons);
  *
  */
 bool tree_restore() {
-    char *globbed = glob_path("~/.i3/_restart.json");
+    char *globbed = resolve_tilde("~/.i3/_restart.json");
 
     if (!path_exists(globbed)) {
         LOG("%s does not exist, not restoring tree\n", globbed);
@@ -27,7 +27,7 @@ bool tree_restore() {
     focused = croot;
 
     tree_append_json(globbed);
-    char *old_restart = glob_path("~/.i3/_restart.json.old");
+    char *old_restart = resolve_tilde("~/.i3/_restart.json.old");
     unlink(old_restart);
     rename(globbed, old_restart);
     free(globbed);
index fc3ada5fdfa1b66a18625bab3501866b489e71de..df69ecc412a79ac97bdeb0f9c99e77922777d2aa 100644 (file)
@@ -485,7 +485,7 @@ void store_restart_layout() {
         unsigned int length;
         y(get_buf, &payload, &length);
 
-        char *globbed = glob_path("~/.i3/_restart.json");
+        char *globbed = resolve_tilde("~/.i3/_restart.json");
         int fd = open(globbed, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
         free(globbed);
         if (fd == -1) {