From 76cab04b4d7828f3c4f607c49e1e6ad78aa6e3da Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 1 Dec 2016 21:36:43 -0500 Subject: Implement permit and reject commands --- include/sway/commands.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/sway/commands.h') diff --git a/include/sway/commands.h b/include/sway/commands.h index db5e94d9..1d5d56ac 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -122,6 +122,8 @@ sway_cmd cmd_new_float; sway_cmd cmd_new_window; sway_cmd cmd_orientation; sway_cmd cmd_output; +sway_cmd cmd_permit; +sway_cmd cmd_reject; sway_cmd cmd_reload; sway_cmd cmd_resize; sway_cmd cmd_scratchpad; -- cgit v1.2.3 From f23880b1fdd70a21b04317c18208a1f3ce356839 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 2 Dec 2016 08:10:03 -0500 Subject: Add support for command policies in config file --- include/sway/commands.h | 10 +++++- include/sway/security.h | 1 + sway/commands.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++- sway/commands/commands.c | 23 ++++++++++++++ sway/commands/permit.c | 3 +- sway/config.c | 21 ++++++++++++- sway/security.c | 10 ++++-- 7 files changed, 142 insertions(+), 8 deletions(-) create mode 100644 sway/commands/commands.c (limited to 'include/sway/commands.h') diff --git a/include/sway/commands.h b/include/sway/commands.h index 1d5d56ac..ccc3cf58 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -18,7 +18,10 @@ enum cmd_status { CMD_BLOCK_MODE, CMD_BLOCK_BAR, CMD_BLOCK_BAR_COLORS, - CMD_BLOCK_INPUT + CMD_BLOCK_INPUT, + CMD_BLOCK_COMMANDS, + CMD_BLOCK_IPC, + CMD_BLOCK_IPC_EVENTS, }; /** @@ -58,6 +61,10 @@ struct cmd_results *handle_command(char *command); * Do not use this under normal conditions. */ struct cmd_results *config_command(char *command, enum cmd_status block); +/* + * Parses a command policy rule. + */ +struct cmd_results *config_commands_command(char *exec); /** * Allocates a cmd_results object. @@ -93,6 +100,7 @@ sway_cmd cmd_client_unfocused; sway_cmd cmd_client_urgent; sway_cmd cmd_client_placeholder; sway_cmd cmd_client_background; +sway_cmd cmd_commands; sway_cmd cmd_debuglog; sway_cmd cmd_exec; sway_cmd cmd_exec_always; diff --git a/include/sway/security.h b/include/sway/security.h index ae2de0d8..aa51fd81 100644 --- a/include/sway/security.h +++ b/include/sway/security.h @@ -7,5 +7,6 @@ enum secure_feature get_feature_policy(pid_t pid); enum command_context get_command_policy(const char *cmd); struct feature_policy *alloc_feature_policy(const char *program); +struct command_policy *alloc_command_policy(const char *command); #endif diff --git a/sway/commands.c b/sway/commands.c index e2bafcb2..0bfe9d13 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -26,6 +26,7 @@ #include "sway/input_state.h" #include "sway/criteria.h" #include "sway/ipc-server.h" +#include "sway/security.h" #include "sway/input.h" #include "sway/border.h" #include "stringop.h" @@ -158,6 +159,7 @@ static struct cmd_handler handlers[] = { { "client.placeholder", cmd_client_placeholder }, { "client.unfocused", cmd_client_unfocused }, { "client.urgent", cmd_client_urgent }, + { "commands", cmd_commands }, { "debuglog", cmd_debuglog }, { "default_orientation", cmd_orientation }, { "exec", cmd_exec }, @@ -460,7 +462,85 @@ struct cmd_results *config_command(char *exec, enum cmd_status block) { } else { results = cmd_results_new(CMD_INVALID, argv[0], "This command is shimmed, but unimplemented"); } - cleanup: + +cleanup: + free_argv(argc, argv); + return results; +} + +struct cmd_results *config_commands_command(char *exec) { + struct cmd_results *results = NULL; + int argc; + char **argv = split_args(exec, &argc); + if (!argc) { + results = cmd_results_new(CMD_SUCCESS, NULL, NULL); + goto cleanup; + } + + // Find handler for the command this is setting a policy for + char *cmd = argv[0]; + + if (strcmp(cmd, "}") == 0) { + results = cmd_results_new(CMD_BLOCK_END, NULL, NULL); + goto cleanup; + } + + struct cmd_handler *handler = find_handler(cmd, CMD_BLOCK_END); + if (!handler) { + char *input = cmd ? cmd : "(empty)"; + results = cmd_results_new(CMD_INVALID, input, "Unknown/invalid command"); + goto cleanup; + } + + enum command_context context = 0; + + struct { + char *name; + enum command_context context; + } context_names[] = { + { "config", CONTEXT_CONFIG }, + { "binding", CONTEXT_BINDING }, + { "ipc", CONTEXT_IPC }, + { "criteria", CONTEXT_CRITERIA }, + { "all", CONTEXT_ALL }, + }; + size_t names_len = 5; + + for (int i = 1; i < argc; ++i) { + size_t j; + for (j = 0; j < names_len; ++j) { + if (strcmp(context_names[j].name, argv[i]) == 0) { + break; + } + } + if (j == names_len) { + results = cmd_results_new(CMD_INVALID, cmd, + "Invalid command context %s", argv[i]); + goto cleanup; + } + context |= context_names[j].context; + } + + struct command_policy *policy = NULL; + for (int i = 0; i < config->command_policies->length; ++i) { + struct command_policy *p = config->command_policies->items[i]; + if (strcmp(p->command, cmd) == 0) { + policy = p; + break; + } + } + if (!policy) { + policy = alloc_command_policy(cmd); + list_add(config->command_policies, policy); + } + policy->context = context; + + sway_log(L_INFO, "Set command policy for %s to %d", + policy->command, policy->context); + + results = cmd_results_new(CMD_SUCCESS, NULL, NULL); + +cleanup: free_argv(argc, argv); return results; } diff --git a/sway/commands/commands.c b/sway/commands/commands.c new file mode 100644 index 00000000..5d248e30 --- /dev/null +++ b/sway/commands/commands.c @@ -0,0 +1,23 @@ +#include +#include +#include "sway/commands.h" +#include "sway/config.h" +#include "list.h" +#include "log.h" + +struct cmd_results *cmd_commands(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "commands", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (strcmp(argv[0], "{") != 0) { + return cmd_results_new(CMD_FAILURE, "commands", "Expected block declaration"); + } + + if (!config->reading) { + return cmd_results_new(CMD_FAILURE, "commands", "Can only be used in config file."); + } + + return cmd_results_new(CMD_BLOCK_COMMANDS, NULL, NULL); +} diff --git a/sway/commands/permit.c b/sway/commands/permit.c index 8a7bb98c..258ea5b2 100644 --- a/sway/commands/permit.c +++ b/sway/commands/permit.c @@ -20,8 +20,7 @@ static enum secure_feature get_features(int argc, char **argv, { "keyboard", FEATURE_KEYBOARD }, { "mouse", FEATURE_MOUSE }, }; - size_t names_len = sizeof(feature_names) / - (sizeof(char *) + sizeof(enum secure_feature)); + size_t names_len = 7; for (int i = 1; i < argc; ++i) { size_t j; diff --git a/sway/config.c b/sway/config.c index a2f6a728..e55c6dea 100644 --- a/sway/config.c +++ b/sway/config.c @@ -580,7 +580,13 @@ bool read_config(FILE *file, struct sway_config *config) { free(line); continue; } - struct cmd_results *res = config_command(line, block); + struct cmd_results *res; + if (block == CMD_BLOCK_COMMANDS) { + // Special case + res = config_commands_command(line); + } else { + res = config_command(line, block); + } switch(res->status) { case CMD_FAILURE: case CMD_INVALID: @@ -626,6 +632,14 @@ bool read_config(FILE *file, struct sway_config *config) { } break; + case CMD_BLOCK_COMMANDS: + if (block == CMD_BLOCK_END) { + block = CMD_BLOCK_COMMANDS; + } else { + sway_log(L_ERROR, "Invalid block '%s'", line); + } + break; + case CMD_BLOCK_END: switch(block) { case CMD_BLOCK_MODE: @@ -651,6 +665,11 @@ bool read_config(FILE *file, struct sway_config *config) { block = CMD_BLOCK_BAR; break; + case CMD_BLOCK_COMMANDS: + sway_log(L_DEBUG, "End of commands block"); + block = CMD_BLOCK_END; + break; + case CMD_BLOCK_END: sway_log(L_ERROR, "Unmatched }"); break; diff --git a/sway/security.c b/sway/security.c index a4cecf16..670cae56 100644 --- a/sway/security.c +++ b/sway/security.c @@ -11,6 +11,13 @@ struct feature_policy *alloc_feature_policy(const char *program) { return policy; } +struct command_policy *alloc_command_policy(const char *command) { + struct command_policy *policy = malloc(sizeof(struct command_policy)); + policy->command = strdup(command); + policy->context = CONTEXT_ALL; + return policy; +} + enum secure_feature get_feature_policy(pid_t pid) { const char *fmt = "/proc/%d/exe"; int pathlen = snprintf(NULL, 0, fmt, pid); @@ -50,9 +57,6 @@ enum command_context get_command_policy(const char *cmd) { for (int i = 0; i < config->command_policies->length; ++i) { struct command_policy *policy = config->command_policies->items[i]; - if (strcmp(policy->command, "*") == 0) { - default_policy = policy->context; - } if (strcmp(policy->command, cmd) == 0) { return policy->context; } -- cgit v1.2.3 From 39cf9a82f7c1f7e5d7b4952cabf215c8459a99e2 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 2 Dec 2016 08:17:45 -0500 Subject: Enforce command policies --- include/sway/commands.h | 2 +- include/sway/security.h | 2 ++ sway/commands.c | 12 +++++++++++- sway/handlers.c | 14 +++++++------- sway/ipc-server.c | 2 +- sway/security.c | 17 +++++++++++++++++ 6 files changed, 39 insertions(+), 10 deletions(-) (limited to 'include/sway/commands.h') diff --git a/include/sway/commands.h b/include/sway/commands.h index ccc3cf58..9e8d013e 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -54,7 +54,7 @@ int sp_index; /** * Parse and handles a command. */ -struct cmd_results *handle_command(char *command); +struct cmd_results *handle_command(char *command, enum command_context context); /** * Parse and handles a command during config file loading. * diff --git a/include/sway/security.h b/include/sway/security.h index aa51fd81..1cc85bee 100644 --- a/include/sway/security.h +++ b/include/sway/security.h @@ -6,6 +6,8 @@ enum secure_feature get_feature_policy(pid_t pid); enum command_context get_command_policy(const char *cmd); +const char *command_policy_str(enum command_context context); + struct feature_policy *alloc_feature_policy(const char *program); struct command_policy *alloc_command_policy(const char *command); diff --git a/sway/commands.c b/sway/commands.c index 0bfe9d13..5d5087b1 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -323,7 +323,7 @@ static struct cmd_handler *find_handler(char *line, enum cmd_status block) { return res; } -struct cmd_results *handle_command(char *_exec) { +struct cmd_results *handle_command(char *_exec, enum command_context context) { // Even though this function will process multiple commands we will only // return the last error, if any (for now). (Since we have access to an // error string we could e.g. concatonate all errors there.) @@ -397,6 +397,16 @@ struct cmd_results *handle_command(char *_exec) { free_argv(argc, argv); goto cleanup; } + if (!(get_command_policy(argv[0]) & context)) { + if (results) { + free_cmd_results(results); + } + results = cmd_results_new(CMD_INVALID, cmd, + "Permission denied for %s via %s", cmd, + command_policy_str(context)); + free_argv(argc, argv); + goto cleanup; + } struct cmd_results *res = handler->handle(argc-1, argv+1); if (res->status != CMD_SUCCESS) { free_argv(argc, argv); diff --git a/sway/handlers.c b/sway/handlers.c index a329329d..ee52ba38 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -386,7 +386,7 @@ static bool handle_view_created(wlc_handle handle) { struct criteria *crit = criteria->items[i]; sway_log(L_DEBUG, "for_window '%s' matches new view %p, cmd: '%s'", crit->crit_raw, newview, crit->cmdlist); - struct cmd_results *res = handle_command(crit->cmdlist); + struct cmd_results *res = handle_command(crit->cmdlist, CONTEXT_CRITERIA); if (res->status != CMD_SUCCESS) { sway_log(L_ERROR, "Command '%s' failed: %s", res->input, res->error); } @@ -585,7 +585,7 @@ static void handle_binding_command(struct sway_binding *binding) { reload = true; } - struct cmd_results *res = handle_command(binding->command); + struct cmd_results *res = handle_command(binding->command, CONTEXT_BINDING); if (res->status != CMD_SUCCESS) { sway_log(L_ERROR, "Command '%s' failed: %s", res->input, res->error); } @@ -936,18 +936,18 @@ bool handle_pointer_scroll(wlc_handle view, uint32_t time, const struct wlc_modi int y_amount = (int)_amount[1]; if (x_amount > 0 && strcmp(config->floating_scroll_up_cmd, "")) { - handle_command(config->floating_scroll_up_cmd); + handle_command(config->floating_scroll_up_cmd, CONTEXT_BINDING); return EVENT_HANDLED; } else if (x_amount < 0 && strcmp(config->floating_scroll_down_cmd, "")) { - handle_command(config->floating_scroll_down_cmd); + handle_command(config->floating_scroll_down_cmd, CONTEXT_BINDING); return EVENT_HANDLED; } if (y_amount > 0 && strcmp(config->floating_scroll_right_cmd, "")) { - handle_command(config->floating_scroll_right_cmd); + handle_command(config->floating_scroll_right_cmd, CONTEXT_BINDING); return EVENT_HANDLED; } else if (y_amount < 0 && strcmp(config->floating_scroll_left_cmd, "")) { - handle_command(config->floating_scroll_left_cmd); + handle_command(config->floating_scroll_left_cmd, CONTEXT_BINDING); return EVENT_HANDLED; } } @@ -960,7 +960,7 @@ static void handle_wlc_ready(void) { config->active = true; while (config->cmd_queue->length) { char *line = config->cmd_queue->items[0]; - struct cmd_results *res = handle_command(line); + struct cmd_results *res = handle_command(line, CONTEXT_CONFIG); if (res->status != CMD_SUCCESS) { sway_log(L_ERROR, "Error on line '%s': %s", line, res->error); } diff --git a/sway/ipc-server.c b/sway/ipc-server.c index ebb5ce58..e575081b 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -312,7 +312,7 @@ void ipc_client_handle_command(struct ipc_client *client) { switch (client->current_command) { case IPC_COMMAND: { - struct cmd_results *results = handle_command(buf); + struct cmd_results *results = handle_command(buf, CONTEXT_IPC); const char *json = cmd_results_to_json(results); char reply[256]; int length = snprintf(reply, sizeof(reply), "%s", json); diff --git a/sway/security.c b/sway/security.c index 670cae56..2ccc30fd 100644 --- a/sway/security.c +++ b/sway/security.c @@ -64,3 +64,20 @@ enum command_context get_command_policy(const char *cmd) { return default_policy; } + +const char *command_policy_str(enum command_context context) { + switch (context) { + case CONTEXT_ALL: + return "all"; + case CONTEXT_CONFIG: + return "config"; + case CONTEXT_BINDING: + return "binding"; + case CONTEXT_IPC: + return "IPC"; + case CONTEXT_CRITERIA: + return "criteria"; + default: + return "unknown"; + } +} -- cgit v1.2.3 From c8dc4925d1e0f5d5086a4c15415ee9fb0b7e6155 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 2 Dec 2016 17:34:26 -0500 Subject: Add IPC security policy command handlers --- include/sway/commands.h | 5 ++ sway/commands.c | 30 ++++++++++- sway/commands/ipc.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++++ sway/config.c | 26 +++++++++ 4 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 sway/commands/ipc.c (limited to 'include/sway/commands.h') diff --git a/include/sway/commands.h b/include/sway/commands.h index 9e8d013e..3ab8d5af 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -120,6 +120,7 @@ sway_cmd cmd_gaps; sway_cmd cmd_hide_edge_borders; sway_cmd cmd_include; sway_cmd cmd_input; +sway_cmd cmd_ipc; sway_cmd cmd_kill; sway_cmd cmd_layout; sway_cmd cmd_log_colors; @@ -192,4 +193,8 @@ sway_cmd input_cmd_pointer_accel; sway_cmd input_cmd_scroll_method; sway_cmd input_cmd_tap; +sway_cmd cmd_ipc_cmd; +sway_cmd cmd_ipc_events; +sway_cmd cmd_ipc_event_cmd; + #endif diff --git a/sway/commands.c b/sway/commands.c index 5d5087b1..47f7533c 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -180,6 +180,7 @@ static struct cmd_handler handlers[] = { { "hide_edge_borders", cmd_hide_edge_borders }, { "include", cmd_include }, { "input", cmd_input }, + { "ipc", cmd_ipc }, { "kill", cmd_kill }, { "layout", cmd_layout }, { "log_colors", cmd_log_colors }, @@ -292,6 +293,26 @@ static struct cmd_handler bar_colors_handlers[] = { { "urgent_workspace", bar_colors_cmd_urgent_workspace }, }; +static struct cmd_handler ipc_handlers[] = { + { "bar-config", cmd_ipc_cmd }, + { "command", cmd_ipc_cmd }, + { "events", cmd_ipc_events }, + { "inputs", cmd_ipc_cmd }, + { "marks", cmd_ipc_cmd }, + { "outputs", cmd_ipc_cmd }, + { "tree", cmd_ipc_cmd }, + { "workspaces", cmd_ipc_cmd }, +}; + +static struct cmd_handler ipc_event_handlers[] = { + { "binding", cmd_ipc_event_cmd }, + { "input", cmd_ipc_event_cmd }, + { "mode", cmd_ipc_event_cmd }, + { "output", cmd_ipc_event_cmd }, + { "window", cmd_ipc_event_cmd }, + { "workspace", cmd_ipc_event_cmd }, +}; + static int handler_compare(const void *_a, const void *_b) { const struct cmd_handler *a = _a; const struct cmd_handler *b = _b; @@ -311,10 +332,17 @@ static struct cmd_handler *find_handler(char *line, enum cmd_status block) { sizeof(bar_colors_handlers) / sizeof(struct cmd_handler), sizeof(struct cmd_handler), handler_compare); } else if (block == CMD_BLOCK_INPUT) { - sway_log(L_DEBUG, "looking at input handlers"); res = bsearch(&d, input_handlers, sizeof(input_handlers) / sizeof(struct cmd_handler), sizeof(struct cmd_handler), handler_compare); + } else if (block == CMD_BLOCK_IPC) { + res = bsearch(&d, ipc_handlers, + sizeof(ipc_handlers) / sizeof(struct cmd_handler), + sizeof(struct cmd_handler), handler_compare); + } else if (block == CMD_BLOCK_IPC_EVENTS) { + res = bsearch(&d, ipc_event_handlers, + sizeof(ipc_event_handlers) / sizeof(struct cmd_handler), + sizeof(struct cmd_handler), handler_compare); } else { res = bsearch(&d, handlers, sizeof(handlers) / sizeof(struct cmd_handler), diff --git a/sway/commands/ipc.c b/sway/commands/ipc.c new file mode 100644 index 00000000..e6ae27a4 --- /dev/null +++ b/sway/commands/ipc.c @@ -0,0 +1,140 @@ +#include +#include +#include "sway/commands.h" +#include "sway/config.h" +#include "ipc.h" +#include "log.h" +#include "util.h" + +struct cmd_results *cmd_ipc(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "ipc", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (config->reading && strcmp("{", argv[0]) != 0) { + return cmd_results_new(CMD_INVALID, "ipc", + "Expected '{' at start of IPC config definition."); + } + + if (!config->reading) { + return cmd_results_new(CMD_FAILURE, "ipc", "Can only be used in config file."); + } + + return cmd_results_new(CMD_BLOCK_IPC, NULL, NULL); +} + +struct cmd_results *cmd_ipc_events(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "events", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (config->reading && strcmp("{", argv[0]) != 0) { + return cmd_results_new(CMD_INVALID, "events", + "Expected '{' at start of IPC event config definition."); + } + + if (!config->reading) { + return cmd_results_new(CMD_FAILURE, "events", "Can only be used in config file."); + } + + return cmd_results_new(CMD_BLOCK_IPC_EVENTS, NULL, NULL); +} + +struct cmd_results *cmd_ipc_cmd(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "ipc", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + bool enabled; + if (strcmp(argv[0], "enabled") == 0) { + enabled = true; + } else if (strcmp(argv[0], "disabled") == 0) { + enabled = false; + } else { + return cmd_results_new(CMD_INVALID, argv[-1], + "Argument must be one of 'enabled' or 'disabled'"); + } + + struct { + char *name; + enum ipc_command_type type; + } types[] = { + { "command", IPC_COMMAND }, + { "workspaces", IPC_GET_WORKSPACES }, + { "outputs", IPC_GET_OUTPUTS }, + { "tree", IPC_GET_TREE }, + { "marks", IPC_GET_MARKS }, + { "bar-config", IPC_GET_BAR_CONFIG }, + { "inputs", IPC_GET_INPUTS }, + }; + + uint32_t type = 0; + + for (size_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i) { + if (strcmp(types[i].name, argv[-1]) == 0) { + type = types[i].type; + break; + } + } + + if (enabled) { + config->ipc_policy |= type; + sway_log(L_DEBUG, "Enabled IPC %s feature", argv[-1]); + } else { + config->ipc_policy &= ~type; + sway_log(L_DEBUG, "Disabled IPC %s feature", argv[-1]); + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} + +struct cmd_results *cmd_ipc_event_cmd(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "ipc", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + bool enabled; + if (strcmp(argv[0], "enabled") == 0) { + enabled = true; + } else if (strcmp(argv[0], "disabled") == 0) { + enabled = false; + } else { + return cmd_results_new(CMD_INVALID, argv[-1], + "Argument must be one of 'enabled' or 'disabled'"); + } + + struct { + char *name; + enum ipc_command_type type; + } types[] = { + { "workspace", event_mask(IPC_EVENT_WORKSPACE) }, + { "output", event_mask(IPC_EVENT_OUTPUT) }, + { "mode", event_mask(IPC_EVENT_MODE) }, + { "window", event_mask(IPC_EVENT_WINDOW) }, + { "binding", event_mask(IPC_EVENT_BINDING) }, + { "input", event_mask(IPC_EVENT_INPUT) }, + }; + + uint32_t type = 0; + + for (size_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i) { + if (strcmp(types[i].name, argv[-1]) == 0) { + type = types[i].type; + break; + } + } + + if (enabled) { + config->ipc_policy |= type; + sway_log(L_DEBUG, "Enabled IPC %s event", argv[-1]); + } else { + config->ipc_policy &= ~type; + sway_log(L_DEBUG, "Disabled IPC %s event", argv[-1]); + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/config.c b/sway/config.c index b1b0aac9..e737f83c 100644 --- a/sway/config.c +++ b/sway/config.c @@ -641,6 +641,22 @@ bool read_config(FILE *file, struct sway_config *config) { } break; + case CMD_BLOCK_IPC: + if (block == CMD_BLOCK_END) { + block = CMD_BLOCK_IPC; + } else { + sway_log(L_ERROR, "Invalid block '%s'", line); + } + break; + + case CMD_BLOCK_IPC_EVENTS: + if (block == CMD_BLOCK_IPC) { + block = CMD_BLOCK_IPC_EVENTS; + } else { + sway_log(L_ERROR, "Invalid block '%s'", line); + } + break; + case CMD_BLOCK_END: switch(block) { case CMD_BLOCK_MODE: @@ -671,6 +687,16 @@ bool read_config(FILE *file, struct sway_config *config) { block = CMD_BLOCK_END; break; + case CMD_BLOCK_IPC: + sway_log(L_DEBUG, "End of IPC block"); + block = CMD_BLOCK_END; + break; + + case CMD_BLOCK_IPC_EVENTS: + sway_log(L_DEBUG, "End of IPC events block"); + block = CMD_BLOCK_IPC; + break; + case CMD_BLOCK_END: sway_log(L_ERROR, "Unmatched }"); break; -- cgit v1.2.3