aboutsummaryrefslogtreecommitdiffstats
path: root/sway/config.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/config.c')
-rw-r--r--sway/config.c127
1 files changed, 87 insertions, 40 deletions
diff --git a/sway/config.c b/sway/config.c
index 89b7d349..c620e4c7 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -24,6 +24,7 @@
24#include "sway/input/seat.h" 24#include "sway/input/seat.h"
25#include "sway/commands.h" 25#include "sway/commands.h"
26#include "sway/config.h" 26#include "sway/config.h"
27#include "sway/criteria.h"
27#include "sway/tree/arrange.h" 28#include "sway/tree/arrange.h"
28#include "sway/tree/layout.h" 29#include "sway/tree/layout.h"
29#include "sway/tree/workspace.h" 30#include "sway/tree/workspace.h"
@@ -105,7 +106,12 @@ void free_config(struct sway_config *config) {
105 } 106 }
106 list_free(config->seat_configs); 107 list_free(config->seat_configs);
107 } 108 }
108 list_free(config->criteria); 109 if (config->criteria) {
110 for (int i = 0; i < config->criteria->length; ++i) {
111 criteria_destroy(config->criteria->items[i]);
112 }
113 list_free(config->criteria);
114 }
109 list_free(config->no_focus); 115 list_free(config->no_focus);
110 list_free(config->active_bar_modifiers); 116 list_free(config->active_bar_modifiers);
111 list_free(config->config_chain); 117 list_free(config->config_chain);
@@ -117,6 +123,7 @@ void free_config(struct sway_config *config) {
117 free(config->floating_scroll_left_cmd); 123 free(config->floating_scroll_left_cmd);
118 free(config->floating_scroll_right_cmd); 124 free(config->floating_scroll_right_cmd);
119 free(config->font); 125 free(config->font);
126 free((char *)config->current_config_path);
120 free((char *)config->current_config); 127 free((char *)config->current_config);
121 free(config); 128 free(config);
122} 129}
@@ -205,6 +212,7 @@ static void config_defaults(struct sway_config *config) {
205 if (!(config->active_bar_modifiers = create_list())) goto cleanup; 212 if (!(config->active_bar_modifiers = create_list())) goto cleanup;
206 213
207 if (!(config->config_chain = create_list())) goto cleanup; 214 if (!(config->config_chain = create_list())) goto cleanup;
215 config->current_config_path = NULL;
208 config->current_config = NULL; 216 config->current_config = NULL;
209 217
210 // borders 218 // borders
@@ -276,12 +284,12 @@ static char *get_config_path(void) {
276 char *home = getenv("HOME"); 284 char *home = getenv("HOME");
277 char *config_home = malloc(strlen(home) + strlen("/.config") + 1); 285 char *config_home = malloc(strlen(home) + strlen("/.config") + 1);
278 if (!config_home) { 286 if (!config_home) {
279 wlr_log(L_ERROR, "Unable to allocate $HOME/.config"); 287 wlr_log(WLR_ERROR, "Unable to allocate $HOME/.config");
280 } else { 288 } else {
281 strcpy(config_home, home); 289 strcpy(config_home, home);
282 strcat(config_home, "/.config"); 290 strcat(config_home, "/.config");
283 setenv("XDG_CONFIG_HOME", config_home, 1); 291 setenv("XDG_CONFIG_HOME", config_home, 1);
284 wlr_log(L_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home); 292 wlr_log(WLR_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home);
285 free(config_home); 293 free(config_home);
286 } 294 }
287 } 295 }
@@ -304,16 +312,13 @@ static char *get_config_path(void) {
304 return NULL; // Not reached 312 return NULL; // Not reached
305} 313}
306 314
307const char *current_config_path;
308
309static bool load_config(const char *path, struct sway_config *config) { 315static bool load_config(const char *path, struct sway_config *config) {
310 if (path == NULL) { 316 if (path == NULL) {
311 wlr_log(L_ERROR, "Unable to find a config file!"); 317 wlr_log(WLR_ERROR, "Unable to find a config file!");
312 return false; 318 return false;
313 } 319 }
314 320
315 wlr_log(L_INFO, "Loading config from %s", path); 321 wlr_log(WLR_INFO, "Loading config from %s", path);
316 current_config_path = path;
317 322
318 struct stat sb; 323 struct stat sb;
319 if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { 324 if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
@@ -322,7 +327,7 @@ static bool load_config(const char *path, struct sway_config *config) {
322 327
323 FILE *f = fopen(path, "r"); 328 FILE *f = fopen(path, "r");
324 if (!f) { 329 if (!f) {
325 wlr_log(L_ERROR, "Unable to open %s for reading", path); 330 wlr_log(WLR_ERROR, "Unable to open %s for reading", path);
326 return false; 331 return false;
327 } 332 }
328 333
@@ -330,10 +335,9 @@ static bool load_config(const char *path, struct sway_config *config) {
330 fclose(f); 335 fclose(f);
331 336
332 if (!config_load_success) { 337 if (!config_load_success) {
333 wlr_log(L_ERROR, "Error(s) loading config!"); 338 wlr_log(WLR_ERROR, "Error(s) loading config!");
334 } 339 }
335 340
336 current_config_path = NULL;
337 return true; 341 return true;
338} 342}
339 343
@@ -353,12 +357,12 @@ bool load_main_config(const char *file, bool is_active) {
353 357
354 config_defaults(config); 358 config_defaults(config);
355 if (is_active) { 359 if (is_active) {
356 wlr_log(L_DEBUG, "Performing configuration file reload"); 360 wlr_log(WLR_DEBUG, "Performing configuration file reload");
357 config->reloading = true; 361 config->reloading = true;
358 config->active = true; 362 config->active = true;
359 } 363 }
360 364
361 config->current_config = path; 365 config->current_config_path = path;
362 list_add(config->config_chain, path); 366 list_add(config->config_chain, path);
363 367
364 config->reading = true; 368 config->reading = true;
@@ -369,7 +373,7 @@ bool load_main_config(const char *file, bool is_active) {
369 /* 373 /*
370 DIR *dir = opendir(SYSCONFDIR "/sway/security.d"); 374 DIR *dir = opendir(SYSCONFDIR "/sway/security.d");
371 if (!dir) { 375 if (!dir) {
372 wlr_log(L_ERROR, 376 wlr_log(WLR_ERROR,
373 "%s does not exist, sway will have no security configuration" 377 "%s does not exist, sway will have no security configuration"
374 " and will probably be broken", SYSCONFDIR "/sway/security.d"); 378 " and will probably be broken", SYSCONFDIR "/sway/security.d");
375 } else { 379 } else {
@@ -398,7 +402,7 @@ bool load_main_config(const char *file, bool is_active) {
398 if (stat(_path, &s) || s.st_uid != 0 || s.st_gid != 0 || 402 if (stat(_path, &s) || s.st_uid != 0 || s.st_gid != 0 ||
399 (((s.st_mode & 0777) != 0644) && 403 (((s.st_mode & 0777) != 0644) &&
400 (s.st_mode & 0777) != 0444)) { 404 (s.st_mode & 0777) != 0444)) {
401 wlr_log(L_ERROR, 405 wlr_log(WLR_ERROR,
402 "Refusing to load %s - it must be owned by root " 406 "Refusing to load %s - it must be owned by root "
403 "and mode 644 or 444", _path); 407 "and mode 644 or 444", _path);
404 success = false; 408 success = false;
@@ -428,7 +432,7 @@ bool load_main_config(const char *file, bool is_active) {
428static bool load_include_config(const char *path, const char *parent_dir, 432static bool load_include_config(const char *path, const char *parent_dir,
429 struct sway_config *config) { 433 struct sway_config *config) {
430 // save parent config 434 // save parent config
431 const char *parent_config = config->current_config; 435 const char *parent_config = config->current_config_path;
432 436
433 char *full_path; 437 char *full_path;
434 int len = strlen(path); 438 int len = strlen(path);
@@ -436,7 +440,7 @@ static bool load_include_config(const char *path, const char *parent_dir,
436 len = len + strlen(parent_dir) + 2; 440 len = len + strlen(parent_dir) + 2;
437 full_path = malloc(len * sizeof(char)); 441 full_path = malloc(len * sizeof(char));
438 if (!full_path) { 442 if (!full_path) {
439 wlr_log(L_ERROR, 443 wlr_log(WLR_ERROR,
440 "Unable to allocate full path to included config"); 444 "Unable to allocate full path to included config");
441 return false; 445 return false;
442 } 446 }
@@ -449,7 +453,7 @@ static bool load_include_config(const char *path, const char *parent_dir,
449 free(full_path); 453 free(full_path);
450 454
451 if (real_path == NULL) { 455 if (real_path == NULL) {
452 wlr_log(L_DEBUG, "%s not found.", path); 456 wlr_log(WLR_DEBUG, "%s not found.", path);
453 return false; 457 return false;
454 } 458 }
455 459
@@ -458,7 +462,7 @@ static bool load_include_config(const char *path, const char *parent_dir,
458 for (j = 0; j < config->config_chain->length; ++j) { 462 for (j = 0; j < config->config_chain->length; ++j) {
459 char *old_path = config->config_chain->items[j]; 463 char *old_path = config->config_chain->items[j];
460 if (strcmp(real_path, old_path) == 0) { 464 if (strcmp(real_path, old_path) == 0) {
461 wlr_log(L_DEBUG, 465 wlr_log(WLR_DEBUG,
462 "%s already included once, won't be included again.", 466 "%s already included once, won't be included again.",
463 real_path); 467 real_path);
464 free(real_path); 468 free(real_path);
@@ -466,25 +470,25 @@ static bool load_include_config(const char *path, const char *parent_dir,
466 } 470 }
467 } 471 }
468 472
469 config->current_config = real_path; 473 config->current_config_path = real_path;
470 list_add(config->config_chain, real_path); 474 list_add(config->config_chain, real_path);
471 int index = config->config_chain->length - 1; 475 int index = config->config_chain->length - 1;
472 476
473 if (!load_config(real_path, config)) { 477 if (!load_config(real_path, config)) {
474 free(real_path); 478 free(real_path);
475 config->current_config = parent_config; 479 config->current_config_path = parent_config;
476 list_del(config->config_chain, index); 480 list_del(config->config_chain, index);
477 return false; 481 return false;
478 } 482 }
479 483
480 // restore current_config 484 // restore current_config_path
481 config->current_config = parent_config; 485 config->current_config_path = parent_config;
482 return true; 486 return true;
483} 487}
484 488
485bool load_include_configs(const char *path, struct sway_config *config) { 489bool load_include_configs(const char *path, struct sway_config *config) {
486 char *wd = getcwd(NULL, 0); 490 char *wd = getcwd(NULL, 0);
487 char *parent_path = strdup(config->current_config); 491 char *parent_path = strdup(config->current_config_path);
488 const char *parent_dir = dirname(parent_path); 492 const char *parent_dir = dirname(parent_path);
489 493
490 if (chdir(parent_dir) < 0) { 494 if (chdir(parent_dir) < 0) {
@@ -512,7 +516,7 @@ bool load_include_configs(const char *path, struct sway_config *config) {
512 // restore wd 516 // restore wd
513 if (chdir(wd) < 0) { 517 if (chdir(wd) < 0) {
514 free(wd); 518 free(wd);
515 wlr_log(L_ERROR, "failed to restore working directory"); 519 wlr_log(WLR_ERROR, "failed to restore working directory");
516 return false; 520 return false;
517 } 521 }
518 522
@@ -527,13 +531,13 @@ static int detect_brace_on_following_line(FILE *file, char *line,
527 char *peeked = NULL; 531 char *peeked = NULL;
528 long position = 0; 532 long position = 0;
529 do { 533 do {
530 wlr_log(L_DEBUG, "Peeking line %d", line_number + lines + 1); 534 wlr_log(WLR_DEBUG, "Peeking line %d", line_number + lines + 1);
531 free(peeked); 535 free(peeked);
532 peeked = peek_line(file, lines, &position); 536 peeked = peek_line(file, lines, &position);
533 if (peeked) { 537 if (peeked) {
534 peeked = strip_whitespace(peeked); 538 peeked = strip_whitespace(peeked);
535 } 539 }
536 wlr_log(L_DEBUG, "Peeked line: `%s`", peeked); 540 wlr_log(WLR_DEBUG, "Peeked line: `%s`", peeked);
537 lines++; 541 lines++;
538 } while (peeked && strlen(peeked) == 0); 542 } while (peeked && strlen(peeked) == 0);
539 543
@@ -552,7 +556,7 @@ static char *expand_line(const char *block, const char *line, bool add_brace) {
552 + (add_brace ? 2 : 0) + 1; 556 + (add_brace ? 2 : 0) + 1;
553 char *expanded = calloc(1, size); 557 char *expanded = calloc(1, size);
554 if (!expanded) { 558 if (!expanded) {
555 wlr_log(L_ERROR, "Cannot allocate expanded line buffer"); 559 wlr_log(WLR_ERROR, "Cannot allocate expanded line buffer");
556 return NULL; 560 return NULL;
557 } 561 }
558 snprintf(expanded, size, "%s%s%s%s", block ? block : "", 562 snprintf(expanded, size, "%s%s%s%s", block ? block : "",
@@ -561,10 +565,33 @@ static char *expand_line(const char *block, const char *line, bool add_brace) {
561} 565}
562 566
563bool read_config(FILE *file, struct sway_config *config) { 567bool read_config(FILE *file, struct sway_config *config) {
568 bool reading_main_config = false;
569 char *this_config = NULL;
570 size_t config_size = 0;
571 if (config->current_config == NULL) {
572 reading_main_config = true;
573
574 int ret_seek = fseek(file, 0, SEEK_END);
575 long ret_tell = ftell(file);
576 if (ret_seek == -1 || ret_tell == -1) {
577 wlr_log(WLR_ERROR, "Unable to get size of config file");
578 return false;
579 }
580 config_size = ret_tell;
581 rewind(file);
582
583 config->current_config = this_config = calloc(1, config_size + 1);
584 if (this_config == NULL) {
585 wlr_log(WLR_ERROR, "Unable to allocate buffer for config contents");
586 return false;
587 }
588 }
589
564 bool success = true; 590 bool success = true;
565 int line_number = 0; 591 int line_number = 0;
566 char *line; 592 char *line;
567 list_t *stack = create_list(); 593 list_t *stack = create_list();
594 size_t read = 0;
568 while (!feof(file)) { 595 while (!feof(file)) {
569 char *block = stack->length ? stack->items[0] : NULL; 596 char *block = stack->length ? stack->items[0] : NULL;
570 line = read_line(file); 597 line = read_line(file);
@@ -572,7 +599,26 @@ bool read_config(FILE *file, struct sway_config *config) {
572 continue; 599 continue;
573 } 600 }
574 line_number++; 601 line_number++;
575 wlr_log(L_DEBUG, "Read line %d: %s", line_number, line); 602 wlr_log(WLR_DEBUG, "Read line %d: %s", line_number, line);
603
604 if (reading_main_config) {
605 size_t length = strlen(line);
606
607 if (read + length > config_size) {
608 wlr_log(WLR_ERROR, "Config file changed during reading");
609 list_foreach(stack, free);
610 list_free(stack);
611 free(line);
612 return false;
613 }
614
615 strcpy(this_config + read, line);
616 if (line_number != 1) {
617 this_config[read - 1] = '\n';
618 }
619 read += length + 1;
620 }
621
576 line = strip_whitespace(line); 622 line = strip_whitespace(line);
577 if (line[0] == '#') { 623 if (line[0] == '#') {
578 free(line); 624 free(line);
@@ -586,15 +632,16 @@ bool read_config(FILE *file, struct sway_config *config) {
586 line_number); 632 line_number);
587 if (brace_detected > 0) { 633 if (brace_detected > 0) {
588 line_number += brace_detected; 634 line_number += brace_detected;
589 wlr_log(L_DEBUG, "Detected open brace on line %d", line_number); 635 wlr_log(WLR_DEBUG, "Detected open brace on line %d", line_number);
590 } 636 }
591 char *expanded = expand_line(block, line, brace_detected > 0); 637 char *expanded = expand_line(block, line, brace_detected > 0);
592 if (!expanded) { 638 if (!expanded) {
593 list_foreach(stack, free); 639 list_foreach(stack, free);
594 list_free(stack); 640 list_free(stack);
641 free(line);
595 return false; 642 return false;
596 } 643 }
597 wlr_log(L_DEBUG, "Expanded line: %s", expanded); 644 wlr_log(WLR_DEBUG, "Expanded line: %s", expanded);
598 struct cmd_results *res; 645 struct cmd_results *res;
599 if (block && strcmp(block, "<commands>") == 0) { 646 if (block && strcmp(block, "<commands>") == 0) {
600 // Special case 647 // Special case
@@ -606,23 +653,23 @@ bool read_config(FILE *file, struct sway_config *config) {
606 switch(res->status) { 653 switch(res->status) {
607 case CMD_FAILURE: 654 case CMD_FAILURE:
608 case CMD_INVALID: 655 case CMD_INVALID:
609 wlr_log(L_ERROR, "Error on line %i '%s': %s (%s)", line_number, 656 wlr_log(WLR_ERROR, "Error on line %i '%s': %s (%s)", line_number,
610 line, res->error, config->current_config); 657 line, res->error, config->current_config_path);
611 success = false; 658 success = false;
612 break; 659 break;
613 660
614 case CMD_DEFER: 661 case CMD_DEFER:
615 wlr_log(L_DEBUG, "Deferring command `%s'", line); 662 wlr_log(WLR_DEBUG, "Deferring command `%s'", line);
616 list_add(config->cmd_queue, strdup(line)); 663 list_add(config->cmd_queue, strdup(line));
617 break; 664 break;
618 665
619 case CMD_BLOCK_COMMANDS: 666 case CMD_BLOCK_COMMANDS:
620 wlr_log(L_DEBUG, "Entering commands block"); 667 wlr_log(WLR_DEBUG, "Entering commands block");
621 list_insert(stack, 0, "<commands>"); 668 list_insert(stack, 0, "<commands>");
622 break; 669 break;
623 670
624 case CMD_BLOCK: 671 case CMD_BLOCK:
625 wlr_log(L_DEBUG, "Entering block '%s'", res->input); 672 wlr_log(WLR_DEBUG, "Entering block '%s'", res->input);
626 list_insert(stack, 0, strdup(res->input)); 673 list_insert(stack, 0, strdup(res->input));
627 if (strcmp(res->input, "bar") == 0) { 674 if (strcmp(res->input, "bar") == 0) {
628 config->current_bar = NULL; 675 config->current_bar = NULL;
@@ -631,7 +678,7 @@ bool read_config(FILE *file, struct sway_config *config) {
631 678
632 case CMD_BLOCK_END: 679 case CMD_BLOCK_END:
633 if (!block) { 680 if (!block) {
634 wlr_log(L_DEBUG, "Unmatched '}' on line %i", line_number); 681 wlr_log(WLR_DEBUG, "Unmatched '}' on line %i", line_number);
635 success = false; 682 success = false;
636 break; 683 break;
637 } 684 }
@@ -639,7 +686,7 @@ bool read_config(FILE *file, struct sway_config *config) {
639 config->current_bar = NULL; 686 config->current_bar = NULL;
640 } 687 }
641 688
642 wlr_log(L_DEBUG, "Exiting block '%s'", block); 689 wlr_log(WLR_DEBUG, "Exiting block '%s'", block);
643 list_del(stack, 0); 690 list_del(stack, 0);
644 free(block); 691 free(block);
645 memset(&config->handler_context, 0, 692 memset(&config->handler_context, 0,
@@ -682,7 +729,7 @@ char *do_var_replacement(char *str) {
682 int vvlen = strlen(var->value); 729 int vvlen = strlen(var->value);
683 char *newstr = malloc(strlen(str) - vnlen + vvlen + 1); 730 char *newstr = malloc(strlen(str) - vnlen + vvlen + 1);
684 if (!newstr) { 731 if (!newstr) {
685 wlr_log(L_ERROR, 732 wlr_log(WLR_ERROR,
686 "Unable to allocate replacement " 733 "Unable to allocate replacement "
687 "during variable expansion"); 734 "during variable expansion");
688 break; 735 break;
@@ -744,6 +791,6 @@ void config_update_font_height(bool recalculate) {
744 } 791 }
745 792
746 if (config->font_height != prev_max_height) { 793 if (config->font_height != prev_max_height) {
747 arrange_and_commit(&root_container); 794 arrange_windows(&root_container);
748 } 795 }
749} 796}