diff --git a/ncat/ncat_listen.c b/ncat/ncat_listen.c index 31b7e35ad..4e33b84b2 100644 --- a/ncat/ncat_listen.c +++ b/ncat/ncat_listen.c @@ -178,6 +178,40 @@ static void sigchld_handler(int signum) decrease_conn_count(); errno = saved_errno; } + +/* Propagate the trapped signal to the entire process group */ +static void signal_propagate_exit(int signum) +{ + /* Send signal to process group */ + kill(0, signum); + /* Exit, since we only use this for INT/TERM/HUP */ + exit(128 + signum); +} + +static void install_signal_handlers(void) +{ + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sigemptyset(&sa.sa_mask); + + /* Ignore the SIGPIPE that occurs when a client disconnects suddenly and we + send data to it before noticing. */ + sa.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &sa, NULL); + + /* Reap on SIGCHLD */ + sa.sa_handler = sigchld_handler; + sa.sa_flags = SA_RESTART; + sigaction(SIGCHLD, &sa, NULL); + + /* Nab any process-terminating signals and propagate them */ + sa.sa_handler = signal_propagate_exit; + sa.sa_flags = SA_RESTART | SA_RESETHAND; + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGHUP, &sa, NULL); + sigaction(SIGQUIT, &sa, NULL); +} #endif int new_listen_socket(int type, int proto, const union sockaddr_u *addr, fd_set *listen_fds) @@ -243,11 +277,7 @@ int ncat_listen() #ifdef WIN32 set_pseudo_sigchld_handler(decrease_conn_count); #else - /* Reap on SIGCHLD */ - Signal(SIGCHLD, sigchld_handler); - /* Ignore the SIGPIPE that occurs when a client disconnects suddenly and we - send data to it before noticing. */ - Signal(SIGPIPE, SIG_IGN); + install_signal_handlers(); #endif #ifdef HAVE_OPENSSL diff --git a/ncat/sys_wrap.c b/ncat/sys_wrap.c index 0151d7d91..2ecf3c9e6 100644 --- a/ncat/sys_wrap.c +++ b/ncat/sys_wrap.c @@ -148,13 +148,15 @@ int Setsockopt(int s, int level, int optname, const void *optval, sighandler_t Signal(int signum, sighandler_t handler) { - sighandler_t ret; + struct sigaction sa, osa; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; - ret = signal(signum, handler); - if (ret == SIG_ERR) - die("signal"); - - return ret; + if (0 > sigaction(signum, &sa, &osa)) + die("sigaction"); + return osa.sa_handler; }