diff --git a/include/libi3.h b/include/libi3.h index fd5fb03b..005167c7 100644 --- a/include/libi3.h +++ b/include/libi3.h @@ -294,6 +294,12 @@ size_t i3string_get_num_glyphs(i3String *str); */ int ipc_connect(const char *socket_path); +/** + * Connects to the socket at the given path with no fallback paths. Returns + * -1 if connect() fails and die()s for other errors. + */ +int ipc_connect_impl(const char *socket_path); + /** * Formats a message (payload) of the given size and type and sends it to i3 via * the given socket file descriptor. diff --git a/libi3/create_socket.c b/libi3/create_socket.c index 4b93ff2d..8b756a38 100644 --- a/libi3/create_socket.c +++ b/libi3/create_socket.c @@ -34,10 +34,20 @@ int create_socket(const char *filename, char **out_socketpath) { } free(copy); + /* Check if the socket is in use by another process (this call does not + * succeed if the socket is stale / the owner already exited) */ + int sockfd = ipc_connect_impl(resolved); + if (sockfd != -1) { + ELOG("Refusing to create UNIX socket at %s: Socket is already in use\n", resolved); + close(sockfd); + errno = EEXIST; + return -1; + } + /* Unlink the unix domain socket before */ unlink(resolved); - int sockfd = socket(AF_LOCAL, SOCK_STREAM, 0); + sockfd = socket(AF_LOCAL, SOCK_STREAM, 0); if (sockfd < 0) { perror("socket()"); free(resolved); diff --git a/libi3/ipc_connect.c b/libi3/ipc_connect.c index 871fe083..5da9f129 100644 --- a/libi3/ipc_connect.c +++ b/libi3/ipc_connect.c @@ -13,6 +13,7 @@ #include #include #include +#include /* * Connects to the i3 IPC socket and returns the file descriptor for the @@ -39,6 +40,20 @@ int ipc_connect(const char *socket_path) { path = sstrdup("/tmp/i3-ipc.sock"); } + int sockfd = ipc_connect_impl(path); + if (sockfd < 0) { + err(EXIT_FAILURE, "Could not connect to i3 on socket %s", path); + } + free(path); + return sockfd; +} + +/** + * Connects to the socket at the given path with no fallback paths. Returns + * -1 if connect() fails and die()s for other errors. + * + */ +int ipc_connect_impl(const char *socket_path) { int sockfd = socket(AF_LOCAL, SOCK_STREAM, 0); if (sockfd == -1) err(EXIT_FAILURE, "Could not create socket"); @@ -48,9 +63,10 @@ int ipc_connect(const char *socket_path) { struct sockaddr_un addr; memset(&addr, 0, sizeof(struct sockaddr_un)); addr.sun_family = AF_LOCAL; - strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1); - if (connect(sockfd, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) - err(EXIT_FAILURE, "Could not connect to i3 on socket %s", path); - free(path); + strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1); + if (connect(sockfd, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) { + close(sockfd); + return -1; + } return sockfd; }