]> git.sur5r.net Git - i3/i3/commitdiff
Port the IPC socket creation code from -next.
authorFernando Tarlá Cardoso Lemos <fernandotcl@gmail.com>
Mon, 15 Nov 2010 01:01:04 +0000 (23:01 -0200)
committerMichael Stapelberg <michael@stapelberg.de>
Mon, 15 Nov 2010 13:00:48 +0000 (14:00 +0100)
src/ipc.c

index eed63bd4e0072820095561d5b044b1feb19b9f81..b8409a929fd7d4c303b55934eaced98bf0553d85 100644 (file)
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -13,6 +13,7 @@
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <fcntl.h>
+#include <libgen.h>
 #include <ev.h>
 #include <yajl/yajl_gen.h>
 #include <yajl/yajl_parse.h>
@@ -38,6 +39,34 @@ static void set_nonblock(int sockfd) {
                 err(-1, "Could not set O_NONBLOCK");
 }
 
+/*
+ * Emulates mkdir -p (creates any missing folders)
+ *
+ */
+static bool mkdirp(const char *path) {
+        if (mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0)
+                return true;
+        if (errno != ENOENT) {
+                ELOG("mkdir(%s) failed: %s\n", path, strerror(errno));
+                return false;
+        }
+        char *copy = strdup(path);
+        /* strip trailing slashes, if any */
+        while (copy[strlen(copy)-1] == '/')
+                copy[strlen(copy)-1] = '\0';
+
+        char *sep = strrchr(copy, '/');
+        if (sep == NULL)
+                return false;
+        *sep = '\0';
+        bool result = false;
+        if (mkdirp(copy))
+                result = mkdirp(path);
+        free(copy);
+
+        return result;
+}
+
 static void ipc_send_message(int fd, const unsigned char *payload,
                              int message_type, int message_size) {
         int buffer_size = strlen("i3-ipc") + sizeof(uint32_t) +
@@ -555,11 +584,20 @@ void ipc_new_client(EV_P_ struct ev_io *w, int revents) {
 int ipc_create_socket(const char *filename) {
         int sockfd;
 
+        char *resolved = resolve_tilde(filename);
+        DLOG("Creating IPC-socket at %s\n", resolved);
+        char *copy = sstrdup(resolved);
+        const char *dir = dirname(copy);
+        if (!path_exists(dir))
+                mkdirp(dir);
+        free(copy);
+
         /* Unlink the unix domain socket before */
         unlink(filename);
 
         if ((sockfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) {
                 perror("socket()");
+                free(resolved);
                 return -1;
         }
 
@@ -568,12 +606,14 @@ int ipc_create_socket(const char *filename) {
         struct sockaddr_un addr;
         memset(&addr, 0, sizeof(struct sockaddr_un));
         addr.sun_family = AF_LOCAL;
-        strcpy(addr.sun_path, filename);
+        strncpy(addr.sun_path, resolved, sizeof(addr.sun_path) - 1);
         if (bind(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_un)) < 0) {
                 perror("bind()");
+                free(resolved);
                 return -1;
         }
 
+        free(resolved);
         set_nonblock(sockfd);
 
         if (listen(sockfd, 5) < 0) {