summaryrefslogtreecommitdiffstats
path: root/sway/commands.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/commands.c')
-rw-r--r--sway/commands.c125
1 files changed, 122 insertions, 3 deletions
diff --git a/sway/commands.c b/sway/commands.c
index de29a7af..d87d0084 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -26,6 +26,7 @@
26#include "sway/input_state.h" 26#include "sway/input_state.h"
27#include "sway/criteria.h" 27#include "sway/criteria.h"
28#include "sway/ipc-server.h" 28#include "sway/ipc-server.h"
29#include "sway/security.h"
29#include "sway/input.h" 30#include "sway/input.h"
30#include "sway/border.h" 31#include "sway/border.h"
31#include "stringop.h" 32#include "stringop.h"
@@ -158,6 +159,7 @@ static struct cmd_handler handlers[] = {
158 { "client.placeholder", cmd_client_placeholder }, 159 { "client.placeholder", cmd_client_placeholder },
159 { "client.unfocused", cmd_client_unfocused }, 160 { "client.unfocused", cmd_client_unfocused },
160 { "client.urgent", cmd_client_urgent }, 161 { "client.urgent", cmd_client_urgent },
162 { "commands", cmd_commands },
161 { "debuglog", cmd_debuglog }, 163 { "debuglog", cmd_debuglog },
162 { "default_orientation", cmd_orientation }, 164 { "default_orientation", cmd_orientation },
163 { "exec", cmd_exec }, 165 { "exec", cmd_exec },
@@ -178,6 +180,7 @@ static struct cmd_handler handlers[] = {
178 { "hide_edge_borders", cmd_hide_edge_borders }, 180 { "hide_edge_borders", cmd_hide_edge_borders },
179 { "include", cmd_include }, 181 { "include", cmd_include },
180 { "input", cmd_input }, 182 { "input", cmd_input },
183 { "ipc", cmd_ipc },
181 { "kill", cmd_kill }, 184 { "kill", cmd_kill },
182 { "layout", cmd_layout }, 185 { "layout", cmd_layout },
183 { "log_colors", cmd_log_colors }, 186 { "log_colors", cmd_log_colors },
@@ -187,6 +190,8 @@ static struct cmd_handler handlers[] = {
187 { "new_float", cmd_new_float }, 190 { "new_float", cmd_new_float },
188 { "new_window", cmd_new_window }, 191 { "new_window", cmd_new_window },
189 { "output", cmd_output }, 192 { "output", cmd_output },
193 { "permit", cmd_permit },
194 { "reject", cmd_reject },
190 { "reload", cmd_reload }, 195 { "reload", cmd_reload },
191 { "resize", cmd_resize }, 196 { "resize", cmd_resize },
192 { "scratchpad", cmd_scratchpad }, 197 { "scratchpad", cmd_scratchpad },
@@ -288,6 +293,26 @@ static struct cmd_handler bar_colors_handlers[] = {
288 { "urgent_workspace", bar_colors_cmd_urgent_workspace }, 293 { "urgent_workspace", bar_colors_cmd_urgent_workspace },
289}; 294};
290 295
296static struct cmd_handler ipc_handlers[] = {
297 { "bar-config", cmd_ipc_cmd },
298 { "command", cmd_ipc_cmd },
299 { "events", cmd_ipc_events },
300 { "inputs", cmd_ipc_cmd },
301 { "marks", cmd_ipc_cmd },
302 { "outputs", cmd_ipc_cmd },
303 { "tree", cmd_ipc_cmd },
304 { "workspaces", cmd_ipc_cmd },
305};
306
307static struct cmd_handler ipc_event_handlers[] = {
308 { "binding", cmd_ipc_event_cmd },
309 { "input", cmd_ipc_event_cmd },
310 { "mode", cmd_ipc_event_cmd },
311 { "output", cmd_ipc_event_cmd },
312 { "window", cmd_ipc_event_cmd },
313 { "workspace", cmd_ipc_event_cmd },
314};
315
291static int handler_compare(const void *_a, const void *_b) { 316static int handler_compare(const void *_a, const void *_b) {
292 const struct cmd_handler *a = _a; 317 const struct cmd_handler *a = _a;
293 const struct cmd_handler *b = _b; 318 const struct cmd_handler *b = _b;
@@ -307,10 +332,17 @@ static struct cmd_handler *find_handler(char *line, enum cmd_status block) {
307 sizeof(bar_colors_handlers) / sizeof(struct cmd_handler), 332 sizeof(bar_colors_handlers) / sizeof(struct cmd_handler),
308 sizeof(struct cmd_handler), handler_compare); 333 sizeof(struct cmd_handler), handler_compare);
309 } else if (block == CMD_BLOCK_INPUT) { 334 } else if (block == CMD_BLOCK_INPUT) {
310 sway_log(L_DEBUG, "looking at input handlers");
311 res = bsearch(&d, input_handlers, 335 res = bsearch(&d, input_handlers,
312 sizeof(input_handlers) / sizeof(struct cmd_handler), 336 sizeof(input_handlers) / sizeof(struct cmd_handler),
313 sizeof(struct cmd_handler), handler_compare); 337 sizeof(struct cmd_handler), handler_compare);
338 } else if (block == CMD_BLOCK_IPC) {
339 res = bsearch(&d, ipc_handlers,
340 sizeof(ipc_handlers) / sizeof(struct cmd_handler),
341 sizeof(struct cmd_handler), handler_compare);
342 } else if (block == CMD_BLOCK_IPC_EVENTS) {
343 res = bsearch(&d, ipc_event_handlers,
344 sizeof(ipc_event_handlers) / sizeof(struct cmd_handler),
345 sizeof(struct cmd_handler), handler_compare);
314 } else { 346 } else {
315 res = bsearch(&d, handlers, 347 res = bsearch(&d, handlers,
316 sizeof(handlers) / sizeof(struct cmd_handler), 348 sizeof(handlers) / sizeof(struct cmd_handler),
@@ -319,7 +351,7 @@ static struct cmd_handler *find_handler(char *line, enum cmd_status block) {
319 return res; 351 return res;
320} 352}
321 353
322struct cmd_results *handle_command(char *_exec) { 354struct cmd_results *handle_command(char *_exec, enum command_context context) {
323 // Even though this function will process multiple commands we will only 355 // Even though this function will process multiple commands we will only
324 // return the last error, if any (for now). (Since we have access to an 356 // return the last error, if any (for now). (Since we have access to an
325 // error string we could e.g. concatonate all errors there.) 357 // error string we could e.g. concatonate all errors there.)
@@ -393,6 +425,16 @@ struct cmd_results *handle_command(char *_exec) {
393 free_argv(argc, argv); 425 free_argv(argc, argv);
394 goto cleanup; 426 goto cleanup;
395 } 427 }
428 if (!(get_command_policy(argv[0]) & context)) {
429 if (results) {
430 free_cmd_results(results);
431 }
432 results = cmd_results_new(CMD_INVALID, cmd,
433 "Permission denied for %s via %s", cmd,
434 command_policy_str(context));
435 free_argv(argc, argv);
436 goto cleanup;
437 }
396 struct cmd_results *res = handler->handle(argc-1, argv+1); 438 struct cmd_results *res = handler->handle(argc-1, argv+1);
397 if (res->status != CMD_SUCCESS) { 439 if (res->status != CMD_SUCCESS) {
398 free_argv(argc, argv); 440 free_argv(argc, argv);
@@ -458,7 +500,84 @@ struct cmd_results *config_command(char *exec, enum cmd_status block) {
458 } else { 500 } else {
459 results = cmd_results_new(CMD_INVALID, argv[0], "This command is shimmed, but unimplemented"); 501 results = cmd_results_new(CMD_INVALID, argv[0], "This command is shimmed, but unimplemented");
460 } 502 }
461 cleanup: 503
504cleanup:
505 free_argv(argc, argv);
506 return results;
507}
508
509struct cmd_results *config_commands_command(char *exec) {
510 struct cmd_results *results = NULL;
511 int argc;
512 char **argv = split_args(exec, &argc);
513 if (!argc) {
514 results = cmd_results_new(CMD_SUCCESS, NULL, NULL);
515 goto cleanup;
516 }
517
518 // Find handler for the command this is setting a policy for
519 char *cmd = argv[0];
520
521 if (strcmp(cmd, "}") == 0) {
522 results = cmd_results_new(CMD_BLOCK_END, NULL, NULL);
523 goto cleanup;
524 }
525
526 struct cmd_handler *handler = find_handler(cmd, CMD_BLOCK_END);
527 if (!handler && strcmp(cmd, "*") != 0) {
528 char *input = cmd ? cmd : "(empty)";
529 results = cmd_results_new(CMD_INVALID, input, "Unknown/invalid command");
530 goto cleanup;
531 }
532
533 enum command_context context = 0;
534
535 struct {
536 char *name;
537 enum command_context context;
538 } context_names[] = {
539 { "config", CONTEXT_CONFIG },
540 { "binding", CONTEXT_BINDING },
541 { "ipc", CONTEXT_IPC },
542 { "criteria", CONTEXT_CRITERIA },
543 { "all", CONTEXT_ALL },
544 };
545
546 for (int i = 1; i < argc; ++i) {
547 size_t j;
548 for (j = 0; j < sizeof(context_names) / sizeof(context_names[0]); ++j) {
549 if (strcmp(context_names[j].name, argv[i]) == 0) {
550 break;
551 }
552 }
553 if (j == sizeof(context_names) / sizeof(context_names[0])) {
554 results = cmd_results_new(CMD_INVALID, cmd,
555 "Invalid command context %s", argv[i]);
556 goto cleanup;
557 }
558 context |= context_names[j].context;
559 }
560
561 struct command_policy *policy = NULL;
562 for (int i = 0; i < config->command_policies->length; ++i) {
563 struct command_policy *p = config->command_policies->items[i];
564 if (strcmp(p->command, cmd) == 0) {
565 policy = p;
566 break;
567 }
568 }
569 if (!policy) {
570 policy = alloc_command_policy(cmd);
571 list_add(config->command_policies, policy);
572 }
573 policy->context = context;
574
575 sway_log(L_INFO, "Set command policy for %s to %d",
576 policy->command, policy->context);
577
578 results = cmd_results_new(CMD_SUCCESS, NULL, NULL);
579
580cleanup:
462 free_argv(argc, argv); 581 free_argv(argc, argv);
463 return results; 582 return results;
464} 583}