aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sway/commands.c1
-rw-r--r--sway/commands/include.c15
-rw-r--r--sway/config.c89
-rw-r--r--sway/meson.build1
4 files changed, 106 insertions, 0 deletions
diff --git a/sway/commands.c b/sway/commands.c
index 17638129..05a66a7f 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -95,6 +95,7 @@ static struct cmd_handler handlers[] = {
95 { "exec", cmd_exec }, 95 { "exec", cmd_exec },
96 { "exec_always", cmd_exec_always }, 96 { "exec_always", cmd_exec_always },
97 { "exit", cmd_exit }, 97 { "exit", cmd_exit },
98 { "include", cmd_include },
98}; 99};
99 100
100static int handler_compare(const void *_a, const void *_b) { 101static int handler_compare(const void *_a, const void *_b) {
diff --git a/sway/commands/include.c b/sway/commands/include.c
new file mode 100644
index 00000000..1ba9a10d
--- /dev/null
+++ b/sway/commands/include.c
@@ -0,0 +1,15 @@
1#include "sway/commands.h"
2#include "sway/config.h"
3
4struct cmd_results *cmd_include(int argc, char **argv) {
5 struct cmd_results *error = NULL;
6 if ((error = checkarg(argc, "include", EXPECTED_EQUAL_TO, 1))) {
7 return error;
8 }
9
10 if (!load_include_configs(argv[0], config)) {
11 return cmd_results_new(CMD_INVALID, "include", "Failed to include sub configuration file: %s", argv[0]);
12 }
13
14 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
15}
diff --git a/sway/config.c b/sway/config.c
index 475e8b04..61131845 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -311,6 +311,95 @@ bool load_main_config(const char *file, bool is_active) {
311 return success; 311 return success;
312} 312}
313 313
314static bool load_include_config(const char *path, const char *parent_dir, struct sway_config *config) {
315 // save parent config
316 const char *parent_config = config->current_config;
317
318 char *full_path = strdup(path);
319 int len = strlen(path);
320 if (len >= 1 && path[0] != '/') {
321 len = len + strlen(parent_dir) + 2;
322 full_path = malloc(len * sizeof(char));
323 if (!full_path) {
324 sway_log(L_ERROR, "Unable to allocate full path to included config");
325 return false;
326 }
327 snprintf(full_path, len, "%s/%s", parent_dir, path);
328 }
329
330 char *real_path = realpath(full_path, NULL);
331 free(full_path);
332
333 if (real_path == NULL) {
334 sway_log(L_DEBUG, "%s not found.", path);
335 return false;
336 }
337
338 // check if config has already been included
339 int j;
340 for (j = 0; j < config->config_chain->length; ++j) {
341 char *old_path = config->config_chain->items[j];
342 if (strcmp(real_path, old_path) == 0) {
343 sway_log(L_DEBUG, "%s already included once, won't be included again.", real_path);
344 free(real_path);
345 return false;
346 }
347 }
348
349 config->current_config = real_path;
350 list_add(config->config_chain, real_path);
351 int index = config->config_chain->length - 1;
352
353 if (!load_config(real_path, config)) {
354 free(real_path);
355 config->current_config = parent_config;
356 list_del(config->config_chain, index);
357 return false;
358 }
359
360 // restore current_config
361 config->current_config = parent_config;
362 return true;
363}
364
365bool load_include_configs(const char *path, struct sway_config *config) {
366 char *wd = getcwd(NULL, 0);
367 char *parent_path = strdup(config->current_config);
368 const char *parent_dir = dirname(parent_path);
369
370 if (chdir(parent_dir) < 0) {
371 free(parent_path);
372 free(wd);
373 return false;
374 }
375
376 wordexp_t p;
377
378 if (wordexp(path, &p, 0) < 0) {
379 free(parent_path);
380 free(wd);
381 return false;
382 }
383
384 char **w = p.we_wordv;
385 size_t i;
386 for (i = 0; i < p.we_wordc; ++i) {
387 load_include_config(w[i], parent_dir, config);
388 }
389 free(parent_path);
390 wordfree(&p);
391
392 // restore wd
393 if (chdir(wd) < 0) {
394 free(wd);
395 sway_log(L_ERROR, "failed to restore working directory");
396 return false;
397 }
398
399 free(wd);
400 return true;
401}
402
314bool read_config(FILE *file, struct sway_config *config) { 403bool read_config(FILE *file, struct sway_config *config) {
315 bool success = true; 404 bool success = true;
316 enum cmd_status block = CMD_BLOCK_END; 405 enum cmd_status block = CMD_BLOCK_END;
diff --git a/sway/meson.build b/sway/meson.build
index 84f48137..ab863e87 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -5,6 +5,7 @@ sway_sources = files(
5 'commands/exit.c', 5 'commands/exit.c',
6 'commands/exec.c', 6 'commands/exec.c',
7 'commands/exec_always.c', 7 'commands/exec_always.c',
8 'commands/include.c',
8 'config.c', 9 'config.c',
9 'ipc-json.c', 10 'ipc-json.c',
10 'ipc-server.c', 11 'ipc-server.c',