Index: SOCKS-SOURCE/client/Xconnect.c
diff -r -u SOCKS-SOURCE/client/Xconnect.c socks-jdp/client/Xconnect.c
--- SOCKS-SOURCE/client/Xconnect.c	Wed Aug  7 19:25:51 1996
+++ socks-jdp/client/Xconnect.c	Thu Oct 24 21:35:47 1996
@@ -24,7 +24,9 @@
 #include <netdb.h>
 #include <arpa/nameser.h>
 int res_init PARAM((void));
+#ifndef __FreeBSD__
 int res_search PARAM((char*,int,int,u_char*,int));
+#endif
 int dn_skipname PARAM((u_char*,u_char*));
 #include <arpa/inet.h>
 #include <resolv.h>
@@ -39,6 +41,10 @@
 #include "bytes.h"
 #include "check_user.h"
 
+#ifndef FIOSNBIO
+# define FIOSNBIO	FIONBIO
+#endif
+
 unsigned char _SOCKS_version=SOCKS_VERSION;
 
 char *socks_dst_serv=NULL, *socks_dst_name=NULL;
@@ -102,6 +108,8 @@
     struct info	*l;		/* must be first field */
     int	snum;
     unsigned short	type;
+    int connect_done:8;
+    int bind_done:8;
     int	sin_valid:8;
     int	peer_valid:8;
     struct sockaddr_in	sin;
@@ -185,16 +193,34 @@
 #ifndef INTERNAL_ONLY
     if (_SOCKS_external) {
 	u_short port;
+	int status, oldf;
+
+	oldf = -1;
+	status = 0;
+	while (1)
+	{
+	    if ((oldf = fcntl(s, F_GETFL, NULL)) == -1)
+	    {
+		break;
+	    }
+	    (void)fcntl(s, F_SETFL, oldf&~(O_NDELAY|O_NONBLOCK));
 	if (_SOCKS_read(s,&net.version,sizeof(net.version)) < -1)
-	    return -1;
+		break;
 	if (_SOCKS_read(s,&net.cmd,sizeof(net.cmd)) < -1)
-	    return -1;
+		break;
 	if (_SOCKS_read(s,&port,sizeof(port)) < -1)
-	    return -1;
-	net.port=port;
+		break;
+	    net.port = port;
 	if (_SOCKS_read(s,&net.host,sizeof(net.host)) < -1)
-	    return -1;
-    } else
+		break;
+	    status = 1;
+	    break;
+	}
+	if (oldf != -1)
+	    (void)fcntl(s, F_SETFL, oldf);
+	if (!status)
+	    return (-1);
+   } else
 #endif /* INTERNAL_ONLY */
     {
 	if (_SOCKS_read(s,&net,sizeof(net)) < -1)
@@ -297,6 +323,12 @@
 
     if (s>=0 && af == AF_INET) {
 	(void)add_sock(s,NULL,type);
+#if 1
+	bval = size;
+	blen = sizeof(bval);
+	(void)setsockopt(s,SOL_SOCKET,SO_RCVBUF,&bval,blen);
+	(void)setsockopt(s,SOL_SOCKET,SO_SNDBUF,&bval,blen);
+#else
 	if (getsockopt(s,SOL_SOCKET,SO_RCVBUF,&bval,&blen)==0 && bval<size) {
 	    bval=size;
 	    (void)setsockopt(s,SOL_SOCKET,SO_RCVBUF,&bval,blen);
@@ -305,6 +337,7 @@
 	    bval=size;
 	    (void)setsockopt(s,SOL_SOCKET,SO_SNDBUF,&bval,blen);
 	}
+#endif
     }
     return s;
 }
@@ -380,6 +413,7 @@
     oldf=fcntl(sock,F_GETFL,NULL);
     (void)fcntl(sock,F_SETFL,oldf&~(O_NDELAY|O_NONBLOCK));
     (void)ioctl(sock,FIOSNBIO,0);
+    errno = 0;
     if (Xconnect(sock, sin, sizeof(struct sockaddr_in)) == 0) {
 	if (SendDst(sock, dst) < 0) {
 	    ret_val=-1;
@@ -389,6 +423,7 @@
 	    lastSocksHost=sin->sin_addr.s_addr;
 	    lastSocksPort=sin->sin_port;
 	    *dst=mydst;
+	    (void)fcntl(sock,F_SETFL,oldf);
 	    return 0;
 	} else {
 	    errno=ECONNREFUSED;
@@ -402,7 +437,7 @@
 	exit(1);
     }
     Xclose(new_sock);
-
+    (void)fcntl(sock,F_SETFL,oldf);
     return ret_val;
 }
 #ifdef PROTOTYPES
@@ -605,6 +640,12 @@
 	l->sin.sin_family	= AF_INET;
 	l->sin_valid		= 1;
 
+	if (type == SOCKS_CONNECT) {
+	    l->connect_done = 1;
+	} else if (type == SOCKS_BIND) {
+	    l->bind_done = 1;
+	}
+
 	return 0;
 	break;
     default:
@@ -627,9 +668,20 @@
 	struct sockaddr_in *sin=(struct sockaddr_in *)usin;
 
 	if (size == sizeof(struct sockaddr_in) && sin->sin_family == AF_INET) {
+		register infot *l=find_sock(sock);
 		_SOCKS_last_connect=*sin;
-		return _SOCKS_cbind(sock,sin,size,
-				sin->sin_addr.s_addr,SOCKS_CONNECT);
+		if (l == NULL || !l->connect_done) {
+		    return _SOCKS_cbind(sock,sin,size,
+					  sin->sin_addr.s_addr,
+					  SOCKS_CONNECT);
+		    l=find_sock(sock);
+		    if (l) {
+			l->connect_done = 1;
+		    }
+		} else {
+		    errno = EISCONN;
+		    return -1;
+		}
 	} else {
 		register infot *l=find_sock(sock);
 		if (l!=NULL)
@@ -713,10 +765,10 @@
 }
 
 #ifdef PROTOTYPES
-int Rrecvfrom(int s,char *m,int len,int f,struct sockaddr_in *from,int *size)
+int Rrecvfrom(int s,char *m,size_t len,int f,struct sockaddr_in *from,int *size)
 #else
 int Rrecvfrom(s,m,len,f,from,size)
-int s;char *m;int len;int f;struct sockaddr_in *from;int *size;
+int s;char *m;size_t len;int f;struct sockaddr_in *from;int *size;
 #endif
 {
 	infot	*l=find_sock(s);
@@ -758,10 +810,10 @@
 }
 
 #ifdef PROTOTYPES
-int Rrecv(int s,char *m,int len,int f)
+int Rrecv(int s,char *m,size_t len,int f)
 #else
 int Rrecv(s,m,len,f)
-int s;char *m;int len;int f;
+int s;char *m;size_t len;int f;
 #endif
 {
 	struct sockaddr_in from;
@@ -771,10 +823,10 @@
 }
 
 #ifdef PROTOTYPES
-int Rsendto(int s,char *m,int len,int f,struct sockaddr_in *to,int size)
+int Rsendto(int s,char *m,size_t len,int f,struct sockaddr_in *to,int size)
 #else
 int Rsendto(s,m,len,f,to,size)
-int s;char *m;int len;int f;struct sockaddr_in *to;int size;
+int s;char *m;size_t len;int f;struct sockaddr_in *to;int size;
 #endif
 {
 	infot	*l=find_sock(s);
@@ -805,10 +857,10 @@
 	return _SOCKS_write(s,m,len);
 }
 #ifdef PROTOTYPES
-int Rsend(int s,char *m,int len,int f)
+int Rsend(int s,char *m,size_t len,int f)
 #else
 int Rsend(s,m,len,f)
-int s;char *m;int len;int f;
+int s;char *m;size_t len;int f;
 #endif
 {
 	infot	*l=find_sock(s);
@@ -877,17 +929,28 @@
     fd_set		fds;
     Socks_t		dst;
     infot		*l=find_sock(sock);
+    int			nfds;
+    struct timeval	timeout, *tptr=NULL;
+    int flags;
 
+    errno = 0;
     if (l == NULL || !l->sin_valid)
 	return Xaccept(sock,sin,size);
 
     /* if we found the entry, bind or connect was called, so no
        SOCKSinit is needed. */
 
+    flags = fcntl(sock, F_GETFL, 0);
+    if (flags != -1 && (flags & O_NONBLOCK)) {
+	timeout.tv_sec = 0;
+	timeout.tv_usec = 0;
+	tptr = &timeout;
+    }
+
     FD_ZERO(&fds);
     FD_SET(sock, &fds);
 
-    if (select(sock+1, (int*)&fds, NULL, NULL, NULL) > 0)
+    if ((nfds = select(sock+1, &fds, NULL, NULL, tptr)) > 0) {
 	if (FD_ISSET(sock, &fds)) {
 	    if (GetDst(sock, &dst) < 0)
 		return -1;
@@ -901,6 +964,9 @@
 
 	    return dup(sock);
 	}
+    }
+    if (nfds == 0)
+	errno = EWOULDBLOCK;
     return -1;
 }
 #ifdef PROTOTYPES
