terminal.c's from_backend() no longer calls term_out(), because
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Tue, 18 Sep 2001 19:41:07 +0000 (19:41 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Tue, 18 Sep 2001 19:41:07 +0000 (19:41 +0000)
term_out() can in turn call ldisc_send() which calls back to
from_backend() when local echo is enabled. This was giving rise to
crazy re-entrancy stuff and stack overflows. Instead from_backend()
deposits its data in a bufchain which term_out() empties the next
time it's called.

git-svn-id: svn://svn.tartarus.org/sgt/putty@1276 cda61777-01e9-0310-a592-d414129be87e

putty.h
scp.c
terminal.c
window.c

diff --git a/putty.h b/putty.h
index 90e10ff..7a70e37 100644 (file)
--- a/putty.h
+++ b/putty.h
@@ -93,15 +93,6 @@ typedef HDC Context;
 
 GLOBAL int rows, cols, savelines;
 
-#define INBUF_SIZE 2048
-GLOBAL unsigned char inbuf[INBUF_SIZE];
-GLOBAL int inbuf_head;
-
-#define OUTBUF_SIZE 2048
-#define OUTBUF_MASK (OUTBUF_SIZE-1)
-GLOBAL unsigned char outbuf[OUTBUF_SIZE];
-GLOBAL int outbuf_head, outbuf_reap;
-
 GLOBAL int has_focus;
 
 GLOBAL int in_vbell;
diff --git a/scp.c b/scp.c
index f4c8d79..2361d80 100644 (file)
--- a/scp.c
+++ b/scp.c
@@ -375,8 +375,6 @@ int from_backend(int is_stderr, char *data, int datalen)
        return 0;
     }
 
-    inbuf_head = 0;
-
     /*
      * If this is before the real session begins, just return.
      */
index 5245cdb..3b9d4e8 100644 (file)
@@ -86,6 +86,7 @@ typedef struct {
 #define incpos(p) ( (p).x == cols ? ((p).x = 0, (p).y++, 1) : ((p).x++, 0) )
 #define decpos(p) ( (p).x == 0 ? ((p).x = cols, (p).y--, 1) : ((p).x--, 0) )
 
+static bufchain inbuf;                /* terminal input buffer */
 static pos curs;                      /* cursor */
 static pos savecurs;                  /* saved cursor position */
 static int marg_t, marg_b;            /* scroll margins */
@@ -973,20 +974,38 @@ static void do_osc(void)
  */
 void term_out(void)
 {
-    int c, inbuf_reap;
+    int c, unget;
+    unsigned char localbuf[256], *chars;
+    int nchars = 0;
+
+    unget = -1;
+
+    while (nchars > 0 || bufchain_size(&inbuf) > 0) {
+       if (unget == -1) {
+           if (nchars == 0) {
+               void *ret;
+               bufchain_prefix(&inbuf, &ret, &nchars);
+               if (nchars > sizeof(localbuf))
+                   nchars = sizeof(localbuf);
+               memcpy(localbuf, ret, nchars);
+               bufchain_consume(&inbuf, nchars);
+               chars = localbuf;
+               assert(chars != NULL);
+           }
+           c = *chars++;
+           nchars--;
 
-    /*
-     * Optionally log the session traffic to a file. Useful for
-     * debugging and possibly also useful for actual logging.
-     */
-    if (cfg.logtype == LGTYP_DEBUG)
-       for (inbuf_reap = 0; inbuf_reap < inbuf_head; inbuf_reap++) {
-           logtraffic((unsigned char) inbuf[inbuf_reap], LGTYP_DEBUG);
+           /*
+            * Optionally log the session traffic to a file. Useful for
+            * debugging and possibly also useful for actual logging.
+            */
+           if (cfg.logtype == LGTYP_DEBUG)
+               logtraffic((unsigned char) &c, LGTYP_DEBUG);
+       } else {
+           c = unget;
+           unget = -1;
        }
 
-    for (inbuf_reap = 0; inbuf_reap < inbuf_head; inbuf_reap++) {
-       c = inbuf[inbuf_reap];
-
        /* Note only VT220+ are 8-bit VT102 is seven bit, it shouldn't even
         * be able to display 8-bit characters, but I'll let that go 'cause
         * of i18n.
@@ -1029,7 +1048,7 @@ void term_out(void)
                  case 4:
                  case 5:
                    if ((c & 0xC0) != 0x80) {
-                       inbuf_reap--;
+                       unget = c;
                        c = UCSERR;
                        utf_state = 0;
                        break;
@@ -2480,7 +2499,6 @@ void term_out(void)
            check_selection(curs, cursplus);
        }
     }
-    inbuf_head = 0;
 }
 
 #if 0
@@ -3358,18 +3376,15 @@ int term_ldisc(int option)
  */
 int from_backend(int is_stderr, char *data, int len)
 {
-    while (len--) {
-       if (inbuf_head >= INBUF_SIZE)
-           term_out();
-       inbuf[inbuf_head++] = *data++;
-    }
+    bufchain_add(&inbuf, data, len);
 
     /*
-     * We process all stdout/stderr data immediately we receive it,
-     * and don't return until it's all gone. Therefore, there's no
-     * reason at all to return anything other than zero from this
-     * function.
-     * 
+     * term_out() always completely empties inbuf. Therefore,
+     * there's no reason at all to return anything other than zero
+     * from this function, because there _can't_ be a question of
+     * the remote side needing to wait until term_out() has cleared
+     * a backlog.
+     *
      * This is a slightly suboptimal way to deal with SSH2 - in
      * principle, the window mechanism would allow us to continue
      * to accept data on forwarded ports and X connections even
@@ -3379,7 +3394,7 @@ int from_backend(int is_stderr, char *data, int len)
      * portability. So we manage stdout buffering the old SSH1 way:
      * if the terminal processing goes slowly, the whole SSH
      * connection stops accepting data until it's ready.
-     * 
+     *
      * In practice, I can't imagine this causing serious trouble.
      */
     return 0;
index cd5f703..3347260 100644 (file)
--- a/window.c
+++ b/window.c
@@ -526,12 +526,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
     session_closed = FALSE;
 
     /*
-     * Set up the input and output buffers.
-     */
-    inbuf_head = 0;
-    outbuf_reap = outbuf_head = 0;
-
-    /*
      * Prepare the mouse handler.
      */
     lastact = MA_NOTHING;
@@ -660,8 +654,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
                timer_id = 0;
            }
            HideCaret(hwnd);
-           if (inbuf_head)
-               term_out();
+           term_out();
            term_update();
            ShowCaret(hwnd);
 
@@ -1392,8 +1385,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
       case WM_TIMER:
        if (pending_netevent)
            enact_pending_netevent();
-       if (inbuf_head)
-           term_out();
+       term_out();
        noise_regular();
        HideCaret(hwnd);
        term_update();