diff options
Diffstat (limited to 'other/bootstrap_daemon')
-rw-r--r-- | other/bootstrap_daemon/src/tox-bootstrapd.c | 142 |
1 files changed, 81 insertions, 61 deletions
diff --git a/other/bootstrap_daemon/src/tox-bootstrapd.c b/other/bootstrap_daemon/src/tox-bootstrapd.c index 3bbddf98..a8098e41 100644 --- a/other/bootstrap_daemon/src/tox-bootstrapd.c +++ b/other/bootstrap_daemon/src/tox-bootstrapd.c | |||
@@ -523,6 +523,7 @@ bool print_help() | |||
523 | { | 523 | { |
524 | // 2 space ident | 524 | // 2 space ident |
525 | // make sure all lines fit into 80 columns | 525 | // make sure all lines fit into 80 columns |
526 | // make sure options are listed in alphabetical order | ||
526 | write_log(LOG_LEVEL_INFO, | 527 | write_log(LOG_LEVEL_INFO, |
527 | "Usage: tox-bootstrapd [OPTION]... --config=FILE_PATH\n" | 528 | "Usage: tox-bootstrapd [OPTION]... --config=FILE_PATH\n" |
528 | "\n" | 529 | "\n" |
@@ -531,6 +532,8 @@ bool print_help() | |||
531 | " This is a required option.\n" | 532 | " This is a required option.\n" |
532 | " Set FILE_PATH to a path to an empty file in order to\n" | 533 | " Set FILE_PATH to a path to an empty file in order to\n" |
533 | " use default settings.\n" | 534 | " use default settings.\n" |
535 | " --foreground Run the daemon in foreground. The daemon won't fork\n" | ||
536 | " (detach from the terminal) and won't use the PID file.\n" | ||
534 | " --help Print this help message.\n" | 537 | " --help Print this help message.\n" |
535 | " --log-backend=BACKEND Specify which logging backend to use.\n" | 538 | " --log-backend=BACKEND Specify which logging backend to use.\n" |
536 | " Valid BACKEND values (case sensetive):\n" | 539 | " Valid BACKEND values (case sensetive):\n" |
@@ -544,7 +547,7 @@ bool print_help() | |||
544 | // Handels command line arguments, setting cfg_file_path and log_backend. | 547 | // Handels command line arguments, setting cfg_file_path and log_backend. |
545 | // Terminates the application if incorrect arguments are specified. | 548 | // Terminates the application if incorrect arguments are specified. |
546 | 549 | ||
547 | void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, LOG_BACKEND *log_backend) | 550 | void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, LOG_BACKEND *log_backend, bool *run_in_foreground) |
548 | { | 551 | { |
549 | if (argc < 2) { | 552 | if (argc < 2) { |
550 | write_log(LOG_LEVEL_ERROR, "Error: No arguments provided.\n\n"); | 553 | write_log(LOG_LEVEL_ERROR, "Error: No arguments provided.\n\n"); |
@@ -557,6 +560,7 @@ void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, | |||
557 | static struct option long_options[] = { | 560 | static struct option long_options[] = { |
558 | {"help", no_argument, 0, 'h'}, | 561 | {"help", no_argument, 0, 'h'}, |
559 | {"config", required_argument, 0, 'c'}, // required option | 562 | {"config", required_argument, 0, 'c'}, // required option |
563 | {"foreground", no_argument, 0, 'f'}, | ||
560 | {"log-backend", required_argument, 0, 'l'}, // optional, defaults to syslog | 564 | {"log-backend", required_argument, 0, 'l'}, // optional, defaults to syslog |
561 | {"version", no_argument, 0, 'v'}, | 565 | {"version", no_argument, 0, 'v'}, |
562 | {0, 0, 0, 0 } | 566 | {0, 0, 0, 0 } |
@@ -565,6 +569,8 @@ void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, | |||
565 | bool cfg_file_path_set = false; | 569 | bool cfg_file_path_set = false; |
566 | bool log_backend_set = false; | 570 | bool log_backend_set = false; |
567 | 571 | ||
572 | *run_in_foreground = false; | ||
573 | |||
568 | int opt; | 574 | int opt; |
569 | 575 | ||
570 | while ((opt = getopt_long(argc, argv, ":", long_options, NULL)) != -1) { | 576 | while ((opt = getopt_long(argc, argv, ":", long_options, NULL)) != -1) { |
@@ -579,6 +585,10 @@ void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, | |||
579 | cfg_file_path_set = true; | 585 | cfg_file_path_set = true; |
580 | break; | 586 | break; |
581 | 587 | ||
588 | case 'f': | ||
589 | *run_in_foreground = true; | ||
590 | break; | ||
591 | |||
582 | case 'l': | 592 | case 'l': |
583 | if (strcmp(optarg, "syslog") == 0) { | 593 | if (strcmp(optarg, "syslog") == 0) { |
584 | *log_backend = LOG_BACKEND_SYSLOG; | 594 | *log_backend = LOG_BACKEND_SYSLOG; |
@@ -620,16 +630,77 @@ void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, | |||
620 | } | 630 | } |
621 | } | 631 | } |
622 | 632 | ||
633 | // Demonizes the process, appending PID to the PID file and closing file descriptors based on log backend | ||
634 | // Terminates the application if the daemonization fails. | ||
635 | |||
636 | void daemonize(LOG_BACKEND log_backend, char *pid_file_path) | ||
637 | { | ||
638 | // Check if the PID file exists | ||
639 | FILE *pid_file; | ||
640 | |||
641 | if ((pid_file = fopen(pid_file_path, "r"))) { | ||
642 | write_log(LOG_LEVEL_WARNING, "Another instance of the daemon is already running, PID file %s exists.\n", pid_file_path); | ||
643 | fclose(pid_file); | ||
644 | } | ||
645 | |||
646 | // Open the PID file for writing | ||
647 | pid_file = fopen(pid_file_path, "a+"); | ||
648 | if (pid_file == NULL) { | ||
649 | write_log(LOG_LEVEL_ERROR, "Couldn't open the PID file for writing: %s. Exiting.\n", pid_file_path); | ||
650 | exit(1); | ||
651 | } | ||
652 | |||
653 | // Fork off from the parent process | ||
654 | const pid_t pid = fork(); | ||
655 | |||
656 | if (pid > 0) { | ||
657 | fprintf(pid_file, "%d", pid); | ||
658 | fclose(pid_file); | ||
659 | write_log(LOG_LEVEL_INFO, "Forked successfully: PID: %d.\n", pid); | ||
660 | exit(0); | ||
661 | } else { | ||
662 | fclose(pid_file); | ||
663 | } | ||
664 | |||
665 | if (pid < 0) { | ||
666 | write_log(LOG_LEVEL_ERROR, "Forking failed. Exiting.\n"); | ||
667 | exit(1); | ||
668 | } | ||
669 | |||
670 | // Create a new SID for the child process | ||
671 | if (setsid() < 0) { | ||
672 | write_log(LOG_LEVEL_ERROR, "SID creation failure. Exiting.\n"); | ||
673 | exit(1); | ||
674 | } | ||
675 | |||
676 | // Change the file mode mask | ||
677 | umask(0); | ||
678 | |||
679 | // Change the current working directory | ||
680 | if ((chdir("/")) < 0) { | ||
681 | write_log(LOG_LEVEL_ERROR, "Couldn't change working directory to '/'. Exiting.\n"); | ||
682 | exit(1); | ||
683 | } | ||
684 | |||
685 | // Go quiet | ||
686 | if (log_backend != LOG_BACKEND_STDOUT) { | ||
687 | close(STDOUT_FILENO); | ||
688 | close(STDIN_FILENO); | ||
689 | close(STDERR_FILENO); | ||
690 | } | ||
691 | } | ||
692 | |||
623 | int main(int argc, char *argv[]) | 693 | int main(int argc, char *argv[]) |
624 | { | 694 | { |
625 | char *cfg_file_path; | 695 | char *cfg_file_path; |
626 | LOG_BACKEND log_backend; | 696 | LOG_BACKEND log_backend; |
697 | bool run_in_foreground; | ||
627 | 698 | ||
628 | // choose backend for printing command line argument parsing output based on whether the daemon is being run from a terminal | 699 | // choose backend for printing command line argument parsing output based on whether the daemon is being run from a terminal |
629 | log_backend = isatty(STDOUT_FILENO) ? LOG_BACKEND_STDOUT : LOG_BACKEND_SYSLOG; | 700 | log_backend = isatty(STDOUT_FILENO) ? LOG_BACKEND_STDOUT : LOG_BACKEND_SYSLOG; |
630 | 701 | ||
631 | open_log(log_backend); | 702 | open_log(log_backend); |
632 | handle_command_line_arguments(argc, argv, &cfg_file_path, &log_backend); | 703 | handle_command_line_arguments(argc, argv, &cfg_file_path, &log_backend, &run_in_foreground); |
633 | close_log(); | 704 | close_log(); |
634 | 705 | ||
635 | open_log(log_backend); | 706 | open_log(log_backend); |
@@ -660,14 +731,12 @@ int main(int argc, char *argv[]) | |||
660 | return 1; | 731 | return 1; |
661 | } | 732 | } |
662 | 733 | ||
663 | // Check if the PID file exists | 734 | if (!run_in_foreground) { |
664 | FILE *pid_file; | 735 | daemonize(log_backend, pid_file_path); |
665 | |||
666 | if ((pid_file = fopen(pid_file_path, "r"))) { | ||
667 | write_log(LOG_LEVEL_WARNING, "Another instance of the daemon is already running, PID file %s exists.\n", pid_file_path); | ||
668 | fclose(pid_file); | ||
669 | } | 736 | } |
670 | 737 | ||
738 | free(pid_file_path); | ||
739 | |||
671 | IP ip; | 740 | IP ip; |
672 | ip_init(&ip, enable_ipv6); | 741 | ip_init(&ip, enable_ipv6); |
673 | 742 | ||
@@ -690,7 +759,6 @@ int main(int argc, char *argv[]) | |||
690 | } | 759 | } |
691 | } | 760 | } |
692 | 761 | ||
693 | |||
694 | DHT *dht = new_DHT(net); | 762 | DHT *dht = new_DHT(net); |
695 | 763 | ||
696 | if (dht == NULL) { | 764 | if (dht == NULL) { |
@@ -724,6 +792,8 @@ int main(int argc, char *argv[]) | |||
724 | return 1; | 792 | return 1; |
725 | } | 793 | } |
726 | 794 | ||
795 | free(keys_file_path); | ||
796 | |||
727 | TCP_Server *tcp_server = NULL; | 797 | TCP_Server *tcp_server = NULL; |
728 | 798 | ||
729 | if (enable_tcp_relay) { | 799 | if (enable_tcp_relay) { |
@@ -754,56 +824,6 @@ int main(int argc, char *argv[]) | |||
754 | 824 | ||
755 | print_public_key(dht->self_public_key); | 825 | print_public_key(dht->self_public_key); |
756 | 826 | ||
757 | // Write the PID file | ||
758 | FILE *pidf = fopen(pid_file_path, "a+"); | ||
759 | |||
760 | if (pidf == NULL) { | ||
761 | write_log(LOG_LEVEL_ERROR, "Couldn't open the PID file for writing: %s. Exiting.\n", pid_file_path); | ||
762 | return 1; | ||
763 | } | ||
764 | |||
765 | free(pid_file_path); | ||
766 | free(keys_file_path); | ||
767 | |||
768 | // Fork off from the parent process | ||
769 | const pid_t pid = fork(); | ||
770 | |||
771 | if (pid > 0) { | ||
772 | fprintf(pidf, "%d", pid); | ||
773 | fclose(pidf); | ||
774 | write_log(LOG_LEVEL_INFO, "Forked successfully: PID: %d.\n", pid); | ||
775 | return 0; | ||
776 | } else { | ||
777 | fclose(pidf); | ||
778 | } | ||
779 | |||
780 | if (pid < 0) { | ||
781 | write_log(LOG_LEVEL_ERROR, "Forking failed. Exiting.\n"); | ||
782 | return 1; | ||
783 | } | ||
784 | |||
785 | // Change the file mode mask | ||
786 | umask(0); | ||
787 | |||
788 | // Create a new SID for the child process | ||
789 | if (setsid() < 0) { | ||
790 | write_log(LOG_LEVEL_ERROR, "SID creation failure. Exiting.\n"); | ||
791 | return 1; | ||
792 | } | ||
793 | |||
794 | // Change the current working directory | ||
795 | if ((chdir("/")) < 0) { | ||
796 | write_log(LOG_LEVEL_ERROR, "Couldn't change working directory to '/'. Exiting.\n"); | ||
797 | return 1; | ||
798 | } | ||
799 | |||
800 | // Go quiet | ||
801 | if (log_backend != LOG_BACKEND_STDOUT) { | ||
802 | close(STDOUT_FILENO); | ||
803 | close(STDIN_FILENO); | ||
804 | close(STDERR_FILENO); | ||
805 | } | ||
806 | |||
807 | uint64_t last_LANdiscovery = 0; | 827 | uint64_t last_LANdiscovery = 0; |
808 | const uint16_t htons_port = htons(port); | 828 | const uint16_t htons_port = htons(port); |
809 | 829 | ||
@@ -811,7 +831,7 @@ int main(int argc, char *argv[]) | |||
811 | 831 | ||
812 | if (enable_lan_discovery) { | 832 | if (enable_lan_discovery) { |
813 | LANdiscovery_init(dht); | 833 | LANdiscovery_init(dht); |
814 | write_log(LOG_LEVEL_INFO, "Initialized LAN discovery.\n"); | 834 | write_log(LOG_LEVEL_INFO, "Initialized LAN discovery successfully.\n"); |
815 | } | 835 | } |
816 | 836 | ||
817 | while (1) { | 837 | while (1) { |
@@ -829,7 +849,7 @@ int main(int argc, char *argv[]) | |||
829 | networking_poll(dht->net); | 849 | networking_poll(dht->net); |
830 | 850 | ||
831 | if (waiting_for_dht_connection && DHT_isconnected(dht)) { | 851 | if (waiting_for_dht_connection && DHT_isconnected(dht)) { |
832 | write_log(LOG_LEVEL_INFO, "Connected to other bootstrap node successfully.\n"); | 852 | write_log(LOG_LEVEL_INFO, "Connected to another bootstrap node successfully.\n"); |
833 | waiting_for_dht_connection = 0; | 853 | waiting_for_dht_connection = 0; |
834 | } | 854 | } |
835 | 855 | ||