int bufsize;
int in_synch;
int sb_opt, sb_len;
- char *sb_buf;
+ unsigned char *sb_buf;
int sb_size;
enum {
SEENSB, SUBNEGOT, SUBNEG_IAC, SEENCR
} state;
+ Config cfg;
} *Telnet;
#define TELNET_MAX_BACKLOG 4096
b[0] = IAC;
b[1] = cmd;
b[2] = option;
- telnet->bufsize = sk_write(telnet->s, b, 3);
+ telnet->bufsize = sk_write(telnet->s, (char *)b, 3);
log_option(telnet, "client", cmd, option);
}
b[1] = SB;
b[2] = TELOPT_TSPEED;
b[3] = TELQUAL_IS;
- strcpy(b + 4, cfg.termspeed);
- n = 4 + strlen(cfg.termspeed);
+ strcpy((char *)(b + 4), telnet->cfg.termspeed);
+ n = 4 + strlen(telnet->cfg.termspeed);
b[n] = IAC;
b[n + 1] = SE;
- telnet->bufsize = sk_write(telnet->s, b, n + 2);
+ telnet->bufsize = sk_write(telnet->s, (char *)b, n + 2);
logevent(telnet->frontend, "server:\tSB TSPEED SEND");
- logbuf = dupprintf("client:\tSB TSPEED IS %s", cfg.termspeed);
+ logbuf = dupprintf("client:\tSB TSPEED IS %s", telnet->cfg.termspeed);
logevent(telnet->frontend, logbuf);
sfree(logbuf);
} else
b[1] = SB;
b[2] = TELOPT_TTYPE;
b[3] = TELQUAL_IS;
- for (n = 0; cfg.termtype[n]; n++)
- b[n + 4] = (cfg.termtype[n] >= 'a'
- && cfg.termtype[n] <=
- 'z' ? cfg.termtype[n] + 'A' -
- 'a' : cfg.termtype[n]);
+ 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]);
b[n + 4] = IAC;
b[n + 5] = SE;
- telnet->bufsize = sk_write(telnet->s, b, n + 6);
+ telnet->bufsize = sk_write(telnet->s, (char *)b, n + 6);
b[n + 4] = 0;
logevent(telnet->frontend, "server:\tSB TTYPE SEND");
logbuf = dupprintf("client:\tSB TTYPE IS %s", b + 4);
logevent(telnet->frontend, logbuf);
sfree(logbuf);
if (telnet->sb_opt == TELOPT_OLD_ENVIRON) {
- if (cfg.rfc_environ) {
+ if (telnet->cfg.rfc_environ) {
value = RFC_VALUE;
var = RFC_VAR;
} else {
b[2] = telnet->sb_opt;
b[3] = TELQUAL_IS;
n = 4;
- e = cfg.environmt;
+ e = telnet->cfg.environmt;
while (*e) {
b[n++] = var;
while (*e && *e != '\t')
b[n++] = *e++;
e++;
}
- if (*cfg.username) {
+ if (*telnet->cfg.username) {
b[n++] = var;
b[n++] = 'U';
b[n++] = 'S';
b[n++] = 'E';
b[n++] = 'R';
b[n++] = value;
- e = cfg.username;
+ e = telnet->cfg.username;
while (*e)
b[n++] = *e++;
}
b[n++] = IAC;
b[n++] = SE;
- telnet->bufsize = sk_write(telnet->s, b, n);
+ telnet->bufsize = sk_write(telnet->s, (char *)b, n);
logbuf = dupprintf("client:\tSB %s IS %s", telopt(telnet->sb_opt),
n == 6 ? "<nothing>" : "<stuff>");
logevent(telnet->frontend, logbuf);
else {
subneg_addchar:
if (telnet->sb_len >= telnet->sb_size) {
- char *newbuf;
+ unsigned char *newbuf;
telnet->sb_size += SB_DELTA;
newbuf = (telnet->sb_buf ?
srealloc(telnet->sb_buf, telnet->sb_size) :
* freed by the caller.
*/
static char *telnet_init(void *frontend_handle, void **backend_handle,
+ Config *cfg,
char *host, int port, char **realhost, int nodelay)
{
static const struct plug_function_table fn_table = {
telnet = smalloc(sizeof(*telnet));
telnet->fn = &fn_table;
+ telnet->cfg = *cfg; /* STRUCTURE COPY */
telnet->s = NULL;
telnet->echoing = TRUE;
telnet->editing = TRUE;
telnet->sb_buf = NULL;
telnet->sb_size = 0;
telnet->frontend = frontend_handle;
- telnet->term_width = cfg.width;
- telnet->term_height = cfg.height;
+ telnet->term_width = telnet->cfg.width;
+ telnet->term_height = telnet->cfg.height;
telnet->state = TOP_LEVEL;
*backend_handle = telnet;
logevent(telnet->frontend, buf);
sfree(buf);
}
- addr = name_lookup(host, port, realhost);
- if ((err = sk_addr_error(addr)))
+ addr = name_lookup(host, port, realhost, &telnet->cfg);
+ if ((err = sk_addr_error(addr)) != NULL)
return err;
if (port < 0)
sfree(buf);
}
telnet->s = new_connection(addr, *realhost, port, 0, 1,
- nodelay, (Plug) telnet);
- if ((err = sk_socket_error(telnet->s)))
+ nodelay, (Plug) telnet, &telnet->cfg);
+ if ((err = sk_socket_error(telnet->s)) != NULL)
return err;
sk_addr_free(addr);
/*
* Initialise option states.
*/
- if (cfg.passive_telnet) {
+ if (telnet->cfg.passive_telnet) {
const struct Opt *const *o;
for (o = opts; *o; o++)
return NULL;
}
+static void telnet_free(void *handle)
+{
+ Telnet telnet = (Telnet) handle;
+
+ sfree(telnet->sb_buf);
+ if (telnet->s)
+ sk_close(telnet->s);
+ sfree(telnet);
+}
+/*
+ * Reconfigure the Telnet backend. There's no immediate action
+ * necessary, in this backend: we just save the fresh config for
+ * any subsequent negotiations.
+ */
+static void telnet_reconfig(void *handle, Config *cfg)
+{
+ Telnet telnet = (Telnet) handle;
+ telnet->cfg = *cfg; /* STRUCTURE COPY */
+}
+
/*
* Called to send data down the Telnet connection.
*/
static int telnet_send(void *handle, char *buf, int len)
{
Telnet telnet = (Telnet) handle;
- char *p;
- static unsigned char iac[2] = { IAC, IAC };
- static unsigned char cr[2] = { CR, NUL };
+ unsigned char *p, *end;
+ static const unsigned char iac[2] = { IAC, IAC };
+ static const unsigned char cr[2] = { CR, NUL };
#if 0
- static unsigned char nl[2] = { CR, LF };
+ static const unsigned char nl[2] = { CR, LF };
#endif
if (telnet->s == NULL)
return 0;
- p = buf;
- while (p < buf + len) {
- char *q = p;
+ p = (unsigned char *)buf;
+ end = (unsigned char *)(buf + len);
+ while (p < end) {
+ unsigned char *q = p;
- while (p < buf + len && iswritable((unsigned char) *p))
+ while (p < end && iswritable(*p))
p++;
- telnet->bufsize = sk_write(telnet->s, q, p - q);
+ telnet->bufsize = sk_write(telnet->s, (char *)q, p - q);
- while (p < buf + len && !iswritable((unsigned char) *p)) {
+ while (p < end && !iswritable(*p)) {
telnet->bufsize =
- sk_write(telnet->s, (unsigned char) *p == IAC ? iac : cr, 2);
+ sk_write(telnet->s, (char *)(*p == IAC ? iac : cr), 2);
p++;
}
}
if (b[n-1] == IAC) b[n++] = IAC; /* duplicate any IAC byte occurs */
b[n++] = IAC;
b[n++] = SE;
- telnet->bufsize = sk_write(telnet->s, b, n);
+ telnet->bufsize = sk_write(telnet->s, (char *)b, n);
logbuf = dupprintf("client:\tSB NAWS %d,%d",
telnet->term_width, telnet->term_height);
logevent(telnet->frontend, logbuf);
switch (code) {
case TS_AYT:
b[1] = AYT;
- telnet->bufsize = sk_write(telnet->s, b, 2);
+ telnet->bufsize = sk_write(telnet->s, (char *)b, 2);
break;
case TS_BRK:
b[1] = BREAK;
- telnet->bufsize = sk_write(telnet->s, b, 2);
+ telnet->bufsize = sk_write(telnet->s, (char *)b, 2);
break;
case TS_EC:
b[1] = EC;
- telnet->bufsize = sk_write(telnet->s, b, 2);
+ telnet->bufsize = sk_write(telnet->s, (char *)b, 2);
break;
case TS_EL:
b[1] = EL;
- telnet->bufsize = sk_write(telnet->s, b, 2);
+ telnet->bufsize = sk_write(telnet->s, (char *)b, 2);
break;
case TS_GA:
b[1] = GA;
- telnet->bufsize = sk_write(telnet->s, b, 2);
+ telnet->bufsize = sk_write(telnet->s, (char *)b, 2);
break;
case TS_NOP:
b[1] = NOP;
- telnet->bufsize = sk_write(telnet->s, b, 2);
+ telnet->bufsize = sk_write(telnet->s, (char *)b, 2);
break;
case TS_ABORT:
b[1] = ABORT;
- telnet->bufsize = sk_write(telnet->s, b, 2);
+ telnet->bufsize = sk_write(telnet->s, (char *)b, 2);
break;
case TS_AO:
b[1] = AO;
- telnet->bufsize = sk_write(telnet->s, b, 2);
+ telnet->bufsize = sk_write(telnet->s, (char *)b, 2);
break;
case TS_IP:
b[1] = IP;
- telnet->bufsize = sk_write(telnet->s, b, 2);
+ telnet->bufsize = sk_write(telnet->s, (char *)b, 2);
break;
case TS_SUSP:
b[1] = SUSP;
- telnet->bufsize = sk_write(telnet->s, b, 2);
+ telnet->bufsize = sk_write(telnet->s, (char *)b, 2);
break;
case TS_EOR:
b[1] = EOR;
- telnet->bufsize = sk_write(telnet->s, b, 2);
+ telnet->bufsize = sk_write(telnet->s, (char *)b, 2);
break;
case TS_EOF:
b[1] = xEOF;
- telnet->bufsize = sk_write(telnet->s, b, 2);
+ telnet->bufsize = sk_write(telnet->s, (char *)b, 2);
break;
case TS_EOL:
/* In BINARY mode, CR-LF becomes just CR. */
break;
case TS_SYNCH:
b[1] = DM;
- telnet->bufsize = sk_write(telnet->s, b, 1);
- telnet->bufsize = sk_write_oob(telnet->s, b + 1, 1);
+ telnet->bufsize = sk_write(telnet->s, (char *)b, 1);
+ telnet->bufsize = sk_write_oob(telnet->s, (char *)(b + 1), 1);
break;
case TS_RECHO:
if (telnet->opt_states[o_echo.index] == INACTIVE ||
case TS_PING:
if (telnet->opt_states[o_they_sga.index] == ACTIVE) {
b[1] = NOP;
- telnet->bufsize = sk_write(telnet->s, b, 2);
+ telnet->bufsize = sk_write(telnet->s, (char *)b, 2);
}
break;
}
Backend telnet_backend = {
telnet_init,
+ telnet_free,
+ telnet_reconfig,
telnet_send,
telnet_sendbuffer,
telnet_size,