summaryrefslogtreecommitdiffstats
path: root/swaylock/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'swaylock/main.c')
-rw-r--r--swaylock/main.c241
1 files changed, 184 insertions, 57 deletions
diff --git a/swaylock/main.c b/swaylock/main.c
index faebc757..3d57eb75 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,140 @@ 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 (int i = 0; i < (int)(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 for (int i = 0; i < argc; i++) {
793 if (strcmp(argv[i], "-C") == 0 || strcmp(argv[i], "--config") == 0) {
794 if (i + 1 == argc) {
795 wlr_log(WLR_ERROR, "Config file path is missing");
796 return 1;
797 }
798 config_path = strdup(argv[i + 1]);
799 break;
800 }
801 }
802 if (!config_path) {
803 config_path = get_config_path();
804 }
805
806 if (config_path) {
807 wlr_log(WLR_DEBUG, "Found config at %s", config_path);
808 int config_status = load_config(config_path, &state, &line_mode);
809 free(config_path);
810 if (config_status != 0) {
811 return config_status;
812 }
813 }
814
815 if (argc > 1) {
816 wlr_log(WLR_DEBUG, "Parsing CLI Args");
817 int result = parse_options(argc, argv, &state, &line_mode);
818 if (result != 0) {
819 return result;
820 }
821 }
822
696 if (line_mode == LM_INSIDE) { 823 if (line_mode == LM_INSIDE) {
697 state.args.colors.line = state.args.colors.inside; 824 state.args.colors.line = state.args.colors.inside;
698 } else if (line_mode == LM_RING) { 825 } else if (line_mode == LM_RING) {