X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/putty/blobdiff_plain/5f95fdf1635ee92d80711c264f3dd2fa27f7d5c1..d0370c96527b48387a0fb0fbf5ccc8b9d8cc6458:/telnet.c diff --git a/telnet.c b/telnet.c index 54b9a7c7..ed685f10 100644 --- a/telnet.c +++ b/telnet.c @@ -1,3 +1,7 @@ +/* + * Telnet backend. + */ + #include #include @@ -250,11 +254,10 @@ typedef struct telnet_tag { #define SB_DELTA 1024 -static void c_write1(Telnet telnet, int c) +static void c_write(Telnet telnet, char *buf, int len) { int backlog; - char cc = (char) c; - backlog = from_backend(telnet->frontend, 0, &cc, 1); + backlog = from_backend(telnet->frontend, 0, buf, len); sk_set_frozen(telnet->s, backlog > TELNET_MAX_BACKLOG); } @@ -394,9 +397,12 @@ static void proc_rec_opt(Telnet telnet, int cmd, int option) } /* * If we reach here, the option was one we weren't prepared to - * cope with. So send a negative ack. + * cope with. If the request was positive (WILL or DO), we send + * a negative ack to indicate refusal. If the request was + * negative (WONT / DONT), we must do nothing. */ - send_opt(telnet, (cmd == WILL ? DONT : WONT), option); + if (cmd == WILL || cmd == DO) + send_opt(telnet, (cmd == WILL ? DONT : WONT), option); } static void process_subneg(Telnet telnet) @@ -534,6 +540,16 @@ static void process_subneg(Telnet telnet) static void do_telnet_read(Telnet telnet, char *buf, int len) { + char *outbuf = NULL; + int outbuflen = 0, outbufsize = 0; + +#define ADDTOBUF(c) do { \ + if (outbuflen >= outbufsize) { \ + outbufsize = outbuflen + 256; \ + outbuf = sresize(outbuf, outbufsize, char); \ + } \ + outbuf[outbuflen++] = (c); \ +} while (0) while (len--) { int c = (unsigned char) *buf++; @@ -547,7 +563,7 @@ static void do_telnet_read(Telnet telnet, char *buf, int len) telnet->state = SEENIAC; else { if (!telnet->in_synch) - c_write1(telnet, c); + ADDTOBUF(c); #if 1 /* I can't get the F***ing winsock to insert the urgent IAC @@ -584,7 +600,7 @@ static void do_telnet_read(Telnet telnet, char *buf, int len) } else { /* ignore everything else; print it if it's IAC */ if (c == IAC) { - c_write1(telnet, c); + ADDTOBUF(c); } telnet->state = TOP_LEVEL; } @@ -634,6 +650,10 @@ static void do_telnet_read(Telnet telnet, char *buf, int len) break; } } + + if (outbuflen) + c_write(telnet, outbuf, outbuflen); + sfree(outbuf); } static void telnet_log(Plug plug, int type, SockAddr addr, int port, @@ -785,6 +805,25 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle, */ update_specials_menu(telnet->frontend); + /* + * loghost overrides realhost, if specified. + */ + if (*telnet->cfg.loghost) { + char *colon; + + sfree(*realhost); + *realhost = dupstr(telnet->cfg.loghost); + colon = strrchr(*realhost, ':'); + if (colon) { + /* + * FIXME: if we ever update this aspect of ssh.c for + * IPv6 literal management, this should change in line + * with it. + */ + *colon++ = '\0'; + } + } + return NULL; } @@ -1012,10 +1051,10 @@ static const struct telnet_special *telnet_get_specials(void *handle) return specials; } -static Socket telnet_socket(void *handle) +static int telnet_connected(void *handle) { Telnet telnet = (Telnet) handle; - return telnet->s; + return telnet->s != NULL; } static int telnet_sendok(void *handle) @@ -1078,7 +1117,7 @@ Backend telnet_backend = { telnet_size, telnet_special, telnet_get_specials, - telnet_socket, + telnet_connected, telnet_exitcode, telnet_sendok, telnet_ldisc, @@ -1086,5 +1125,7 @@ Backend telnet_backend = { telnet_provide_logctx, telnet_unthrottle, telnet_cfg_info, + "telnet", + PROT_TELNET, 23 };