From 546ddbcd5bd76def3bb51114d4e1e6eb93eb16e7 Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Sat, 30 Jun 2018 17:02:23 +0900 Subject: ipc-server: fix double-free on send error in ipc_send_event ipc_send_reply already does client disconnect on error, so we shouldn't do it again. We also need to process current index again as disconnect removes client from the list we currently are processing (this is an indexed "list") Found through static analysis. --- sway/ipc-server.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sway/ipc-server.c') diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 241fe742..ec933ec3 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -263,7 +263,10 @@ static void ipc_send_event(const char *json_string, enum ipc_command_type event) client->current_command = event; if (!ipc_send_reply(client, json_string, (uint32_t) strlen(json_string))) { wlr_log_errno(L_INFO, "Unable to send reply to IPC client"); - ipc_client_disconnect(client); + /* ipc_send_reply destroys client on error, which also + * removes it from the list, so we need to process + * current index again */ + i--; } } } -- cgit v1.2.3 From 0ab04b7434306c5faceda2b4d2922e9d78de0184 Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Sat, 30 Jun 2018 17:03:45 +0900 Subject: ipc-server: minor code cleanup No logic change here, this one is mostly to please static analyzer: - client->fd can never be -1 (and if it could, close() a few lines below would have needed the same check) - we never send permission denied error (dead code) --- sway/ipc-server.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'sway/ipc-server.c') diff --git a/sway/ipc-server.c b/sway/ipc-server.c index ec933ec3..2dfe2d03 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -386,9 +386,7 @@ void ipc_client_disconnect(struct ipc_client *client) { return; } - if (client->fd != -1) { - shutdown(client->fd, SHUT_RDWR); - } + shutdown(client->fd, SHUT_RDWR); wlr_log(L_INFO, "IPC Client %d disconnected", client->fd); wl_event_source_remove(client->event_source); @@ -468,8 +466,6 @@ void ipc_client_handle_command(struct ipc_client *client) { } buf[client->payload_length] = '\0'; - const char *error_denied = "{ \"success\": false, \"error\": \"Permission denied\" }"; - switch (client->current_command) { case IPC_COMMAND: { @@ -650,9 +646,6 @@ void ipc_client_handle_command(struct ipc_client *client) { goto exit_cleanup; } - ipc_send_reply(client, error_denied, (uint32_t)strlen(error_denied)); - wlr_log(L_DEBUG, "Denied IPC client access to %i", client->current_command); - exit_cleanup: client->payload_length = 0; free(buf); -- cgit v1.2.3 From ebe69583c7304fe50247b5929106e3e5ce95b53a Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Sat, 30 Jun 2018 17:18:47 +0900 Subject: ipc-server: fix more use-after-frees on ipc_send_reply error Since ipc_send_reply frees the client on error, we need to check the return value properly as we access client later on Found through static analysis. --- sway/ipc-server.c | 46 +++++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 15 deletions(-) (limited to 'sway/ipc-server.c') diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 2dfe2d03..3e510c2e 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -466,6 +466,7 @@ void ipc_client_handle_command(struct ipc_client *client) { } buf[client->payload_length] = '\0'; + bool client_valid = true; switch (client->current_command) { case IPC_COMMAND: { @@ -473,7 +474,7 @@ void ipc_client_handle_command(struct ipc_client *client) { const char *json = cmd_results_to_json(results); char reply[256]; int length = snprintf(reply, sizeof(reply), "%s", json); - ipc_send_reply(client, reply, (uint32_t) length); + client_valid = ipc_send_reply(client, reply, (uint32_t)length); free_cmd_results(results); goto exit_cleanup; } @@ -496,7 +497,8 @@ void ipc_client_handle_command(struct ipc_client *client) { } } const char *json_string = json_object_to_json_string(outputs); - ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); + client_valid = + ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); json_object_put(outputs); // free goto exit_cleanup; } @@ -507,7 +509,8 @@ void ipc_client_handle_command(struct ipc_client *client) { container_for_each_descendant_dfs(&root_container, ipc_get_workspaces_callback, workspaces); const char *json_string = json_object_to_json_string(workspaces); - ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); + client_valid = + ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); json_object_put(workspaces); // free goto exit_cleanup; } @@ -517,7 +520,7 @@ void ipc_client_handle_command(struct ipc_client *client) { // TODO: Check if they're permitted to use these events struct json_object *request = json_tokener_parse(buf); if (request == NULL) { - ipc_send_reply(client, "{\"success\": false}", 18); + client_valid = ipc_send_reply(client, "{\"success\": false}", 18); wlr_log_errno(L_INFO, "Failed to read request"); goto exit_cleanup; } @@ -538,7 +541,8 @@ void ipc_client_handle_command(struct ipc_client *client) { } else if (strcmp(event_type, "binding") == 0) { client->subscribed_events |= event_mask(IPC_EVENT_BINDING); } else { - ipc_send_reply(client, "{\"success\": false}", 18); + client_valid = + ipc_send_reply(client, "{\"success\": false}", 18); json_object_put(request); wlr_log_errno(L_INFO, "Failed to parse request"); goto exit_cleanup; @@ -546,7 +550,7 @@ void ipc_client_handle_command(struct ipc_client *client) { } json_object_put(request); - ipc_send_reply(client, "{\"success\": true}", 17); + client_valid = ipc_send_reply(client, "{\"success\": true}", 17); goto exit_cleanup; } @@ -558,7 +562,8 @@ void ipc_client_handle_command(struct ipc_client *client) { json_object_array_add(inputs, ipc_json_describe_input(device)); } const char *json_string = json_object_to_json_string(inputs); - ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); + client_valid = + ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); json_object_put(inputs); // free goto exit_cleanup; } @@ -571,7 +576,8 @@ void ipc_client_handle_command(struct ipc_client *client) { json_object_array_add(seats, ipc_json_describe_seat(seat)); } const char *json_string = json_object_to_json_string(seats); - ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); + client_valid = + ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); json_object_put(seats); // free goto exit_cleanup; } @@ -581,7 +587,8 @@ void ipc_client_handle_command(struct ipc_client *client) { json_object *tree = ipc_json_describe_container_recursive(&root_container); const char *json_string = json_object_to_json_string(tree); - ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); + client_valid = + ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); json_object_put(tree); goto exit_cleanup; } @@ -592,7 +599,8 @@ void ipc_client_handle_command(struct ipc_client *client) { container_descendants(&root_container, C_VIEW, ipc_get_marks_callback, marks); const char *json_string = json_object_to_json_string(marks); - ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); + client_valid = + ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); json_object_put(marks); goto exit_cleanup; } @@ -601,7 +609,8 @@ void ipc_client_handle_command(struct ipc_client *client) { { json_object *version = ipc_json_get_version(); const char *json_string = json_object_to_json_string(version); - ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); + client_valid = + ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); json_object_put(version); // free goto exit_cleanup; } @@ -616,7 +625,9 @@ void ipc_client_handle_command(struct ipc_client *client) { json_object_array_add(bars, json_object_new_string(bar->id)); } const char *json_string = json_object_to_json_string(bars); - ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); + client_valid = + ipc_send_reply(client, json_string, + (uint32_t)strlen(json_string)); json_object_put(bars); // free } else { // Send particular bar's details @@ -630,12 +641,15 @@ void ipc_client_handle_command(struct ipc_client *client) { } if (!bar) { const char *error = "{ \"success\": false, \"error\": \"No bar with that ID\" }"; - ipc_send_reply(client, error, (uint32_t)strlen(error)); + client_valid = + ipc_send_reply(client, error, (uint32_t)strlen(error)); goto exit_cleanup; } json_object *json = ipc_json_describe_bar_config(bar); const char *json_string = json_object_to_json_string(json); - ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); + client_valid = + ipc_send_reply(client, json_string, + (uint32_t)strlen(json_string)); json_object_put(json); // free } goto exit_cleanup; @@ -647,7 +661,9 @@ void ipc_client_handle_command(struct ipc_client *client) { } exit_cleanup: - client->payload_length = 0; + if (client_valid) { + client->payload_length = 0; + } free(buf); return; } -- cgit v1.2.3 From b0918b1058a704675fc2590ee9ff3bef6324f734 Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Wed, 4 Jul 2018 14:45:35 +0900 Subject: ipc-server: add display destroy listener and remove ipc_terminate wl_event_source_remove() is illegal after display has been destroyed, so just destroy everything when we still can. ==20392==ERROR: AddressSanitizer: heap-use-after-free on address 0x607000001240 at pc 0x00000048e86e bp 0x7ffe4b557e00 sp 0x7ffe4b557df0 READ of size 8 at 0x607000001240 thread T0 #0 0x48e86d in wl_list_insert ../common/list.c:149 #1 0x7fdf673d4d7d in wl_event_source_remove src/event-loop.c:487 #2 0x41b742 in ipc_terminate ../sway/ipc-server.c:94 #3 0x40b1ad in main ../sway/main.c:440 #4 0x7fdf6664c18a in __libc_start_main ../csu/libc-start.c:308 #5 0x409359 in _start (/opt/wayland/bin/sway+0x409359) 0x607000001240 is located 48 bytes inside of 72-byte region [0x607000001210,0x607000001258) freed by thread T0 here: #0 0x7fdf692c4880 in __interceptor_free (/lib64/libasan.so.5+0xee880) #1 0x7fdf673d371a in wl_display_destroy src/wayland-server.c:1097 previously allocated by thread T0 here: #0 0x7fdf692c4c48 in malloc (/lib64/libasan.so.5+0xeec48) #1 0x7fdf673d4d9e in wl_event_loop_create src/event-loop.c:522 #2 0x40acb2 in main ../sway/main.c:363 #3 0x7fdf6664c18a in __libc_start_main ../csu/libc-start.c:308 --- sway/ipc-server.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) (limited to 'sway/ipc-server.c') diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 3e510c2e..abc2d7cb 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -31,6 +31,7 @@ static int ipc_socket = -1; static struct wl_event_source *ipc_event_source = NULL; static struct sockaddr_un *ipc_sockaddr = NULL; static list_t *ipc_client_list = NULL; +static struct wl_listener ipc_display_destroy; static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'}; @@ -56,6 +57,22 @@ void ipc_client_disconnect(struct ipc_client *client); void ipc_client_handle_command(struct ipc_client *client); bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length); +static void handle_display_destroy(struct wl_listener *listener, void *data) { + if (ipc_event_source) { + wl_event_source_remove(ipc_event_source); + } + close(ipc_socket); + unlink(ipc_sockaddr->sun_path); + + list_free(ipc_client_list); + + if (ipc_sockaddr) { + free(ipc_sockaddr); + } + + wl_list_remove(&ipc_display_destroy.link); +} + void ipc_init(struct sway_server *server) { ipc_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); if (ipc_socket == -1) { @@ -85,24 +102,13 @@ void ipc_init(struct sway_server *server) { ipc_client_list = create_list(); + ipc_display_destroy.notify = handle_display_destroy; + wl_display_add_destroy_listener(server->wl_display, &ipc_display_destroy); + ipc_event_source = wl_event_loop_add_fd(server->wl_event_loop, ipc_socket, WL_EVENT_READABLE, ipc_handle_connection, server); } -void ipc_terminate(void) { - if (ipc_event_source) { - wl_event_source_remove(ipc_event_source); - } - close(ipc_socket); - unlink(ipc_sockaddr->sun_path); - - list_free(ipc_client_list); - - if (ipc_sockaddr) { - free(ipc_sockaddr); - } -} - struct sockaddr_un *ipc_user_sockaddr(void) { struct sockaddr_un *ipc_sockaddr = malloc(sizeof(struct sockaddr_un)); if (ipc_sockaddr == NULL) { -- cgit v1.2.3 From ffe9de6e24b451ba7885bc52c78fd676598bf7cd Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Wed, 4 Jul 2018 18:48:57 +0900 Subject: ipc-server: free clients at destroy --- sway/ipc-server.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sway/ipc-server.c') diff --git a/sway/ipc-server.c b/sway/ipc-server.c index abc2d7cb..01b80b05 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -64,6 +64,10 @@ static void handle_display_destroy(struct wl_listener *listener, void *data) { close(ipc_socket); unlink(ipc_sockaddr->sun_path); + while (ipc_client_list->length) { + struct ipc_client *client = ipc_client_list->items[0]; + ipc_client_disconnect(client); + } list_free(ipc_client_list); if (ipc_sockaddr) { @@ -480,6 +484,7 @@ void ipc_client_handle_command(struct ipc_client *client) { const char *json = cmd_results_to_json(results); char reply[256]; int length = snprintf(reply, sizeof(reply), "%s", json); + free(json); client_valid = ipc_send_reply(client, reply, (uint32_t)length); free_cmd_results(results); goto exit_cleanup; -- cgit v1.2.3 From fe72e3b349f0905519481b77b22c525aca9c704d Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Thu, 5 Jul 2018 07:07:59 +0900 Subject: cmd_results_to_json: return copied string and properly free the json The only user of this function would copy the string right away to get rid of the const flag anyway, and freeing a const string afterwards might work but is not meant to be done according to the json-c API. --- sway/ipc-server.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'sway/ipc-server.c') diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 01b80b05..96889b39 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -481,11 +481,10 @@ void ipc_client_handle_command(struct ipc_client *client) { case IPC_COMMAND: { struct cmd_results *results = execute_command(buf, NULL); - const char *json = cmd_results_to_json(results); - char reply[256]; - int length = snprintf(reply, sizeof(reply), "%s", json); + char *json = cmd_results_to_json(results); + int length = strlen(json); + client_valid = ipc_send_reply(client, json, (uint32_t)length); free(json); - client_valid = ipc_send_reply(client, reply, (uint32_t)length); free_cmd_results(results); goto exit_cleanup; } -- cgit v1.2.3 From 78c08fb0a281cbe74c56f0a2ea4b9370b9372661 Mon Sep 17 00:00:00 2001 From: Brian Ashworth Date: Thu, 5 Jul 2018 18:12:14 -0400 Subject: Implement mode --pango_markup --- sway/ipc-server.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sway/ipc-server.c') diff --git a/sway/ipc-server.c b/sway/ipc-server.c index abc2d7cb..8cfd9f26 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -332,13 +332,15 @@ void ipc_event_barconfig_update(struct bar_config *bar) { json_object_put(json); } -void ipc_event_mode(const char *mode) { +void ipc_event_mode(const char *mode, bool pango) { if (!ipc_has_event_listeners(IPC_EVENT_MODE)) { return; } wlr_log(L_DEBUG, "Sending mode::%s event", mode); json_object *obj = json_object_new_object(); json_object_object_add(obj, "change", json_object_new_string(mode)); + json_object_object_add(obj, "pango_markup", + json_object_new_boolean(pango)); const char *json_string = json_object_to_json_string(obj); ipc_send_event(json_string, IPC_EVENT_MODE); -- cgit v1.2.3 From 63b4bf500020cf35cebfdce2d73f8e359ff495c2 Mon Sep 17 00:00:00 2001 From: emersion Date: Mon, 9 Jul 2018 22:54:30 +0100 Subject: Update for swaywm/wlroots#1126 --- sway/ipc-server.c | 62 +++++++++++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) (limited to 'sway/ipc-server.c') diff --git a/sway/ipc-server.c b/sway/ipc-server.c index abdaa237..197851cf 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -138,32 +138,32 @@ struct sockaddr_un *ipc_user_sockaddr(void) { int ipc_handle_connection(int fd, uint32_t mask, void *data) { (void) fd; struct sway_server *server = data; - wlr_log(L_DEBUG, "Event on IPC listening socket"); + wlr_log(WLR_DEBUG, "Event on IPC listening socket"); assert(mask == WL_EVENT_READABLE); int client_fd = accept(ipc_socket, NULL, NULL); if (client_fd == -1) { - wlr_log_errno(L_ERROR, "Unable to accept IPC client connection"); + wlr_log_errno(WLR_ERROR, "Unable to accept IPC client connection"); return 0; } int flags; if ((flags = fcntl(client_fd, F_GETFD)) == -1 || fcntl(client_fd, F_SETFD, flags|FD_CLOEXEC) == -1) { - wlr_log_errno(L_ERROR, "Unable to set CLOEXEC on IPC client socket"); + wlr_log_errno(WLR_ERROR, "Unable to set CLOEXEC on IPC client socket"); close(client_fd); return 0; } if ((flags = fcntl(client_fd, F_GETFL)) == -1 || fcntl(client_fd, F_SETFL, flags|O_NONBLOCK) == -1) { - wlr_log_errno(L_ERROR, "Unable to set NONBLOCK on IPC client socket"); + wlr_log_errno(WLR_ERROR, "Unable to set NONBLOCK on IPC client socket"); close(client_fd); return 0; } struct ipc_client *client = malloc(sizeof(struct ipc_client)); if (!client) { - wlr_log(L_ERROR, "Unable to allocate ipc client"); + wlr_log(WLR_ERROR, "Unable to allocate ipc client"); close(client_fd); return 0; } @@ -179,12 +179,12 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) { client->write_buffer_len = 0; client->write_buffer = malloc(client->write_buffer_size); if (!client->write_buffer) { - wlr_log(L_ERROR, "Unable to allocate ipc client write buffer"); + wlr_log(WLR_ERROR, "Unable to allocate ipc client write buffer"); close(client_fd); return 0; } - wlr_log(L_DEBUG, "New client: fd %d", client_fd); + wlr_log(WLR_DEBUG, "New client: fd %d", client_fd); list_add(ipc_client_list, client); return 0; } @@ -195,22 +195,22 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { struct ipc_client *client = data; if (mask & WL_EVENT_ERROR) { - wlr_log(L_ERROR, "IPC Client socket error, removing client"); + wlr_log(WLR_ERROR, "IPC Client socket error, removing client"); ipc_client_disconnect(client); return 0; } if (mask & WL_EVENT_HANGUP) { - wlr_log(L_DEBUG, "Client %d hung up", client->fd); + wlr_log(WLR_DEBUG, "Client %d hung up", client->fd); ipc_client_disconnect(client); return 0; } - wlr_log(L_DEBUG, "Client %d readable", client->fd); + wlr_log(WLR_DEBUG, "Client %d readable", client->fd); int read_available; if (ioctl(client_fd, FIONREAD, &read_available) == -1) { - wlr_log_errno(L_INFO, "Unable to read IPC socket buffer size"); + wlr_log_errno(WLR_INFO, "Unable to read IPC socket buffer size"); ipc_client_disconnect(client); return 0; } @@ -232,13 +232,13 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { // Should be fully available, because read_available >= ipc_header_size ssize_t received = recv(client_fd, buf, ipc_header_size, 0); if (received == -1) { - wlr_log_errno(L_INFO, "Unable to receive header from IPC client"); + wlr_log_errno(WLR_INFO, "Unable to receive header from IPC client"); ipc_client_disconnect(client); return 0; } if (memcmp(buf, ipc_magic, sizeof(ipc_magic)) != 0) { - wlr_log(L_DEBUG, "IPC header check failed"); + wlr_log(WLR_DEBUG, "IPC header check failed"); ipc_client_disconnect(client); return 0; } @@ -272,7 +272,7 @@ static void ipc_send_event(const char *json_string, enum ipc_command_type event) } client->current_command = event; if (!ipc_send_reply(client, json_string, (uint32_t) strlen(json_string))) { - wlr_log_errno(L_INFO, "Unable to send reply to IPC client"); + wlr_log_errno(WLR_INFO, "Unable to send reply to IPC client"); /* ipc_send_reply destroys client on error, which also * removes it from the list, so we need to process * current index again */ @@ -286,7 +286,7 @@ void ipc_event_workspace(struct sway_container *old, if (!ipc_has_event_listeners(IPC_EVENT_WORKSPACE)) { return; } - wlr_log(L_DEBUG, "Sending workspace::%s event", change); + wlr_log(WLR_DEBUG, "Sending workspace::%s event", change); json_object *obj = json_object_new_object(); json_object_object_add(obj, "change", json_object_new_string(change)); if (strcmp("focus", change) == 0) { @@ -314,7 +314,7 @@ void ipc_event_window(struct sway_container *window, const char *change) { if (!ipc_has_event_listeners(IPC_EVENT_WINDOW)) { return; } - wlr_log(L_DEBUG, "Sending window::%s event", change); + wlr_log(WLR_DEBUG, "Sending window::%s event", change); json_object *obj = json_object_new_object(); json_object_object_add(obj, "change", json_object_new_string(change)); json_object_object_add(obj, "container", ipc_json_describe_container_recursive(window)); @@ -328,7 +328,7 @@ void ipc_event_barconfig_update(struct bar_config *bar) { if (!ipc_has_event_listeners(IPC_EVENT_BARCONFIG_UPDATE)) { return; } - wlr_log(L_DEBUG, "Sending barconfig_update event"); + wlr_log(WLR_DEBUG, "Sending barconfig_update event"); json_object *json = ipc_json_describe_bar_config(bar); const char *json_string = json_object_to_json_string(json); @@ -340,7 +340,7 @@ void ipc_event_mode(const char *mode, bool pango) { if (!ipc_has_event_listeners(IPC_EVENT_MODE)) { return; } - wlr_log(L_DEBUG, "Sending mode::%s event", mode); + wlr_log(WLR_DEBUG, "Sending mode::%s event", mode); json_object *obj = json_object_new_object(); json_object_object_add(obj, "change", json_object_new_string(mode)); json_object_object_add(obj, "pango_markup", @@ -355,13 +355,13 @@ int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { struct ipc_client *client = data; if (mask & WL_EVENT_ERROR) { - wlr_log(L_ERROR, "IPC Client socket error, removing client"); + wlr_log(WLR_ERROR, "IPC Client socket error, removing client"); ipc_client_disconnect(client); return 0; } if (mask & WL_EVENT_HANGUP) { - wlr_log(L_DEBUG, "Client %d hung up", client->fd); + wlr_log(WLR_DEBUG, "Client %d hung up", client->fd); ipc_client_disconnect(client); return 0; } @@ -370,14 +370,14 @@ int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { return 0; } - wlr_log(L_DEBUG, "Client %d writable", client->fd); + wlr_log(WLR_DEBUG, "Client %d writable", client->fd); ssize_t written = write(client->fd, client->write_buffer, client->write_buffer_len); if (written == -1 && errno == EAGAIN) { return 0; } else if (written == -1) { - wlr_log_errno(L_INFO, "Unable to send data from queue to IPC client"); + wlr_log_errno(WLR_INFO, "Unable to send data from queue to IPC client"); ipc_client_disconnect(client); return 0; } @@ -400,7 +400,7 @@ void ipc_client_disconnect(struct ipc_client *client) { shutdown(client->fd, SHUT_RDWR); - wlr_log(L_INFO, "IPC Client %d disconnected", client->fd); + wlr_log(WLR_INFO, "IPC Client %d disconnected", client->fd); wl_event_source_remove(client->event_source); if (client->writable_event_source) { wl_event_source_remove(client->writable_event_source); @@ -461,7 +461,7 @@ void ipc_client_handle_command(struct ipc_client *client) { char *buf = malloc(client->payload_length + 1); if (!buf) { - wlr_log_errno(L_INFO, "Unable to allocate IPC payload"); + wlr_log_errno(WLR_INFO, "Unable to allocate IPC payload"); ipc_client_disconnect(client); return; } @@ -470,7 +470,7 @@ void ipc_client_handle_command(struct ipc_client *client) { ssize_t received = recv(client->fd, buf, client->payload_length, 0); if (received == -1) { - wlr_log_errno(L_INFO, "Unable to receive payload from IPC client"); + wlr_log_errno(WLR_INFO, "Unable to receive payload from IPC client"); ipc_client_disconnect(client); free(buf); return; @@ -533,7 +533,7 @@ void ipc_client_handle_command(struct ipc_client *client) { struct json_object *request = json_tokener_parse(buf); if (request == NULL) { client_valid = ipc_send_reply(client, "{\"success\": false}", 18); - wlr_log_errno(L_INFO, "Failed to read request"); + wlr_log_errno(WLR_INFO, "Failed to read request"); goto exit_cleanup; } @@ -556,7 +556,7 @@ void ipc_client_handle_command(struct ipc_client *client) { client_valid = ipc_send_reply(client, "{\"success\": false}", 18); json_object_put(request); - wlr_log_errno(L_INFO, "Failed to parse request"); + wlr_log_errno(WLR_INFO, "Failed to parse request"); goto exit_cleanup; } } @@ -668,7 +668,7 @@ void ipc_client_handle_command(struct ipc_client *client) { } default: - wlr_log(L_INFO, "Unknown IPC command type %i", client->current_command); + wlr_log(WLR_INFO, "Unknown IPC command type %i", client->current_command); goto exit_cleanup; } @@ -696,14 +696,14 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay } if (client->write_buffer_size > 4e6) { // 4 MB - wlr_log(L_ERROR, "Client write buffer too big, disconnecting client"); + wlr_log(WLR_ERROR, "Client write buffer too big, disconnecting client"); ipc_client_disconnect(client); return false; } char *new_buffer = realloc(client->write_buffer, client->write_buffer_size); if (!new_buffer) { - wlr_log(L_ERROR, "Unable to reallocate ipc client write buffer"); + wlr_log(WLR_ERROR, "Unable to reallocate ipc client write buffer"); ipc_client_disconnect(client); return false; } @@ -720,6 +720,6 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay ipc_client_handle_writable, client); } - wlr_log(L_DEBUG, "Added IPC reply to client %d queue: %s", client->fd, payload); + wlr_log(WLR_DEBUG, "Added IPC reply to client %d queue: %s", client->fd, payload); return true; } -- cgit v1.2.3 From 5fd36164a008f931def993413facf9058c56641d Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sun, 8 Jul 2018 20:32:42 +0100 Subject: Add get_binding_modes message type to ipc --- sway/ipc-server.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'sway/ipc-server.c') diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 197851cf..70a4141e 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -667,6 +667,20 @@ void ipc_client_handle_command(struct ipc_client *client) { goto exit_cleanup; } + case IPC_GET_BINDING_MODES: + { + json_object *modes = json_object_new_array(); + for (int i = 0; i < config->modes->length; i++) { + struct sway_mode *mode = config->modes->items[i]; + json_object_array_add(modes, json_object_new_string(mode->name)); + } + const char *json_string = json_object_to_json_string(modes); + client_valid = + ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); + json_object_put(modes); // free + goto exit_cleanup; + } + default: wlr_log(WLR_INFO, "Unknown IPC command type %i", client->current_command); goto exit_cleanup; -- cgit v1.2.3 From 23c1c26c3fedf5470dbee9fe97c2374a48588863 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sun, 8 Jul 2018 20:34:47 +0100 Subject: Add get_config message type to ipc --- sway/ipc-server.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'sway/ipc-server.c') diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 70a4141e..c5161a6b 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -17,6 +17,7 @@ #include #include #include "sway/commands.h" +#include "sway/config.h" #include "sway/ipc-json.h" #include "sway/ipc-server.h" #include "sway/output.h" @@ -681,6 +682,17 @@ void ipc_client_handle_command(struct ipc_client *client) { goto exit_cleanup; } + case IPC_GET_CONFIG: + { + json_object *json = json_object_new_object(); + json_object_object_add(json, "config", json_object_new_string(config->current_config)); + const char *json_string = json_object_to_json_string(json); + client_valid = + ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); + json_object_put(json); // free + goto exit_cleanup; + } + default: wlr_log(WLR_INFO, "Unknown IPC command type %i", client->current_command); goto exit_cleanup; -- cgit v1.2.3 From a120d4c79f9406a2f7cc38c60069d3183c98ea87 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Sun, 15 Jul 2018 15:20:21 +1000 Subject: Make focus part of transactions Rather than maintain copies of the entire focus stack, this PR transactionises the focus by introducing two new properties to the container state and using those when rendering. * `bool focused` means this container has actual focus. Only one container should have this equalling true in its current state. * `struct sway_container *focus_inactive_child` points to the immediate child that was most recently focused (eg. for tabbed and stacked containers). --- sway/ipc-server.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sway/ipc-server.c') diff --git a/sway/ipc-server.c b/sway/ipc-server.c index c5161a6b..be703915 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -18,6 +18,7 @@ #include #include "sway/commands.h" #include "sway/config.h" +#include "sway/desktop/transaction.h" #include "sway/ipc-json.h" #include "sway/ipc-server.h" #include "sway/output.h" @@ -484,6 +485,7 @@ void ipc_client_handle_command(struct ipc_client *client) { case IPC_COMMAND: { struct cmd_results *results = execute_command(buf, NULL); + transaction_commit_dirty(); char *json = cmd_results_to_json(results); int length = strlen(json); client_valid = ipc_send_reply(client, json, (uint32_t)length); -- cgit v1.2.3