aboutsummaryrefslogtreecommitdiffstats
path: root/sway/commands.c
diff options
context:
space:
mode:
authorLibravatar emersion <contact@emersion.fr>2017-12-05 10:40:55 +0100
committerLibravatar emersion <contact@emersion.fr>2017-12-05 10:40:55 +0100
commit90f7f1a0e61fa20ed1b74b9df057aa70abc791ed (patch)
treee201e4fb9fef471dd2fcf9581e26addfe3550502 /sway/commands.c
parentMerge pull request #1497 from emersion/cmd-exec (diff)
downloadsway-90f7f1a0e61fa20ed1b74b9df057aa70abc791ed.tar.gz
sway-90f7f1a0e61fa20ed1b74b9df057aa70abc791ed.tar.zst
sway-90f7f1a0e61fa20ed1b74b9df057aa70abc791ed.zip
Add minimal config subsystem
Diffstat (limited to 'sway/commands.c')
-rw-r--r--sway/commands.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/sway/commands.c b/sway/commands.c
index 5fdcdbb6..17638129 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -7,6 +7,8 @@
7#include <stdio.h> 7#include <stdio.h>
8#include <json-c/json.h> 8#include <json-c/json.h>
9#include "sway/commands.h" 9#include "sway/commands.h"
10#include "sway/config.h"
11#include "sway/security.h"
10#include "stringop.h" 12#include "stringop.h"
11#include "log.h" 13#include "log.h"
12 14
@@ -200,6 +202,136 @@ cleanup:
200 return results; 202 return results;
201} 203}
202 204
205// this is like handle_command above, except:
206// 1) it ignores empty commands (empty lines)
207// 2) it does variable substitution
208// 3) it doesn't split commands (because the multiple commands are supposed to
209// be chained together)
210// 4) handle_command handles all state internally while config_command has some
211// state handled outside (notably the block mode, in read_config)
212struct cmd_results *config_command(char *exec, enum cmd_status block) {
213 struct cmd_results *results = NULL;
214 int argc;
215 char **argv = split_args(exec, &argc);
216 if (!argc) {
217 results = cmd_results_new(CMD_SUCCESS, NULL, NULL);
218 goto cleanup;
219 }
220
221 sway_log(L_INFO, "handling config command '%s'", exec);
222 // Endblock
223 if (**argv == '}') {
224 results = cmd_results_new(CMD_BLOCK_END, NULL, NULL);
225 goto cleanup;
226 }
227 struct cmd_handler *handler = find_handler(argv[0], block);
228 if (!handler) {
229 char *input = argv[0] ? argv[0] : "(empty)";
230 results = cmd_results_new(CMD_INVALID, input, "Unknown/invalid command");
231 goto cleanup;
232 }
233 int i;
234 // Var replacement, for all but first argument of set
235 // TODO commands
236 for (i = /*handler->handle == cmd_set ? 2 :*/ 1; i < argc; ++i) {
237 argv[i] = do_var_replacement(argv[i]);
238 unescape_string(argv[i]);
239 }
240 /* Strip quotes for first argument.
241 * TODO This part needs to be handled much better */
242 if (argc>1 && (*argv[1] == '\"' || *argv[1] == '\'')) {
243 strip_quotes(argv[1]);
244 }
245 if (handler->handle) {
246 results = handler->handle(argc-1, argv+1);
247 } else {
248 results = cmd_results_new(CMD_INVALID, argv[0], "This command is shimmed, but unimplemented");
249 }
250
251cleanup:
252 free_argv(argc, argv);
253 return results;
254}
255
256struct cmd_results *config_commands_command(char *exec) {
257 struct cmd_results *results = NULL;
258 int argc;
259 char **argv = split_args(exec, &argc);
260 if (!argc) {
261 results = cmd_results_new(CMD_SUCCESS, NULL, NULL);
262 goto cleanup;
263 }
264
265 // Find handler for the command this is setting a policy for
266 char *cmd = argv[0];
267
268 if (strcmp(cmd, "}") == 0) {
269 results = cmd_results_new(CMD_BLOCK_END, NULL, NULL);
270 goto cleanup;
271 }
272
273 struct cmd_handler *handler = find_handler(cmd, CMD_BLOCK_END);
274 if (!handler && strcmp(cmd, "*") != 0) {
275 char *input = cmd ? cmd : "(empty)";
276 results = cmd_results_new(CMD_INVALID, input, "Unknown/invalid command");
277 goto cleanup;
278 }
279
280 enum command_context context = 0;
281
282 struct {
283 char *name;
284 enum command_context context;
285 } context_names[] = {
286 { "config", CONTEXT_CONFIG },
287 { "binding", CONTEXT_BINDING },
288 { "ipc", CONTEXT_IPC },
289 { "criteria", CONTEXT_CRITERIA },
290 { "all", CONTEXT_ALL },
291 };
292
293 for (int i = 1; i < argc; ++i) {
294 size_t j;
295 for (j = 0; j < sizeof(context_names) / sizeof(context_names[0]); ++j) {
296 if (strcmp(context_names[j].name, argv[i]) == 0) {
297 break;
298 }
299 }
300 if (j == sizeof(context_names) / sizeof(context_names[0])) {
301 results = cmd_results_new(CMD_INVALID, cmd,
302 "Invalid command context %s", argv[i]);
303 goto cleanup;
304 }
305 context |= context_names[j].context;
306 }
307
308 struct command_policy *policy = NULL;
309 for (int i = 0; i < config->command_policies->length; ++i) {
310 struct command_policy *p = config->command_policies->items[i];
311 if (strcmp(p->command, cmd) == 0) {
312 policy = p;
313 break;
314 }
315 }
316 if (!policy) {
317 policy = alloc_command_policy(cmd);
318 sway_assert(policy, "Unable to allocate security policy");
319 if (policy) {
320 list_add(config->command_policies, policy);
321 }
322 }
323 policy->context = context;
324
325 sway_log(L_INFO, "Set command policy for %s to %d",
326 policy->command, policy->context);
327
328 results = cmd_results_new(CMD_SUCCESS, NULL, NULL);
329
330cleanup:
331 free_argv(argc, argv);
332 return results;
333}
334
203struct cmd_results *cmd_results_new(enum cmd_status status, 335struct cmd_results *cmd_results_new(enum cmd_status status,
204 const char *input, const char *format, ...) { 336 const char *input, const char *format, ...) {
205 struct cmd_results *results = malloc(sizeof(struct cmd_results)); 337 struct cmd_results *results = malloc(sizeof(struct cmd_results));