X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/putty/blobdiff_plain/6196fb7ebed0b7e53b706faacfcc5fb13aa24738..e497389e51d4c6b50e01fb2e30af9c5a8caf9a65:/telnet.c diff --git a/telnet.c b/telnet.c index 4f0a36fe..dc98a727 100644 --- a/telnet.c +++ b/telnet.c @@ -201,7 +201,7 @@ typedef struct telnet_tag { SEENSB, SUBNEGOT, SUBNEG_IAC, SEENCR } state; - Config cfg; + Conf *conf; Pinger pinger; } *Telnet; @@ -363,42 +363,46 @@ static void proc_rec_opt(Telnet telnet, int cmd, int option) static void process_subneg(Telnet telnet) { - unsigned char b[2048], *p, *q; - int var, value, n; - char *e; + unsigned char *b, *p, *q; + int var, value, n, bsize; + char *e, *eval, *ekey, *user; switch (telnet->sb_opt) { case TELOPT_TSPEED: if (telnet->sb_len == 1 && telnet->sb_buf[0] == TELQUAL_SEND) { char *logbuf; + char *termspeed = conf_get_str(telnet->conf, CONF_termspeed); + b = snewn(20 + strlen(termspeed), unsigned char); b[0] = IAC; b[1] = SB; b[2] = TELOPT_TSPEED; b[3] = TELQUAL_IS; - strcpy((char *)(b + 4), telnet->cfg.termspeed); - n = 4 + strlen(telnet->cfg.termspeed); + strcpy((char *)(b + 4), termspeed); + n = 4 + strlen(termspeed); b[n] = IAC; b[n + 1] = SE; telnet->bufsize = sk_write(telnet->s, (char *)b, n + 2); logevent(telnet->frontend, "server:\tSB TSPEED SEND"); - logbuf = dupprintf("client:\tSB TSPEED IS %s", telnet->cfg.termspeed); + logbuf = dupprintf("client:\tSB TSPEED IS %s", termspeed); logevent(telnet->frontend, logbuf); sfree(logbuf); + sfree(b); } else logevent(telnet->frontend, "server:\tSB TSPEED "); break; case TELOPT_TTYPE: if (telnet->sb_len == 1 && telnet->sb_buf[0] == TELQUAL_SEND) { char *logbuf; + char *termtype = conf_get_str(telnet->conf, CONF_termtype); + b = snewn(20 + strlen(termtype), unsigned char); b[0] = IAC; b[1] = SB; b[2] = TELOPT_TTYPE; b[3] = TELQUAL_IS; - for (n = 0; telnet->cfg.termtype[n]; n++) - b[n + 4] = (telnet->cfg.termtype[n] >= 'a' - && telnet->cfg.termtype[n] <= - 'z' ? telnet->cfg.termtype[n] + 'A' - - 'a' : telnet->cfg.termtype[n]); + for (n = 0; termtype[n]; n++) + b[n + 4] = (termtype[n] >= 'a' && termtype[n] <= 'z' ? + termtype[n] + 'A' - 'a' : + termtype[n]); b[n + 4] = IAC; b[n + 5] = SE; telnet->bufsize = sk_write(telnet->s, (char *)b, n + 6); @@ -407,6 +411,7 @@ static void process_subneg(Telnet telnet) logbuf = dupprintf("client:\tSB TTYPE IS %s", b + 4); logevent(telnet->frontend, logbuf); sfree(logbuf); + sfree(b); } else logevent(telnet->frontend, "server:\tSB TTYPE \r\n"); break; @@ -421,7 +426,7 @@ static void process_subneg(Telnet telnet) logevent(telnet->frontend, logbuf); sfree(logbuf); if (telnet->sb_opt == TELOPT_OLD_ENVIRON) { - if (telnet->cfg.rfc_environ) { + if (conf_get_int(telnet->conf, CONF_rfc_environ)) { value = RFC_VALUE; var = RFC_VAR; } else { @@ -449,46 +454,75 @@ static void process_subneg(Telnet telnet) value = RFC_VALUE; var = RFC_VAR; } + bsize = 20; + for (eval = conf_get_str_strs(telnet->conf, CONF_environmt, + NULL, &ekey); + eval != NULL; + eval = conf_get_str_strs(telnet->conf, CONF_environmt, + ekey, &ekey)) + bsize += strlen(ekey) + strlen(eval) + 2; + user = get_remote_username(telnet->conf); + if (user) + bsize += 6 + strlen(user); + + b = snewn(bsize, unsigned char); b[0] = IAC; b[1] = SB; b[2] = telnet->sb_opt; b[3] = TELQUAL_IS; n = 4; - e = telnet->cfg.environmt; - while (*e) { + for (eval = conf_get_str_strs(telnet->conf, CONF_environmt, + NULL, &ekey); + eval != NULL; + eval = conf_get_str_strs(telnet->conf, CONF_environmt, + ekey, &ekey)) { b[n++] = var; - while (*e && *e != '\t') - b[n++] = *e++; - if (*e == '\t') - e++; + for (e = ekey; *e; e++) + b[n++] = *e; b[n++] = value; - while (*e) - b[n++] = *e++; - e++; + for (e = eval; *e; e++) + b[n++] = *e; } - if (*telnet->cfg.username) { + if (user) { b[n++] = var; b[n++] = 'U'; b[n++] = 'S'; b[n++] = 'E'; b[n++] = 'R'; b[n++] = value; - e = telnet->cfg.username; - while (*e) - b[n++] = *e++; + for (e = user; *e; e++) + b[n++] = *e; } b[n++] = IAC; b[n++] = SE; telnet->bufsize = sk_write(telnet->s, (char *)b, n); - logbuf = dupprintf("client:\tSB %s IS %s%s%s%s", - telopt(telnet->sb_opt), - *telnet->cfg.username ? "USER=" : "", - telnet->cfg.username, - *telnet->cfg.username ? " " : "", - n == 6 ? "" : - (*telnet->cfg.environmt ? "" : "")); - logevent(telnet->frontend, logbuf); - sfree(logbuf); + if (n == 6) { + logbuf = dupprintf("client:\tSB %s IS ", + telopt(telnet->sb_opt)); + logevent(telnet->frontend, logbuf); + sfree(logbuf); + } else { + logbuf = dupprintf("client:\tSB %s IS:", + telopt(telnet->sb_opt)); + logevent(telnet->frontend, logbuf); + sfree(logbuf); + for (eval = conf_get_str_strs(telnet->conf, CONF_environmt, + NULL, &ekey); + eval != NULL; + eval = conf_get_str_strs(telnet->conf, CONF_environmt, + ekey, &ekey)) { + logbuf = dupprintf("\t%s=%s", ekey, eval); + logevent(telnet->frontend, logbuf); + sfree(logbuf); + } + if (user) { + logbuf = dupprintf("\tUSER=%s", user); + logevent(telnet->frontend, logbuf); + sfree(logbuf); + } + } + sfree(b); + sfree(user); } break; } @@ -633,6 +667,12 @@ static int telnet_closing(Plug plug, const char *error_msg, int error_code, { Telnet telnet = (Telnet) plug; + /* + * We don't implement independent EOF in each direction for Telnet + * connections; as soon as we get word that the remote side has + * sent us EOF, we wind up the whole connection. + */ + if (telnet->s) { sk_close(telnet->s); telnet->s = NULL; @@ -670,9 +710,8 @@ static void telnet_sent(Plug plug, int bufsize) * freed by the caller. */ static const char *telnet_init(void *frontend_handle, void **backend_handle, - Config *cfg, - char *host, int port, char **realhost, - int nodelay, int keepalive) + Conf *conf, char *host, int port, + char **realhost, int nodelay, int keepalive) { static const struct plug_function_table fn_table = { telnet_log, @@ -683,10 +722,12 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle, SockAddr addr; const char *err; Telnet telnet; + char *loghost; + int addressfamily; telnet = snew(struct telnet_tag); telnet->fn = &fn_table; - telnet->cfg = *cfg; /* STRUCTURE COPY */ + telnet->conf = conf_copy(conf); telnet->s = NULL; telnet->echoing = TRUE; telnet->editing = TRUE; @@ -694,8 +735,8 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle, telnet->sb_buf = NULL; telnet->sb_size = 0; telnet->frontend = frontend_handle; - telnet->term_width = telnet->cfg.width; - telnet->term_height = telnet->cfg.height; + telnet->term_width = conf_get_int(telnet->conf, CONF_width); + telnet->term_height = conf_get_int(telnet->conf, CONF_height); telnet->state = TOP_LEVEL; telnet->ldisc = NULL; telnet->pinger = NULL; @@ -706,14 +747,15 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle, */ { char *buf; + addressfamily = conf_get_int(telnet->conf, CONF_addressfamily); buf = dupprintf("Looking up host \"%s\"%s", host, - (cfg->addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" : - (cfg->addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" : + (addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" : + (addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" : ""))); logevent(telnet->frontend, buf); sfree(buf); } - addr = name_lookup(host, port, realhost, &telnet->cfg, cfg->addressfamily); + addr = name_lookup(host, port, realhost, telnet->conf, addressfamily); if ((err = sk_addr_error(addr)) != NULL) { sk_addr_free(addr); return err; @@ -726,16 +768,16 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle, * Open socket. */ telnet->s = new_connection(addr, *realhost, port, 0, 1, - nodelay, keepalive, (Plug) telnet, &telnet->cfg); + nodelay, keepalive, (Plug) telnet, telnet->conf); if ((err = sk_socket_error(telnet->s)) != NULL) return err; - telnet->pinger = pinger_new(&telnet->cfg, &telnet_backend, telnet); + telnet->pinger = pinger_new(telnet->conf, &telnet_backend, telnet); /* * Initialise option states. */ - if (telnet->cfg.passive_telnet) { + if (conf_get_int(telnet->conf, CONF_passive_telnet)) { const struct Opt *const *o; for (o = opts; *o; o++) @@ -764,11 +806,12 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle, /* * loghost overrides realhost, if specified. */ - if (*telnet->cfg.loghost) { + loghost = conf_get_str(telnet->conf, CONF_loghost); + if (*loghost) { char *colon; sfree(*realhost); - *realhost = dupstr(telnet->cfg.loghost); + *realhost = dupstr(loghost); colon = strrchr(*realhost, ':'); if (colon) { /* @@ -792,6 +835,7 @@ static void telnet_free(void *handle) sk_close(telnet->s); if (telnet->pinger) pinger_free(telnet->pinger); + conf_free(telnet->conf); sfree(telnet); } /* @@ -799,11 +843,12 @@ static void telnet_free(void *handle) * necessary, in this backend: we just save the fresh config for * any subsequent negotiations. */ -static void telnet_reconfig(void *handle, Config *cfg) +static void telnet_reconfig(void *handle, Conf *conf) { Telnet telnet = (Telnet) handle; - pinger_reconfig(telnet->pinger, &telnet->cfg, cfg); - telnet->cfg = *cfg; /* STRUCTURE COPY */ + pinger_reconfig(telnet->pinger, telnet->conf, conf); + conf_free(telnet->conf); + telnet->conf = conf_copy(conf); } /*