From 68da76b74595b9c47e88230b074aefd17e903be9 Mon Sep 17 00:00:00 2001 From: progandy Date: Fri, 8 Jan 2016 18:24:29 +0100 Subject: [PATCH 1/3] swaybar: separate function for status_command exec --- swaybar/main.c | 73 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 20 deletions(-) diff --git a/swaybar/main.c b/swaybar/main.c index 98b75aeed..52d6fe370 100644 --- a/swaybar/main.c +++ b/swaybar/main.c @@ -1184,6 +1184,55 @@ void poll_for_update() { } } +/* + * spawn_sh_cmd forks and executes the specified shell command. + * If infd is set, it receives the fd for the shell's stdin. + * If outfd is set, it recieves the fd for the shell's stdout. + */ +int spawn_sh_cmd(char *command, int *infd, int *outfd) { + int pipeout[2]; + int pipein[2]; + pid_t pid; + if (infd) { + pipe(pipein); + } + if (outfd) { + pipe(pipeout); + } + pid = fork(); + if (pid == 0) { + if (outfd) { + close(pipeout[0]); + dup2(pipeout[1], STDOUT_FILENO); + close(pipeout[1]); + } + if (infd) { + close(pipeout[1]); + dup2(pipeout[0], STDIN_FILENO); + close(pipeout[0]); + } + char *const cmd[] = { + "sh", + "-c", + command, + NULL, + }; + execvp(cmd[0], cmd); + return 0; + } + + close(pipeout[1]); + close(pipein[0]); + if (outfd) { + *outfd = pipeout[0]; + } + if (infd) { + *infd = pipein[1]; + } + return pid; + +} + int main(int argc, char **argv) { char *socket_path = NULL; @@ -1270,27 +1319,11 @@ int main(int argc, char **argv) { bar_ipc_init(desired_output, bar_id); if (status_command) { - int pipefd[2]; - pipe(pipefd); - pid = fork(); - if (pid == 0) { - close(pipefd[0]); - dup2(pipefd[1], STDOUT_FILENO); - close(pipefd[1]); - char *const cmd[] = { - "sh", - "-c", - status_command, - NULL, - }; - execvp(cmd[0], cmd); - return 0; + pid = spawn_sh_cmd(status_command, NULL, &status_read_fd); + if (pid > 0) { + fcntl(status_read_fd, F_SETFL, O_NONBLOCK); + line[0] = '\0'; } - - close(pipefd[1]); - status_read_fd = pipefd[0]; - fcntl(status_read_fd, F_SETFL, O_NONBLOCK); - line[0] = '\0'; } signal(SIGTERM, sig_handler); From 227d9b82e4475c4789f2e9b5ff5409df50271e19 Mon Sep 17 00:00:00 2001 From: progandy Date: Fri, 8 Jan 2016 18:29:06 +0100 Subject: [PATCH 2/3] ipc-client: add functions for send without receive --- common/ipc-client.c | 12 +++++++++--- include/ipc-client.h | 5 +++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/common/ipc-client.c b/common/ipc-client.c index 813489135..acf7ae84f 100644 --- a/common/ipc-client.c +++ b/common/ipc-client.c @@ -76,20 +76,26 @@ void free_ipc_response(struct ipc_response *response) { free(response); } -char *ipc_single_command(int socketfd, uint32_t type, const char *payload, uint32_t *len) { +void ipc_send_command(int socketfd, uint32_t type, const char *payload, uint32_t len) { + char data[ipc_header_size]; uint32_t *data32 = (uint32_t *)(data + sizeof(ipc_magic)); memcpy(data, ipc_magic, sizeof(ipc_magic)); - data32[0] = *len; + data32[0] = len; data32[1] = type; if (write(socketfd, data, ipc_header_size) == -1) { sway_abort("Unable to send IPC header"); } - if (write(socketfd, payload, *len) == -1) { + if (write(socketfd, payload, len) == -1) { sway_abort("Unable to send IPC payload"); } +} + +char *ipc_single_command(int socketfd, uint32_t type, const char *payload, uint32_t *len) { + + ipc_send_command(socketfd, type, payload, *len); struct ipc_response *resp = ipc_recv_response(socketfd); char *response = resp->payload; diff --git a/include/ipc-client.h b/include/ipc-client.h index 030c80b67..141e18e8f 100644 --- a/include/ipc-client.h +++ b/include/ipc-client.h @@ -21,6 +21,11 @@ char *get_socketpath(void); * Opens the sway socket. */ int ipc_open_socket(const char *socket_path); +/** + * Issues a single IPC command without waiting for a response. + * Useful if events are sent on the same socket. + */ +void ipc_send_command(int socketfd, uint32_t type, const char *payload, uint32_t len); /** * Issues a single IPC command and returns the buffer. len will be updated with * the length of the buffer returned from sway. From 96d787fc49738e70c10f50960459c1463a4ab148 Mon Sep 17 00:00:00 2001 From: progandy Date: Fri, 8 Jan 2016 18:32:10 +0100 Subject: [PATCH 3/3] swaybar: combine ipc command and event sockets --- swaybar/main.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/swaybar/main.c b/swaybar/main.c index 52d6fe370..d18774709 100644 --- a/swaybar/main.c +++ b/swaybar/main.c @@ -66,7 +66,7 @@ struct status_block { list_t *status_line = NULL; list_t *workspaces = NULL; -int ipc_socketfd, ipc_event_socketfd; +int ipc_socketfd; pid_t pid; int status_read_fd; char line[1024]; @@ -158,10 +158,6 @@ void swaybar_teardown() { if (ipc_socketfd) { close(ipc_socketfd); } - - if (ipc_event_socketfd) { - close(ipc_event_socketfd); - } } void sway_terminate(void) { @@ -193,18 +189,15 @@ void free_workspace(void *item) { free(ws); } -void ipc_update_workspaces() { +void ipc_update_workspaces(char *payload) { if (workspaces) { list_foreach(workspaces, free_workspace); list_free(workspaces); } workspaces = create_list(); - uint32_t len = 0; - char *res = ipc_single_command(ipc_socketfd, IPC_GET_WORKSPACES, NULL, &len); - json_object *results = json_tokener_parse(res); + json_object *results = json_tokener_parse(payload); if (!results) { - free(res); return; } @@ -234,7 +227,6 @@ void ipc_update_workspaces() { } json_object_put(results); - free(res); } uint32_t parse_color(const char *color) { @@ -421,10 +413,10 @@ void bar_ipc_init(int outputi, const char *bar_id) { const char *subscribe_json = "[ \"workspace\", \"mode\" ]"; len = strlen(subscribe_json); - res = ipc_single_command(ipc_event_socketfd, IPC_SUBSCRIBE, subscribe_json, &len); + res = ipc_single_command(ipc_socketfd, IPC_SUBSCRIBE, subscribe_json, &len); free(res); - ipc_update_workspaces(); + ipc_send_command(ipc_socketfd, IPC_GET_WORKSPACES, NULL, 0); } /** @@ -705,7 +697,7 @@ void render() { double x = 0.5; // Workspaces - if (workspace_buttons) { + if (workspace_buttons && workspaces) { for (i = 0; i < workspaces->length; ++i) { struct workspace *ws = workspaces->items[i]; render_workspace_button(ws, &x); @@ -1076,10 +1068,13 @@ int i3json_handle_fd(int fd) { } bool handle_ipc_event() { - struct ipc_response *resp = ipc_recv_response(ipc_event_socketfd); + struct ipc_response *resp = ipc_recv_response(ipc_socketfd); switch (resp->type) { + case IPC_GET_WORKSPACES: + ipc_update_workspaces(resp->payload); + break; case IPC_EVENT_WORKSPACE: - ipc_update_workspaces(); + ipc_send_command(ipc_socketfd, IPC_GET_WORKSPACES, NULL, 0); break; case IPC_EVENT_MODE: { json_object *result = json_tokener_parse(resp->payload); @@ -1129,7 +1124,7 @@ void poll_for_update() { dirty = false; FD_ZERO(&readfds); - FD_SET(ipc_event_socketfd, &readfds); + FD_SET(ipc_socketfd, &readfds); FD_SET(status_read_fd, &readfds); activity = select(FD_SETSIZE, &readfds, NULL, NULL, NULL); @@ -1137,7 +1132,7 @@ void poll_for_update() { sway_log(L_ERROR, "polling failed: %d", errno); } - if (FD_ISSET(ipc_event_socketfd, &readfds)) { + if (FD_ISSET(ipc_socketfd, &readfds)) { sway_log(L_DEBUG, "Got IPC event."); dirty = handle_ipc_event(); } @@ -1300,7 +1295,6 @@ int main(int argc, char **argv) { } } ipc_socketfd = ipc_open_socket(socket_path); - ipc_event_socketfd = ipc_open_socket(socket_path); if (argc == optind) {