Robert de Bath's multi-purpose patch, slightly modified.
[u/mdw/putty] / telnet.c
index 33b921b..24962bb 100644 (file)
--- a/telnet.c
+++ b/telnet.c
@@ -174,6 +174,9 @@ static void c_write (char *buf, int len) {
        if (new_head != inbuf_reap) {
            inbuf[inbuf_head] = *buf++;
            inbuf_head = new_head;
+       } else {
+            term_out();
+            if( inbuf_head == inbuf_reap ) len++; else break;
        }
     }
 }
@@ -411,9 +414,11 @@ static void do_telnet_read (char *buf, int len) {
            else if (c == WONT) telnet_state = SEENWONT;
            else if (c == SB) telnet_state = SEENSB;
            else {
-               /* ignore (and print) everything else */
-               b[0] = c;
-               c_write(b,1);
+               /* ignore everything else; print it if it's IAC */
+               if (c == IAC) {
+                   b[0] = c;
+                   c_write(b,1);
+               }
                telnet_state = TOPLEVEL;
            }
            break;
@@ -586,14 +591,22 @@ static int telnet_msg (WPARAM wParam, LPARAM lParam) {
     int ret;
     char buf[256];
 
-    if (s == INVALID_SOCKET)          /* how the hell did we get here?! */
-       return -5000;
+    /*
+     * Because reading less than the whole of the available pending
+     * data can generate an FD_READ event, we need to allow for the
+     * possibility that FD_READ may arrive with FD_CLOSE already in
+     * the queue; so it's possible that we can get here even with s
+     * invalid. If so, we return 1 and don't worry about it.
+     */
+    if (s == INVALID_SOCKET)
+       return 1;
 
     if (WSAGETSELECTERROR(lParam) != 0)
        return -WSAGETSELECTERROR(lParam);
 
     switch (WSAGETSELECTEVENT(lParam)) {
       case FD_READ:
+      case FD_CLOSE:
        ret = recv(s, buf, sizeof(buf), 0);
        if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
            return 1;
@@ -601,7 +614,7 @@ static int telnet_msg (WPARAM wParam, LPARAM lParam) {
            return -10000-WSAGetLastError();
        if (ret == 0) {
            s = INVALID_SOCKET;
-           return 0;                  /* can't happen, in theory */
+           return 0;
        }
 #if 0
        if (in_synch) {
@@ -632,9 +645,6 @@ static int telnet_msg (WPARAM wParam, LPARAM lParam) {
        if (outbuf_head != outbuf_reap)
            try_write();
        return 1;
-      case FD_CLOSE:
-       s = INVALID_SOCKET;
-       return 0;
     }
     return 1;                         /* shouldn't happen, but WTF */
 }