From f2e162d2245679f420b40febd1e6da7c23efb166 Mon Sep 17 00:00:00 2001 From: jay Date: Wed, 21 May 2014 17:01:00 +0000 Subject: [PATCH] Fixed a bug which caused Nmap to be unable to have any runtime interaction when called from sudo or from a shell script --- CHANGELOG | 3 +++ nmap_tty.cc | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 5b86273be..2d4d5cb9f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,8 @@ # Nmap Changelog ($Id$); -*-text-*- +o Fixed a bug which caused Nmap to be unable to have any runtime interaction + when called from sudo or from a shell script. [Jay Bosamiya] + o Improvements to whois-ip.nse: fix an unhandled error when a referred-to response could not be understood; add a new pattern to recognise a LACNIC "record not found" type of response and update the way ARIN is diff --git a/nmap_tty.cc b/nmap_tty.cc index 97b92425b..d3e94e4d8 100644 --- a/nmap_tty.cc +++ b/nmap_tty.cc @@ -188,7 +188,7 @@ static int tty_getchar() struct timeval tv; #endif - if (tty_fd && tcgetpgrp(tty_fd) == getpid()) { + if (tty_fd && tcgetpgrp(tty_fd) == getpgrp()) { // This is so that when the terminal has been disconnected, it will be // reconnected when possible. If it slows things down, just remove it @@ -227,6 +227,37 @@ static void tty_flush(void) tcflush(tty_fd, TCIFLUSH); } +static void install_handler(int signo, void (*handler) (int signo)) +{ + struct sigaction sa; + sa.sa_handler = handler; + sigfillset(&sa.sa_mask); /* block all signals during handler execution */ + sa.sa_flags = 0; + sigaction(signo, &sa, NULL); +} + +static void shutdown_clean(int signo) +{ + sigset_t set; + +/* We reinstall the default handler and call tty_done */ + install_handler(signo, SIG_DFL); + tty_done(); + +/* Unblock signo and raise it (thus allowing the default handler to occur) */ + sigemptyset(&set); + sigaddset(&set, signo); + sigprocmask(SIG_UNBLOCK, &set, NULL); + raise(signo); /* This _should_ kill us */ + _exit(EXIT_FAILURE); /* If it does not */ +} + +static void install_all_handlers() { + install_handler(SIGINT, shutdown_clean); + install_handler(SIGTERM, shutdown_clean); + install_handler(SIGQUIT, shutdown_clean); +} + /* * Initializes the terminal for unbuffered non-blocking input. Also * registers tty_done() via atexit(). You need to call this before @@ -239,13 +270,15 @@ void tty_init() if(o.noninteractive) return; + install_all_handlers(); + if (tty_fd) return; if ((tty_fd = open("/dev/tty", O_RDONLY | O_NONBLOCK)) < 0) return; #ifndef __CYGWIN32__ - if (tcgetpgrp(tty_fd) != getpid()) { + if (tcgetpgrp(tty_fd) != getpgrp()) { close(tty_fd); return; } #endif