diff --git a/ncat/ncat_listen.c b/ncat/ncat_listen.c index 3bf7e0e3e..1dd0fd82d 100644 --- a/ncat/ncat_listen.c +++ b/ncat/ncat_listen.c @@ -260,6 +260,23 @@ static int ncat_listen_stream(int proto) setup_ssl_listen(); #endif + /* Check whether stdin is closed. Because we treat this fd specially, we + * can't risk it being reopened for an incoming connection, so we'll hold + * it open instead. */ + if (fcntl(STDIN_FILENO, F_GETFD) == -1 && errno == EBADF) { + logdebug("stdin is closed, attempting to reserve STDIN_FILENO\n"); +#ifdef WIN32 + rc = open("NUL", O_RDONLY); +#else + rc = open("/dev/null", O_RDONLY); +#endif + if (rc >= 0 && rc != STDIN_FILENO) { + /* Oh well, we tried */ + logdebug("Couldn't reserve STDIN_FILENO\n"); + close(rc); + } + } + /* We need a list of fds to keep current fdmax. The second parameter is a number added to the supplied connection limit, that will compensate maxfds for the added by default listen and stdin sockets. */ @@ -673,6 +690,23 @@ static int ncat_listen_dgram(int proto) Signal(SIGPIPE, SIG_IGN); #endif + /* Check whether stdin is closed. Because we treat this fd specially, we + * can't risk it being reopened for an incoming connection, so we'll hold + * it open instead. */ + if (fcntl(STDIN_FILENO, F_GETFD) == -1 && errno == EBADF) { + logdebug("stdin is closed, attempting to reserve STDIN_FILENO\n"); +#ifdef WIN32 + i = open("NUL", O_RDONLY); +#else + i = open("/dev/null", O_RDONLY); +#endif + if (i >= 0 && i != STDIN_FILENO) { + /* Oh well, we tried */ + logdebug("Couldn't reserve STDIN_FILENO\n"); + close(i); + } + } + /* set for selecting udp listening sockets */ fd_set listen_fds; fd_list_t listen_fdlist; @@ -858,11 +892,16 @@ static int ncat_listen_dgram(int proto) if (FD_ISSET(STDIN_FILENO, &fds)) { nbytes = Read(STDIN_FILENO, buf, sizeof(buf)); - if (nbytes < 0) { - loguser("%s.\n", strerror(errno)); - return 1; - } else if (nbytes == 0) { - return 0; + if (nbytes <= 0) { + if (nbytes < 0 && o.verbose) { + logdebug("Error reading from stdin: %s\n", strerror(errno)); + } else if (nbytes == 0 && o.debug) { + logdebug("EOF on stdin\n"); + } + FD_CLR(STDIN_FILENO, &read_fds); + if (nbytes < 0) + return 1; + continue; } if (o.crlf) fix_line_endings((char *) buf, &nbytes, &tempbuf, &crlf_state);