+/*
+ * Perform a non-blocking connect on the socket fd.
+ *
+ * tout contains the timeout. It will be modified to contain the time
+ * remaining (i.e. time provided - time elasped).
+ *
+ * Returns zero on success; otherwise, -1 is returned and errno is set
+ * to reflect the nature of the error.
+ */
+static int connect_nb(int fd, struct sockaddr_in *addr, struct timeval *tout)
+{
+ int flags, ret;
+ socklen_t len;
+ fd_set rset;
+
+ flags = fcntl(fd, F_GETFL, 0);
+ if (flags < 0)
+ return -1;
+
+ ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+ if (ret < 0)
+ return -1;
+
+ /*
+ * From here on subsequent sys calls could change errno so
+ * we set ret = -errno to capture it in case we decide to
+ * use it later.
+ */
+ len = sizeof(struct sockaddr);
+ ret = connect(fd, (struct sockaddr *)addr, len);
+ if (ret < 0 && errno != EINPROGRESS) {
+ ret = -1;
+ goto done;
+ }
+
+ if (ret == 0)
+ goto done;
+
+ /* now wait */
+ FD_ZERO(&rset);
+ FD_SET(fd, &rset);
+
+ ret = select(fd + 1, NULL, &rset, NULL, tout);
+ if (ret <= 0) {
+ if (ret == 0)
+ errno = ETIMEDOUT;
+ ret = -1;
+ goto done;
+ }
+
+ if (FD_ISSET(fd, &rset)) {
+ int status;
+
+ len = sizeof(ret);
+ status = getsockopt(fd, SOL_SOCKET, SO_ERROR, &ret, &len);
+ if (status < 0) {
+ ret = -1;
+ goto done;
+ }
+
+ /* Oops - something wrong with connect */
+ if (ret != 0) {
+ errno = ret;
+ ret = -1;
+ }
+ }
+
+done:
+ fcntl(fd, F_SETFL, flags);
+ return ret;
+}
+
+int main(int argc, char **argv)