Sophie

Sophie

distrib > Mageia > 3 > i586 > media > core-release-src > by-pkgid > 14d66bf8988361107689f9ce2e9a8abf > files > 1

netcat-openbsd-1.89-5.mga3.src.rpm

Index: netcat-openbsd-1.89/netcat.c
===================================================================
--- netcat-openbsd-1.89.orig/netcat.c	2008-01-22 16:17:27.000000000 -0500
+++ netcat-openbsd-1.89/netcat.c	2008-01-22 16:17:30.000000000 -0500
@@ -65,6 +65,10 @@
 #define PORT_MAX	65535
 #define PORT_MAX_LEN	6
 
+#define CONNECTION_SUCCESS 0
+#define CONNECTION_FAILED 1
+#define CONNECTION_TIMEOUT 2
+
 /* Command Line Options */
 int	dflag;					/* detached, no stdin */
 int	iflag;					/* Interval Flag */
@@ -104,6 +108,9 @@
 int	parse_iptos(char *);
 void	usage(int);
 
+static int connect_with_timeout(int fd, const struct sockaddr *sa, 
+		                socklen_t salen, int ctimeout);
+
 int
 main(int argc, char *argv[])
 {
@@ -508,13 +515,15 @@
 		}
 
 		set_common_sockopts(s);
-
-		if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
+		if ((error = connect_with_timeout(s, res0->ai_addr, res0->ai_addrlen, timeout)) == CONNECTION_SUCCESS)
 			break;
-		else if (vflag)
+		else if (vflag && error == CONNECTION_FAILED)
 			warn("connect to %s port %s (%s) failed", host, port,
 			    uflag ? "udp" : "tcp");
-
+		else if (vflag && error == CONNECTION_TIMEOUT)
+			warn("connect to %s port %s (%s) timed out", host, port,
+			    uflag ? "udp" : "tcp");
+		
 		close(s);
 		s = -1;
 	} while ((res0 = res0->ai_next) != NULL);
@@ -524,6 +533,74 @@
 	return (s);
 }
 
+static int connect_with_timeout(int fd, const struct sockaddr *sa, 
+		                socklen_t salen, int ctimeout)
+{
+	int err;
+	struct timeval tv, *tvp = NULL;
+	fd_set connect_fdset;
+	socklen_t len;
+	int orig_flags;	
+
+	orig_flags = fcntl(fd, F_GETFL, 0);
+	if (fcntl(fd, F_SETFL, orig_flags | O_NONBLOCK) < 0 ) {
+		warn("can't set O_NONBLOCK - timeout not avaliable");
+		if (connect(fd, sa, salen) == 0)
+			return CONNECTION_SUCCESS;
+		else
+			return CONNECTION_FAILED;
+	}
+
+	/* set connect timeout */
+	if (ctimeout > 0) {
+		tv.tv_sec = (time_t)ctimeout/1000;
+		tv.tv_usec = 0;
+		tvp = &tv;
+	}
+
+	/* attempt the connection */
+	err = connect(fd, sa, salen);
+	
+	if (err != 0 && errno == EINPROGRESS) {
+		/* connection is proceeding
+		 * it is complete (or failed) when select returns */
+
+		/* initialize connect_fdset */
+		FD_ZERO(&connect_fdset);
+		FD_SET(fd, &connect_fdset);
+
+		/* call select */
+		do {
+			err = select(fd + 1, NULL, &connect_fdset, 
+				     NULL, tvp);
+		} while (err < 0 && errno == EINTR);
+
+		/* select error */
+		if (err < 0)
+			errx(1,"select error: %s", strerror(errno));
+	
+		/* we have reached a timeout */
+		if (err == 0) 
+			return CONNECTION_TIMEOUT;
+		
+		/* select returned successfully, but we must test socket 
+		 * error for result */
+		len = sizeof(err);
+		if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len) < 0)
+			errx(1, "getsockopt error: %s", strerror(errno));
+		
+		/* setup errno according to the result returned by 
+		 * getsockopt */
+		if (err != 0)
+			errno = err;
+	}
+
+	/* return aborted if an error occured, and valid otherwise */
+	fcntl(fd, F_SETFL, orig_flags);
+	return (err != 0)? CONNECTION_FAILED : CONNECTION_SUCCESS;
+}
+						    				
+
 /*
  * local_listen()
  * Returns a socket listening on a local port, binds to specified source