aboutsummaryrefslogtreecommitdiffstats
path: root/sway/ipc-server.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/ipc-server.c')
-rw-r--r--sway/ipc-server.c198
1 files changed, 125 insertions, 73 deletions
diff --git a/sway/ipc-server.c b/sway/ipc-server.c
index 241fe742..be703915 100644
--- a/sway/ipc-server.c
+++ b/sway/ipc-server.c
@@ -17,6 +17,8 @@
17#include <unistd.h> 17#include <unistd.h>
18#include <wayland-server.h> 18#include <wayland-server.h>
19#include "sway/commands.h" 19#include "sway/commands.h"
20#include "sway/config.h"
21#include "sway/desktop/transaction.h"
20#include "sway/ipc-json.h" 22#include "sway/ipc-json.h"
21#include "sway/ipc-server.h" 23#include "sway/ipc-server.h"
22#include "sway/output.h" 24#include "sway/output.h"
@@ -31,6 +33,7 @@ static int ipc_socket = -1;
31static struct wl_event_source *ipc_event_source = NULL; 33static struct wl_event_source *ipc_event_source = NULL;
32static struct sockaddr_un *ipc_sockaddr = NULL; 34static struct sockaddr_un *ipc_sockaddr = NULL;
33static list_t *ipc_client_list = NULL; 35static list_t *ipc_client_list = NULL;
36static struct wl_listener ipc_display_destroy;
34 37
35static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'}; 38static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'};
36 39
@@ -56,6 +59,26 @@ void ipc_client_disconnect(struct ipc_client *client);
56void ipc_client_handle_command(struct ipc_client *client); 59void ipc_client_handle_command(struct ipc_client *client);
57bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length); 60bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length);
58 61
62static void handle_display_destroy(struct wl_listener *listener, void *data) {
63 if (ipc_event_source) {
64 wl_event_source_remove(ipc_event_source);
65 }
66 close(ipc_socket);
67 unlink(ipc_sockaddr->sun_path);
68
69 while (ipc_client_list->length) {
70 struct ipc_client *client = ipc_client_list->items[0];
71 ipc_client_disconnect(client);
72 }
73 list_free(ipc_client_list);
74
75 if (ipc_sockaddr) {
76 free(ipc_sockaddr);
77 }
78
79 wl_list_remove(&ipc_display_destroy.link);
80}
81
59void ipc_init(struct sway_server *server) { 82void ipc_init(struct sway_server *server) {
60 ipc_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); 83 ipc_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
61 if (ipc_socket == -1) { 84 if (ipc_socket == -1) {
@@ -85,24 +108,13 @@ void ipc_init(struct sway_server *server) {
85 108
86 ipc_client_list = create_list(); 109 ipc_client_list = create_list();
87 110
111 ipc_display_destroy.notify = handle_display_destroy;
112 wl_display_add_destroy_listener(server->wl_display, &ipc_display_destroy);
113
88 ipc_event_source = wl_event_loop_add_fd(server->wl_event_loop, ipc_socket, 114 ipc_event_source = wl_event_loop_add_fd(server->wl_event_loop, ipc_socket,
89 WL_EVENT_READABLE, ipc_handle_connection, server); 115 WL_EVENT_READABLE, ipc_handle_connection, server);
90} 116}
91 117
92void ipc_terminate(void) {
93 if (ipc_event_source) {
94 wl_event_source_remove(ipc_event_source);
95 }
96 close(ipc_socket);
97 unlink(ipc_sockaddr->sun_path);
98
99 list_free(ipc_client_list);
100
101 if (ipc_sockaddr) {
102 free(ipc_sockaddr);
103 }
104}
105
106struct sockaddr_un *ipc_user_sockaddr(void) { 118struct sockaddr_un *ipc_user_sockaddr(void) {
107 struct sockaddr_un *ipc_sockaddr = malloc(sizeof(struct sockaddr_un)); 119 struct sockaddr_un *ipc_sockaddr = malloc(sizeof(struct sockaddr_un));
108 if (ipc_sockaddr == NULL) { 120 if (ipc_sockaddr == NULL) {
@@ -128,32 +140,32 @@ struct sockaddr_un *ipc_user_sockaddr(void) {
128int ipc_handle_connection(int fd, uint32_t mask, void *data) { 140int ipc_handle_connection(int fd, uint32_t mask, void *data) {
129 (void) fd; 141 (void) fd;
130 struct sway_server *server = data; 142 struct sway_server *server = data;
131 wlr_log(L_DEBUG, "Event on IPC listening socket"); 143 wlr_log(WLR_DEBUG, "Event on IPC listening socket");
132 assert(mask == WL_EVENT_READABLE); 144 assert(mask == WL_EVENT_READABLE);
133 145
134 int client_fd = accept(ipc_socket, NULL, NULL); 146 int client_fd = accept(ipc_socket, NULL, NULL);
135 if (client_fd == -1) { 147 if (client_fd == -1) {
136 wlr_log_errno(L_ERROR, "Unable to accept IPC client connection"); 148 wlr_log_errno(WLR_ERROR, "Unable to accept IPC client connection");
137 return 0; 149 return 0;
138 } 150 }
139 151
140 int flags; 152 int flags;
141 if ((flags = fcntl(client_fd, F_GETFD)) == -1 153 if ((flags = fcntl(client_fd, F_GETFD)) == -1
142 || fcntl(client_fd, F_SETFD, flags|FD_CLOEXEC) == -1) { 154 || fcntl(client_fd, F_SETFD, flags|FD_CLOEXEC) == -1) {
143 wlr_log_errno(L_ERROR, "Unable to set CLOEXEC on IPC client socket"); 155 wlr_log_errno(WLR_ERROR, "Unable to set CLOEXEC on IPC client socket");
144 close(client_fd); 156 close(client_fd);
145 return 0; 157 return 0;
146 } 158 }
147 if ((flags = fcntl(client_fd, F_GETFL)) == -1 159 if ((flags = fcntl(client_fd, F_GETFL)) == -1
148 || fcntl(client_fd, F_SETFL, flags|O_NONBLOCK) == -1) { 160 || fcntl(client_fd, F_SETFL, flags|O_NONBLOCK) == -1) {
149 wlr_log_errno(L_ERROR, "Unable to set NONBLOCK on IPC client socket"); 161 wlr_log_errno(WLR_ERROR, "Unable to set NONBLOCK on IPC client socket");
150 close(client_fd); 162 close(client_fd);
151 return 0; 163 return 0;
152 } 164 }
153 165
154 struct ipc_client *client = malloc(sizeof(struct ipc_client)); 166 struct ipc_client *client = malloc(sizeof(struct ipc_client));
155 if (!client) { 167 if (!client) {
156 wlr_log(L_ERROR, "Unable to allocate ipc client"); 168 wlr_log(WLR_ERROR, "Unable to allocate ipc client");
157 close(client_fd); 169 close(client_fd);
158 return 0; 170 return 0;
159 } 171 }
@@ -169,12 +181,12 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) {
169 client->write_buffer_len = 0; 181 client->write_buffer_len = 0;
170 client->write_buffer = malloc(client->write_buffer_size); 182 client->write_buffer = malloc(client->write_buffer_size);
171 if (!client->write_buffer) { 183 if (!client->write_buffer) {
172 wlr_log(L_ERROR, "Unable to allocate ipc client write buffer"); 184 wlr_log(WLR_ERROR, "Unable to allocate ipc client write buffer");
173 close(client_fd); 185 close(client_fd);
174 return 0; 186 return 0;
175 } 187 }
176 188
177 wlr_log(L_DEBUG, "New client: fd %d", client_fd); 189 wlr_log(WLR_DEBUG, "New client: fd %d", client_fd);
178 list_add(ipc_client_list, client); 190 list_add(ipc_client_list, client);
179 return 0; 191 return 0;
180} 192}
@@ -185,22 +197,22 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) {
185 struct ipc_client *client = data; 197 struct ipc_client *client = data;
186 198
187 if (mask & WL_EVENT_ERROR) { 199 if (mask & WL_EVENT_ERROR) {
188 wlr_log(L_ERROR, "IPC Client socket error, removing client"); 200 wlr_log(WLR_ERROR, "IPC Client socket error, removing client");
189 ipc_client_disconnect(client); 201 ipc_client_disconnect(client);
190 return 0; 202 return 0;
191 } 203 }
192 204
193 if (mask & WL_EVENT_HANGUP) { 205 if (mask & WL_EVENT_HANGUP) {
194 wlr_log(L_DEBUG, "Client %d hung up", client->fd); 206 wlr_log(WLR_DEBUG, "Client %d hung up", client->fd);
195 ipc_client_disconnect(client); 207 ipc_client_disconnect(client);
196 return 0; 208 return 0;
197 } 209 }
198 210
199 wlr_log(L_DEBUG, "Client %d readable", client->fd); 211 wlr_log(WLR_DEBUG, "Client %d readable", client->fd);
200 212
201 int read_available; 213 int read_available;
202 if (ioctl(client_fd, FIONREAD, &read_available) == -1) { 214 if (ioctl(client_fd, FIONREAD, &read_available) == -1) {
203 wlr_log_errno(L_INFO, "Unable to read IPC socket buffer size"); 215 wlr_log_errno(WLR_INFO, "Unable to read IPC socket buffer size");
204 ipc_client_disconnect(client); 216 ipc_client_disconnect(client);
205 return 0; 217 return 0;
206 } 218 }
@@ -222,13 +234,13 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) {
222 // Should be fully available, because read_available >= ipc_header_size 234 // Should be fully available, because read_available >= ipc_header_size
223 ssize_t received = recv(client_fd, buf, ipc_header_size, 0); 235 ssize_t received = recv(client_fd, buf, ipc_header_size, 0);
224 if (received == -1) { 236 if (received == -1) {
225 wlr_log_errno(L_INFO, "Unable to receive header from IPC client"); 237 wlr_log_errno(WLR_INFO, "Unable to receive header from IPC client");
226 ipc_client_disconnect(client); 238 ipc_client_disconnect(client);
227 return 0; 239 return 0;
228 } 240 }
229 241
230 if (memcmp(buf, ipc_magic, sizeof(ipc_magic)) != 0) { 242 if (memcmp(buf, ipc_magic, sizeof(ipc_magic)) != 0) {
231 wlr_log(L_DEBUG, "IPC header check failed"); 243 wlr_log(WLR_DEBUG, "IPC header check failed");
232 ipc_client_disconnect(client); 244 ipc_client_disconnect(client);
233 return 0; 245 return 0;
234 } 246 }
@@ -262,8 +274,11 @@ static void ipc_send_event(const char *json_string, enum ipc_command_type event)
262 } 274 }
263 client->current_command = event; 275 client->current_command = event;
264 if (!ipc_send_reply(client, json_string, (uint32_t) strlen(json_string))) { 276 if (!ipc_send_reply(client, json_string, (uint32_t) strlen(json_string))) {
265 wlr_log_errno(L_INFO, "Unable to send reply to IPC client"); 277 wlr_log_errno(WLR_INFO, "Unable to send reply to IPC client");
266 ipc_client_disconnect(client); 278 /* ipc_send_reply destroys client on error, which also
279 * removes it from the list, so we need to process
280 * current index again */
281 i--;
267 } 282 }
268 } 283 }
269} 284}
@@ -273,7 +288,7 @@ void ipc_event_workspace(struct sway_container *old,
273 if (!ipc_has_event_listeners(IPC_EVENT_WORKSPACE)) { 288 if (!ipc_has_event_listeners(IPC_EVENT_WORKSPACE)) {
274 return; 289 return;
275 } 290 }
276 wlr_log(L_DEBUG, "Sending workspace::%s event", change); 291 wlr_log(WLR_DEBUG, "Sending workspace::%s event", change);
277 json_object *obj = json_object_new_object(); 292 json_object *obj = json_object_new_object();
278 json_object_object_add(obj, "change", json_object_new_string(change)); 293 json_object_object_add(obj, "change", json_object_new_string(change));
279 if (strcmp("focus", change) == 0) { 294 if (strcmp("focus", change) == 0) {
@@ -301,7 +316,7 @@ void ipc_event_window(struct sway_container *window, const char *change) {
301 if (!ipc_has_event_listeners(IPC_EVENT_WINDOW)) { 316 if (!ipc_has_event_listeners(IPC_EVENT_WINDOW)) {
302 return; 317 return;
303 } 318 }
304 wlr_log(L_DEBUG, "Sending window::%s event", change); 319 wlr_log(WLR_DEBUG, "Sending window::%s event", change);
305 json_object *obj = json_object_new_object(); 320 json_object *obj = json_object_new_object();
306 json_object_object_add(obj, "change", json_object_new_string(change)); 321 json_object_object_add(obj, "change", json_object_new_string(change));
307 json_object_object_add(obj, "container", ipc_json_describe_container_recursive(window)); 322 json_object_object_add(obj, "container", ipc_json_describe_container_recursive(window));
@@ -315,7 +330,7 @@ void ipc_event_barconfig_update(struct bar_config *bar) {
315 if (!ipc_has_event_listeners(IPC_EVENT_BARCONFIG_UPDATE)) { 330 if (!ipc_has_event_listeners(IPC_EVENT_BARCONFIG_UPDATE)) {
316 return; 331 return;
317 } 332 }
318 wlr_log(L_DEBUG, "Sending barconfig_update event"); 333 wlr_log(WLR_DEBUG, "Sending barconfig_update event");
319 json_object *json = ipc_json_describe_bar_config(bar); 334 json_object *json = ipc_json_describe_bar_config(bar);
320 335
321 const char *json_string = json_object_to_json_string(json); 336 const char *json_string = json_object_to_json_string(json);
@@ -323,13 +338,15 @@ void ipc_event_barconfig_update(struct bar_config *bar) {
323 json_object_put(json); 338 json_object_put(json);
324} 339}
325 340
326void ipc_event_mode(const char *mode) { 341void ipc_event_mode(const char *mode, bool pango) {
327 if (!ipc_has_event_listeners(IPC_EVENT_MODE)) { 342 if (!ipc_has_event_listeners(IPC_EVENT_MODE)) {
328 return; 343 return;
329 } 344 }
330 wlr_log(L_DEBUG, "Sending mode::%s event", mode); 345 wlr_log(WLR_DEBUG, "Sending mode::%s event", mode);
331 json_object *obj = json_object_new_object(); 346 json_object *obj = json_object_new_object();
332 json_object_object_add(obj, "change", json_object_new_string(mode)); 347 json_object_object_add(obj, "change", json_object_new_string(mode));
348 json_object_object_add(obj, "pango_markup",
349 json_object_new_boolean(pango));
333 350
334 const char *json_string = json_object_to_json_string(obj); 351 const char *json_string = json_object_to_json_string(obj);
335 ipc_send_event(json_string, IPC_EVENT_MODE); 352 ipc_send_event(json_string, IPC_EVENT_MODE);
@@ -340,13 +357,13 @@ int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) {
340 struct ipc_client *client = data; 357 struct ipc_client *client = data;
341 358
342 if (mask & WL_EVENT_ERROR) { 359 if (mask & WL_EVENT_ERROR) {
343 wlr_log(L_ERROR, "IPC Client socket error, removing client"); 360 wlr_log(WLR_ERROR, "IPC Client socket error, removing client");
344 ipc_client_disconnect(client); 361 ipc_client_disconnect(client);
345 return 0; 362 return 0;
346 } 363 }
347 364
348 if (mask & WL_EVENT_HANGUP) { 365 if (mask & WL_EVENT_HANGUP) {
349 wlr_log(L_DEBUG, "Client %d hung up", client->fd); 366 wlr_log(WLR_DEBUG, "Client %d hung up", client->fd);
350 ipc_client_disconnect(client); 367 ipc_client_disconnect(client);
351 return 0; 368 return 0;
352 } 369 }
@@ -355,14 +372,14 @@ int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) {
355 return 0; 372 return 0;
356 } 373 }
357 374
358 wlr_log(L_DEBUG, "Client %d writable", client->fd); 375 wlr_log(WLR_DEBUG, "Client %d writable", client->fd);
359 376
360 ssize_t written = write(client->fd, client->write_buffer, client->write_buffer_len); 377 ssize_t written = write(client->fd, client->write_buffer, client->write_buffer_len);
361 378
362 if (written == -1 && errno == EAGAIN) { 379 if (written == -1 && errno == EAGAIN) {
363 return 0; 380 return 0;
364 } else if (written == -1) { 381 } else if (written == -1) {
365 wlr_log_errno(L_INFO, "Unable to send data from queue to IPC client"); 382 wlr_log_errno(WLR_INFO, "Unable to send data from queue to IPC client");
366 ipc_client_disconnect(client); 383 ipc_client_disconnect(client);
367 return 0; 384 return 0;
368 } 385 }
@@ -383,11 +400,9 @@ void ipc_client_disconnect(struct ipc_client *client) {
383 return; 400 return;
384 } 401 }
385 402
386 if (client->fd != -1) { 403 shutdown(client->fd, SHUT_RDWR);
387 shutdown(client->fd, SHUT_RDWR);
388 }
389 404
390 wlr_log(L_INFO, "IPC Client %d disconnected", client->fd); 405 wlr_log(WLR_INFO, "IPC Client %d disconnected", client->fd);
391 wl_event_source_remove(client->event_source); 406 wl_event_source_remove(client->event_source);
392 if (client->writable_event_source) { 407 if (client->writable_event_source) {
393 wl_event_source_remove(client->writable_event_source); 408 wl_event_source_remove(client->writable_event_source);
@@ -448,7 +463,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
448 463
449 char *buf = malloc(client->payload_length + 1); 464 char *buf = malloc(client->payload_length + 1);
450 if (!buf) { 465 if (!buf) {
451 wlr_log_errno(L_INFO, "Unable to allocate IPC payload"); 466 wlr_log_errno(WLR_INFO, "Unable to allocate IPC payload");
452 ipc_client_disconnect(client); 467 ipc_client_disconnect(client);
453 return; 468 return;
454 } 469 }
@@ -457,7 +472,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
457 ssize_t received = recv(client->fd, buf, client->payload_length, 0); 472 ssize_t received = recv(client->fd, buf, client->payload_length, 0);
458 if (received == -1) 473 if (received == -1)
459 { 474 {
460 wlr_log_errno(L_INFO, "Unable to receive payload from IPC client"); 475 wlr_log_errno(WLR_INFO, "Unable to receive payload from IPC client");
461 ipc_client_disconnect(client); 476 ipc_client_disconnect(client);
462 free(buf); 477 free(buf);
463 return; 478 return;
@@ -465,16 +480,16 @@ void ipc_client_handle_command(struct ipc_client *client) {
465 } 480 }
466 buf[client->payload_length] = '\0'; 481 buf[client->payload_length] = '\0';
467 482
468 const char *error_denied = "{ \"success\": false, \"error\": \"Permission denied\" }"; 483 bool client_valid = true;
469
470 switch (client->current_command) { 484 switch (client->current_command) {
471 case IPC_COMMAND: 485 case IPC_COMMAND:
472 { 486 {
473 struct cmd_results *results = execute_command(buf, NULL); 487 struct cmd_results *results = execute_command(buf, NULL);
474 const char *json = cmd_results_to_json(results); 488 transaction_commit_dirty();
475 char reply[256]; 489 char *json = cmd_results_to_json(results);
476 int length = snprintf(reply, sizeof(reply), "%s", json); 490 int length = strlen(json);
477 ipc_send_reply(client, reply, (uint32_t) length); 491 client_valid = ipc_send_reply(client, json, (uint32_t)length);
492 free(json);
478 free_cmd_results(results); 493 free_cmd_results(results);
479 goto exit_cleanup; 494 goto exit_cleanup;
480 } 495 }
@@ -497,7 +512,8 @@ void ipc_client_handle_command(struct ipc_client *client) {
497 } 512 }
498 } 513 }
499 const char *json_string = json_object_to_json_string(outputs); 514 const char *json_string = json_object_to_json_string(outputs);
500 ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); 515 client_valid =
516 ipc_send_reply(client, json_string, (uint32_t)strlen(json_string));
501 json_object_put(outputs); // free 517 json_object_put(outputs); // free
502 goto exit_cleanup; 518 goto exit_cleanup;
503 } 519 }
@@ -508,7 +524,8 @@ void ipc_client_handle_command(struct ipc_client *client) {
508 container_for_each_descendant_dfs(&root_container, 524 container_for_each_descendant_dfs(&root_container,
509 ipc_get_workspaces_callback, workspaces); 525 ipc_get_workspaces_callback, workspaces);
510 const char *json_string = json_object_to_json_string(workspaces); 526 const char *json_string = json_object_to_json_string(workspaces);
511 ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); 527 client_valid =
528 ipc_send_reply(client, json_string, (uint32_t)strlen(json_string));
512 json_object_put(workspaces); // free 529 json_object_put(workspaces); // free
513 goto exit_cleanup; 530 goto exit_cleanup;
514 } 531 }
@@ -518,8 +535,8 @@ void ipc_client_handle_command(struct ipc_client *client) {
518 // TODO: Check if they're permitted to use these events 535 // TODO: Check if they're permitted to use these events
519 struct json_object *request = json_tokener_parse(buf); 536 struct json_object *request = json_tokener_parse(buf);
520 if (request == NULL) { 537 if (request == NULL) {
521 ipc_send_reply(client, "{\"success\": false}", 18); 538 client_valid = ipc_send_reply(client, "{\"success\": false}", 18);
522 wlr_log_errno(L_INFO, "Failed to read request"); 539 wlr_log_errno(WLR_INFO, "Failed to read request");
523 goto exit_cleanup; 540 goto exit_cleanup;
524 } 541 }
525 542
@@ -539,15 +556,16 @@ void ipc_client_handle_command(struct ipc_client *client) {
539 } else if (strcmp(event_type, "binding") == 0) { 556 } else if (strcmp(event_type, "binding") == 0) {
540 client->subscribed_events |= event_mask(IPC_EVENT_BINDING); 557 client->subscribed_events |= event_mask(IPC_EVENT_BINDING);
541 } else { 558 } else {
542 ipc_send_reply(client, "{\"success\": false}", 18); 559 client_valid =
560 ipc_send_reply(client, "{\"success\": false}", 18);
543 json_object_put(request); 561 json_object_put(request);
544 wlr_log_errno(L_INFO, "Failed to parse request"); 562 wlr_log_errno(WLR_INFO, "Failed to parse request");
545 goto exit_cleanup; 563 goto exit_cleanup;
546 } 564 }
547 } 565 }
548 566
549 json_object_put(request); 567 json_object_put(request);
550 ipc_send_reply(client, "{\"success\": true}", 17); 568 client_valid = ipc_send_reply(client, "{\"success\": true}", 17);
551 goto exit_cleanup; 569 goto exit_cleanup;
552 } 570 }
553 571
@@ -559,7 +577,8 @@ void ipc_client_handle_command(struct ipc_client *client) {
559 json_object_array_add(inputs, ipc_json_describe_input(device)); 577 json_object_array_add(inputs, ipc_json_describe_input(device));
560 } 578 }
561 const char *json_string = json_object_to_json_string(inputs); 579 const char *json_string = json_object_to_json_string(inputs);
562 ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); 580 client_valid =
581 ipc_send_reply(client, json_string, (uint32_t)strlen(json_string));
563 json_object_put(inputs); // free 582 json_object_put(inputs); // free
564 goto exit_cleanup; 583 goto exit_cleanup;
565 } 584 }
@@ -572,7 +591,8 @@ void ipc_client_handle_command(struct ipc_client *client) {
572 json_object_array_add(seats, ipc_json_describe_seat(seat)); 591 json_object_array_add(seats, ipc_json_describe_seat(seat));
573 } 592 }
574 const char *json_string = json_object_to_json_string(seats); 593 const char *json_string = json_object_to_json_string(seats);
575 ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); 594 client_valid =
595 ipc_send_reply(client, json_string, (uint32_t)strlen(json_string));
576 json_object_put(seats); // free 596 json_object_put(seats); // free
577 goto exit_cleanup; 597 goto exit_cleanup;
578 } 598 }
@@ -582,7 +602,8 @@ void ipc_client_handle_command(struct ipc_client *client) {
582 json_object *tree = 602 json_object *tree =
583 ipc_json_describe_container_recursive(&root_container); 603 ipc_json_describe_container_recursive(&root_container);
584 const char *json_string = json_object_to_json_string(tree); 604 const char *json_string = json_object_to_json_string(tree);
585 ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); 605 client_valid =
606 ipc_send_reply(client, json_string, (uint32_t) strlen(json_string));
586 json_object_put(tree); 607 json_object_put(tree);
587 goto exit_cleanup; 608 goto exit_cleanup;
588 } 609 }
@@ -593,7 +614,8 @@ void ipc_client_handle_command(struct ipc_client *client) {
593 container_descendants(&root_container, C_VIEW, ipc_get_marks_callback, 614 container_descendants(&root_container, C_VIEW, ipc_get_marks_callback,
594 marks); 615 marks);
595 const char *json_string = json_object_to_json_string(marks); 616 const char *json_string = json_object_to_json_string(marks);
596 ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); 617 client_valid =
618 ipc_send_reply(client, json_string, (uint32_t)strlen(json_string));
597 json_object_put(marks); 619 json_object_put(marks);
598 goto exit_cleanup; 620 goto exit_cleanup;
599 } 621 }
@@ -602,7 +624,8 @@ void ipc_client_handle_command(struct ipc_client *client) {
602 { 624 {
603 json_object *version = ipc_json_get_version(); 625 json_object *version = ipc_json_get_version();
604 const char *json_string = json_object_to_json_string(version); 626 const char *json_string = json_object_to_json_string(version);
605 ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); 627 client_valid =
628 ipc_send_reply(client, json_string, (uint32_t)strlen(json_string));
606 json_object_put(version); // free 629 json_object_put(version); // free
607 goto exit_cleanup; 630 goto exit_cleanup;
608 } 631 }
@@ -617,7 +640,9 @@ void ipc_client_handle_command(struct ipc_client *client) {
617 json_object_array_add(bars, json_object_new_string(bar->id)); 640 json_object_array_add(bars, json_object_new_string(bar->id));
618 } 641 }
619 const char *json_string = json_object_to_json_string(bars); 642 const char *json_string = json_object_to_json_string(bars);
620 ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); 643 client_valid =
644 ipc_send_reply(client, json_string,
645 (uint32_t)strlen(json_string));
621 json_object_put(bars); // free 646 json_object_put(bars); // free
622 } else { 647 } else {
623 // Send particular bar's details 648 // Send particular bar's details
@@ -631,27 +656,54 @@ void ipc_client_handle_command(struct ipc_client *client) {
631 } 656 }
632 if (!bar) { 657 if (!bar) {
633 const char *error = "{ \"success\": false, \"error\": \"No bar with that ID\" }"; 658 const char *error = "{ \"success\": false, \"error\": \"No bar with that ID\" }";
634 ipc_send_reply(client, error, (uint32_t)strlen(error)); 659 client_valid =
660 ipc_send_reply(client, error, (uint32_t)strlen(error));
635 goto exit_cleanup; 661 goto exit_cleanup;
636 } 662 }
637 json_object *json = ipc_json_describe_bar_config(bar); 663 json_object *json = ipc_json_describe_bar_config(bar);
638 const char *json_string = json_object_to_json_string(json); 664 const char *json_string = json_object_to_json_string(json);
639 ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); 665 client_valid =
666 ipc_send_reply(client, json_string,
667 (uint32_t)strlen(json_string));
640 json_object_put(json); // free 668 json_object_put(json); // free
641 } 669 }
642 goto exit_cleanup; 670 goto exit_cleanup;
643 } 671 }
644 672
645 default: 673 case IPC_GET_BINDING_MODES:
646 wlr_log(L_INFO, "Unknown IPC command type %i", client->current_command); 674 {
675 json_object *modes = json_object_new_array();
676 for (int i = 0; i < config->modes->length; i++) {
677 struct sway_mode *mode = config->modes->items[i];
678 json_object_array_add(modes, json_object_new_string(mode->name));
679 }
680 const char *json_string = json_object_to_json_string(modes);
681 client_valid =
682 ipc_send_reply(client, json_string, (uint32_t)strlen(json_string));
683 json_object_put(modes); // free
647 goto exit_cleanup; 684 goto exit_cleanup;
648 } 685 }
649 686
650 ipc_send_reply(client, error_denied, (uint32_t)strlen(error_denied)); 687 case IPC_GET_CONFIG:
651 wlr_log(L_DEBUG, "Denied IPC client access to %i", client->current_command); 688 {
689 json_object *json = json_object_new_object();
690 json_object_object_add(json, "config", json_object_new_string(config->current_config));
691 const char *json_string = json_object_to_json_string(json);
692 client_valid =
693 ipc_send_reply(client, json_string, (uint32_t)strlen(json_string));
694 json_object_put(json); // free
695 goto exit_cleanup;
696 }
697
698 default:
699 wlr_log(WLR_INFO, "Unknown IPC command type %i", client->current_command);
700 goto exit_cleanup;
701 }
652 702
653exit_cleanup: 703exit_cleanup:
654 client->payload_length = 0; 704 if (client_valid) {
705 client->payload_length = 0;
706 }
655 free(buf); 707 free(buf);
656 return; 708 return;
657} 709}
@@ -672,14 +724,14 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay
672 } 724 }
673 725
674 if (client->write_buffer_size > 4e6) { // 4 MB 726 if (client->write_buffer_size > 4e6) { // 4 MB
675 wlr_log(L_ERROR, "Client write buffer too big, disconnecting client"); 727 wlr_log(WLR_ERROR, "Client write buffer too big, disconnecting client");
676 ipc_client_disconnect(client); 728 ipc_client_disconnect(client);
677 return false; 729 return false;
678 } 730 }
679 731
680 char *new_buffer = realloc(client->write_buffer, client->write_buffer_size); 732 char *new_buffer = realloc(client->write_buffer, client->write_buffer_size);
681 if (!new_buffer) { 733 if (!new_buffer) {
682 wlr_log(L_ERROR, "Unable to reallocate ipc client write buffer"); 734 wlr_log(WLR_ERROR, "Unable to reallocate ipc client write buffer");
683 ipc_client_disconnect(client); 735 ipc_client_disconnect(client);
684 return false; 736 return false;
685 } 737 }
@@ -696,6 +748,6 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay
696 ipc_client_handle_writable, client); 748 ipc_client_handle_writable, client);
697 } 749 }
698 750
699 wlr_log(L_DEBUG, "Added IPC reply to client %d queue: %s", client->fd, payload); 751 wlr_log(WLR_DEBUG, "Added IPC reply to client %d queue: %s", client->fd, payload);
700 return true; 752 return true;
701} 753}