summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Brian Ashworth <bosrsf04@gmail.com>2018-08-01 23:54:40 -0400
committerLibravatar Brian Ashworth <bosrsf04@gmail.com>2018-08-03 10:37:35 -0400
commitf9a6407111a8730df51258c3b07502814a8ab3e1 (patch)
tree6cf180159caf4a45a8f37b026b2769d24468a07b
parentMerge pull request #2417 from marienz/swaynag-includes (diff)
downloadsway-f9a6407111a8730df51258c3b07502814a8ab3e1.tar.gz
sway-f9a6407111a8730df51258c3b07502814a8ab3e1.tar.zst
sway-f9a6407111a8730df51258c3b07502814a8ab3e1.zip
Show swaynag on config errors
-rw-r--r--include/sway/config.h10
-rw-r--r--sway/commands.c7
-rw-r--r--sway/commands/include.c15
-rw-r--r--sway/commands/reload.c19
-rw-r--r--sway/config.c75
-rw-r--r--sway/main.c12
6 files changed, 118 insertions, 20 deletions
diff --git a/include/sway/config.h b/include/sway/config.h
index 909b6827..4fc3eadb 100644
--- a/include/sway/config.h
+++ b/include/sway/config.h
@@ -308,6 +308,7 @@ enum focus_wrapping_mode {
308 * The configuration struct. The result of loading a config file. 308 * The configuration struct. The result of loading a config file.
309 */ 309 */
310struct sway_config { 310struct sway_config {
311 pid_t swaynag_pid;
311 list_t *symbols; 312 list_t *symbols;
312 list_t *modes; 313 list_t *modes;
313 list_t *bars; 314 list_t *bars;
@@ -403,17 +404,18 @@ struct sway_config {
403 * Loads the main config from the given path. is_active should be true when 404 * Loads the main config from the given path. is_active should be true when
404 * reloading the config. 405 * reloading the config.
405 */ 406 */
406bool load_main_config(const char *path, bool is_active); 407bool load_main_config(const char *path, bool is_active, char **errors);
407 408
408/** 409/**
409 * Loads an included config. Can only be used after load_main_config. 410 * Loads an included config. Can only be used after load_main_config.
410 */ 411 */
411bool load_include_configs(const char *path, struct sway_config *config); 412bool load_include_configs(const char *path, struct sway_config *config,
413 char **errors);
412 414
413/** 415/**
414 * Reads the config from the given FILE. 416 * Reads the config from the given FILE.
415 */ 417 */
416bool read_config(FILE *file, struct sway_config *config); 418bool read_config(FILE *file, struct sway_config *config, char **errors);
417 419
418/** 420/**
419 * Free config struct 421 * Free config struct
@@ -422,6 +424,8 @@ void free_config(struct sway_config *config);
422 424
423void free_sway_variable(struct sway_variable *var); 425void free_sway_variable(struct sway_variable *var);
424 426
427void spawn_swaynag_config_errors(struct sway_config *config, char *errors);
428
425/** 429/**
426 * Does variable replacement for a string based on the config's currently loaded variables. 430 * Does variable replacement for a string based on the config's currently loaded variables.
427 */ 431 */
diff --git a/sway/commands.c b/sway/commands.c
index fdae1961..81e9ea42 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -511,11 +511,14 @@ struct cmd_results *cmd_results_new(enum cmd_status status,
511 results->input = NULL; 511 results->input = NULL;
512 } 512 }
513 if (format) { 513 if (format) {
514 char *error = malloc(256);
515 va_list args; 514 va_list args;
516 va_start(args, format); 515 va_start(args, format);
516 size_t length = vsnprintf(NULL, 0, format, args) + 1;
517 char *error = malloc(length);
518 va_end(args);
519 va_start(args, format);
517 if (error) { 520 if (error) {
518 vsnprintf(error, 256, format, args); 521 vsnprintf(error, length, format, args);
519 } 522 }
520 va_end(args); 523 va_end(args);
521 results->error = error; 524 results->error = error;
diff --git a/sway/commands/include.c b/sway/commands/include.c
index 1ba9a10d..72fec7cc 100644
--- a/sway/commands/include.c
+++ b/sway/commands/include.c
@@ -7,8 +7,19 @@ struct cmd_results *cmd_include(int argc, char **argv) {
7 return error; 7 return error;
8 } 8 }
9 9
10 if (!load_include_configs(argv[0], config)) { 10 char *errors = NULL;
11 return cmd_results_new(CMD_INVALID, "include", "Failed to include sub configuration file: %s", argv[0]); 11 if (!load_include_configs(argv[0], config, &errors)) {
12 struct cmd_results *result = cmd_results_new(CMD_INVALID, "include",
13 "Failed to include sub configuration file: %s", argv[0]);
14 free(errors);
15 return result;
16 }
17
18 if (errors) {
19 struct cmd_results *result = cmd_results_new(CMD_INVALID, "include",
20 "There are errors in the included config\n%s", errors);
21 free(errors);
22 return result;
12 } 23 }
13 24
14 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 25 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
diff --git a/sway/commands/reload.c b/sway/commands/reload.c
index 5c1b19b4..9bf671d9 100644
--- a/sway/commands/reload.c
+++ b/sway/commands/reload.c
@@ -1,4 +1,5 @@
1#define _XOPEN_SOURCE 500 1#define _XOPEN_SOURCE 500
2#include <signal.h>
2#include <string.h> 3#include <string.h>
3#include "sway/commands.h" 4#include "sway/commands.h"
4#include "sway/config.h" 5#include "sway/config.h"
@@ -19,8 +20,11 @@ struct cmd_results *cmd_reload(int argc, char **argv) {
19 list_add(bar_ids, strdup(bar->id)); 20 list_add(bar_ids, strdup(bar->id));
20 } 21 }
21 22
22 if (!load_main_config(config->current_config_path, true)) { 23 char *errors = NULL;
23 return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config."); 24 if (!load_main_config(config->current_config_path, true, &errors)) {
25 free(errors);
26 return cmd_results_new(CMD_FAILURE, "reload",
27 "Error(s) reloading config.");
24 } 28 }
25 ipc_event_workspace(NULL, NULL, "reload"); 29 ipc_event_workspace(NULL, NULL, "reload");
26 30
@@ -42,5 +46,16 @@ struct cmd_results *cmd_reload(int argc, char **argv) {
42 list_free(bar_ids); 46 list_free(bar_ids);
43 47
44 arrange_windows(&root_container); 48 arrange_windows(&root_container);
49
50 if (config->swaynag_pid > 0) {
51 kill(config->swaynag_pid, SIGTERM);
52 config->swaynag_pid = -1;
53 }
54
55 if (errors) {
56 spawn_swaynag_config_errors(config, errors);
57 free(errors);
58 }
59
45 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 60 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
46} 61}
diff --git a/sway/config.c b/sway/config.c
index 2afffab1..bd282541 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -158,6 +158,7 @@ static void set_color(float dest[static 4], uint32_t color) {
158} 158}
159 159
160static void config_defaults(struct sway_config *config) { 160static void config_defaults(struct sway_config *config) {
161 config->swaynag_pid = -1;
161 if (!(config->symbols = create_list())) goto cleanup; 162 if (!(config->symbols = create_list())) goto cleanup;
162 if (!(config->modes = create_list())) goto cleanup; 163 if (!(config->modes = create_list())) goto cleanup;
163 if (!(config->bars = create_list())) goto cleanup; 164 if (!(config->bars = create_list())) goto cleanup;
@@ -319,7 +320,8 @@ static char *get_config_path(void) {
319 return NULL; // Not reached 320 return NULL; // Not reached
320} 321}
321 322
322static bool load_config(const char *path, struct sway_config *config) { 323static bool load_config(const char *path, struct sway_config *config,
324 char **errors) {
323 if (path == NULL) { 325 if (path == NULL) {
324 wlr_log(WLR_ERROR, "Unable to find a config file!"); 326 wlr_log(WLR_ERROR, "Unable to find a config file!");
325 return false; 327 return false;
@@ -338,7 +340,7 @@ static bool load_config(const char *path, struct sway_config *config) {
338 return false; 340 return false;
339 } 341 }
340 342
341 bool config_load_success = read_config(f, config); 343 bool config_load_success = read_config(f, config, errors);
342 fclose(f); 344 fclose(f);
343 345
344 if (!config_load_success) { 346 if (!config_load_success) {
@@ -348,7 +350,7 @@ static bool load_config(const char *path, struct sway_config *config) {
348 return true; 350 return true;
349} 351}
350 352
351bool load_main_config(const char *file, bool is_active) { 353bool load_main_config(const char *file, bool is_active, char **errors) {
352 char *path; 354 char *path;
353 if (file != NULL) { 355 if (file != NULL) {
354 path = strdup(file); 356 path = strdup(file);
@@ -365,6 +367,7 @@ bool load_main_config(const char *file, bool is_active) {
365 config_defaults(config); 367 config_defaults(config);
366 if (is_active) { 368 if (is_active) {
367 wlr_log(WLR_DEBUG, "Performing configuration file reload"); 369 wlr_log(WLR_DEBUG, "Performing configuration file reload");
370 config->swaynag_pid = old_config->swaynag_pid;
368 config->reloading = true; 371 config->reloading = true;
369 config->active = true; 372 config->active = true;
370 create_default_output_configs(); 373 create_default_output_configs();
@@ -423,7 +426,7 @@ bool load_main_config(const char *file, bool is_active) {
423 } 426 }
424 */ 427 */
425 428
426 success = success && load_config(path, config); 429 success = success && load_config(path, config, errors);
427 430
428 if (is_active) { 431 if (is_active) {
429 for (int i = 0; i < config->output_configs->length; i++) { 432 for (int i = 0; i < config->output_configs->length; i++) {
@@ -441,7 +444,7 @@ bool load_main_config(const char *file, bool is_active) {
441} 444}
442 445
443static bool load_include_config(const char *path, const char *parent_dir, 446static bool load_include_config(const char *path, const char *parent_dir,
444 struct sway_config *config) { 447 struct sway_config *config, char **errors) {
445 // save parent config 448 // save parent config
446 const char *parent_config = config->current_config_path; 449 const char *parent_config = config->current_config_path;
447 450
@@ -485,7 +488,7 @@ static bool load_include_config(const char *path, const char *parent_dir,
485 list_add(config->config_chain, real_path); 488 list_add(config->config_chain, real_path);
486 int index = config->config_chain->length - 1; 489 int index = config->config_chain->length - 1;
487 490
488 if (!load_config(real_path, config)) { 491 if (!load_config(real_path, config, errors)) {
489 free(real_path); 492 free(real_path);
490 config->current_config_path = parent_config; 493 config->current_config_path = parent_config;
491 list_del(config->config_chain, index); 494 list_del(config->config_chain, index);
@@ -497,7 +500,8 @@ static bool load_include_config(const char *path, const char *parent_dir,
497 return true; 500 return true;
498} 501}
499 502
500bool load_include_configs(const char *path, struct sway_config *config) { 503bool load_include_configs(const char *path, struct sway_config *config,
504 char **errors) {
501 char *wd = getcwd(NULL, 0); 505 char *wd = getcwd(NULL, 0);
502 char *parent_path = strdup(config->current_config_path); 506 char *parent_path = strdup(config->current_config_path);
503 const char *parent_dir = dirname(parent_path); 507 const char *parent_dir = dirname(parent_path);
@@ -519,7 +523,7 @@ bool load_include_configs(const char *path, struct sway_config *config) {
519 char **w = p.we_wordv; 523 char **w = p.we_wordv;
520 size_t i; 524 size_t i;
521 for (i = 0; i < p.we_wordc; ++i) { 525 for (i = 0; i < p.we_wordc; ++i) {
522 load_include_config(w[i], parent_dir, config); 526 load_include_config(w[i], parent_dir, config, errors);
523 } 527 }
524 free(parent_path); 528 free(parent_path);
525 wordfree(&p); 529 wordfree(&p);
@@ -575,7 +579,26 @@ static char *expand_line(const char *block, const char *line, bool add_brace) {
575 return expanded; 579 return expanded;
576} 580}
577 581
578bool read_config(FILE *file, struct sway_config *config) { 582static void log_error(char **errors, const char *fmt, ...) {
583 va_list args;
584 va_start(args, fmt);
585 size_t length = vsnprintf(NULL, 0, fmt, args) + 1;
586 va_end(args);
587
588 int offset = *errors ? strlen(*errors) : 0;
589 char *temp = realloc(*errors, offset + length + 1);
590 if (!temp) {
591 wlr_log(WLR_ERROR, "Failed to realloc error log");
592 return;
593 }
594 *errors = temp;
595
596 va_start(args, fmt);
597 vsnprintf(*errors + offset, length, fmt, args);
598 va_end(args);
599}
600
601bool read_config(FILE *file, struct sway_config *config, char **errors) {
579 bool reading_main_config = false; 602 bool reading_main_config = false;
580 char *this_config = NULL; 603 char *this_config = NULL;
581 size_t config_size = 0; 604 size_t config_size = 0;
@@ -665,6 +688,8 @@ bool read_config(FILE *file, struct sway_config *config) {
665 case CMD_INVALID: 688 case CMD_INVALID:
666 wlr_log(WLR_ERROR, "Error on line %i '%s': %s (%s)", line_number, 689 wlr_log(WLR_ERROR, "Error on line %i '%s': %s (%s)", line_number,
667 line, res->error, config->current_config_path); 690 line, res->error, config->current_config_path);
691 log_error(errors, "Error on line %i (%s) '%s': %s\n", line_number,
692 config->current_config_path, line, res->error);
668 success = false; 693 success = false;
669 break; 694 break;
670 695
@@ -713,6 +738,38 @@ bool read_config(FILE *file, struct sway_config *config) {
713 return success; 738 return success;
714} 739}
715 740
741void spawn_swaynag_config_errors(struct sway_config *config, char *errors) {
742 char *command = "swaynag "
743 "--type error "
744 "--message 'There are errors in your config file' "
745 "--detailed-message "
746 "--button 'Exit sway' 'swaymsg exit' "
747 "--button 'Reload sway' 'swaymsg reload'";
748
749 int fd[2];
750 if (pipe(fd) != 0) {
751 wlr_log(WLR_ERROR, "Failed to create pipe for swaynag");
752 return;
753 }
754
755 pid_t pid;
756 if ((pid = fork()) == 0) {
757 close(fd[1]);
758 dup2(fd[0], STDIN_FILENO);
759 close(fd[0]);
760 execl("/bin/sh", "/bin/sh", "-c", command, NULL);
761 _exit(0);
762 } else if (pid < 0) {
763 wlr_log(WLR_ERROR, "Failed to create fork for swaynag");
764 }
765
766 close(fd[0]);
767 write(fd[1], errors, strlen(errors));
768 close(fd[1]);
769
770 config->swaynag_pid = pid;
771}
772
716char *do_var_replacement(char *str) { 773char *do_var_replacement(char *str) {
717 int i; 774 int i;
718 char *find = str; 775 char *find = str;
diff --git a/sway/main.c b/sway/main.c
index 477ffa5a..de2445a8 100644
--- a/sway/main.c
+++ b/sway/main.c
@@ -415,12 +415,14 @@ int main(int argc, char **argv) {
415 ipc_init(&server); 415 ipc_init(&server);
416 log_env(); 416 log_env();
417 417
418 char *errors = NULL;
418 if (validate) { 419 if (validate) {
419 bool valid = load_main_config(config_path, false); 420 bool valid = load_main_config(config_path, false, &errors);
421 free(errors);
420 return valid ? 0 : 1; 422 return valid ? 0 : 1;
421 } 423 }
422 424
423 if (!load_main_config(config_path, false)) { 425 if (!load_main_config(config_path, false, &errors)) {
424 sway_terminate(EXIT_FAILURE); 426 sway_terminate(EXIT_FAILURE);
425 } 427 }
426 428
@@ -433,6 +435,7 @@ int main(int argc, char **argv) {
433 setenv("WAYLAND_DISPLAY", server.socket, true); 435 setenv("WAYLAND_DISPLAY", server.socket, true);
434 if (!terminate_request) { 436 if (!terminate_request) {
435 if (!server_start_backend(&server)) { 437 if (!server_start_backend(&server)) {
438 free(errors);
436 sway_terminate(EXIT_FAILURE); 439 sway_terminate(EXIT_FAILURE);
437 } 440 }
438 } 441 }
@@ -452,6 +455,11 @@ int main(int argc, char **argv) {
452 } 455 }
453 transaction_commit_dirty(); 456 transaction_commit_dirty();
454 457
458 if (errors) {
459 spawn_swaynag_config_errors(config, errors);
460 free(errors);
461 }
462
455 if (!terminate_request) { 463 if (!terminate_request) {
456 server_run(&server); 464 server_run(&server);
457 } 465 }