diff options
author | 2018-07-16 22:25:25 +0100 | |
---|---|---|
committer | 2018-07-16 22:25:25 +0100 | |
commit | 297e32126f1f8b27f51989b863e4ea1c9fce6a96 (patch) | |
tree | 8387d2550524394e1ac7275ac040a355f2a4bfbf /swaylock/main.c | |
parent | Merge pull request #2283 from RyanDwyer/no-focus (diff) | |
parent | Switch to using getopt_long for config flag (diff) | |
download | sway-297e32126f1f8b27f51989b863e4ea1c9fce6a96.tar.gz sway-297e32126f1f8b27f51989b863e4ea1c9fce6a96.tar.zst sway-297e32126f1f8b27f51989b863e4ea1c9fce6a96.zip |
Merge pull request #2265 from RedSoxFan/implement-1962
Implement swaylock configuration file parsing
Diffstat (limited to 'swaylock/main.c')
-rw-r--r-- | swaylock/main.c | 244 |
1 files changed, 187 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 | ||
415 | static struct swaylock_state state; | 416 | enum line_mode { |
416 | 417 | LM_LINE, | |
417 | int 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 | ||
422 | static 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 | |||
692 | static bool file_exists(const char *path) { | ||
693 | return path && access(path, R_OK) != -1; | ||
694 | } | ||
695 | |||
696 | static 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 | |||
733 | static 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 | |||
774 | static struct swaylock_state state; | ||
775 | |||
776 | int 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) { |