aboutsummaryrefslogtreecommitdiff
path: root/tools/plink/telnet.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/plink/telnet.c')
-rw-r--r--tools/plink/telnet.c167
1 files changed, 104 insertions, 63 deletions
diff --git a/tools/plink/telnet.c b/tools/plink/telnet.c
index 8fbe88679..c024538b9 100644
--- a/tools/plink/telnet.c
+++ b/tools/plink/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 <something weird>");
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 <something weird>\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,50 +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;
}
- {
- char user[sizeof(telnet->cfg.username)];
- (void) get_remote_username(&telnet->cfg, user, sizeof(user));
- if (*user) {
- b[n++] = var;
- b[n++] = 'U';
- b[n++] = 'S';
- b[n++] = 'E';
- b[n++] = 'R';
- b[n++] = value;
- e = user;
- while (*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),
- *user ? "USER=" : "",
- user,
- *user ? " " : "",
- n == 6 ? "<nothing>" :
- (*telnet->cfg.environmt ? "<stuff>" : ""));
+ if (user) {
+ b[n++] = var;
+ b[n++] = 'U';
+ b[n++] = 'S';
+ b[n++] = 'E';
+ b[n++] = 'R';
+ b[n++] = value;
+ for (e = user; *e; e++)
+ b[n++] = *e;
+ }
+ b[n++] = IAC;
+ b[n++] = SE;
+ telnet->bufsize = sk_write(telnet->s, (char *)b, n);
+ if (n == 6) {
+ logbuf = dupprintf("client:\tSB %s IS <nothing>",
+ 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;
}
@@ -637,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;
@@ -674,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,
@@ -687,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;
@@ -698,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;
@@ -710,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;
@@ -730,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++)
@@ -768,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) {
/*
@@ -796,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);
}
/*
@@ -803,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);
}
/*