summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar emersion <contact@emersion.fr>2018-07-16 22:25:25 +0100
committerLibravatar GitHub <noreply@github.com>2018-07-16 22:25:25 +0100
commit297e32126f1f8b27f51989b863e4ea1c9fce6a96 (patch)
tree8387d2550524394e1ac7275ac040a355f2a4bfbf
parentMerge pull request #2283 from RyanDwyer/no-focus (diff)
parentSwitch to using getopt_long for config flag (diff)
downloadsway-297e32126f1f8b27f51989b863e4ea1c9fce6a96.tar.gz
sway-297e32126f1f8b27f51989b863e4ea1c9fce6a96.tar.zst
sway-297e32126f1f8b27f51989b863e4ea1c9fce6a96.zip
Merge pull request #2265 from RedSoxFan/implement-1962
Implement swaylock configuration file parsing
-rw-r--r--swaylock/main.c244
-rw-r--r--swaylock/swaylock.1.scd9
2 files changed, 196 insertions, 57 deletions
diff --git a/swaylock/main.c b/swaylock/main.c
index faebc757..ae5b86b9 100644
--- a/swaylock/main.c
+++ b/swaylock/main.c
@@ -21,6 +21,7 @@
21#include "pool-buffer.h" 21#include "pool-buffer.h"
22#include "cairo.h" 22#include "cairo.h"
23#include "log.h" 23#include "log.h"
24#include "readline.h"
24#include "stringop.h" 25#include "stringop.h"
25#include "util.h" 26#include "util.h"
26#include "wlr-input-inhibitor-unstable-v1-client-protocol.h" 27#include "wlr-input-inhibitor-unstable-v1-client-protocol.h"
@@ -412,15 +413,14 @@ static void set_default_colors(struct swaylock_colors *colors) {
412 }; 413 };
413} 414}
414 415
415static struct swaylock_state state; 416enum line_mode {
416 417 LM_LINE,
417int main(int argc, char **argv) { 418 LM_INSIDE,
418 enum line_mode { 419 LM_RING,
419 LM_LINE, 420};
420 LM_INSIDE,
421 LM_RING,
422 };
423 421
422static int parse_options(int argc, char **argv, struct swaylock_state *state,
423 enum line_mode *line_mode) {
424 enum long_option_codes { 424 enum long_option_codes {
425 LO_BS_HL_COLOR = 256, 425 LO_BS_HL_COLOR = 256,
426 LO_FONT, 426 LO_FONT,
@@ -447,6 +447,7 @@ int main(int argc, char **argv) {
447 }; 447 };
448 448
449 static struct option long_options[] = { 449 static struct option long_options[] = {
450 {"config", required_argument, NULL, 'C'},
450 {"color", required_argument, NULL, 'c'}, 451 {"color", required_argument, NULL, 'c'},
451 {"ignore-empty-password", no_argument, NULL, 'e'}, 452 {"ignore-empty-password", no_argument, NULL, 'e'},
452 {"daemonize", no_argument, NULL, 'f'}, 453 {"daemonize", no_argument, NULL, 'f'},
@@ -487,6 +488,8 @@ int main(int argc, char **argv) {
487 const char usage[] = 488 const char usage[] =
488 "Usage: swaylock [options...]\n" 489 "Usage: swaylock [options...]\n"
489 "\n" 490 "\n"
491 " -C, --config <config_file> "
492 "Path to the config file.\n"
490 " -c, --color <color> " 493 " -c, --color <color> "
491 "Turn the screen into the given color instead of white.\n" 494 "Turn the screen into the given color instead of white.\n"
492 " -e, --ignore-empty-password " 495 " -e, --ignore-empty-password "
@@ -559,58 +562,48 @@ int main(int argc, char **argv) {
559 "\n" 562 "\n"
560 "All <color> options are of the form <rrggbb[aa]>.\n"; 563 "All <color> options are of the form <rrggbb[aa]>.\n";
561 564
562 enum line_mode line_mode = LM_LINE;
563 state.args = (struct swaylock_args){
564 .mode = BACKGROUND_MODE_SOLID_COLOR,
565 .font = strdup("sans-serif"),
566 .radius = 50,
567 .thickness = 10,
568 .ignore_empty = false,
569 .show_indicator = true,
570 };
571 wl_list_init(&state.images);
572 set_default_colors(&state.args.colors);
573
574 wlr_log_init(WLR_DEBUG, NULL);
575
576 int c; 565 int c;
566 optind = 1;
577 while (1) { 567 while (1) {
578 int opt_idx = 0; 568 int opt_idx = 0;
579 c = getopt_long(argc, argv, "c:efhi:nrs:tuv", long_options, &opt_idx); 569 c = getopt_long(argc, argv, "c:efhi:nrs:tuvC:", long_options, &opt_idx);
580 if (c == -1) { 570 if (c == -1) {
581 break; 571 break;
582 } 572 }
583 switch (c) { 573 switch (c) {
574 case 'C':
575 // Config file. This will have already been handled so just ignore.
576 break;
584 case 'c': 577 case 'c':
585 state.args.colors.background = parse_color(optarg); 578 state->args.colors.background = parse_color(optarg);
586 state.args.mode = BACKGROUND_MODE_SOLID_COLOR; 579 state->args.mode = BACKGROUND_MODE_SOLID_COLOR;
587 break; 580 break;
588 case 'e': 581 case 'e':
589 state.args.ignore_empty = true; 582 state->args.ignore_empty = true;
590 break; 583 break;
591 case 'f': 584 case 'f':
592 state.args.daemonize = true; 585 state->args.daemonize = true;
593 break; 586 break;
594 case 'i': 587 case 'i':
595 load_image(optarg, &state); 588 load_image(optarg, state);
596 break; 589 break;
597 case 'n': 590 case 'n':
598 line_mode = LM_INSIDE; 591 *line_mode = LM_INSIDE;
599 break; 592 break;
600 case 'r': 593 case 'r':
601 line_mode = LM_RING; 594 *line_mode = LM_RING;
602 break; 595 break;
603 case 's': 596 case 's':
604 state.args.mode = parse_background_mode(optarg); 597 state->args.mode = parse_background_mode(optarg);
605 if (state.args.mode == BACKGROUND_MODE_INVALID) { 598 if (state->args.mode == BACKGROUND_MODE_INVALID) {
606 return 1; 599 return 1;
607 } 600 }
608 break; 601 break;
609 case 't': 602 case 't':
610 state.args.mode = BACKGROUND_MODE_TILE; 603 state->args.mode = BACKGROUND_MODE_TILE;
611 break; 604 break;
612 case 'u': 605 case 'u':
613 state.args.show_indicator = false; 606 state->args.show_indicator = false;
614 break; 607 break;
615 case 'v': 608 case 'v':
616#if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE 609#if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE
@@ -621,71 +614,71 @@ int main(int argc, char **argv) {
621#endif 614#endif
622 return 0; 615 return 0;
623 case LO_BS_HL_COLOR: 616 case LO_BS_HL_COLOR:
624 state.args.colors.bs_highlight = parse_color(optarg); 617 state->args.colors.bs_highlight = parse_color(optarg);
625 break; 618 break;
626 case LO_FONT: 619 case LO_FONT:
627 free(state.args.font); 620 free(state->args.font);
628 state.args.font = strdup(optarg); 621 state->args.font = strdup(optarg);
629 break; 622 break;
630 case LO_IND_RADIUS: 623 case LO_IND_RADIUS:
631 state.args.radius = strtol(optarg, NULL, 0); 624 state->args.radius = strtol(optarg, NULL, 0);
632 break; 625 break;
633 case LO_IND_THICKNESS: 626 case LO_IND_THICKNESS:
634 state.args.thickness = strtol(optarg, NULL, 0); 627 state->args.thickness = strtol(optarg, NULL, 0);
635 break; 628 break;
636 case LO_INSIDE_COLOR: 629 case LO_INSIDE_COLOR:
637 state.args.colors.inside.input = parse_color(optarg); 630 state->args.colors.inside.input = parse_color(optarg);
638 break; 631 break;
639 case LO_INSIDE_CLEAR_COLOR: 632 case LO_INSIDE_CLEAR_COLOR:
640 state.args.colors.inside.cleared = parse_color(optarg); 633 state->args.colors.inside.cleared = parse_color(optarg);
641 break; 634 break;
642 case LO_INSIDE_VER_COLOR: 635 case LO_INSIDE_VER_COLOR:
643 state.args.colors.inside.verifying = parse_color(optarg); 636 state->args.colors.inside.verifying = parse_color(optarg);
644 break; 637 break;
645 case LO_INSIDE_WRONG_COLOR: 638 case LO_INSIDE_WRONG_COLOR:
646 state.args.colors.inside.wrong = parse_color(optarg); 639 state->args.colors.inside.wrong = parse_color(optarg);
647 break; 640 break;
648 case LO_KEY_HL_COLOR: 641 case LO_KEY_HL_COLOR:
649 state.args.colors.key_highlight = parse_color(optarg); 642 state->args.colors.key_highlight = parse_color(optarg);
650 break; 643 break;
651 case LO_LINE_COLOR: 644 case LO_LINE_COLOR:
652 state.args.colors.line.input = parse_color(optarg); 645 state->args.colors.line.input = parse_color(optarg);
653 break; 646 break;
654 case LO_LINE_CLEAR_COLOR: 647 case LO_LINE_CLEAR_COLOR:
655 state.args.colors.line.cleared = parse_color(optarg); 648 state->args.colors.line.cleared = parse_color(optarg);
656 break; 649 break;
657 case LO_LINE_VER_COLOR: 650 case LO_LINE_VER_COLOR:
658 state.args.colors.line.verifying = parse_color(optarg); 651 state->args.colors.line.verifying = parse_color(optarg);
659 break; 652 break;
660 case LO_LINE_WRONG_COLOR: 653 case LO_LINE_WRONG_COLOR:
661 state.args.colors.line.wrong = parse_color(optarg); 654 state->args.colors.line.wrong = parse_color(optarg);
662 break; 655 break;
663 case LO_RING_COLOR: 656 case LO_RING_COLOR:
664 state.args.colors.ring.input = parse_color(optarg); 657 state->args.colors.ring.input = parse_color(optarg);
665 break; 658 break;
666 case LO_RING_CLEAR_COLOR: 659 case LO_RING_CLEAR_COLOR:
667 state.args.colors.ring.cleared = parse_color(optarg); 660 state->args.colors.ring.cleared = parse_color(optarg);
668 break; 661 break;
669 case LO_RING_VER_COLOR: 662 case LO_RING_VER_COLOR:
670 state.args.colors.ring.verifying = parse_color(optarg); 663 state->args.colors.ring.verifying = parse_color(optarg);
671 break; 664 break;
672 case LO_RING_WRONG_COLOR: 665 case LO_RING_WRONG_COLOR:
673 state.args.colors.ring.wrong = parse_color(optarg); 666 state->args.colors.ring.wrong = parse_color(optarg);
674 break; 667 break;
675 case LO_SEP_COLOR: 668 case LO_SEP_COLOR:
676 state.args.colors.separator = parse_color(optarg); 669 state->args.colors.separator = parse_color(optarg);
677 break; 670 break;
678 case LO_TEXT_COLOR: 671 case LO_TEXT_COLOR:
679 state.args.colors.text.input = parse_color(optarg); 672 state->args.colors.text.input = parse_color(optarg);
680 break; 673 break;
681 case LO_TEXT_CLEAR_COLOR: 674 case LO_TEXT_CLEAR_COLOR:
682 state.args.colors.text.cleared = parse_color(optarg); 675 state->args.colors.text.cleared = parse_color(optarg);
683 break; 676 break;
684 case LO_TEXT_VER_COLOR: 677 case LO_TEXT_VER_COLOR:
685 state.args.colors.text.verifying = parse_color(optarg); 678 state->args.colors.text.verifying = parse_color(optarg);
686 break; 679 break;
687 case LO_TEXT_WRONG_COLOR: 680 case LO_TEXT_WRONG_COLOR:
688 state.args.colors.text.wrong = parse_color(optarg); 681 state->args.colors.text.wrong = parse_color(optarg);
689 break; 682 break;
690 default: 683 default:
691 fprintf(stderr, "%s", usage); 684 fprintf(stderr, "%s", usage);
@@ -693,6 +686,143 @@ int main(int argc, char **argv) {
693 } 686 }
694 } 687 }
695 688
689 return 0;
690}
691
692static bool file_exists(const char *path) {
693 return path && access(path, R_OK) != -1;
694}
695
696static char *get_config_path(void) {
697 static const char *config_paths[] = {
698 "$HOME/.swaylock/config",
699 "$XDG_CONFIG_HOME/swaylock/config",
700 SYSCONFDIR "/swaylock/config",
701 };
702
703 if (!getenv("XDG_CONFIG_HOME")) {
704 char *home = getenv("HOME");
705 char *config_home = malloc(strlen(home) + strlen("/.config") + 1);
706 if (!config_home) {
707 wlr_log(WLR_ERROR, "Unable to allocate $HOME/.config");
708 } else {
709 strcpy(config_home, home);
710 strcat(config_home, "/.config");
711 setenv("XDG_CONFIG_HOME", config_home, 1);
712 wlr_log(WLR_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home);
713 free(config_home);
714 }
715 }
716
717 wordexp_t p;
718 char *path;
719 for (size_t i = 0; i < sizeof(config_paths) / sizeof(char *); ++i) {
720 if (wordexp(config_paths[i], &p, 0) == 0) {
721 path = strdup(p.we_wordv[0]);
722 wordfree(&p);
723 if (file_exists(path)) {
724 return path;
725 }
726 free(path);
727 }
728 }
729
730 return NULL;
731}
732
733static int load_config(char *path, struct swaylock_state *state,
734 enum line_mode *line_mode) {
735 FILE *config = fopen(path, "r");
736 if (!config) {
737 wlr_log(WLR_ERROR, "Failed to read config. Running without it.");
738 return 0;
739 }
740 char *line;
741 int line_number = 0;
742 while (!feof(config)) {
743 line = read_line(config);
744 if (!line) {
745 continue;
746 }
747
748 line_number++;
749 if (line[0] == '#') {
750 free(line);
751 continue;
752 }
753 if (strlen(line) == 0) {
754 free(line);
755 continue;
756 }
757
758 wlr_log(WLR_DEBUG, "Config Line #%d: %s", line_number, line);
759 char flag[strlen(line) + 3];
760 sprintf(flag, "--%s", line);
761 char *argv[] = {"swaylock", flag};
762 int result = parse_options(2, argv, state, line_mode);
763 if (result != 0) {
764 free(line);
765 fclose(config);
766 return result;
767 }
768 free(line);
769 }
770 fclose(config);
771 return 0;
772}
773
774static struct swaylock_state state;
775
776int main(int argc, char **argv) {
777 enum line_mode line_mode = LM_LINE;
778 state.args = (struct swaylock_args){
779 .mode = BACKGROUND_MODE_SOLID_COLOR,
780 .font = strdup("sans-serif"),
781 .radius = 50,
782 .thickness = 10,
783 .ignore_empty = false,
784 .show_indicator = true,
785 };
786 wl_list_init(&state.images);
787 set_default_colors(&state.args.colors);
788
789 wlr_log_init(WLR_DEBUG, NULL);
790
791 char *config_path = NULL;
792 static struct option long_options[] = {
793 {"config", required_argument, NULL, 'C'},
794 {0, 0, 0, 0},
795 };
796 while (1) {
797 int c = getopt_long(argc, argv, "C:", long_options, NULL);
798 if (c == -1) {
799 break;
800 } else if (c == 'C') {
801 config_path = strdup(optarg);
802 break;
803 }
804 }
805 if (!config_path) {
806 config_path = get_config_path();
807 }
808
809 if (config_path) {
810 wlr_log(WLR_DEBUG, "Found config at %s", config_path);
811 int config_status = load_config(config_path, &state, &line_mode);
812 free(config_path);
813 if (config_status != 0) {
814 return config_status;
815 }
816 }
817
818 if (argc > 1) {
819 wlr_log(WLR_DEBUG, "Parsing CLI Args");
820 int result = parse_options(argc, argv, &state, &line_mode);
821 if (result != 0) {
822 return result;
823 }
824 }
825
696 if (line_mode == LM_INSIDE) { 826 if (line_mode == LM_INSIDE) {
697 state.args.colors.line = state.args.colors.inside; 827 state.args.colors.line = state.args.colors.inside;
698 } else if (line_mode == LM_RING) { 828 } else if (line_mode == LM_RING) {
diff --git a/swaylock/swaylock.1.scd b/swaylock/swaylock.1.scd
index eea62c2a..3107124f 100644
--- a/swaylock/swaylock.1.scd
+++ b/swaylock/swaylock.1.scd
@@ -12,6 +12,15 @@ Locks your Wayland session.
12 12
13# OPTIONS 13# OPTIONS
14 14
15*-C, --config* <path>
16 The config file to use. By default, the following paths are checked:
17 _$HOME/.swaylock/config_, _$XDG\_CONFIG\_HOME/swaylock/config_, and
18 _SYSCONFDIR/swaylock/config_. All flags aside from this one are valid
19 options in the configuration file using the format _long-option=value_.
20 For options such as _ignore-empty-password_, just supply the _long-option_.
21 All leading dashes should be omitted and the equals sign is required for
22 flags that take an argument.
23
15*-c, --color* <rrggbb[aa]> 24*-c, --color* <rrggbb[aa]>
16 Turn the screen into the given color. If -i is used, this sets the 25 Turn the screen into the given color. If -i is used, this sets the
17 background of the image to the given color. Defaults to white (FFFFFF), or 26 background of the image to the given color. Defaults to white (FFFFFF), or