From d8df5f35946db56b630db60f4869ba5d9cb12a99 Mon Sep 17 00:00:00 2001
From: fgsch <>
Date: Tue, 4 Oct 2011 08:34:34 +0000
Subject: change -w to apply to the connection as well. manpage bit from jmc@
 nicm@ ok.

---
 src/usr.bin/nc/nc.1     |  8 ++++----
 src/usr.bin/nc/netcat.c | 42 ++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 44 insertions(+), 6 deletions(-)

(limited to 'src')

diff --git a/src/usr.bin/nc/nc.1 b/src/usr.bin/nc/nc.1
index 6a1538cb45..d249aa18b1 100644
--- a/src/usr.bin/nc/nc.1
+++ b/src/usr.bin/nc/nc.1
@@ -1,4 +1,4 @@
-.\"     $OpenBSD: nc.1,v 1.58 2011/09/17 14:10:05 haesbaert Exp $
+.\"     $OpenBSD: nc.1,v 1.59 2011/10/04 08:34:34 fgsch Exp $
 .\"
 .\" Copyright (c) 1996 David Sacerdote
 .\" All rights reserved.
@@ -25,7 +25,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd $Mdocdate: September 17 2011 $
+.Dd $Mdocdate: October 4 2011 $
 .Dt NC 1
 .Os
 .Sh NAME
@@ -210,9 +210,9 @@ Have
 .Nm
 give more verbose output.
 .It Fl w Ar timeout
-If a connection and stdin are idle for more than
+Connections which cannot be established or are idle timeout after
 .Ar timeout
-seconds, then the connection is silently closed.
+seconds.
 The
 .Fl w
 flag has no effect on the
diff --git a/src/usr.bin/nc/netcat.c b/src/usr.bin/nc/netcat.c
index 952bfb7dda..7880c7f452 100644
--- a/src/usr.bin/nc/netcat.c
+++ b/src/usr.bin/nc/netcat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: netcat.c,v 1.102 2011/09/17 14:10:05 haesbaert Exp $ */
+/* $OpenBSD: netcat.c,v 1.103 2011/10/04 08:34:34 fgsch Exp $ */
 /*
  * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
  *
@@ -98,6 +98,7 @@ void	help(void);
 int	local_listen(char *, char *, struct addrinfo);
 void	readwrite(int);
 int	remote_connect(const char *, const char *, struct addrinfo);
+int	timeout_connect(int, const struct sockaddr *, socklen_t);
 int	socks_connect(const char *, const char *, struct addrinfo,
 	    const char *, const char *, struct addrinfo, int, const char *);
 int	udptest(int);
@@ -590,7 +591,7 @@ remote_connect(const char *host, const char *port, struct addrinfo hints)
 
 		set_common_sockopts(s);
 
-		if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
+		if (timeout_connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
 			break;
 		else if (vflag)
 			warn("connect to %s port %s (%s) failed", host, port,
@@ -605,6 +606,43 @@ remote_connect(const char *host, const char *port, struct addrinfo hints)
 	return (s);
 }
 
+int
+timeout_connect(int s, const struct sockaddr *name, socklen_t namelen)
+{
+	struct pollfd pfd;
+	socklen_t optlen;
+	int flags, optval;
+	int ret;
+
+	if (timeout != -1) {
+		flags = fcntl(s, F_GETFL, 0);
+		if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
+			err(1, "set non-blocking mode");
+	}
+
+	if ((ret = connect(s, name, namelen)) != 0 && errno == EINPROGRESS) {
+		pfd.fd = s;
+		pfd.events = POLLOUT;
+		if ((ret = poll(&pfd, 1, timeout)) == 1) {
+			optlen = sizeof(optval);
+			if ((ret = getsockopt(s, SOL_SOCKET, SO_ERROR,
+			    &optval, &optlen)) == 0) {
+				errno = optval;
+				ret = optval == 0 ? 0 : -1;
+			}
+		} else if (ret == 0) {
+			errno = ETIMEDOUT;
+			ret = -1;
+		} else
+			err(1, "poll failed");
+	}
+
+	if (timeout != -1 && fcntl(s, F_SETFL, flags) == -1)
+		err(1, "restoring flags");
+
+	return (ret);
+}
+
 /*
  * local_listen()
  * Returns a socket listening on a local port, binds to specified source
-- 
cgit v1.2.3-55-g6feb