]> git.sur5r.net Git - i3/i3/blobdiff - src/util.c
Add force_xinerama configuration option
[i3/i3] / src / util.c
index f95ccaf36a23b2d003ef3ba3a89373c1ad073f0a..2d6c3e147138d147de2f80dacb5bc1d74b950a67 100644 (file)
@@ -19,6 +19,7 @@
 #include <fcntl.h>
 #include <pwd.h>
 #include <yajl/yajl_version.h>
+#include <libgen.h>
 
 #include "all.h"
 
@@ -76,7 +77,8 @@ void *scalloc(size_t size) {
 
 void *srealloc(void *ptr, size_t size) {
     void *result = realloc(ptr, size);
-    exit_if_null(result, "Error: out memory (realloc(%zd))\n", size);
+    if (result == NULL && size > 0)
+        die("Error: out memory (realloc(%zd))\n", size);
     return result;
 }
 
@@ -118,6 +120,53 @@ void start_application(const char *command) {
     wait(0);
 }
 
+/*
+ * exec()s an i3 utility, for example the config file migration script or
+ * i3-nagbar. This function first searches $PATH for the given utility named,
+ * then falls back to the dirname() of the i3 executable path and then falls
+ * back to the dirname() of the target of /proc/self/exe (on linux).
+ *
+ * This function should be called after fork()ing.
+ *
+ * The first argument of the given argv vector will be overwritten with the
+ * executable name, so pass NULL.
+ *
+ * If the utility cannot be found in any of these locations, it exits with
+ * return code 2.
+ *
+ */
+void exec_i3_utility(char *name, char *argv[]) {
+    /* start the migration script, search PATH first */
+    char *migratepath = name;
+    argv[0] = migratepath;
+    execvp(migratepath, argv);
+
+    /* if the script is not in path, maybe the user installed to a strange
+     * location and runs the i3 binary with an absolute path. We use
+     * argv[0]’s dirname */
+    char *pathbuf = strdup(start_argv[0]);
+    char *dir = dirname(pathbuf);
+    asprintf(&migratepath, "%s/%s", dir, name);
+    argv[0] = migratepath;
+    execvp(migratepath, argv);
+
+#if defined(__linux__)
+    /* on linux, we have one more fall-back: dirname(/proc/self/exe) */
+    char buffer[BUFSIZ];
+    if (readlink("/proc/self/exe", buffer, BUFSIZ) == -1) {
+        warn("could not read /proc/self/exe");
+        exit(1);
+    }
+    dir = dirname(buffer);
+    asprintf(&migratepath, "%s/%s", dir, name);
+    argv[0] = migratepath;
+    execvp(migratepath, argv);
+#endif
+
+    warn("Could not start %s", name);
+    exit(2);
+}
+
 /*
  * Checks a generic cookie for errors and quits with the given message if there
  * was an error.
@@ -325,11 +374,13 @@ char *store_restart_layout() {
         if (n == -1) {
             perror("write()");
             free(filename);
+            close(fd);
             return NULL;
         }
         if (n == 0) {
             printf("write == 0?\n");
             free(filename);
+            close(fd);
             return NULL;
         }
         written += n;
@@ -358,6 +409,8 @@ char *store_restart_layout() {
 void i3_restart(bool forget_layout) {
     char *restart_filename = forget_layout ? NULL : store_restart_layout();
 
+    kill_configerror_nagbar(true);
+
     restore_geometry();
 
     ipc_shutdown();
@@ -398,9 +451,7 @@ void i3_restart(bool forget_layout) {
     /* not reached */
 }
 
-#if 0
-
-#if defined(__OpenBSD__)
+#if defined(__OpenBSD__) || defined(__APPLE__)
 
 /*
  * Taken from FreeBSD
@@ -408,31 +459,54 @@ void i3_restart(bool forget_layout) {
  *
  */
 void *memmem(const void *l, size_t l_len, const void *s, size_t s_len) {
-        register char *cur, *last;
-        const char *cl = (const char *)l;
-        const char *cs = (const char *)s;
+    register char *cur, *last;
+    const char *cl = (const char *)l;
+    const char *cs = (const char *)s;
 
-        /* we need something to compare */
-        if (l_len == 0 || s_len == 0)
-                return NULL;
+    /* we need something to compare */
+    if (l_len == 0 || s_len == 0)
+        return NULL;
 
-        /* "s" must be smaller or equal to "l" */
-        if (l_len < s_len)
-                return NULL;
+    /* "s" must be smaller or equal to "l" */
+    if (l_len < s_len)
+        return NULL;
 
-        /* special case where s_len == 1 */
-        if (s_len == 1)
-                return memchr(l, (int)*cs, l_len);
+    /* special case where s_len == 1 */
+    if (s_len == 1)
+        return memchr(l, (int)*cs, l_len);
 
-        /* the last position where its possible to find "s" in "l" */
-        last = (char *)cl + l_len - s_len;
+    /* the last position where its possible to find "s" in "l" */
+    last = (char *)cl + l_len - s_len;
 
-        for (cur = (char *)cl; cur <= last; cur++)
-                if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0)
-                        return cur;
+    for (cur = (char *)cl; cur <= last; cur++)
+        if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0)
+            return cur;
 
-        return NULL;
+    return NULL;
 }
 
 #endif
+
+#if defined(__APPLE__)
+
+/*
+ * Taken from FreeBSD
+ * Returns a pointer to a new string which is a duplicate of the
+ * string, but only copies at most n characters.
+ *
+ */
+char *strndup(const char *str, size_t n) {
+    size_t len;
+    char *copy;
+
+    for (len = 0; len < n && str[len]; len++)
+        continue;
+
+    if ((copy = malloc(len + 1)) == NULL)
+        return (NULL);
+    memcpy(copy, str, len);
+    copy[len] = '\0';
+    return (copy);
+}
+
 #endif