diff --git a/interface.c b/interface.c index eb463f6..4e6dafe 100644 --- a/interface.c +++ b/interface.c @@ -36,6 +36,7 @@ #include #include #endif +#include #include "include.h" //#include "queries.h" @@ -100,6 +101,9 @@ extern int disable_output; struct in_ev *notify_ev; +extern int usfd; +extern int sfd; + int is_same_word (const char *s, size_t l, const char *word) { return s && word && strlen (word) == l && !memcmp (s, word, l); } @@ -833,7 +837,7 @@ void do_status_offline (int arg_num, struct arg args[], struct in_ev *ev) { } void do_quit (int arg_num, struct arg args[], struct in_ev *ev) { - exit (0); + do_halt (0); } void do_safe_quit (int arg_num, struct arg args[], struct in_ev *ev) { diff --git a/loop.c b/loop.c index 8a276ac..3429273 100644 --- a/loop.c +++ b/loop.c @@ -79,6 +79,7 @@ extern int disable_output; extern int reset_authorization; extern int sfd; +extern int usfd; void got_it (char *line, int len); void write_state_file (void); @@ -88,6 +89,8 @@ static int line_buffer_size; static int line_buffer_pos; static int delete_stdin_event; +extern volatile int sigterm_cnt; + static void stdin_read_callback_all (int arg, short what, struct event *self) { if (!readline_disabled) { if (((long)arg) & 1) { @@ -179,10 +182,10 @@ void net_loop (int flags, int (*is_end)(void)) { #endif if (safe_quit && !tgl_state.active_queries) { printf ("All done. Exit\n"); - if (!readline_disabled) { - rl_callback_handler_remove (); - } - exit (0); + do_halt (0); + } + if (sigterm_cnt > 0) { + do_halt (0); } if (time (0) - last_get_state > 3600) { tgl_do_lookup_state (); @@ -264,7 +267,7 @@ int got_config (void) { void on_get_config (void *extra, int success) { if (!success) { logprintf ("Can not get config.\n"); - exit (1); + do_halt (1); } config_got = 1; @@ -275,7 +278,7 @@ char *hash; void sign_in_callback (void *extra, int success, int registered, const char *mhash) { if (!success) { logprintf ("Can not send code\n"); - exit (1); + do_halt (1); } should_register = !registered; hash = strdup (mhash); @@ -288,7 +291,7 @@ int signed_in_ok; void sign_in_result (void *extra, int success, struct tgl_user *U) { if (!success) { logprintf ("Can not login\n"); - exit (1); + do_halt (1); } signed_in_ok = 1; } @@ -308,7 +311,7 @@ int dc_signed_in (void) { void export_auth_callback (void *DC, int success) { if (!success) { logprintf ("Can not export auth\n"); - exit (1); + do_halt (1); } } @@ -378,7 +381,7 @@ void write_state_file (void) { int state_file_fd = open (get_state_filename (), O_CREAT | O_RDWR, 0600); if (state_file_fd < 0) { logprintf ("Can not write state file '%s': %m\n", get_state_filename ()); - exit (2); + do_halt (1); } int x[6]; x[0] = STATE_FILE_MAGIC; @@ -646,7 +649,7 @@ static void accept_incoming (evutil_socket_t efd, short what, void *arg) { vlogprintf (E_WARNING, "Accepting incoming connection\n"); unsigned clilen; struct sockaddr_in cli_addr; - int fd = accept (sfd, (struct sockaddr *)&cli_addr, &clilen); + int fd = accept (efd, (struct sockaddr *)&cli_addr, &clilen); assert (fd >= 0); struct bufferevent *bev = bufferevent_socket_new (tgl_state.ev_base, fd, 0); @@ -691,6 +694,10 @@ int loop (void) { struct event *ev = event_new (tgl_state.ev_base, sfd, EV_READ | EV_PERSIST, accept_incoming, 0); event_add (ev, 0); } + if (usfd >= 0) { + struct event *ev = event_new (tgl_state.ev_base, usfd, EV_READ | EV_PERSIST, accept_incoming, 0); + event_add (ev, 0); + } update_prompt (); if (reset_authorization) { @@ -711,7 +718,7 @@ int loop (void) { if (!tgl_signed_dc (tgl_state.DC_working)) { if (disable_output) { fprintf (stderr, "Can not login without output\n"); - exit (2); + do_halt (1); } if (!default_username) { size_t size = 0; @@ -721,7 +728,7 @@ int loop (void) { printf ("Telephone number (with '+' sign): "); if (net_getline (&user, &size) == -1) { perror ("getline()"); - exit (EXIT_FAILURE); + do_halt (1); } set_default_username (user); } @@ -739,7 +746,7 @@ int loop (void) { while (1) { if (net_getline (&code, &size) == -1) { perror ("getline()"); - exit (EXIT_FAILURE); + do_halt (1); } if (!strcmp (code, "call")) { printf ("You typed \"call\", switching to phone system.\n"); @@ -759,31 +766,31 @@ int loop (void) { size_t size; if (net_getline (&code, &size) == -1) { perror ("getline()"); - exit (EXIT_FAILURE); + do_halt (1); } if (!*code || *code == 'y' || *code == 'Y') { printf ("Ok, starting registartion.\n"); } else { printf ("Then try again\n"); - exit (EXIT_SUCCESS); + do_halt (1); } char *first_name; printf ("First name: "); if (net_getline (&first_name, &size) == -1) { perror ("getline()"); - exit (EXIT_FAILURE); + do_halt (1); } char *last_name; printf ("Last name: "); if (net_getline (&last_name, &size) == -1) { perror ("getline()"); - exit (EXIT_FAILURE); + do_halt (1); } printf ("Code from sms (if you did not receive an SMS and want to be called, type \"call\"): "); while (1) { if (net_getline (&code, &size) == -1) { perror ("getline()"); - exit (EXIT_FAILURE); + do_halt (1); } if (!strcmp (code, "call")) { printf ("You typed \"call\", switching to phone system.\n"); diff --git a/loop.h b/loop.h index 8e1c938..ee0f1c5 100644 --- a/loop.h +++ b/loop.h @@ -19,6 +19,7 @@ #ifndef __LOOP_H__ #define __LOOP_H__ int loop (void); +void do_halt (int error); void net_loop (int flags, int (*end)(void)); void write_auth_file (void); void write_state_file (void); diff --git a/main.c b/main.c index 78861ab..6fc1ec5 100644 --- a/main.c +++ b/main.c @@ -36,6 +36,8 @@ #endif #include +#include +#include #include #include @@ -72,6 +74,7 @@ #define DOWNLOADS_DIRECTORY "downloads" #define BINLOG_FILE "binlog" + #define CONFIG_DIRECTORY_MODE 0700 #define DEFAULT_CONFIG_CONTENTS \ @@ -423,6 +426,7 @@ void usage (void) { printf (" -G change gid after start\n"); printf (" -D disable output\n"); printf (" -P port to listen for input commands\n"); + printf (" -S unix socket to create\n"); exit (1); } @@ -521,9 +525,11 @@ int change_user_group () { return 0; } +char *unix_socket; + void args_parse (int argc, char **argv) { int opt = 0; - while ((opt = getopt (argc, argv, "u:hk:vNl:fEwWCRdL:DU:G:qP:" + while ((opt = getopt (argc, argv, "u:hk:vNl:fEwWCRdL:DU:G:qP:S:" #ifdef HAVE_LIBCONFIG "c:p:" #else @@ -609,6 +615,9 @@ void args_parse (int argc, char **argv) { case 'P': port = atoi (optarg); break; + case 'S': + unix_socket = optarg; + break; case 'h': default: usage (); @@ -631,29 +640,83 @@ void print_backtrace (void) { } #endif -void sig_segv_handler (int signum __attribute__ ((unused))) { - set_terminal_attributes (); - if (write (1, "SIGSEGV received\n", 18) < 0) { - // Sad thing - } - print_backtrace (); - exit (EXIT_FAILURE); -} - -void sig_abrt_handler (int signum __attribute__ ((unused))) { - set_terminal_attributes (); - if (write (1, "SIGABRT received\n", 18) < 0) { - // Sad thing - } - print_backtrace (); - exit (EXIT_FAILURE); -} - int sfd; +int usfd; + +void termination_signal_handler (int signum) { + if (!readline_disabled) { + rl_free_line_state (); + rl_cleanup_after_signal (); + } + + if (write (1, "SIGNAL received\n", 18) < 0) { + // Sad thing + } + + if (unix_socket) { + unlink (unix_socket); + } + + if (usfd > 0) { + close (usfd); + } + if (sfd > 0) { + close (sfd); + } + print_backtrace (); + + exit (EXIT_FAILURE); +} + +volatile int sigterm_cnt; + +void sig_term_handler (int signum __attribute__ ((unused))) { + signal (signum, termination_signal_handler); + //set_terminal_attributes (); + if (write (1, "SIGTERM/SIGINT received\n", 25) < 0) { + // Sad thing + } + sigterm_cnt ++; +} + +void do_halt (int error) { + if (!readline_disabled) { + rl_free_line_state (); + rl_cleanup_after_signal (); + } + + if (write (1, "halt\n", 5) < 0) { + // Sad thing + } + + if (unix_socket) { + unlink (unix_socket); + } + + if (usfd > 0) { + close (usfd); + } + if (sfd > 0) { + close (sfd); + } + + exit (error ? EXIT_FAILURE : EXIT_SUCCESS); +} int main (int argc, char **argv) { - signal (SIGSEGV, sig_segv_handler); - signal (SIGABRT, sig_abrt_handler); + signal (SIGSEGV, termination_signal_handler); + signal (SIGABRT, termination_signal_handler); + signal (SIGBUS, termination_signal_handler); + signal (SIGQUIT, termination_signal_handler); + signal (SIGFPE, termination_signal_handler); + + signal (SIGPIPE, SIG_IGN); + + signal (SIGTERM, sig_term_handler); + signal (SIGINT, sig_term_handler); + + rl_catch_signals = 0; + log_level = 10; @@ -681,10 +744,36 @@ int main (int argc, char **argv) { exit(1); } - listen (sfd,5); + listen (sfd, 5); } else { sfd = -1; } + + if (unix_socket) { + assert (strlen (unix_socket) < 100); + struct sockaddr_un serv_addr; + + usfd = socket (AF_UNIX, SOCK_STREAM, 0); + if (usfd < 0) { + perror ("socket"); + exit(1); + } + + memset (&serv_addr, 0, sizeof (serv_addr)); + + serv_addr.sun_family = AF_UNIX; + + snprintf (serv_addr.sun_path, 108, "%s", unix_socket); + + if (bind (usfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) { + perror ("bind"); + exit(1); + } + + listen (usfd, 5); + } else { + usfd = -1; + } if (daemonize) { signal (SIGHUP, sighup_handler);