mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	Add IPC security policy command handlers
This commit is contained in:
		
							parent
							
								
									e9e1a6a409
								
							
						
					
					
						commit
						c8dc4925d1
					
				
					 4 changed files with 200 additions and 1 deletions
				
			
		| 
						 | 
					@ -120,6 +120,7 @@ sway_cmd cmd_gaps;
 | 
				
			||||||
sway_cmd cmd_hide_edge_borders;
 | 
					sway_cmd cmd_hide_edge_borders;
 | 
				
			||||||
sway_cmd cmd_include;
 | 
					sway_cmd cmd_include;
 | 
				
			||||||
sway_cmd cmd_input;
 | 
					sway_cmd cmd_input;
 | 
				
			||||||
 | 
					sway_cmd cmd_ipc;
 | 
				
			||||||
sway_cmd cmd_kill;
 | 
					sway_cmd cmd_kill;
 | 
				
			||||||
sway_cmd cmd_layout;
 | 
					sway_cmd cmd_layout;
 | 
				
			||||||
sway_cmd cmd_log_colors;
 | 
					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_scroll_method;
 | 
				
			||||||
sway_cmd input_cmd_tap;
 | 
					sway_cmd input_cmd_tap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sway_cmd cmd_ipc_cmd;
 | 
				
			||||||
 | 
					sway_cmd cmd_ipc_events;
 | 
				
			||||||
 | 
					sway_cmd cmd_ipc_event_cmd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -180,6 +180,7 @@ static struct cmd_handler handlers[] = {
 | 
				
			||||||
	{ "hide_edge_borders", cmd_hide_edge_borders },
 | 
						{ "hide_edge_borders", cmd_hide_edge_borders },
 | 
				
			||||||
	{ "include", cmd_include },
 | 
						{ "include", cmd_include },
 | 
				
			||||||
	{ "input", cmd_input },
 | 
						{ "input", cmd_input },
 | 
				
			||||||
 | 
						{ "ipc", cmd_ipc },
 | 
				
			||||||
	{ "kill", cmd_kill },
 | 
						{ "kill", cmd_kill },
 | 
				
			||||||
	{ "layout", cmd_layout },
 | 
						{ "layout", cmd_layout },
 | 
				
			||||||
	{ "log_colors", cmd_log_colors },
 | 
						{ "log_colors", cmd_log_colors },
 | 
				
			||||||
| 
						 | 
					@ -292,6 +293,26 @@ static struct cmd_handler bar_colors_handlers[] = {
 | 
				
			||||||
	{ "urgent_workspace", bar_colors_cmd_urgent_workspace },
 | 
						{ "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) {
 | 
					static int handler_compare(const void *_a, const void *_b) {
 | 
				
			||||||
	const struct cmd_handler *a = _a;
 | 
						const struct cmd_handler *a = _a;
 | 
				
			||||||
	const struct cmd_handler *b = _b;
 | 
						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(bar_colors_handlers) / sizeof(struct cmd_handler),
 | 
				
			||||||
			sizeof(struct cmd_handler), handler_compare);
 | 
								sizeof(struct cmd_handler), handler_compare);
 | 
				
			||||||
	} else if (block == CMD_BLOCK_INPUT) {
 | 
						} else if (block == CMD_BLOCK_INPUT) {
 | 
				
			||||||
		sway_log(L_DEBUG, "looking at input handlers");
 | 
					 | 
				
			||||||
		res = bsearch(&d, input_handlers,
 | 
							res = bsearch(&d, input_handlers,
 | 
				
			||||||
			sizeof(input_handlers) / sizeof(struct cmd_handler),
 | 
								sizeof(input_handlers) / sizeof(struct cmd_handler),
 | 
				
			||||||
			sizeof(struct cmd_handler), handler_compare);
 | 
								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 {
 | 
						} else {
 | 
				
			||||||
		res = bsearch(&d, handlers,
 | 
							res = bsearch(&d, handlers,
 | 
				
			||||||
			sizeof(handlers) / sizeof(struct cmd_handler),
 | 
								sizeof(handlers) / sizeof(struct cmd_handler),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										140
									
								
								sway/commands/ipc.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								sway/commands/ipc.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,140 @@
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -641,6 +641,22 @@ bool read_config(FILE *file, struct sway_config *config) {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			break;
 | 
								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:
 | 
							case CMD_BLOCK_END:
 | 
				
			||||||
			switch(block) {
 | 
								switch(block) {
 | 
				
			||||||
			case CMD_BLOCK_MODE:
 | 
								case CMD_BLOCK_MODE:
 | 
				
			||||||
| 
						 | 
					@ -671,6 +687,16 @@ bool read_config(FILE *file, struct sway_config *config) {
 | 
				
			||||||
				block = CMD_BLOCK_END;
 | 
									block = CMD_BLOCK_END;
 | 
				
			||||||
				break;
 | 
									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:
 | 
								case CMD_BLOCK_END:
 | 
				
			||||||
				sway_log(L_ERROR, "Unmatched }");
 | 
									sway_log(L_ERROR, "Unmatched }");
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue