diff options
Diffstat (limited to 'sway/commands.c')
-rw-r--r-- | sway/commands.c | 125 |
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 | ||
296 | static 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 | |||
307 | static 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 | |||
291 | static int handler_compare(const void *_a, const void *_b) { | 316 | static 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 | ||
322 | struct cmd_results *handle_command(char *_exec) { | 354 | struct 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 | |
504 | cleanup: | ||
505 | free_argv(argc, argv); | ||
506 | return results; | ||
507 | } | ||
508 | |||
509 | struct 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 | |||
580 | cleanup: | ||
462 | free_argv(argc, argv); | 581 | free_argv(argc, argv); |
463 | return results; | 582 | return results; |
464 | } | 583 | } |