summaryrefslogtreecommitdiff
path: root/other/bootstrap_daemon/src
diff options
context:
space:
mode:
authorMaxim Biro <nurupo.contributions@gmail.com>2015-12-31 23:18:39 -0500
committerMaxim Biro <nurupo.contributions@gmail.com>2015-12-31 23:18:39 -0500
commite1fc8c1d3cca7e915a73cfe44462f71d2938ecba (patch)
treeddce1ac54faaa8dab32e6c3aa62f634b130407a8 /other/bootstrap_daemon/src
parent2ef1ce9421bbddb8a2ad89f81ca85ca6500fe3fc (diff)
Add ability to run the daemon in foreground
Useful for things like a Docker container or just running it in the terminal. Complements the stdout logging option. This is actually why the stdout logging was added in the first place -- to be used in the foreground mode, though nothing stops one from using stdout in the background mode, which one could redirect to a file.
Diffstat (limited to 'other/bootstrap_daemon/src')
-rw-r--r--other/bootstrap_daemon/src/tox-bootstrapd.c142
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
547void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, LOG_BACKEND *log_backend) 550void 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
636void 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
623int main(int argc, char *argv[]) 693int 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