X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/8ce72d2c1c7651def2425be607ef623e6b0b9bd2..df96b74b1748ca51b21d41e69f7a52eed3f79810:/telnet.c diff --git a/telnet.c b/telnet.c index 399c1260..1cd4df47 100644 --- 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; } } } @@ -213,6 +216,11 @@ static void activate_option (struct Opt *o) { */ deactivate_option (o->option==TELOPT_NEW_ENVIRON ? &o_oenv : &o_nenv); } + if (o->option == TELOPT_ECHO) + { + cfg.ldisc_term = FALSE; + ldisc = &ldisc_simple; + } } static void refused_option (struct Opt *o) { @@ -221,6 +229,11 @@ static void refused_option (struct Opt *o) { send_opt (WILL, TELOPT_OLD_ENVIRON); o_oenv.state = REQUESTED; } + if (o->option == TELOPT_ECHO) + { + cfg.ldisc_term = TRUE; + ldisc = &ldisc_term; + } } static void proc_rec_opt (int cmd, int option) { @@ -411,9 +424,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; @@ -560,6 +575,15 @@ static char *telnet_init (HWND hwnd, char *host, int port, char **realhost) { /* * Initialise option states. */ + if( cfg.ldisc_term ) + { + struct Opt **o; + + for (o = opts; *o; o++) + if ((*o)->state == REQUESTED) + (*o)->state = INACTIVE; + } + else { struct Opt **o; @@ -651,19 +675,41 @@ static void telnet_send (char *buf, int len) { char *p; static unsigned char iac[2] = { IAC, IAC }; static unsigned char cr[2] = { CR, NUL }; + static unsigned char nl[2] = { CR, LF }; if (s == INVALID_SOCKET) return; p = buf; - while (p < buf+len) { + if (cfg.ldisc_term) { + while (p < buf+len) { + char *q = p; + unsigned char * cstr = 0; + while (p < buf+len) { + if ((unsigned char)*p == IAC) { + cstr = iac; + break; + } + if (*p == '\r') { + if( p+1 >= buf+len || ( p[1] != '\n' && p[1] != '\0')) + { + cstr = cr; + break; + } + } + p++; + } + if (p!=q) s_write (q, p-q); + if (cstr) s_write (cstr,2), p++; + } + } else while (p < buf+len) { char *q = p; while (iswritable((unsigned char)*p) && p < buf+len) p++; s_write (q, p-q); while (p < buf+len && !iswritable((unsigned char)*p)) { - s_write ((unsigned char)*p == IAC ? iac : cr, 2); + s_write ((unsigned char)*p == IAC ? iac : nl, 2); p++; } } @@ -714,8 +760,20 @@ static void telnet_special (Telnet_Special code) { case TS_EOF: b[1] = xEOF; s_write (b, 2); break; case TS_SYNCH: outbuf_head = outbuf_reap = 0; - b[0] = DM; - send (s, b, 1, MSG_OOB); + b[1] = DM; + send (s, b, 2, MSG_OOB); + break; + case TS_RECHO: + if (o_echo.state == INACTIVE || o_echo.state == REALLY_INACTIVE) { + o_echo.state = REQUESTED; + send_opt (o_echo.send, o_echo.option); + } + break; + case TS_LECHO: + if (o_echo.state == ACTIVE) { + o_echo.state = REQUESTED; + send_opt (o_echo.nsend, o_echo.option); + } break; } }