From 131a6158c851aed4c569c382829f756b5c167d89 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 15 Jan 2021 14:48:10 +0100 Subject: [PATCH] move set_nonblock, create_socket and path_exists to libi3 --- include/libi3.h | 24 ++++++++++++++ libi3/create_socket.c | 70 +++++++++++++++++++++++++++++++++++++++++ libi3/get_config_path.c | 9 ------ libi3/nonblock.c | 20 ++++++++++++ libi3/path_exists.c | 21 +++++++++++++ meson.build | 3 ++ src/ipc.c | 60 +---------------------------------- src/util.c | 8 ----- 8 files changed, 139 insertions(+), 76 deletions(-) create mode 100644 libi3/create_socket.c create mode 100644 libi3/nonblock.c create mode 100644 libi3/path_exists.c diff --git a/include/libi3.h b/include/libi3.h index c0b9ddbd3..e693c3ad4 100644 --- a/include/libi3.h +++ b/include/libi3.h @@ -638,3 +638,27 @@ void draw_util_clear_surface(surface_t *surface, color_t color); */ void draw_util_copy_surface(surface_t *src, surface_t *dest, double src_x, double src_y, double dest_x, double dest_y, double width, double height); + +/** + * Puts the given socket file descriptor into non-blocking mode or dies if + * setting O_NONBLOCK failed. Non-blocking sockets are a good idea for our + * IPC model because we should by no means block the window manager. + * + */ +void set_nonblock(int sockfd); + +/** + * Creates the UNIX domain socket at the given path, sets it to non-blocking + * mode, bind()s and listen()s on it. + * + * The full path to the socket is stored in the char* that out_socketpath points + * to. + * + */ +int create_socket(const char *filename, char **out_socketpath); + +/** + * Checks if the given path exists by calling stat(). + * + */ +bool path_exists(const char *path); diff --git a/libi3/create_socket.c b/libi3/create_socket.c new file mode 100644 index 000000000..1de7422a3 --- /dev/null +++ b/libi3/create_socket.c @@ -0,0 +1,70 @@ +/* + * vim:ts=4:sw=4:expandtab + * + * i3 - an improved dynamic tiling window manager + * © 2009 Michael Stapelberg and contributors (see also: LICENSE) + * + */ +#include "libi3.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Creates the UNIX domain socket at the given path, sets it to non-blocking + * mode, bind()s and listen()s on it. + * + * The full path to the socket is stored in the char* that out_socketpath points + * to. + * + */ +int create_socket(const char *filename, char **out_socketpath) { + int sockfd; + + char *resolved = resolve_tilde(filename); + DLOG("Creating UNIX socket at %s\n", resolved); + char *copy = sstrdup(resolved); + const char *dir = dirname(copy); + if (!path_exists(dir)) + mkdirp(dir, DEFAULT_DIR_MODE); + free(copy); + + /* Unlink the unix domain socket before */ + unlink(resolved); + + if ((sockfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) { + perror("socket()"); + free(resolved); + return -1; + } + + (void)fcntl(sockfd, F_SETFD, FD_CLOEXEC); + + struct sockaddr_un addr; + memset(&addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family = AF_LOCAL; + 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; + } + + set_nonblock(sockfd); + + if (listen(sockfd, 5) < 0) { + perror("listen()"); + free(resolved); + return -1; + } + + free(*out_socketpath); + *out_socketpath = resolved; + return sockfd; +} diff --git a/libi3/get_config_path.c b/libi3/get_config_path.c index 4909e116b..1f2b4c05a 100644 --- a/libi3/get_config_path.c +++ b/libi3/get_config_path.c @@ -11,15 +11,6 @@ #include #include -/* - * Checks if the given path exists by calling stat(). - * - */ -static bool path_exists(const char *path) { - struct stat buf; - return (stat(path, &buf) == 0); -} - /* * Get the path of the first configuration file found. If override_configpath is * specified, that path is returned and saved for further calls. Otherwise, diff --git a/libi3/nonblock.c b/libi3/nonblock.c new file mode 100644 index 000000000..77347e32e --- /dev/null +++ b/libi3/nonblock.c @@ -0,0 +1,20 @@ +#include "libi3.h" + +#include +#include + +/* + * Puts the given socket file descriptor into non-blocking mode or dies if + * setting O_NONBLOCK failed. Non-blocking sockets are a good idea for our + * IPC model because we should by no means block the window manager. + * + */ +void set_nonblock(int sockfd) { + int flags = fcntl(sockfd, F_GETFL, 0); + if (flags & O_NONBLOCK) { + return; + } + flags |= O_NONBLOCK; + if (fcntl(sockfd, F_SETFL, flags) < 0) + err(-1, "Could not set O_NONBLOCK"); +} diff --git a/libi3/path_exists.c b/libi3/path_exists.c new file mode 100644 index 000000000..5451c3bdd --- /dev/null +++ b/libi3/path_exists.c @@ -0,0 +1,21 @@ +/* + * vim:ts=4:sw=4:expandtab + * + * i3 - an improved dynamic tiling window manager + * © 2009 Michael Stapelberg and contributors (see also: LICENSE) + * + */ +#include "libi3.h" + +#include +#include +#include + +/* + * Checks if the given path exists by calling stat(). + * + */ +bool path_exists(const char *path) { + struct stat buf; + return (stat(path, &buf) == 0); +} diff --git a/meson.build b/meson.build index 2c2d63e9f..ad519e802 100644 --- a/meson.build +++ b/meson.build @@ -325,6 +325,7 @@ ev_dep = cc.find_library('ev') inc = include_directories('include') libi3srcs = [ + 'libi3/create_socket.c', 'libi3/dpi.c', 'libi3/draw_util.c', 'libi3/fake_configure_notify.c', @@ -341,11 +342,13 @@ libi3srcs = [ 'libi3/ipc_recv_message.c', 'libi3/ipc_send_message.c', 'libi3/is_debug_build.c', + 'libi3/path_exists.c', 'libi3/resolve_tilde.c', 'libi3/root_atom_contents.c', 'libi3/safewrappers.c', 'libi3/string.c', 'libi3/ucs2_conversion.c', + 'libi3/nonblock.c', ] if not cdata.get('HAVE_STRNDUP') diff --git a/src/ipc.c b/src/ipc.c index 1711c5260..862e748e1 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -27,22 +27,6 @@ char *current_socketpath = NULL; TAILQ_HEAD(ipc_client_head, ipc_client) all_clients = TAILQ_HEAD_INITIALIZER(all_clients); -/* - * Puts the given socket file descriptor into non-blocking mode or dies if - * setting O_NONBLOCK failed. Non-blocking sockets are a good idea for our - * IPC model because we should by no means block the window manager. - * - */ -static void set_nonblock(int sockfd) { - int flags = fcntl(sockfd, F_GETFL, 0); - if (flags & O_NONBLOCK) { - return; - } - flags |= O_NONBLOCK; - if (fcntl(sockfd, F_SETFL, flags) < 0) - err(-1, "Could not set O_NONBLOCK"); -} - static void ipc_client_timeout(EV_P_ ev_timer *w, int revents); static void ipc_socket_writeable_cb(EV_P_ struct ev_io *w, int revents); @@ -1529,49 +1513,7 @@ ipc_client *ipc_new_client_on_fd(EV_P_ int fd) { * */ int ipc_create_socket(const char *filename) { - int sockfd; - - FREE(current_socketpath); - - 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, DEFAULT_DIR_MODE); - free(copy); - - /* Unlink the unix domain socket before */ - unlink(resolved); - - if ((sockfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) { - perror("socket()"); - free(resolved); - return -1; - } - - (void)fcntl(sockfd, F_SETFD, FD_CLOEXEC); - - struct sockaddr_un addr; - memset(&addr, 0, sizeof(struct sockaddr_un)); - addr.sun_family = AF_LOCAL; - 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; - } - - set_nonblock(sockfd); - - if (listen(sockfd, 5) < 0) { - perror("listen()"); - free(resolved); - return -1; - } - - current_socketpath = resolved; - return sockfd; + return create_socket(filename, ¤t_socketpath); } /* diff --git a/src/util.c b/src/util.c index cf7f41c8a..cba7319cf 100644 --- a/src/util.c +++ b/src/util.c @@ -176,14 +176,6 @@ void exec_i3_utility(char *name, char *argv[]) { _exit(2); } -/* - * Checks if the given path exists by calling stat(). - * - */ -bool path_exists(const char *path) { - struct stat buf; - return (stat(path, &buf) == 0); -} /* * Goes through the list of arguments (for exec()) and add/replace the given option,