1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-25 01:02:24 +00:00

Turn Backend into a sensible classoid.

Nearly every part of the code that ever handles a full backend
structure has historically done it using a pair of pointer variables,
one pointing at a constant struct full of function pointers, and the
other pointing to a 'void *' state object that's passed to each of
those.

While I'm modernising the rest of the code, this seems like a good
time to turn that into the same more or less type-safe and less
cumbersome system as I'm using for other parts of the code, such as
Socket, Plug, BinaryPacketProtocol and so forth: the Backend structure
contains a vtable pointer, and a system of macro wrappers handles
dispatching through that vtable.
This commit is contained in:
Simon Tatham 2018-09-11 16:23:38 +01:00
parent c51fe7c217
commit eefebaaa9e
36 changed files with 633 additions and 611 deletions

View File

@ -22,7 +22,7 @@ const int be_default_protocol = PROT_TELNET;
const int be_default_protocol = PROT_SSH; const int be_default_protocol = PROT_SSH;
#endif #endif
Backend *backends[] = { const struct Backend_vtable *const backends[] = {
&ssh_backend, &ssh_backend,
&telnet_backend, &telnet_backend,
&rlogin_backend, &rlogin_backend,

View File

@ -22,7 +22,7 @@ const int be_default_protocol = PROT_TELNET;
const int be_default_protocol = PROT_SSH; const int be_default_protocol = PROT_SSH;
#endif #endif
Backend *backends[] = { const struct Backend_vtable *const backends[] = {
&ssh_backend, &ssh_backend,
&telnet_backend, &telnet_backend,
&rlogin_backend, &rlogin_backend,

View File

@ -6,6 +6,6 @@
#include <stdio.h> #include <stdio.h>
#include "putty.h" #include "putty.h"
Backend *backends[] = { const struct Backend_vtable *const backends[] = {
NULL NULL
}; };

View File

@ -10,7 +10,7 @@ const int be_default_protocol = PROT_TELNET;
const char *const appname = "PuTTYtel"; const char *const appname = "PuTTYtel";
Backend *backends[] = { const struct Backend_vtable *const backends[] = {
&telnet_backend, &telnet_backend,
&rlogin_backend, &rlogin_backend,
&raw_backend, &raw_backend,

View File

@ -10,7 +10,7 @@ const int be_default_protocol = PROT_TELNET;
const char *const appname = "PuTTYtel"; const char *const appname = "PuTTYtel";
Backend *backends[] = { const struct Backend_vtable *const backends[] = {
&telnet_backend, &telnet_backend,
&rlogin_backend, &rlogin_backend,
&raw_backend, &raw_backend,

View File

@ -10,7 +10,7 @@
const int be_default_protocol = PROT_SSH; const int be_default_protocol = PROT_SSH;
Backend *backends[] = { const struct Backend_vtable *const backends[] = {
&ssh_backend, &ssh_backend,
NULL NULL
}; };

View File

@ -275,13 +275,14 @@ int cmdline_process_param(const char *p, char *value,
const char *comma = strchr(p, ','); const char *comma = strchr(p, ',');
if (comma) { if (comma) {
char *prefix = dupprintf("%.*s", (int)(comma - p), p); char *prefix = dupprintf("%.*s", (int)(comma - p), p);
const Backend *b = backend_from_name(prefix); const struct Backend_vtable *vt =
backend_vt_from_name(prefix);
if (b) { if (vt) {
default_protocol = b->protocol; default_protocol = vt->protocol;
conf_set_int(conf, CONF_protocol, conf_set_int(conf, CONF_protocol,
default_protocol); default_protocol);
port_override = b->default_port; port_override = vt->default_port;
} else { } else {
cmdline_error("unrecognised protocol prefix '%s'", cmdline_error("unrecognised protocol prefix '%s'",
prefix); prefix);

View File

@ -267,10 +267,10 @@ void config_protocolbuttons_handler(union control *ctrl, void *dlg,
conf_set_int(conf, CONF_protocol, newproto); conf_set_int(conf, CONF_protocol, newproto);
if (oldproto != newproto) { if (oldproto != newproto) {
Backend *ob = backend_from_proto(oldproto); const struct Backend_vtable *ovt = backend_vt_from_proto(oldproto);
Backend *nb = backend_from_proto(newproto); const struct Backend_vtable *nvt = backend_vt_from_proto(newproto);
assert(ob); assert(ovt);
assert(nb); assert(nvt);
/* Iff the user hasn't changed the port from the old protocol's /* Iff the user hasn't changed the port from the old protocol's
* default, update it with the new protocol's default. * default, update it with the new protocol's default.
* (This includes a "default" of 0, implying that there is no * (This includes a "default" of 0, implying that there is no
@ -281,8 +281,8 @@ void config_protocolbuttons_handler(union control *ctrl, void *dlg,
* getting to the protocol; we want that non-default port * getting to the protocol; we want that non-default port
* to be preserved. */ * to be preserved. */
port = conf_get_int(conf, CONF_port); port = conf_get_int(conf, CONF_port);
if (port == ob->default_port) if (port == ovt->default_port)
conf_set_int(conf, CONF_port, nb->default_port); conf_set_int(conf, CONF_port, nvt->default_port);
} }
dlg_refresh(hp->host, dlg); dlg_refresh(hp->host, dlg);
dlg_refresh(hp->port, dlg); dlg_refresh(hp->port, dlg);
@ -1503,7 +1503,7 @@ void setup_config_box(struct controlbox *b, int midsession,
hp->port = c; hp->port = c;
ctrl_columns(s, 1, 100); ctrl_columns(s, 1, 100);
if (!backend_from_proto(PROT_SSH)) { if (!backend_vt_from_proto(PROT_SSH)) {
ctrl_radiobuttons(s, "Connection type:", NO_SHORTCUT, 3, ctrl_radiobuttons(s, "Connection type:", NO_SHORTCUT, 3,
HELPCTX(session_hostname), HELPCTX(session_hostname),
config_protocolbuttons_handler, P(hp), config_protocolbuttons_handler, P(hp),
@ -1594,7 +1594,7 @@ void setup_config_box(struct controlbox *b, int midsession,
{ {
const char *sshlogname, *sshrawlogname; const char *sshlogname, *sshrawlogname;
if ((midsession && protocol == PROT_SSH) || if ((midsession && protocol == PROT_SSH) ||
(!midsession && backend_from_proto(PROT_SSH))) { (!midsession && backend_vt_from_proto(PROT_SSH))) {
sshlogname = "SSH packets"; sshlogname = "SSH packets";
sshrawlogname = "SSH packets and raw data"; sshrawlogname = "SSH packets and raw data";
} else { } else {
@ -1630,7 +1630,7 @@ void setup_config_box(struct controlbox *b, int midsession,
conf_checkbox_handler, I(CONF_logflush)); conf_checkbox_handler, I(CONF_logflush));
if ((midsession && protocol == PROT_SSH) || if ((midsession && protocol == PROT_SSH) ||
(!midsession && backend_from_proto(PROT_SSH))) { (!midsession && backend_vt_from_proto(PROT_SSH))) {
s = ctrl_getset(b, "Session/Logging", "ssh", s = ctrl_getset(b, "Session/Logging", "ssh",
"Options specific to SSH packet logging"); "Options specific to SSH packet logging");
ctrl_checkbox(s, "Omit known password fields", 'k', ctrl_checkbox(s, "Omit known password fields", 'k',
@ -2107,7 +2107,7 @@ void setup_config_box(struct controlbox *b, int midsession,
#endif #endif
{ {
const char *label = backend_from_proto(PROT_SSH) ? const char *label = backend_vt_from_proto(PROT_SSH) ?
"Logical name of remote host (e.g. for SSH key lookup):" : "Logical name of remote host (e.g. for SSH key lookup):" :
"Logical name of remote host:"; "Logical name of remote host:";
s = ctrl_getset(b, "Connection", "identity", s = ctrl_getset(b, "Connection", "identity",
@ -2319,7 +2319,8 @@ void setup_config_box(struct controlbox *b, int midsession,
* when we're not doing SSH. * when we're not doing SSH.
*/ */
if (backend_from_proto(PROT_SSH) && (!midsession || protocol == PROT_SSH)) { if (backend_vt_from_proto(PROT_SSH) &&
(!midsession || protocol == PROT_SSH)) {
/* /*
* The Connection/SSH panel. * The Connection/SSH panel.

5
defs.h
View File

@ -21,7 +21,6 @@
#endif #endif
typedef struct conf_tag Conf; typedef struct conf_tag Conf;
typedef struct backend_tag Backend;
typedef struct terminal_tag Terminal; typedef struct terminal_tag Terminal;
typedef struct Filename Filename; typedef struct Filename Filename;
@ -44,10 +43,14 @@ typedef struct SockAddr_tag *SockAddr;
typedef struct Socket_vtable Socket_vtable; typedef struct Socket_vtable Socket_vtable;
typedef struct Plug_vtable Plug_vtable; typedef struct Plug_vtable Plug_vtable;
typedef struct Backend Backend;
typedef struct Backend_vtable Backend_vtable;
typedef struct Ldisc_tag Ldisc; typedef struct Ldisc_tag Ldisc;
typedef struct LogContext_tag LogContext; typedef struct LogContext_tag LogContext;
typedef struct ssh_tag *Ssh; typedef struct ssh_tag *Ssh;
/* Note indirection: for historical reasons (it used to be closer to /* Note indirection: for historical reasons (it used to be closer to
* the OS socket type), the type that most code uses for a socket is * the OS socket type), the type that most code uses for a socket is
* 'Socket', not 'Socket *'. So an implementation of Socket or Plug * 'Socket', not 'Socket *'. So an implementation of Socket or Plug

55
ldisc.c
View File

@ -15,11 +15,11 @@
#define ECHOING (ldisc->localecho == FORCE_ON || \ #define ECHOING (ldisc->localecho == FORCE_ON || \
(ldisc->localecho == AUTO && \ (ldisc->localecho == AUTO && \
(ldisc->back->ldisc(ldisc->backhandle, LD_ECHO) || \ (backend_ldisc_option_state(ldisc->backend, LD_ECHO) || \
term_ldisc(ldisc->term, LD_ECHO)))) term_ldisc(ldisc->term, LD_ECHO))))
#define EDITING (ldisc->localedit == FORCE_ON || \ #define EDITING (ldisc->localedit == FORCE_ON || \
(ldisc->localedit == AUTO && \ (ldisc->localedit == AUTO && \
(ldisc->back->ldisc(ldisc->backhandle, LD_EDIT) || \ (backend_ldisc_option_state(ldisc->backend, LD_EDIT) || \
term_ldisc(ldisc->term, LD_EDIT)))) term_ldisc(ldisc->term, LD_EDIT))))
static void c_write(Ldisc *ldisc, const void *buf, int len) static void c_write(Ldisc *ldisc, const void *buf, int len)
@ -78,8 +78,7 @@ static void bsb(Ldisc *ldisc, int n)
#define KCTRL(x) ((x^'@') | 0x100) #define KCTRL(x) ((x^'@') | 0x100)
Ldisc *ldisc_create(Conf *conf, Terminal *term, Ldisc *ldisc_create(Conf *conf, Terminal *term,
Backend *back, void *backhandle, Backend *backend, void *frontend)
void *frontend)
{ {
Ldisc *ldisc = snew(Ldisc); Ldisc *ldisc = snew(Ldisc);
@ -88,8 +87,7 @@ Ldisc *ldisc_create(Conf *conf, Terminal *term,
ldisc->bufsiz = 0; ldisc->bufsiz = 0;
ldisc->quotenext = 0; ldisc->quotenext = 0;
ldisc->back = back; ldisc->backend = backend;
ldisc->backhandle = backhandle;
ldisc->term = term; ldisc->term = term;
ldisc->frontend = frontend; ldisc->frontend = frontend;
@ -98,8 +96,8 @@ Ldisc *ldisc_create(Conf *conf, Terminal *term,
/* Link ourselves into the backend and the terminal */ /* Link ourselves into the backend and the terminal */
if (term) if (term)
term->ldisc = ldisc; term->ldisc = ldisc;
if (back) if (backend)
back->provide_ldisc(backhandle, ldisc); backend_provide_ldisc(backend, ldisc);
return ldisc; return ldisc;
} }
@ -117,8 +115,8 @@ void ldisc_free(Ldisc *ldisc)
{ {
if (ldisc->term) if (ldisc->term)
ldisc->term->ldisc = NULL; ldisc->term->ldisc = NULL;
if (ldisc->back) if (ldisc->backend)
ldisc->back->provide_ldisc(ldisc->backhandle, NULL); backend_provide_ldisc(ldisc->backend, NULL);
if (ldisc->buf) if (ldisc->buf)
sfree(ldisc->buf); sfree(ldisc->buf);
sfree(ldisc); sfree(ldisc);
@ -219,7 +217,7 @@ void ldisc_send(Ldisc *ldisc, const void *vbuf, int len, int interactive)
bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1])); bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1]));
ldisc->buflen--; ldisc->buflen--;
} }
ldisc->back->special(ldisc->backhandle, TS_EL); backend_special(ldisc->backend, TS_EL);
/* /*
* We don't send IP, SUSP or ABORT if the user has * We don't send IP, SUSP or ABORT if the user has
* configured telnet specials off! This breaks * configured telnet specials off! This breaks
@ -228,11 +226,11 @@ void ldisc_send(Ldisc *ldisc, const void *vbuf, int len, int interactive)
if (!ldisc->telnet_keyboard) if (!ldisc->telnet_keyboard)
goto default_case; goto default_case;
if (c == CTRL('C')) if (c == CTRL('C'))
ldisc->back->special(ldisc->backhandle, TS_IP); backend_special(ldisc->backend, TS_IP);
if (c == CTRL('Z')) if (c == CTRL('Z'))
ldisc->back->special(ldisc->backhandle, TS_SUSP); backend_special(ldisc->backend, TS_SUSP);
if (c == CTRL('\\')) if (c == CTRL('\\'))
ldisc->back->special(ldisc->backhandle, TS_ABORT); backend_special(ldisc->backend, TS_ABORT);
break; break;
case CTRL('R'): /* redraw line */ case CTRL('R'): /* redraw line */
if (ECHOING) { if (ECHOING) {
@ -247,9 +245,9 @@ void ldisc_send(Ldisc *ldisc, const void *vbuf, int len, int interactive)
break; break;
case CTRL('D'): /* logout or send */ case CTRL('D'): /* logout or send */
if (ldisc->buflen == 0) { if (ldisc->buflen == 0) {
ldisc->back->special(ldisc->backhandle, TS_EOF); backend_special(ldisc->backend, TS_EOF);
} else { } else {
ldisc->back->send(ldisc->backhandle, ldisc->buf, ldisc->buflen); backend_send(ldisc->backend, ldisc->buf, ldisc->buflen);
ldisc->buflen = 0; ldisc->buflen = 0;
} }
break; break;
@ -285,13 +283,14 @@ void ldisc_send(Ldisc *ldisc, const void *vbuf, int len, int interactive)
/* FALLTHROUGH */ /* FALLTHROUGH */
case KCTRL('M'): /* send with newline */ case KCTRL('M'): /* send with newline */
if (ldisc->buflen > 0) if (ldisc->buflen > 0)
ldisc->back->send(ldisc->backhandle, ldisc->buf, ldisc->buflen); backend_send(ldisc->backend,
ldisc->buf, ldisc->buflen);
if (ldisc->protocol == PROT_RAW) if (ldisc->protocol == PROT_RAW)
ldisc->back->send(ldisc->backhandle, "\r\n", 2); backend_send(ldisc->backend, "\r\n", 2);
else if (ldisc->protocol == PROT_TELNET && ldisc->telnet_newline) else if (ldisc->protocol == PROT_TELNET && ldisc->telnet_newline)
ldisc->back->special(ldisc->backhandle, TS_EOL); backend_special(ldisc->backend, TS_EOL);
else else
ldisc->back->send(ldisc->backhandle, "\r", 1); backend_send(ldisc->backend, "\r", 1);
if (ECHOING) if (ECHOING)
c_write(ldisc, "\r\n", 2); c_write(ldisc, "\r\n", 2);
ldisc->buflen = 0; ldisc->buflen = 0;
@ -313,7 +312,7 @@ void ldisc_send(Ldisc *ldisc, const void *vbuf, int len, int interactive)
} }
} else { } else {
if (ldisc->buflen != 0) { if (ldisc->buflen != 0) {
ldisc->back->send(ldisc->backhandle, ldisc->buf, ldisc->buflen); backend_send(ldisc->backend, ldisc->buf, ldisc->buflen);
while (ldisc->buflen > 0) { while (ldisc->buflen > 0) {
bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1])); bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1]));
ldisc->buflen--; ldisc->buflen--;
@ -326,33 +325,33 @@ void ldisc_send(Ldisc *ldisc, const void *vbuf, int len, int interactive)
switch (buf[0]) { switch (buf[0]) {
case CTRL('M'): case CTRL('M'):
if (ldisc->protocol == PROT_TELNET && ldisc->telnet_newline) if (ldisc->protocol == PROT_TELNET && ldisc->telnet_newline)
ldisc->back->special(ldisc->backhandle, TS_EOL); backend_special(ldisc->backend, TS_EOL);
else else
ldisc->back->send(ldisc->backhandle, "\r", 1); backend_send(ldisc->backend, "\r", 1);
break; break;
case CTRL('?'): case CTRL('?'):
case CTRL('H'): case CTRL('H'):
if (ldisc->telnet_keyboard) { if (ldisc->telnet_keyboard) {
ldisc->back->special(ldisc->backhandle, TS_EC); backend_special(ldisc->backend, TS_EC);
break; break;
} }
case CTRL('C'): case CTRL('C'):
if (ldisc->telnet_keyboard) { if (ldisc->telnet_keyboard) {
ldisc->back->special(ldisc->backhandle, TS_IP); backend_special(ldisc->backend, TS_IP);
break; break;
} }
case CTRL('Z'): case CTRL('Z'):
if (ldisc->telnet_keyboard) { if (ldisc->telnet_keyboard) {
ldisc->back->special(ldisc->backhandle, TS_SUSP); backend_special(ldisc->backend, TS_SUSP);
break; break;
} }
default: default:
ldisc->back->send(ldisc->backhandle, buf, len); backend_send(ldisc->backend, buf, len);
break; break;
} }
} else } else
ldisc->back->send(ldisc->backhandle, buf, len); backend_send(ldisc->backend, buf, len);
} }
} }
} }

View File

@ -10,8 +10,7 @@
struct Ldisc_tag { struct Ldisc_tag {
Terminal *term; Terminal *term;
Backend *back; Backend *backend;
void *backhandle;
void *frontend; void *frontend;
/* /*

View File

@ -9,8 +9,7 @@ struct pinger_tag {
int interval; int interval;
int pending; int pending;
unsigned long when_set, next; unsigned long when_set, next;
Backend *back; Backend *backend;
void *backhandle;
}; };
static void pinger_schedule(Pinger pinger); static void pinger_schedule(Pinger pinger);
@ -20,7 +19,7 @@ static void pinger_timer(void *ctx, unsigned long now)
Pinger pinger = (Pinger)ctx; Pinger pinger = (Pinger)ctx;
if (pinger->pending && now == pinger->next) { if (pinger->pending && now == pinger->next) {
pinger->back->special(pinger->backhandle, TS_PING); backend_special(pinger->backend, TS_PING);
pinger->pending = FALSE; pinger->pending = FALSE;
pinger_schedule(pinger); pinger_schedule(pinger);
} }
@ -45,14 +44,13 @@ static void pinger_schedule(Pinger pinger)
} }
} }
Pinger pinger_new(Conf *conf, Backend *back, void *backhandle) Pinger pinger_new(Conf *conf, Backend *backend)
{ {
Pinger pinger = snew(struct pinger_tag); Pinger pinger = snew(struct pinger_tag);
pinger->interval = conf_get_int(conf, CONF_ping_interval); pinger->interval = conf_get_int(conf, CONF_ping_interval);
pinger->pending = FALSE; pinger->pending = FALSE;
pinger->back = back; pinger->backend = backend;
pinger->backhandle = backhandle;
pinger_schedule(pinger); pinger_schedule(pinger);
return pinger; return pinger;

80
pscp.c
View File

@ -43,8 +43,7 @@ static int fallback_cmd_is_sftp = 0;
static int using_sftp = 0; static int using_sftp = 0;
static int uploading = 0; static int uploading = 0;
static Backend *back; static Backend *backend;
static void *backhandle;
static Conf *conf; static Conf *conf;
int sent_eof = FALSE; int sent_eof = FALSE;
@ -247,7 +246,7 @@ static int ssh_scp_recv(void *buf, int len)
} }
while (outlen > 0) { while (outlen > 0) {
if (back->exitcode(backhandle) >= 0 || ssh_sftp_loop_iteration() < 0) if (backend_exitcode(backend) >= 0 || ssh_sftp_loop_iteration() < 0)
return 0; /* doom */ return 0; /* doom */
} }
@ -259,8 +258,8 @@ static int ssh_scp_recv(void *buf, int len)
*/ */
static void ssh_scp_init(void) static void ssh_scp_init(void)
{ {
while (!back->sendok(backhandle)) { while (!backend_sendok(backend)) {
if (back->exitcode(backhandle) >= 0) { if (backend_exitcode(backend) >= 0) {
errs++; errs++;
return; return;
} }
@ -271,7 +270,7 @@ static void ssh_scp_init(void)
} }
/* Work out which backend we ended up using. */ /* Work out which backend we ended up using. */
if (!ssh_fallback_cmd(backhandle)) if (!ssh_fallback_cmd(backend))
using_sftp = main_cmd_is_sftp; using_sftp = main_cmd_is_sftp;
else else
using_sftp = fallback_cmd_is_sftp; using_sftp = fallback_cmd_is_sftp;
@ -300,9 +299,9 @@ static void bump(const char *fmt, ...)
sfree(str2); sfree(str2);
errs++; errs++;
if (back != NULL && back->connected(backhandle)) { if (backend && backend_connected(backend)) {
char ch; char ch;
back->special(backhandle, TS_EOF); backend_special(backend, TS_EOF);
sent_eof = TRUE; sent_eof = TRUE;
ssh_scp_recv(&ch, 1); ssh_scp_recv(&ch, 1);
} }
@ -498,21 +497,19 @@ static void do_cmd(char *host, char *user, char *cmd)
} }
conf_set_int(conf, CONF_nopty, TRUE); conf_set_int(conf, CONF_nopty, TRUE);
back = &ssh_backend;
logctx = log_init(NULL, conf); logctx = log_init(NULL, conf);
console_provide_logctx(logctx); console_provide_logctx(logctx);
platform_psftp_pre_conn_setup(); platform_psftp_pre_conn_setup();
err = back->init(NULL, &backhandle, conf, err = backend_init(&ssh_backend, NULL, &backend, conf,
conf_get_str(conf, CONF_host), conf_get_str(conf, CONF_host),
conf_get_int(conf, CONF_port), conf_get_int(conf, CONF_port),
&realhost, 0, &realhost, 0,
conf_get_int(conf, CONF_tcp_keepalives)); conf_get_int(conf, CONF_tcp_keepalives));
if (err != NULL) if (err != NULL)
bump("ssh_init: %s", err); bump("ssh_init: %s", err);
back->provide_logctx(backhandle, logctx); backend_provide_logctx(backend, logctx);
ssh_scp_init(); ssh_scp_init();
if (verbose && realhost != NULL && errs == 0) if (verbose && realhost != NULL && errs == 0)
tell_user(stderr, "Connected to %s", realhost); tell_user(stderr, "Connected to %s", realhost);
@ -644,12 +641,12 @@ int sftp_recvdata(char *buf, int len)
} }
int sftp_senddata(char *buf, int len) int sftp_senddata(char *buf, int len)
{ {
back->send(backhandle, buf, len); backend_send(backend, buf, len);
return 1; return 1;
} }
int sftp_sendbuffer(void) int sftp_sendbuffer(void)
{ {
return back->sendbuffer(backhandle); return backend_sendbuffer(backend);
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
@ -806,8 +803,8 @@ int scp_send_errmsg(char *str)
if (using_sftp) { if (using_sftp) {
/* do nothing; we never need to send our errors to the server */ /* do nothing; we never need to send our errors to the server */
} else { } else {
back->send(backhandle, "\001", 1);/* scp protocol error prefix */ backend_send(backend, "\001", 1);/* scp protocol error prefix */
back->send(backhandle, str, strlen(str)); backend_send(backend, str, strlen(str));
} }
return 0; /* can't fail */ return 0; /* can't fail */
} }
@ -822,7 +819,7 @@ int scp_send_filetimes(unsigned long mtime, unsigned long atime)
} else { } else {
char buf[80]; char buf[80];
sprintf(buf, "T%lu 0 %lu 0\n", mtime, atime); sprintf(buf, "T%lu 0 %lu 0\n", mtime, atime);
back->send(backhandle, buf, strlen(buf)); backend_send(backend, buf, strlen(buf));
return response(); return response();
} }
} }
@ -869,9 +866,9 @@ int scp_send_filename(const char *name, uint64 size, int permissions)
if (permissions < 0) if (permissions < 0)
permissions = 0644; permissions = 0644;
sprintf(buf, "C%04o %s ", (int)(permissions & 07777), sizestr); sprintf(buf, "C%04o %s ", (int)(permissions & 07777), sizestr);
back->send(backhandle, buf, strlen(buf)); backend_send(backend, buf, strlen(buf));
back->send(backhandle, name, strlen(name)); backend_send(backend, name, strlen(name));
back->send(backhandle, "\n", 1); backend_send(backend, "\n", 1);
return response(); return response();
} }
} }
@ -903,7 +900,7 @@ int scp_send_filedata(char *data, int len)
scp_sftp_fileoffset = uint64_add32(scp_sftp_fileoffset, len); scp_sftp_fileoffset = uint64_add32(scp_sftp_fileoffset, len);
return 0; return 0;
} else { } else {
int bufsize = back->send(backhandle, data, len); int bufsize = backend_send(backend, data, len);
/* /*
* If the network transfer is backing up - that is, the * If the network transfer is backing up - that is, the
@ -914,7 +911,7 @@ int scp_send_filedata(char *data, int len)
while (bufsize > MAX_SCP_BUFSIZE) { while (bufsize > MAX_SCP_BUFSIZE) {
if (ssh_sftp_loop_iteration() < 0) if (ssh_sftp_loop_iteration() < 0)
return 1; return 1;
bufsize = back->sendbuffer(backhandle); bufsize = backend_sendbuffer(backend);
} }
return 0; return 0;
@ -963,7 +960,7 @@ int scp_send_finish(void)
scp_has_times = 0; scp_has_times = 0;
return 0; return 0;
} else { } else {
back->send(backhandle, "", 1); backend_send(backend, "", 1);
return response(); return response();
} }
} }
@ -1033,9 +1030,9 @@ int scp_send_dirname(const char *name, int modes)
} else { } else {
char buf[40]; char buf[40];
sprintf(buf, "D%04o 0 ", modes); sprintf(buf, "D%04o 0 ", modes);
back->send(backhandle, buf, strlen(buf)); backend_send(backend, buf, strlen(buf));
back->send(backhandle, name, strlen(name)); backend_send(backend, name, strlen(name));
back->send(backhandle, "\n", 1); backend_send(backend, "\n", 1);
return response(); return response();
} }
} }
@ -1046,7 +1043,7 @@ int scp_send_enddir(void)
sfree(scp_sftp_remotepath); sfree(scp_sftp_remotepath);
return 0; return 0;
} else { } else {
back->send(backhandle, "E\n", 2); backend_send(backend, "E\n", 2);
return response(); return response();
} }
} }
@ -1144,7 +1141,7 @@ int scp_sink_setup(const char *source, int preserve, int recursive)
int scp_sink_init(void) int scp_sink_init(void)
{ {
if (!using_sftp) { if (!using_sftp) {
back->send(backhandle, "", 1); backend_send(backend, "", 1);
} }
return 0; return 0;
} }
@ -1457,14 +1454,14 @@ int scp_get_sink_action(struct scp_sink_action *act)
case '\02': /* fatal error */ case '\02': /* fatal error */
bump("%s", act->buf); bump("%s", act->buf);
case 'E': case 'E':
back->send(backhandle, "", 1); backend_send(backend, "", 1);
act->action = SCP_SINK_ENDDIR; act->action = SCP_SINK_ENDDIR;
return 0; return 0;
case 'T': case 'T':
if (sscanf(act->buf, "%lu %*d %lu %*d", if (sscanf(act->buf, "%lu %*d %lu %*d",
&act->mtime, &act->atime) == 2) { &act->mtime, &act->atime) == 2) {
act->settime = 1; act->settime = 1;
back->send(backhandle, "", 1); backend_send(backend, "", 1);
continue; /* go round again */ continue; /* go round again */
} }
bump("Protocol error: Illegal time format"); bump("Protocol error: Illegal time format");
@ -1521,7 +1518,7 @@ int scp_accept_filexfer(void)
sfree(scp_sftp_currentname); sfree(scp_sftp_currentname);
return 0; return 0;
} else { } else {
back->send(backhandle, "", 1); backend_send(backend, "", 1);
return 0; /* can't fail */ return 0; /* can't fail */
} }
} }
@ -1606,7 +1603,7 @@ int scp_finish_filerecv(void)
fxp_close_recv(pktin, req); fxp_close_recv(pktin, req);
return 0; return 0;
} else { } else {
back->send(backhandle, "", 1); backend_send(backend, "", 1);
return response(); return response();
} }
} }
@ -2355,7 +2352,7 @@ int psftp_main(int argc, char *argv[])
} }
argc -= i; argc -= i;
argv += i; argv += i;
back = NULL; backend = NULL;
if (list) { if (list) {
if (argc != 1) if (argc != 1)
@ -2375,9 +2372,9 @@ int psftp_main(int argc, char *argv[])
tolocal(argc, argv); tolocal(argc, argv);
} }
if (back != NULL && back->connected(backhandle)) { if (backend && backend_connected(backend)) {
char ch; char ch;
back->special(backhandle, TS_EOF); backend_special(backend, TS_EOF);
sent_eof = TRUE; sent_eof = TRUE;
ssh_scp_recv(&ch, 1); ssh_scp_recv(&ch, 1);
} }
@ -2385,9 +2382,8 @@ int psftp_main(int argc, char *argv[])
cmdline_cleanup(); cmdline_cleanup();
console_provide_logctx(NULL); console_provide_logctx(NULL);
back->free(backhandle); backend_free(backend);
backhandle = NULL; backend = NULL;
back = NULL;
sk_cleanup(); sk_cleanup();
return (errs == 0 ? 0 : 1); return (errs == 0 ? 0 : 1);
} }

74
psftp.c
View File

@ -34,8 +34,7 @@ void do_sftp_cleanup();
*/ */
char *pwd, *homedir; char *pwd, *homedir;
static Backend *back; static Backend *backend;
static void *backhandle;
static Conf *conf; static Conf *conf;
int sent_eof = FALSE; int sent_eof = FALSE;
@ -967,14 +966,14 @@ int sftp_cmd_quit(struct sftp_command *cmd)
int sftp_cmd_close(struct sftp_command *cmd) int sftp_cmd_close(struct sftp_command *cmd)
{ {
if (back == NULL) { if (!backend) {
not_connected(); not_connected();
return 0; return 0;
} }
if (back != NULL && back->connected(backhandle)) { if (backend_connected(backend)) {
char ch; char ch;
back->special(backhandle, TS_EOF); backend_special(backend, TS_EOF);
sent_eof = TRUE; sent_eof = TRUE;
sftp_recvdata(&ch, 1); sftp_recvdata(&ch, 1);
} }
@ -999,7 +998,7 @@ int sftp_cmd_ls(struct sftp_command *cmd)
struct sftp_request *req; struct sftp_request *req;
int i; int i;
if (back == NULL) { if (!backend) {
not_connected(); not_connected();
return 0; return 0;
} }
@ -1123,7 +1122,7 @@ int sftp_cmd_cd(struct sftp_command *cmd)
struct sftp_request *req; struct sftp_request *req;
char *dir; char *dir;
if (back == NULL) { if (!backend) {
not_connected(); not_connected();
return 0; return 0;
} }
@ -1164,7 +1163,7 @@ int sftp_cmd_cd(struct sftp_command *cmd)
*/ */
int sftp_cmd_pwd(struct sftp_command *cmd) int sftp_cmd_pwd(struct sftp_command *cmd)
{ {
if (back == NULL) { if (!backend) {
not_connected(); not_connected();
return 0; return 0;
} }
@ -1188,7 +1187,7 @@ int sftp_general_get(struct sftp_command *cmd, int restart, int multiple)
int i, ret; int i, ret;
int recurse = FALSE; int recurse = FALSE;
if (back == NULL) { if (!backend) {
not_connected(); not_connected();
return 0; return 0;
} }
@ -1304,7 +1303,7 @@ int sftp_general_put(struct sftp_command *cmd, int restart, int multiple)
int i, ret; int i, ret;
int recurse = FALSE; int recurse = FALSE;
if (back == NULL) { if (!backend) {
not_connected(); not_connected();
return 0; return 0;
} }
@ -1405,7 +1404,7 @@ int sftp_cmd_mkdir(struct sftp_command *cmd)
int result; int result;
int i, ret; int i, ret;
if (back == NULL) { if (!backend) {
not_connected(); not_connected();
return 0; return 0;
} }
@ -1463,7 +1462,7 @@ int sftp_cmd_rmdir(struct sftp_command *cmd)
{ {
int i, ret; int i, ret;
if (back == NULL) { if (!backend) {
not_connected(); not_connected();
return 0; return 0;
} }
@ -1504,7 +1503,7 @@ int sftp_cmd_rm(struct sftp_command *cmd)
{ {
int i, ret; int i, ret;
if (back == NULL) { if (!backend) {
not_connected(); not_connected();
return 0; return 0;
} }
@ -1597,7 +1596,7 @@ int sftp_cmd_mv(struct sftp_command *cmd)
struct sftp_context_mv actx, *ctx = &actx; struct sftp_context_mv actx, *ctx = &actx;
int i, ret; int i, ret;
if (back == NULL) { if (!backend) {
not_connected(); not_connected();
return 0; return 0;
} }
@ -1689,7 +1688,7 @@ int sftp_cmd_chmod(struct sftp_command *cmd)
int i, ret; int i, ret;
struct sftp_context_chmod actx, *ctx = &actx; struct sftp_context_chmod actx, *ctx = &actx;
if (back == NULL) { if (!backend) {
not_connected(); not_connected();
return 0; return 0;
} }
@ -1815,7 +1814,7 @@ static int sftp_cmd_open(struct sftp_command *cmd)
{ {
int portnumber; int portnumber;
if (back != NULL) { if (backend) {
printf("psftp: already connected\n"); printf("psftp: already connected\n");
return 0; return 0;
} }
@ -1835,7 +1834,7 @@ static int sftp_cmd_open(struct sftp_command *cmd)
portnumber = 0; portnumber = 0;
if (psftp_connect(cmd->words[1], NULL, portnumber)) { if (psftp_connect(cmd->words[1], NULL, portnumber)) {
back = NULL; /* connection is already closed */ backend = NULL; /* connection is already closed */
return -1; /* this is fatal */ return -1; /* this is fatal */
} }
do_sftp_init(); do_sftp_init();
@ -2214,7 +2213,7 @@ struct sftp_command *sftp_getcmd(FILE *fp, int mode, int modeflags)
printf("psftp> "); printf("psftp> ");
line = fgetline(fp); line = fgetline(fp);
} else { } else {
line = ssh_sftp_get_cmdline("psftp> ", back == NULL); line = ssh_sftp_get_cmdline("psftp> ", !backend);
} }
if (!line || !*line) { if (!line || !*line) {
@ -2355,14 +2354,13 @@ static int do_sftp_init(void)
void do_sftp_cleanup() void do_sftp_cleanup()
{ {
char ch; char ch;
if (back) { if (backend) {
back->special(backhandle, TS_EOF); backend_special(backend, TS_EOF);
sent_eof = TRUE; sent_eof = TRUE;
sftp_recvdata(&ch, 1); sftp_recvdata(&ch, 1);
back->free(backhandle); backend_free(backend);
sftp_cleanup_request(); sftp_cleanup_request();
back = NULL; backend = NULL;
backhandle = NULL;
} }
if (pwd) { if (pwd) {
sfree(pwd); sfree(pwd);
@ -2602,7 +2600,7 @@ int sftp_recvdata(char *buf, int len)
} }
while (outlen > 0) { while (outlen > 0) {
if (back->exitcode(backhandle) >= 0 || ssh_sftp_loop_iteration() < 0) if (backend_exitcode(backend) >= 0 || ssh_sftp_loop_iteration() < 0)
return 0; /* doom */ return 0; /* doom */
} }
@ -2610,12 +2608,12 @@ int sftp_recvdata(char *buf, int len)
} }
int sftp_senddata(char *buf, int len) int sftp_senddata(char *buf, int len)
{ {
back->send(backhandle, buf, len); backend_send(backend, buf, len);
return 1; return 1;
} }
int sftp_sendbuffer(void) int sftp_sendbuffer(void)
{ {
return back->sendbuffer(backhandle); return backend_sendbuffer(backend);
} }
/* /*
@ -2826,25 +2824,23 @@ static int psftp_connect(char *userhost, char *user, int portnumber)
"exec sftp-server"); "exec sftp-server");
conf_set_int(conf, CONF_ssh_subsys2, FALSE); conf_set_int(conf, CONF_ssh_subsys2, FALSE);
back = &ssh_backend;
logctx = log_init(NULL, conf); logctx = log_init(NULL, conf);
console_provide_logctx(logctx); console_provide_logctx(logctx);
platform_psftp_pre_conn_setup(); platform_psftp_pre_conn_setup();
err = back->init(NULL, &backhandle, conf, err = backend_init(&ssh_backend, NULL, &backend, conf,
conf_get_str(conf, CONF_host), conf_get_str(conf, CONF_host),
conf_get_int(conf, CONF_port), conf_get_int(conf, CONF_port),
&realhost, 0, &realhost, 0,
conf_get_int(conf, CONF_tcp_keepalives)); conf_get_int(conf, CONF_tcp_keepalives));
if (err != NULL) { if (err != NULL) {
fprintf(stderr, "ssh_init: %s\n", err); fprintf(stderr, "ssh_init: %s\n", err);
return 1; return 1;
} }
back->provide_logctx(backhandle, logctx); backend_provide_logctx(backend, logctx);
while (!back->sendok(backhandle)) { while (!backend_sendok(backend)) {
if (back->exitcode(backhandle) >= 0) if (backend_exitcode(backend) >= 0)
return 1; return 1;
if (ssh_sftp_loop_iteration() < 0) { if (ssh_sftp_loop_iteration() < 0) {
fprintf(stderr, "ssh_init: error during SSH connection setup\n"); fprintf(stderr, "ssh_init: error during SSH connection setup\n");
@ -2945,7 +2941,7 @@ int psftp_main(int argc, char *argv[])
} }
argc -= i; argc -= i;
argv += i; argv += i;
back = NULL; backend = NULL;
/* /*
* If the loaded session provides a hostname, and a hostname has not * If the loaded session provides a hostname, and a hostname has not
@ -2975,9 +2971,9 @@ int psftp_main(int argc, char *argv[])
ret = do_sftp(mode, modeflags, batchfile); ret = do_sftp(mode, modeflags, batchfile);
if (back != NULL && back->connected(backhandle)) { if (backend && backend_connected(backend)) {
char ch; char ch;
back->special(backhandle, TS_EOF); backend_special(backend, TS_EOF);
sent_eof = TRUE; sent_eof = TRUE;
sftp_recvdata(&ch, 1); sftp_recvdata(&ch, 1);
} }

102
putty.h
View File

@ -441,43 +441,67 @@ enum {
ADDRTYPE_UNSPEC, ADDRTYPE_IPV4, ADDRTYPE_IPV6, ADDRTYPE_NAME ADDRTYPE_UNSPEC, ADDRTYPE_IPV4, ADDRTYPE_IPV6, ADDRTYPE_NAME
}; };
struct backend_tag { struct Backend {
const char *(*init) (void *frontend_handle, void **backend_handle, const Backend_vtable *vt;
};
struct Backend_vtable {
const char *(*init) (void *frontend_handle, Backend **backend_out,
Conf *conf, const char *host, int port, Conf *conf, const char *host, int port,
char **realhost, int nodelay, int keepalive); char **realhost, int nodelay, int keepalive);
void (*free) (void *handle);
/* back->reconfig() passes in a replacement configuration. */ void (*free) (Backend *be);
void (*reconfig) (void *handle, Conf *conf); /* Pass in a replacement configuration. */
/* back->send() returns the current amount of buffered data. */ void (*reconfig) (Backend *be, Conf *conf);
int (*send) (void *handle, const char *buf, int len); /* send() returns the current amount of buffered data. */
/* back->sendbuffer() does the same thing but without attempting a send */ int (*send) (Backend *be, const char *buf, int len);
int (*sendbuffer) (void *handle); /* sendbuffer() does the same thing but without attempting a send */
void (*size) (void *handle, int width, int height); int (*sendbuffer) (Backend *be);
void (*special) (void *handle, Telnet_Special code); void (*size) (Backend *be, int width, int height);
const struct telnet_special *(*get_specials) (void *handle); void (*special) (Backend *be, Telnet_Special code);
int (*connected) (void *handle); const struct telnet_special *(*get_specials) (Backend *be);
int (*exitcode) (void *handle); int (*connected) (Backend *be);
/* If back->sendok() returns FALSE, data sent to it from the frontend int (*exitcode) (Backend *be);
* may be lost. */ /* If back->sendok() returns FALSE, the backend doesn't currently
int (*sendok) (void *handle); * want input data, so the frontend should avoid acquiring any if
int (*ldisc) (void *handle, int); * possible (passing back-pressure on to its sender). */
void (*provide_ldisc) (void *handle, Ldisc *ldisc); int (*sendok) (Backend *be);
void (*provide_logctx) (void *handle, LogContext *logctx); int (*ldisc_option_state) (Backend *be, int);
/* void (*provide_ldisc) (Backend *be, Ldisc *ldisc);
* back->unthrottle() tells the back end that the front end void (*provide_logctx) (Backend *be, LogContext *logctx);
* buffer is clearing. /* Tells the back end that the front end buffer is clearing. */
*/ void (*unthrottle) (Backend *be, int bufsize);
void (*unthrottle) (void *handle, int); int (*cfg_info) (Backend *be);
int (*cfg_info) (void *handle);
/* Only implemented in the SSH protocol: check whether a /* Only implemented in the SSH protocol: check whether a
* connection-sharing upstream exists for a given configuration. */ * connection-sharing upstream exists for a given configuration. */
int (*test_for_upstream)(const char *host, int port, Conf *conf); int (*test_for_upstream)(const char *host, int port, Conf *conf);
const char *name; const char *name;
int protocol; int protocol;
int default_port; int default_port;
}; };
extern Backend *backends[]; #define backend_init(vt, fe, out, conf, host, port, rhost, nd, ka) \
((vt)->init(fe, out, conf, host, port, rhost, nd, ka))
#define backend_free(be) ((be)->vt->free(be))
#define backend_reconfig(be, conf) ((be)->vt->reconfig(be, conf))
#define backend_send(be, buf, len) ((be)->vt->send(be, buf, len))
#define backend_sendbuffer(be) ((be)->vt->sendbuffer(be))
#define backend_size(be, w, h) ((be)->vt->size(be, w, h))
#define backend_special(be, code) ((be)->vt->special(be, code))
#define backend_get_specials(be) ((be)->vt->get_specials(be))
#define backend_connected(be) ((be)->vt->connected(be))
#define backend_exitcode(be) ((be)->vt->exitcode(be))
#define backend_sendok(be) ((be)->vt->sendok(be))
#define backend_ldisc_option_state(be, opt) \
((be)->vt->ldisc_option_state(be, opt))
#define backend_provide_ldisc(be, ldisc) ((be)->vt->provide_ldisc(be, ldisc))
#define backend_provide_logctx(be, logctx) \
((be)->vt->provide_logctx(be, logctx))
#define backend_unthrottle(be, bufsize) ((be)->vt->unthrottle(be, bufsize))
#define backend_cfg_info(be) ((be)->vt->cfg_info(be))
extern const struct Backend_vtable *const backends[];
/* /*
* Suggested default protocol provided by the backend link module. * Suggested default protocol provided by the backend link module.
@ -1046,8 +1070,8 @@ void random_destroy_seed(void);
/* /*
* Exports from settings.c. * Exports from settings.c.
*/ */
Backend *backend_from_name(const char *name); const struct Backend_vtable *backend_vt_from_name(const char *name);
Backend *backend_from_proto(int proto); const struct Backend_vtable *backend_vt_from_proto(int proto);
char *get_remote_username(Conf *conf); /* dynamically allocated */ char *get_remote_username(Conf *conf); /* dynamically allocated */
char *save_settings(const char *section, Conf *conf); char *save_settings(const char *section, Conf *conf);
void save_open_settings(void *sesskey, Conf *conf); void save_open_settings(void *sesskey, Conf *conf);
@ -1107,9 +1131,7 @@ void term_request_paste(Terminal *, int clipboard);
void term_seen_key_event(Terminal *); void term_seen_key_event(Terminal *);
int term_data(Terminal *, int is_stderr, const void *data, int len); int term_data(Terminal *, int is_stderr, const void *data, int len);
int term_data_untrusted(Terminal *, const void *data, int len); int term_data_untrusted(Terminal *, const void *data, int len);
void term_provide_resize_fn(Terminal *term, void term_provide_backend(Terminal *term, Backend *backend);
void (*resize_fn)(void *, int, int),
void *resize_ctx);
void term_provide_logctx(Terminal *term, LogContext *logctx); void term_provide_logctx(Terminal *term, LogContext *logctx);
void term_set_focus(Terminal *term, int has_focus); void term_set_focus(Terminal *term, int has_focus);
char *term_get_ttymode(Terminal *term, const char *mode); char *term_get_ttymode(Terminal *term, const char *mode);
@ -1145,36 +1167,36 @@ void log_packet(LogContext *logctx, int direction, int type,
* Exports from testback.c * Exports from testback.c
*/ */
extern Backend null_backend; extern const struct Backend_vtable null_backend;
extern Backend loop_backend; extern const struct Backend_vtable loop_backend;
/* /*
* Exports from raw.c. * Exports from raw.c.
*/ */
extern Backend raw_backend; extern const struct Backend_vtable raw_backend;
/* /*
* Exports from rlogin.c. * Exports from rlogin.c.
*/ */
extern Backend rlogin_backend; extern const struct Backend_vtable rlogin_backend;
/* /*
* Exports from telnet.c. * Exports from telnet.c.
*/ */
extern Backend telnet_backend; extern const struct Backend_vtable telnet_backend;
/* /*
* Exports from ssh.c. * Exports from ssh.c.
*/ */
extern Backend ssh_backend; extern const struct Backend_vtable ssh_backend;
/* /*
* Exports from ldisc.c. * Exports from ldisc.c.
*/ */
Ldisc *ldisc_create(Conf *, Terminal *, Backend *, void *, void *); Ldisc *ldisc_create(Conf *, Terminal *, Backend *, void *);
void ldisc_configure(Ldisc *, Conf *); void ldisc_configure(Ldisc *, Conf *);
void ldisc_free(Ldisc *); void ldisc_free(Ldisc *);
void ldisc_send(Ldisc *, const void *buf, int len, int interactive); void ldisc_send(Ldisc *, const void *buf, int len, int interactive);
@ -1205,7 +1227,7 @@ void random_unref(void);
* Exports from pinger.c. * Exports from pinger.c.
*/ */
typedef struct pinger_tag *Pinger; typedef struct pinger_tag *Pinger;
Pinger pinger_new(Conf *conf, Backend *back, void *backhandle); Pinger pinger_new(Conf *conf, Backend *backend);
void pinger_reconfig(Pinger, Conf *oldconf, Conf *newconf); void pinger_reconfig(Pinger, Conf *oldconf, Conf *newconf);
void pinger_free(Pinger); void pinger_free(Pinger);

54
raw.c
View File

@ -20,9 +20,10 @@ typedef struct raw_backend_data {
Conf *conf; Conf *conf;
const Plug_vtable *plugvt; const Plug_vtable *plugvt;
Backend backend;
} *Raw; } *Raw;
static void raw_size(void *handle, int width, int height); static void raw_size(Backend *be, int width, int height);
static void c_write(Raw raw, const void *buf, int len) static void c_write(Raw raw, const void *buf, int len)
{ {
@ -116,7 +117,7 @@ static const Plug_vtable Raw_plugvt = {
* Also places the canonical host name into `realhost'. It must be * Also places the canonical host name into `realhost'. It must be
* freed by the caller. * freed by the caller.
*/ */
static const char *raw_init(void *frontend_handle, void **backend_handle, static const char *raw_init(void *frontend_handle, Backend **backend_handle,
Conf *conf, Conf *conf,
const char *host, int port, char **realhost, const char *host, int port, char **realhost,
int nodelay, int keepalive) int nodelay, int keepalive)
@ -129,9 +130,10 @@ static const char *raw_init(void *frontend_handle, void **backend_handle,
raw = snew(struct raw_backend_data); raw = snew(struct raw_backend_data);
raw->plugvt = &Raw_plugvt; raw->plugvt = &Raw_plugvt;
raw->backend.vt = &raw_backend;
raw->s = NULL; raw->s = NULL;
raw->closed_on_socket_error = FALSE; raw->closed_on_socket_error = FALSE;
*backend_handle = raw; *backend_handle = &raw->backend;
raw->sent_console_eof = raw->sent_socket_eof = FALSE; raw->sent_console_eof = raw->sent_socket_eof = FALSE;
raw->bufsize = 0; raw->bufsize = 0;
raw->session_started = FALSE; raw->session_started = FALSE;
@ -176,9 +178,9 @@ static const char *raw_init(void *frontend_handle, void **backend_handle,
return NULL; return NULL;
} }
static void raw_free(void *handle) static void raw_free(Backend *be)
{ {
Raw raw = (Raw) handle; Raw raw = FROMFIELD(be, struct raw_backend_data, backend);
if (raw->s) if (raw->s)
sk_close(raw->s); sk_close(raw->s);
@ -189,16 +191,16 @@ static void raw_free(void *handle)
/* /*
* Stub routine (we don't have any need to reconfigure this backend). * Stub routine (we don't have any need to reconfigure this backend).
*/ */
static void raw_reconfig(void *handle, Conf *conf) static void raw_reconfig(Backend *be, Conf *conf)
{ {
} }
/* /*
* Called to send data down the raw connection. * Called to send data down the raw connection.
*/ */
static int raw_send(void *handle, const char *buf, int len) static int raw_send(Backend *be, const char *buf, int len)
{ {
Raw raw = (Raw) handle; Raw raw = FROMFIELD(be, struct raw_backend_data, backend);
if (raw->s == NULL) if (raw->s == NULL)
return 0; return 0;
@ -211,16 +213,16 @@ static int raw_send(void *handle, const char *buf, int len)
/* /*
* Called to query the current socket sendability status. * Called to query the current socket sendability status.
*/ */
static int raw_sendbuffer(void *handle) static int raw_sendbuffer(Backend *be)
{ {
Raw raw = (Raw) handle; Raw raw = FROMFIELD(be, struct raw_backend_data, backend);
return raw->bufsize; return raw->bufsize;
} }
/* /*
* Called to set the size of the window * Called to set the size of the window
*/ */
static void raw_size(void *handle, int width, int height) static void raw_size(Backend *be, int width, int height)
{ {
/* Do nothing! */ /* Do nothing! */
return; return;
@ -229,9 +231,9 @@ static void raw_size(void *handle, int width, int height)
/* /*
* Send raw special codes. We only handle outgoing EOF here. * Send raw special codes. We only handle outgoing EOF here.
*/ */
static void raw_special(void *handle, Telnet_Special code) static void raw_special(Backend *be, Telnet_Special code)
{ {
Raw raw = (Raw) handle; Raw raw = FROMFIELD(be, struct raw_backend_data, backend);
if (code == TS_EOF && raw->s) { if (code == TS_EOF && raw->s) {
sk_write_eof(raw->s); sk_write_eof(raw->s);
raw->sent_socket_eof= TRUE; raw->sent_socket_eof= TRUE;
@ -245,48 +247,48 @@ static void raw_special(void *handle, Telnet_Special code)
* Return a list of the special codes that make sense in this * Return a list of the special codes that make sense in this
* protocol. * protocol.
*/ */
static const struct telnet_special *raw_get_specials(void *handle) static const struct telnet_special *raw_get_specials(Backend *be)
{ {
return NULL; return NULL;
} }
static int raw_connected(void *handle) static int raw_connected(Backend *be)
{ {
Raw raw = (Raw) handle; Raw raw = FROMFIELD(be, struct raw_backend_data, backend);
return raw->s != NULL; return raw->s != NULL;
} }
static int raw_sendok(void *handle) static int raw_sendok(Backend *be)
{ {
return 1; return 1;
} }
static void raw_unthrottle(void *handle, int backlog) static void raw_unthrottle(Backend *be, int backlog)
{ {
Raw raw = (Raw) handle; Raw raw = FROMFIELD(be, struct raw_backend_data, backend);
sk_set_frozen(raw->s, backlog > RAW_MAX_BACKLOG); sk_set_frozen(raw->s, backlog > RAW_MAX_BACKLOG);
} }
static int raw_ldisc(void *handle, int option) static int raw_ldisc(Backend *be, int option)
{ {
if (option == LD_EDIT || option == LD_ECHO) if (option == LD_EDIT || option == LD_ECHO)
return 1; return 1;
return 0; return 0;
} }
static void raw_provide_ldisc(void *handle, Ldisc *ldisc) static void raw_provide_ldisc(Backend *be, Ldisc *ldisc)
{ {
/* This is a stub. */ /* This is a stub. */
} }
static void raw_provide_logctx(void *handle, LogContext *logctx) static void raw_provide_logctx(Backend *be, LogContext *logctx)
{ {
/* This is a stub. */ /* This is a stub. */
} }
static int raw_exitcode(void *handle) static int raw_exitcode(Backend *be)
{ {
Raw raw = (Raw) handle; Raw raw = FROMFIELD(be, struct raw_backend_data, backend);
if (raw->s != NULL) if (raw->s != NULL)
return -1; /* still connected */ return -1; /* still connected */
else if (raw->closed_on_socket_error) else if (raw->closed_on_socket_error)
@ -299,12 +301,12 @@ static int raw_exitcode(void *handle)
/* /*
* cfg_info for Raw does nothing at all. * cfg_info for Raw does nothing at all.
*/ */
static int raw_cfg_info(void *handle) static int raw_cfg_info(Backend *be)
{ {
return 0; return 0;
} }
Backend raw_backend = { const struct Backend_vtable raw_backend = {
raw_init, raw_init,
raw_free, raw_free,
raw_reconfig, raw_reconfig,

View File

@ -26,10 +26,9 @@ typedef struct rlogin_tag {
prompts_t *prompt; prompts_t *prompt;
const Plug_vtable *plugvt; const Plug_vtable *plugvt;
Backend backend;
} *Rlogin; } *Rlogin;
static void rlogin_size(void *handle, int width, int height);
static void c_write(Rlogin rlogin, const void *buf, int len) static void c_write(Rlogin rlogin, const void *buf, int len)
{ {
int backlog = from_backend(rlogin->frontend, 0, buf, len); int backlog = from_backend(rlogin->frontend, 0, buf, len);
@ -80,7 +79,8 @@ static void rlogin_receive(Plug plug, int urgent, char *data, int len)
len--; len--;
if (c == '\x80') { if (c == '\x80') {
rlogin->cansize = 1; rlogin->cansize = 1;
rlogin_size(rlogin, rlogin->term_width, rlogin->term_height); backend_size(&rlogin->backend,
rlogin->term_width, rlogin->term_height);
} }
/* /*
* We should flush everything (aka Telnet SYNCH) if we see * We should flush everything (aka Telnet SYNCH) if we see
@ -148,7 +148,7 @@ static const Plug_vtable Rlogin_plugvt = {
* Also places the canonical host name into `realhost'. It must be * Also places the canonical host name into `realhost'. It must be
* freed by the caller. * freed by the caller.
*/ */
static const char *rlogin_init(void *frontend_handle, void **backend_handle, static const char *rlogin_init(void *frontend_handle, Backend **backend_handle,
Conf *conf, Conf *conf,
const char *host, int port, char **realhost, const char *host, int port, char **realhost,
int nodelay, int keepalive) int nodelay, int keepalive)
@ -162,6 +162,7 @@ static const char *rlogin_init(void *frontend_handle, void **backend_handle,
rlogin = snew(struct rlogin_tag); rlogin = snew(struct rlogin_tag);
rlogin->plugvt = &Rlogin_plugvt; rlogin->plugvt = &Rlogin_plugvt;
rlogin->backend.vt = &rlogin_backend;
rlogin->s = NULL; rlogin->s = NULL;
rlogin->closed_on_socket_error = FALSE; rlogin->closed_on_socket_error = FALSE;
rlogin->frontend = frontend_handle; rlogin->frontend = frontend_handle;
@ -171,7 +172,7 @@ static const char *rlogin_init(void *frontend_handle, void **backend_handle,
rlogin->cansize = 0; rlogin->cansize = 0;
rlogin->prompt = NULL; rlogin->prompt = NULL;
rlogin->conf = conf_copy(conf); rlogin->conf = conf_copy(conf);
*backend_handle = rlogin; *backend_handle = &rlogin->backend;
addressfamily = conf_get_int(conf, CONF_addressfamily); addressfamily = conf_get_int(conf, CONF_addressfamily);
/* /*
@ -232,9 +233,9 @@ static const char *rlogin_init(void *frontend_handle, void **backend_handle,
return NULL; return NULL;
} }
static void rlogin_free(void *handle) static void rlogin_free(Backend *be)
{ {
Rlogin rlogin = (Rlogin) handle; Rlogin rlogin = FROMFIELD(be, struct rlogin_tag, backend);
if (rlogin->prompt) if (rlogin->prompt)
free_prompts(rlogin->prompt); free_prompts(rlogin->prompt);
@ -247,16 +248,16 @@ static void rlogin_free(void *handle)
/* /*
* Stub routine (we don't have any need to reconfigure this backend). * Stub routine (we don't have any need to reconfigure this backend).
*/ */
static void rlogin_reconfig(void *handle, Conf *conf) static void rlogin_reconfig(Backend *be, Conf *conf)
{ {
} }
/* /*
* Called to send data down the rlogin connection. * Called to send data down the rlogin connection.
*/ */
static int rlogin_send(void *handle, const char *buf, int len) static int rlogin_send(Backend *be, const char *buf, int len)
{ {
Rlogin rlogin = (Rlogin) handle; Rlogin rlogin = FROMFIELD(be, struct rlogin_tag, backend);
bufchain bc; bufchain bc;
if (rlogin->s == NULL) if (rlogin->s == NULL)
@ -296,18 +297,18 @@ static int rlogin_send(void *handle, const char *buf, int len)
/* /*
* Called to query the current socket sendability status. * Called to query the current socket sendability status.
*/ */
static int rlogin_sendbuffer(void *handle) static int rlogin_sendbuffer(Backend *be)
{ {
Rlogin rlogin = (Rlogin) handle; Rlogin rlogin = FROMFIELD(be, struct rlogin_tag, backend);
return rlogin->bufsize; return rlogin->bufsize;
} }
/* /*
* Called to set the size of the window * Called to set the size of the window
*/ */
static void rlogin_size(void *handle, int width, int height) static void rlogin_size(Backend *be, int width, int height)
{ {
Rlogin rlogin = (Rlogin) handle; Rlogin rlogin = FROMFIELD(be, struct rlogin_tag, backend);
char b[12] = { '\xFF', '\xFF', 0x73, 0x73, 0, 0, 0, 0, 0, 0, 0, 0 }; char b[12] = { '\xFF', '\xFF', 0x73, 0x73, 0, 0, 0, 0, 0, 0, 0, 0 };
rlogin->term_width = width; rlogin->term_width = width;
@ -327,7 +328,7 @@ static void rlogin_size(void *handle, int width, int height)
/* /*
* Send rlogin special codes. * Send rlogin special codes.
*/ */
static void rlogin_special(void *handle, Telnet_Special code) static void rlogin_special(Backend *be, Telnet_Special code)
{ {
/* Do nothing! */ /* Do nothing! */
return; return;
@ -337,48 +338,48 @@ static void rlogin_special(void *handle, Telnet_Special code)
* Return a list of the special codes that make sense in this * Return a list of the special codes that make sense in this
* protocol. * protocol.
*/ */
static const struct telnet_special *rlogin_get_specials(void *handle) static const struct telnet_special *rlogin_get_specials(Backend *be)
{ {
return NULL; return NULL;
} }
static int rlogin_connected(void *handle) static int rlogin_connected(Backend *be)
{ {
Rlogin rlogin = (Rlogin) handle; Rlogin rlogin = FROMFIELD(be, struct rlogin_tag, backend);
return rlogin->s != NULL; return rlogin->s != NULL;
} }
static int rlogin_sendok(void *handle) static int rlogin_sendok(Backend *be)
{ {
/* Rlogin rlogin = (Rlogin) handle; */ /* Rlogin rlogin = FROMFIELD(be, struct rlogin_tag, backend); */
return 1; return 1;
} }
static void rlogin_unthrottle(void *handle, int backlog) static void rlogin_unthrottle(Backend *be, int backlog)
{ {
Rlogin rlogin = (Rlogin) handle; Rlogin rlogin = FROMFIELD(be, struct rlogin_tag, backend);
sk_set_frozen(rlogin->s, backlog > RLOGIN_MAX_BACKLOG); sk_set_frozen(rlogin->s, backlog > RLOGIN_MAX_BACKLOG);
} }
static int rlogin_ldisc(void *handle, int option) static int rlogin_ldisc(Backend *be, int option)
{ {
/* Rlogin rlogin = (Rlogin) handle; */ /* Rlogin rlogin = FROMFIELD(be, struct rlogin_tag, backend); */
return 0; return 0;
} }
static void rlogin_provide_ldisc(void *handle, Ldisc *ldisc) static void rlogin_provide_ldisc(Backend *be, Ldisc *ldisc)
{ {
/* This is a stub. */ /* This is a stub. */
} }
static void rlogin_provide_logctx(void *handle, LogContext *logctx) static void rlogin_provide_logctx(Backend *be, LogContext *logctx)
{ {
/* This is a stub. */ /* This is a stub. */
} }
static int rlogin_exitcode(void *handle) static int rlogin_exitcode(Backend *be)
{ {
Rlogin rlogin = (Rlogin) handle; Rlogin rlogin = FROMFIELD(be, struct rlogin_tag, backend);
if (rlogin->s != NULL) if (rlogin->s != NULL)
return -1; /* still connected */ return -1; /* still connected */
else if (rlogin->closed_on_socket_error) else if (rlogin->closed_on_socket_error)
@ -391,12 +392,12 @@ static int rlogin_exitcode(void *handle)
/* /*
* cfg_info for rlogin does nothing at all. * cfg_info for rlogin does nothing at all.
*/ */
static int rlogin_cfg_info(void *handle) static int rlogin_cfg_info(Backend *be)
{ {
return 0; return 0;
} }
Backend rlogin_backend = { const struct Backend_vtable rlogin_backend = {
rlogin_init, rlogin_init,
rlogin_free, rlogin_free,
rlogin_reconfig, rlogin_reconfig,

View File

@ -74,18 +74,18 @@ const char *const ttymodes[] = {
* (which is only present in tools that manage settings). * (which is only present in tools that manage settings).
*/ */
Backend *backend_from_name(const char *name) const struct Backend_vtable *backend_vt_from_name(const char *name)
{ {
Backend **p; const struct Backend_vtable *const *p;
for (p = backends; *p != NULL; p++) for (p = backends; *p != NULL; p++)
if (!strcmp((*p)->name, name)) if (!strcmp((*p)->name, name))
return *p; return *p;
return NULL; return NULL;
} }
Backend *backend_from_proto(int proto) const struct Backend_vtable *backend_vt_from_proto(int proto)
{ {
Backend **p; const struct Backend_vtable *const *p;
for (p = backends; *p != NULL; p++) for (p = backends; *p != NULL; p++)
if ((*p)->protocol == proto) if ((*p)->protocol == proto)
return *p; return *p;
@ -528,9 +528,10 @@ void save_open_settings(void *sesskey, Conf *conf)
write_setting_i(sesskey, "SSHLogOmitData", conf_get_int(conf, CONF_logomitdata)); write_setting_i(sesskey, "SSHLogOmitData", conf_get_int(conf, CONF_logomitdata));
p = "raw"; p = "raw";
{ {
const Backend *b = backend_from_proto(conf_get_int(conf, CONF_protocol)); const struct Backend_vtable *vt =
if (b) backend_vt_from_proto(conf_get_int(conf, CONF_protocol));
p = b->name; if (vt)
p = vt->name;
} }
write_setting_s(sesskey, "Protocol", p); write_setting_s(sesskey, "Protocol", p);
write_setting_i(sesskey, "PortNumber", conf_get_int(conf, CONF_port)); write_setting_i(sesskey, "PortNumber", conf_get_int(conf, CONF_port));
@ -791,9 +792,9 @@ void load_open_settings(void *sesskey, Conf *conf)
conf_set_int(conf, CONF_protocol, default_protocol); conf_set_int(conf, CONF_protocol, default_protocol);
conf_set_int(conf, CONF_port, default_port); conf_set_int(conf, CONF_port, default_port);
{ {
const Backend *b = backend_from_name(prot); const struct Backend_vtable *vt = backend_vt_from_name(prot);
if (b) { if (vt) {
conf_set_int(conf, CONF_protocol, b->protocol); conf_set_int(conf, CONF_protocol, vt->protocol);
gppi(sesskey, "PortNumber", default_port, conf, CONF_port); gppi(sesskey, "PortNumber", default_port, conf, CONF_port);
} }
} }

92
ssh.c
View File

@ -561,14 +561,14 @@ struct ssh_portfwd {
static void ssh1_protocol_setup(Ssh ssh); static void ssh1_protocol_setup(Ssh ssh);
static void ssh2_protocol_setup(Ssh ssh); static void ssh2_protocol_setup(Ssh ssh);
static void ssh2_bare_connection_protocol_setup(Ssh ssh); static void ssh2_bare_connection_protocol_setup(Ssh ssh);
static void ssh_size(void *handle, int width, int height); static void ssh_size(Backend *be, int width, int height);
static void ssh_special(void *handle, Telnet_Special); static void ssh_special(Backend *be, Telnet_Special);
static int ssh2_try_send(struct ssh_channel *c); static int ssh2_try_send(struct ssh_channel *c);
static int ssh_send_channel_data(struct ssh_channel *c, static int ssh_send_channel_data(struct ssh_channel *c,
const char *buf, int len); const char *buf, int len);
static void ssh_throttle_all(Ssh ssh, int enable, int bufsize); static void ssh_throttle_all(Ssh ssh, int enable, int bufsize);
static void ssh2_set_window(struct ssh_channel *c, int newwin); static void ssh2_set_window(struct ssh_channel *c, int newwin);
static int ssh_sendbuffer(void *handle); static int ssh_sendbuffer(Backend *be);
static int ssh_do_close(Ssh ssh, int notify_exit); static int ssh_do_close(Ssh ssh, int notify_exit);
static void ssh2_timer(void *ctx, unsigned long now); static void ssh2_timer(void *ctx, unsigned long now);
static int ssh2_timer_update(Ssh ssh, unsigned long rekey_time); static int ssh2_timer_update(Ssh ssh, unsigned long rekey_time);
@ -699,6 +699,7 @@ struct ssh_tag {
Socket s; Socket s;
const Plug_vtable *plugvt; const Plug_vtable *plugvt;
Backend backend;
Ldisc *ldisc; Ldisc *ldisc;
LogContext *logctx; LogContext *logctx;
@ -1877,7 +1878,7 @@ static void do_ssh_init(Ssh ssh)
update_specials_menu(ssh->frontend); update_specials_menu(ssh->frontend);
ssh->state = SSH_STATE_BEFORE_SIZE; ssh->state = SSH_STATE_BEFORE_SIZE;
ssh->pinger = pinger_new(ssh->conf, &ssh_backend, ssh); ssh->pinger = pinger_new(ssh->conf, &ssh->backend);
sfree(s->vstring); sfree(s->vstring);
@ -2029,7 +2030,7 @@ static void do_ssh_connection_init(Ssh ssh)
update_specials_menu(ssh->frontend); update_specials_menu(ssh->frontend);
ssh->state = SSH_STATE_BEFORE_SIZE; ssh->state = SSH_STATE_BEFORE_SIZE;
ssh->pinger = pinger_new(ssh->conf, &ssh_backend, ssh); ssh->pinger = pinger_new(ssh->conf, &ssh->backend);
/* /*
* Get connection protocol under way. * Get connection protocol under way.
@ -4726,9 +4727,9 @@ static void do_ssh1_connection(void *vctx)
ssh->state = SSH_STATE_SESSION; ssh->state = SSH_STATE_SESSION;
if (ssh->size_needed) if (ssh->size_needed)
ssh_size(ssh, ssh->term_width, ssh->term_height); backend_size(&ssh->backend, ssh->term_width, ssh->term_height);
if (ssh->eof_needed) if (ssh->eof_needed)
ssh_special(ssh, TS_EOF); backend_special(&ssh->backend, TS_EOF);
if (ssh->ldisc) if (ssh->ldisc)
ldisc_echoedit_update(ssh->ldisc); /* cause ldisc to notice changes */ ldisc_echoedit_update(ssh->ldisc); /* cause ldisc to notice changes */
@ -10110,9 +10111,9 @@ static void do_ssh2_connection(void *vctx)
ssh->state = SSH_STATE_SESSION; ssh->state = SSH_STATE_SESSION;
if (ssh->size_needed) if (ssh->size_needed)
ssh_size(ssh, ssh->term_width, ssh->term_height); backend_size(&ssh->backend, ssh->term_width, ssh->term_height);
if (ssh->eof_needed) if (ssh->eof_needed)
ssh_special(ssh, TS_EOF); backend_special(&ssh->backend, TS_EOF);
/* /*
* Transfer data! * Transfer data!
@ -10664,7 +10665,7 @@ static void ssh_cache_conf_values(Ssh ssh)
* *
* Returns an error message, or NULL on success. * Returns an error message, or NULL on success.
*/ */
static const char *ssh_init(void *frontend_handle, void **backend_handle, static const char *ssh_init(void *frontend_handle, Backend **backend_handle,
Conf *conf, Conf *conf,
const char *host, int port, char **realhost, const char *host, int port, char **realhost,
int nodelay, int keepalive) int nodelay, int keepalive)
@ -10777,7 +10778,8 @@ static const char *ssh_init(void *frontend_handle, void **backend_handle,
#endif #endif
ssh->gss_kex_used = FALSE; ssh->gss_kex_used = FALSE;
*backend_handle = ssh; ssh->backend.vt = &ssh_backend;
*backend_handle = &ssh->backend;
ssh->frontend = frontend_handle; ssh->frontend = frontend_handle;
ssh->term_width = conf_get_int(ssh->conf, CONF_width); ssh->term_width = conf_get_int(ssh->conf, CONF_width);
@ -10826,9 +10828,9 @@ static const char *ssh_init(void *frontend_handle, void **backend_handle,
return NULL; return NULL;
} }
static void ssh_free(void *handle) static void ssh_free(Backend *be)
{ {
Ssh ssh = (Ssh) handle; Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
struct ssh_channel *c; struct ssh_channel *c;
struct ssh_rportfwd *pf; struct ssh_rportfwd *pf;
struct X11FakeAuth *auth; struct X11FakeAuth *auth;
@ -10937,9 +10939,9 @@ static void ssh_free(void *handle)
/* /*
* Reconfigure the SSH backend. * Reconfigure the SSH backend.
*/ */
static void ssh_reconfig(void *handle, Conf *conf) static void ssh_reconfig(Backend *be, Conf *conf)
{ {
Ssh ssh = (Ssh) handle; Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
const char *rekeying = NULL; const char *rekeying = NULL;
int rekey_mandatory = FALSE; int rekey_mandatory = FALSE;
unsigned long old_max_data_size; unsigned long old_max_data_size;
@ -10999,9 +11001,9 @@ static void ssh_reconfig(void *handle, Conf *conf)
/* /*
* Called to send data down the SSH connection. * Called to send data down the SSH connection.
*/ */
static int ssh_send(void *handle, const char *buf, int len) static int ssh_send(Backend *be, const char *buf, int len)
{ {
Ssh ssh = (Ssh) handle; Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
if (ssh == NULL || ssh->s == NULL) if (ssh == NULL || ssh->s == NULL)
return 0; return 0;
@ -11009,15 +11011,15 @@ static int ssh_send(void *handle, const char *buf, int len)
bufchain_add(&ssh->user_input, buf, len); bufchain_add(&ssh->user_input, buf, len);
queue_idempotent_callback(&ssh->user_input_consumer); queue_idempotent_callback(&ssh->user_input_consumer);
return ssh_sendbuffer(ssh); return backend_sendbuffer(&ssh->backend);
} }
/* /*
* Called to query the current amount of buffered stdin data. * Called to query the current amount of buffered stdin data.
*/ */
static int ssh_sendbuffer(void *handle) static int ssh_sendbuffer(Backend *be)
{ {
Ssh ssh = (Ssh) handle; Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
int override_value; int override_value;
if (ssh == NULL || ssh->s == NULL) if (ssh == NULL || ssh->s == NULL)
@ -11047,9 +11049,9 @@ static int ssh_sendbuffer(void *handle)
/* /*
* Called to set the size of the window from SSH's POV. * Called to set the size of the window from SSH's POV.
*/ */
static void ssh_size(void *handle, int width, int height) static void ssh_size(Backend *be, int width, int height)
{ {
Ssh ssh = (Ssh) handle; Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
PktOut *pktout; PktOut *pktout;
ssh->term_width = width; ssh->term_width = width;
@ -11090,7 +11092,7 @@ static void ssh_size(void *handle, int width, int height)
* Return a list of the special codes that make sense in this * Return a list of the special codes that make sense in this
* protocol. * protocol.
*/ */
static const struct telnet_special *ssh_get_specials(void *handle) static const struct telnet_special *ssh_get_specials(Backend *be)
{ {
static const struct telnet_special ssh1_ignore_special[] = { static const struct telnet_special ssh1_ignore_special[] = {
{"IGNORE message", TS_NOP} {"IGNORE message", TS_NOP}
@ -11126,7 +11128,7 @@ static const struct telnet_special *ssh_get_specials(void *handle)
struct telnet_special *specials = NULL; struct telnet_special *specials = NULL;
int nspecials = 0, specialsize = 0; int nspecials = 0, specialsize = 0;
Ssh ssh = (Ssh) handle; Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
sfree(ssh->specials); sfree(ssh->specials);
@ -11196,9 +11198,9 @@ static const struct telnet_special *ssh_get_specials(void *handle)
* can send an EOF and collect resulting output (e.g. `plink * can send an EOF and collect resulting output (e.g. `plink
* hostname sort'). * hostname sort').
*/ */
static void ssh_special(void *handle, Telnet_Special code) static void ssh_special(Backend *be, Telnet_Special code)
{ {
Ssh ssh = (Ssh) handle; Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
PktOut *pktout; PktOut *pktout;
if (code == TS_EOF) { if (code == TS_EOF) {
@ -11344,9 +11346,9 @@ void ssh_send_packet_from_downstream(Ssh ssh, unsigned id, int type,
* This is called when stdout/stderr (the entity to which * This is called when stdout/stderr (the entity to which
* from_backend sends data) manages to clear some backlog. * from_backend sends data) manages to clear some backlog.
*/ */
static void ssh_unthrottle(void *handle, int bufsize) static void ssh_unthrottle(Backend *be, int bufsize)
{ {
Ssh ssh = (Ssh) handle; Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
if (ssh->version == 1) { if (ssh->version == 1) {
if (ssh->v1_stdout_throttling && bufsize < SSH1_BUFFER_LIMIT) { if (ssh->v1_stdout_throttling && bufsize < SSH1_BUFFER_LIMIT) {
@ -11405,21 +11407,21 @@ void ssh_send_port_open(void *channel, const char *hostname, int port,
} }
} }
static int ssh_connected(void *handle) static int ssh_connected(Backend *be)
{ {
Ssh ssh = (Ssh) handle; Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
return ssh->s != NULL; return ssh->s != NULL;
} }
static int ssh_sendok(void *handle) static int ssh_sendok(Backend *be)
{ {
Ssh ssh = (Ssh) handle; Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
return ssh->send_ok; return ssh->send_ok;
} }
static int ssh_ldisc(void *handle, int option) static int ssh_ldisc(Backend *be, int option)
{ {
Ssh ssh = (Ssh) handle; Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
if (option == LD_ECHO) if (option == LD_ECHO)
return ssh->echoing; return ssh->echoing;
if (option == LD_EDIT) if (option == LD_EDIT)
@ -11427,21 +11429,21 @@ static int ssh_ldisc(void *handle, int option)
return FALSE; return FALSE;
} }
static void ssh_provide_ldisc(void *handle, Ldisc *ldisc) static void ssh_provide_ldisc(Backend *be, Ldisc *ldisc)
{ {
Ssh ssh = (Ssh) handle; Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
ssh->ldisc = ldisc; ssh->ldisc = ldisc;
} }
static void ssh_provide_logctx(void *handle, LogContext *logctx) static void ssh_provide_logctx(Backend *be, LogContext *logctx)
{ {
Ssh ssh = (Ssh) handle; Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
ssh->logctx = logctx; ssh->logctx = logctx;
} }
static int ssh_return_exitcode(void *handle) static int ssh_return_exitcode(Backend *be)
{ {
Ssh ssh = (Ssh) handle; Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
if (ssh->s != NULL) if (ssh->s != NULL)
return -1; return -1;
else else
@ -11453,9 +11455,9 @@ static int ssh_return_exitcode(void *handle)
* (1 or 2 for the full SSH-1 or SSH-2 protocol; -1 for the bare * (1 or 2 for the full SSH-1 or SSH-2 protocol; -1 for the bare
* SSH-2 connection protocol, i.e. a downstream; 0 for not-decided-yet.) * SSH-2 connection protocol, i.e. a downstream; 0 for not-decided-yet.)
*/ */
static int ssh_cfg_info(void *handle) static int ssh_cfg_info(Backend *be)
{ {
Ssh ssh = (Ssh) handle; Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
if (ssh->version == 0) if (ssh->version == 0)
return 0; /* don't know yet */ return 0; /* don't know yet */
else if (ssh->bare_connection) else if (ssh->bare_connection)
@ -11469,13 +11471,13 @@ static int ssh_cfg_info(void *handle)
* that fails. This variable is the means by which scp.c can reach * that fails. This variable is the means by which scp.c can reach
* into the SSH code and find out which one it got. * into the SSH code and find out which one it got.
*/ */
extern int ssh_fallback_cmd(void *handle) extern int ssh_fallback_cmd(Backend *be)
{ {
Ssh ssh = (Ssh) handle; Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
return ssh->fallback_cmd; return ssh->fallback_cmd;
} }
Backend ssh_backend = { const struct Backend_vtable ssh_backend = {
ssh_init, ssh_init,
ssh_free, ssh_free,
ssh_reconfig, ssh_reconfig,

2
ssh.h
View File

@ -629,7 +629,7 @@ extern const char sshver[];
* that fails. This variable is the means by which scp.c can reach * that fails. This variable is the means by which scp.c can reach
* into the SSH code and find out which one it got. * into the SSH code and find out which one it got.
*/ */
extern int ssh_fallback_cmd(void *handle); extern int ssh_fallback_cmd(Backend *backend);
void SHATransform(word32 * digest, word32 * data); void SHATransform(word32 * digest, word32 * data);

View File

@ -117,8 +117,6 @@ static const char *telopt(int opt)
#undef telnet_str #undef telnet_str
} }
static void telnet_size(void *handle, int width, int height);
struct Opt { struct Opt {
int send; /* what we initially send */ int send; /* what we initially send */
int nsend; /* -ve send if requested to stop it */ int nsend; /* -ve send if requested to stop it */
@ -199,6 +197,7 @@ typedef struct telnet_tag {
Pinger pinger; Pinger pinger;
const Plug_vtable *plugvt; const Plug_vtable *plugvt;
Backend backend;
} *Telnet; } *Telnet;
#define TELNET_MAX_BACKLOG 4096 #define TELNET_MAX_BACKLOG 4096
@ -280,7 +279,8 @@ static void option_side_effects(Telnet telnet, const struct Opt *o, int enabled)
static void activate_option(Telnet telnet, const struct Opt *o) static void activate_option(Telnet telnet, const struct Opt *o)
{ {
if (o->send == WILL && o->option == TELOPT_NAWS) if (o->send == WILL && o->option == TELOPT_NAWS)
telnet_size(telnet, telnet->term_width, telnet->term_height); backend_size(&telnet->backend,
telnet->term_width, telnet->term_height);
if (o->send == WILL && if (o->send == WILL &&
(o->option == TELOPT_NEW_ENVIRON || (o->option == TELOPT_NEW_ENVIRON ||
o->option == TELOPT_OLD_ENVIRON)) { o->option == TELOPT_OLD_ENVIRON)) {
@ -705,7 +705,7 @@ static const Plug_vtable Telnet_plugvt = {
* Also places the canonical host name into `realhost'. It must be * Also places the canonical host name into `realhost'. It must be
* freed by the caller. * freed by the caller.
*/ */
static const char *telnet_init(void *frontend_handle, void **backend_handle, static const char *telnet_init(void *frontend_handle, Backend **backend_handle,
Conf *conf, const char *host, int port, Conf *conf, const char *host, int port,
char **realhost, int nodelay, int keepalive) char **realhost, int nodelay, int keepalive)
{ {
@ -717,6 +717,7 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle,
telnet = snew(struct telnet_tag); telnet = snew(struct telnet_tag);
telnet->plugvt = &Telnet_plugvt; telnet->plugvt = &Telnet_plugvt;
telnet->backend.vt = &telnet_backend;
telnet->conf = conf_copy(conf); telnet->conf = conf_copy(conf);
telnet->s = NULL; telnet->s = NULL;
telnet->closed_on_socket_error = FALSE; telnet->closed_on_socket_error = FALSE;
@ -732,7 +733,7 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle,
telnet->ldisc = NULL; telnet->ldisc = NULL;
telnet->pinger = NULL; telnet->pinger = NULL;
telnet->session_started = TRUE; telnet->session_started = TRUE;
*backend_handle = telnet; *backend_handle = &telnet->backend;
/* /*
* Try to find host. * Try to find host.
@ -756,7 +757,7 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle,
if ((err = sk_socket_error(telnet->s)) != NULL) if ((err = sk_socket_error(telnet->s)) != NULL)
return err; return err;
telnet->pinger = pinger_new(telnet->conf, &telnet_backend, telnet); telnet->pinger = pinger_new(telnet->conf, &telnet->backend);
/* /*
* Initialise option states. * Initialise option states.
@ -805,9 +806,9 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle,
return NULL; return NULL;
} }
static void telnet_free(void *handle) static void telnet_free(Backend *be)
{ {
Telnet telnet = (Telnet) handle; Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
sfree(telnet->sb_buf); sfree(telnet->sb_buf);
if (telnet->s) if (telnet->s)
@ -822,9 +823,9 @@ static void telnet_free(void *handle)
* necessary, in this backend: we just save the fresh config for * necessary, in this backend: we just save the fresh config for
* any subsequent negotiations. * any subsequent negotiations.
*/ */
static void telnet_reconfig(void *handle, Conf *conf) static void telnet_reconfig(Backend *be, Conf *conf)
{ {
Telnet telnet = (Telnet) handle; Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
pinger_reconfig(telnet->pinger, telnet->conf, conf); pinger_reconfig(telnet->pinger, telnet->conf, conf);
conf_free(telnet->conf); conf_free(telnet->conf);
telnet->conf = conf_copy(conf); telnet->conf = conf_copy(conf);
@ -833,9 +834,9 @@ static void telnet_reconfig(void *handle, Conf *conf)
/* /*
* Called to send data down the Telnet connection. * Called to send data down the Telnet connection.
*/ */
static int telnet_send(void *handle, const char *buf, int len) static int telnet_send(Backend *be, const char *buf, int len)
{ {
Telnet telnet = (Telnet) handle; Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
unsigned char *p, *end; unsigned char *p, *end;
static const unsigned char iac[2] = { IAC, IAC }; static const unsigned char iac[2] = { IAC, IAC };
static const unsigned char cr[2] = { CR, NUL }; static const unsigned char cr[2] = { CR, NUL };
@ -868,18 +869,18 @@ static int telnet_send(void *handle, const char *buf, int len)
/* /*
* Called to query the current socket sendability status. * Called to query the current socket sendability status.
*/ */
static int telnet_sendbuffer(void *handle) static int telnet_sendbuffer(Backend *be)
{ {
Telnet telnet = (Telnet) handle; Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
return telnet->bufsize; return telnet->bufsize;
} }
/* /*
* Called to set the size of the window from Telnet's POV. * Called to set the size of the window from Telnet's POV.
*/ */
static void telnet_size(void *handle, int width, int height) static void telnet_size(Backend *be, int width, int height)
{ {
Telnet telnet = (Telnet) handle; Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
unsigned char b[24]; unsigned char b[24];
int n; int n;
char *logbuf; char *logbuf;
@ -913,9 +914,9 @@ static void telnet_size(void *handle, int width, int height)
/* /*
* Send Telnet special codes. * Send Telnet special codes.
*/ */
static void telnet_special(void *handle, Telnet_Special code) static void telnet_special(Backend *be, Telnet_Special code)
{ {
Telnet telnet = (Telnet) handle; Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
unsigned char b[2]; unsigned char b[2];
if (telnet->s == NULL) if (telnet->s == NULL)
@ -1008,7 +1009,7 @@ static void telnet_special(void *handle, Telnet_Special code)
} }
} }
static const struct telnet_special *telnet_get_specials(void *handle) static const struct telnet_special *telnet_get_specials(Backend *be)
{ {
static const struct telnet_special specials[] = { static const struct telnet_special specials[] = {
{"Are You There", TS_AYT}, {"Are You There", TS_AYT},
@ -1031,27 +1032,27 @@ static const struct telnet_special *telnet_get_specials(void *handle)
return specials; return specials;
} }
static int telnet_connected(void *handle) static int telnet_connected(Backend *be)
{ {
Telnet telnet = (Telnet) handle; Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
return telnet->s != NULL; return telnet->s != NULL;
} }
static int telnet_sendok(void *handle) static int telnet_sendok(Backend *be)
{ {
/* Telnet telnet = (Telnet) handle; */ /* Telnet telnet = FROMFIELD(be, struct telnet_tag, backend); */
return 1; return 1;
} }
static void telnet_unthrottle(void *handle, int backlog) static void telnet_unthrottle(Backend *be, int backlog)
{ {
Telnet telnet = (Telnet) handle; Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
sk_set_frozen(telnet->s, backlog > TELNET_MAX_BACKLOG); sk_set_frozen(telnet->s, backlog > TELNET_MAX_BACKLOG);
} }
static int telnet_ldisc(void *handle, int option) static int telnet_ldisc(Backend *be, int option)
{ {
Telnet telnet = (Telnet) handle; Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
if (option == LD_ECHO) if (option == LD_ECHO)
return telnet->echoing; return telnet->echoing;
if (option == LD_EDIT) if (option == LD_EDIT)
@ -1059,20 +1060,20 @@ static int telnet_ldisc(void *handle, int option)
return FALSE; return FALSE;
} }
static void telnet_provide_ldisc(void *handle, Ldisc *ldisc) static void telnet_provide_ldisc(Backend *be, Ldisc *ldisc)
{ {
Telnet telnet = (Telnet) handle; Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
telnet->ldisc = ldisc; telnet->ldisc = ldisc;
} }
static void telnet_provide_logctx(void *handle, LogContext *logctx) static void telnet_provide_logctx(Backend *be, LogContext *logctx)
{ {
/* This is a stub. */ /* This is a stub. */
} }
static int telnet_exitcode(void *handle) static int telnet_exitcode(Backend *be)
{ {
Telnet telnet = (Telnet) handle; Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
if (telnet->s != NULL) if (telnet->s != NULL)
return -1; /* still connected */ return -1; /* still connected */
else if (telnet->closed_on_socket_error) else if (telnet->closed_on_socket_error)
@ -1085,12 +1086,12 @@ static int telnet_exitcode(void *handle)
/* /*
* cfg_info for Telnet does nothing at all. * cfg_info for Telnet does nothing at all.
*/ */
static int telnet_cfg_info(void *handle) static int telnet_cfg_info(Backend *be)
{ {
return 0; return 0;
} }
Backend telnet_backend = { const struct Backend_vtable telnet_backend = {
telnet_init, telnet_init,
telnet_free, telnet_free,
telnet_reconfig, telnet_reconfig,

View File

@ -1693,8 +1693,7 @@ Terminal *term_init(Conf *myconf, struct unicode_data *ucsdata,
term->lastbeep = FALSE; term->lastbeep = FALSE;
term->beep_overloaded = FALSE; term->beep_overloaded = FALSE;
term->attr_mask = 0xffffffff; term->attr_mask = 0xffffffff;
term->resize_fn = NULL; term->backend = NULL;
term->resize_ctx = NULL;
term->in_term_out = FALSE; term->in_term_out = FALSE;
term->ltemp = NULL; term->ltemp = NULL;
term->ltemp_size = 0; term->ltemp_size = 0;
@ -1964,22 +1963,18 @@ void term_size(Terminal *term, int newrows, int newcols, int newsavelines)
update_sbar(term); update_sbar(term);
term_update(term); term_update(term);
if (term->resize_fn) if (term->backend)
term->resize_fn(term->resize_ctx, term->cols, term->rows); backend_size(term->backend, term->cols, term->rows);
} }
/* /*
* Hand a function and context pointer to the terminal which it can * Hand a backend to the terminal, so it can be notified of resizes.
* use to notify a back end of resizes.
*/ */
void term_provide_resize_fn(Terminal *term, void term_provide_backend(Terminal *term, Backend *backend)
void (*resize_fn)(void *, int, int),
void *resize_ctx)
{ {
term->resize_fn = resize_fn; term->backend = backend;
term->resize_ctx = resize_ctx; if (term->backend && term->cols > 0 && term->rows > 0)
if (resize_fn && term->cols > 0 && term->rows > 0) backend_size(term->backend, term->cols, term->rows);
resize_fn(resize_ctx, term->cols, term->rows);
} }
/* Find the bottom line on the screen that has any content. /* Find the bottom line on the screen that has any content.

View File

@ -227,8 +227,7 @@ struct terminal_tag {
wchar_t *paste_buffer; wchar_t *paste_buffer;
int paste_len, paste_pos; int paste_len, paste_pos;
void (*resize_fn)(void *, int, int); Backend *backend;
void *resize_ctx;
Ldisc *ldisc; Ldisc *ldisc;

View File

@ -32,36 +32,36 @@
#include "putty.h" #include "putty.h"
static const char *null_init(void *, void **, Conf *, const char *, int, static const char *null_init(void *, Backend **, Conf *, const char *, int,
char **, int, int); char **, int, int);
static const char *loop_init(void *, void **, Conf *, const char *, int, static const char *loop_init(void *, Backend **, Conf *, const char *, int,
char **, int, int); char **, int, int);
static void null_free(void *); static void null_free(Backend *);
static void loop_free(void *); static void loop_free(Backend *);
static void null_reconfig(void *, Conf *); static void null_reconfig(Backend *, Conf *);
static int null_send(void *, const char *, int); static int null_send(Backend *, const char *, int);
static int loop_send(void *, const char *, int); static int loop_send(Backend *, const char *, int);
static int null_sendbuffer(void *); static int null_sendbuffer(Backend *);
static void null_size(void *, int, int); static void null_size(Backend *, int, int);
static void null_special(void *, Telnet_Special); static void null_special(Backend *, Telnet_Special);
static const struct telnet_special *null_get_specials(void *handle); static const struct telnet_special *null_get_specials(Backend *);
static int null_connected(void *); static int null_connected(Backend *);
static int null_exitcode(void *); static int null_exitcode(Backend *);
static int null_sendok(void *); static int null_sendok(Backend *);
static int null_ldisc(void *, int); static int null_ldisc(Backend *, int);
static void null_provide_ldisc(void *, Ldisc *); static void null_provide_ldisc(Backend *, Ldisc *);
static void null_provide_logctx(void *, LogContext *); static void null_provide_logctx(Backend *, LogContext *);
static void null_unthrottle(void *, int); static void null_unthrottle(Backend *, int);
static int null_cfg_info(void *); static int null_cfg_info(Backend *);
Backend null_backend = { const struct Backend_vtable null_backend = {
null_init, null_free, null_reconfig, null_send, null_sendbuffer, null_size, null_init, null_free, null_reconfig, null_send, null_sendbuffer, null_size,
null_special, null_get_specials, null_connected, null_exitcode, null_sendok, null_special, null_get_specials, null_connected, null_exitcode, null_sendok,
null_ldisc, null_provide_ldisc, null_provide_logctx, null_unthrottle, null_ldisc, null_provide_ldisc, null_provide_logctx, null_unthrottle,
null_cfg_info, NULL /* test_for_upstream */, "null", -1, 0 null_cfg_info, NULL /* test_for_upstream */, "null", -1, 0
}; };
Backend loop_backend = { const struct Backend_vtable loop_backend = {
loop_init, loop_free, null_reconfig, loop_send, null_sendbuffer, null_size, loop_init, loop_free, null_reconfig, loop_send, null_sendbuffer, null_size,
null_special, null_get_specials, null_connected, null_exitcode, null_sendok, null_special, null_get_specials, null_connected, null_exitcode, null_sendok,
null_ldisc, null_provide_ldisc, null_provide_logctx, null_unthrottle, null_ldisc, null_provide_ldisc, null_provide_logctx, null_unthrottle,
@ -70,102 +70,104 @@ Backend loop_backend = {
struct loop_state { struct loop_state {
Terminal *term; Terminal *term;
Backend backend;
}; };
static const char *null_init(void *frontend_handle, void **backend_handle, static const char *null_init(void *frontend_handle, Backend **backend_handle,
Conf *conf, const char *host, int port, Conf *conf, const char *host, int port,
char **realhost, int nodelay, int keepalive) { char **realhost, int nodelay, int keepalive) {
*backend_handle = NULL;
return NULL; return NULL;
} }
static const char *loop_init(void *frontend_handle, void **backend_handle, static const char *loop_init(void *frontend_handle, Backend **backend_handle,
Conf *conf, const char *host, int port, Conf *conf, const char *host, int port,
char **realhost, int nodelay, int keepalive) { char **realhost, int nodelay, int keepalive) {
struct loop_state *st = snew(struct loop_state); struct loop_state *st = snew(struct loop_state);
st->term = frontend_handle; st->term = frontend_handle;
*backend_handle = st; *backend_handle = &st->backend;
return NULL; return NULL;
} }
static void null_free(void *handle) static void null_free(Backend *be)
{ {
} }
static void loop_free(void *handle) static void loop_free(Backend *be)
{ {
struct loop_state *st = FROMFIELD(be, struct loop_state, backend);
sfree(handle); sfree(st);
} }
static void null_reconfig(void *handle, Conf *conf) { static void null_reconfig(Backend *be, Conf *conf) {
} }
static int null_send(void *handle, const char *buf, int len) { static int null_send(Backend *be, const char *buf, int len) {
return 0; return 0;
} }
static int loop_send(void *handle, const char *buf, int len) { static int loop_send(Backend *be, const char *buf, int len) {
struct loop_state *st = handle; struct loop_state *st = FROMFIELD(be, struct loop_state, backend);
return from_backend(st->term, 0, buf, len); return from_backend(st->term, 0, buf, len);
} }
static int null_sendbuffer(void *handle) { static int null_sendbuffer(Backend *be) {
return 0; return 0;
} }
static void null_size(void *handle, int width, int height) { static void null_size(Backend *be, int width, int height) {
} }
static void null_special(void *handle, Telnet_Special code) { static void null_special(Backend *be, Telnet_Special code) {
} }
static const struct telnet_special *null_get_specials (void *handle) { static const struct telnet_special *null_get_specials (Backend *be) {
return NULL; return NULL;
} }
static int null_connected(void *handle) { static int null_connected(Backend *be) {
return 0; return 0;
} }
static int null_exitcode(void *handle) { static int null_exitcode(Backend *be) {
return 0; return 0;
} }
static int null_sendok(void *handle) { static int null_sendok(Backend *be) {
return 1; return 1;
} }
static void null_unthrottle(void *handle, int backlog) { static void null_unthrottle(Backend *be, int backlog) {
} }
static int null_ldisc(void *handle, int option) { static int null_ldisc(Backend *be, int option) {
return 0; return 0;
} }
static void null_provide_ldisc (void *handle, Ldisc *ldisc) { static void null_provide_ldisc (Backend *be, Ldisc *ldisc) {
} }
static void null_provide_logctx(void *handle, LogContext *logctx) { static void null_provide_logctx(Backend *be, LogContext *logctx) {
} }
static int null_cfg_info(void *handle) static int null_cfg_info(Backend *be)
{ {
return 0; return 0;
} }

View File

@ -159,8 +159,7 @@ struct gui_data {
char *icontitle; char *icontitle;
int master_fd, master_func_id; int master_fd, master_func_id;
Ldisc *ldisc; Ldisc *ldisc;
Backend *back; Backend *backend;
void *backhandle;
Terminal *term; Terminal *term;
LogContext *logctx; LogContext *logctx;
int exited; int exited;
@ -1609,8 +1608,8 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
#ifdef KEY_EVENT_DIAGNOSTICS #ifdef KEY_EVENT_DIAGNOSTICS
debug((" - Ctrl-Break special case, sending TS_BRK\n")); debug((" - Ctrl-Break special case, sending TS_BRK\n"));
#endif #endif
if (inst->back) if (inst->backend)
inst->back->special(inst->backhandle, TS_BRK); backend_special(inst->backend, TS_BRK);
return TRUE; return TRUE;
} }
@ -2399,7 +2398,7 @@ static void exit_callback(void *vinst)
int exitcode, close_on_exit; int exitcode, close_on_exit;
if (!inst->exited && if (!inst->exited &&
(exitcode = inst->back->exitcode(inst->backhandle)) >= 0) { (exitcode = backend_exitcode(inst->backend)) >= 0) {
destroy_inst_connection(inst); destroy_inst_connection(inst);
close_on_exit = conf_get_int(inst->conf, CONF_close_on_exit); close_on_exit = conf_get_int(inst->conf, CONF_close_on_exit);
@ -2424,13 +2423,12 @@ static void destroy_inst_connection(struct gui_data *inst)
ldisc_free(inst->ldisc); ldisc_free(inst->ldisc);
inst->ldisc = NULL; inst->ldisc = NULL;
} }
if (inst->backhandle) { if (inst->backend) {
inst->back->free(inst->backhandle); backend_free(inst->backend);
inst->backhandle = NULL; inst->backend = NULL;
inst->back = NULL;
} }
if (inst->term) if (inst->term)
term_provide_resize_fn(inst->term, NULL, NULL); term_provide_backend(inst->term, NULL);
if (inst->menu) { if (inst->menu) {
update_specials_menu(inst); update_specials_menu(inst);
gtk_widget_set_sensitive(inst->restartitem, TRUE); gtk_widget_set_sensitive(inst->restartitem, TRUE);
@ -4480,8 +4478,8 @@ void special_menuitem(GtkMenuItem *item, gpointer data)
int code = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(item), int code = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(item),
"user-data")); "user-data"));
if (inst->back) if (inst->backend)
inst->back->special(inst->backhandle, code); backend_special(inst->backend, code);
} }
void about_menuitem(GtkMenuItem *item, gpointer data) void about_menuitem(GtkMenuItem *item, gpointer data)
@ -4582,7 +4580,7 @@ void change_settings_menuitem(GtkMenuItem *item, gpointer data)
dialog = create_config_box( dialog = create_config_box(
title, ctx->newconf, 1, title, ctx->newconf, 1,
inst->back ? inst->back->cfg_info(inst->backhandle) : 0, inst->backend ? backend_cfg_info(inst->backend) : 0,
after_change_settings_dialog, ctx); after_change_settings_dialog, ctx);
register_dialog(inst, DIALOG_SLOT_RECONFIGURE, dialog); register_dialog(inst, DIALOG_SLOT_RECONFIGURE, dialog);
@ -4633,8 +4631,8 @@ static void after_change_settings_dialog(void *vctx, int retval)
term_reconfig(inst->term, inst->conf); term_reconfig(inst->term, inst->conf);
setup_clipboards(inst, inst->term, inst->conf); setup_clipboards(inst, inst->term, inst->conf);
/* Pass new config data to the back end */ /* Pass new config data to the back end */
if (inst->back) if (inst->backend)
inst->back->reconfig(inst->backhandle, inst->conf); backend_reconfig(inst->backend, inst->conf);
cache_conf_values(inst); cache_conf_values(inst);
@ -4851,7 +4849,7 @@ void restart_session_menuitem(GtkMenuItem *item, gpointer data)
{ {
struct gui_data *inst = (struct gui_data *)data; struct gui_data *inst = (struct gui_data *)data;
if (!inst->back) { if (!inst->backend) {
logevent(inst, "----- Session restarted -----"); logevent(inst, "----- Session restarted -----");
term_pwron(inst->term, FALSE); term_pwron(inst->term, FALSE);
start_backend(inst); start_backend(inst);
@ -4984,8 +4982,8 @@ void update_specials_menu(void *frontend)
const struct telnet_special *specials; const struct telnet_special *specials;
if (inst->back) if (inst->backend)
specials = inst->back->get_specials(inst->backhandle); specials = backend_get_specials(inst->backend);
else else
specials = NULL; specials = NULL;
@ -5045,20 +5043,20 @@ void update_specials_menu(void *frontend)
static void start_backend(struct gui_data *inst) static void start_backend(struct gui_data *inst)
{ {
extern Backend *select_backend(Conf *conf); const struct Backend_vtable *vt;
char *realhost; char *realhost;
const char *error; const char *error;
char *s; char *s;
inst->back = select_backend(inst->conf); vt = select_backend(inst->conf);
error = inst->back->init((void *)inst, &inst->backhandle, error = backend_init(vt, (void *)inst, &inst->backend,
inst->conf, inst->conf,
conf_get_str(inst->conf, CONF_host), conf_get_str(inst->conf, CONF_host),
conf_get_int(inst->conf, CONF_port), conf_get_int(inst->conf, CONF_port),
&realhost, &realhost,
conf_get_int(inst->conf, CONF_tcp_nodelay), conf_get_int(inst->conf, CONF_tcp_nodelay),
conf_get_int(inst->conf, CONF_tcp_keepalives)); conf_get_int(inst->conf, CONF_tcp_keepalives));
if (error) { if (error) {
char *msg = dupprintf("Unable to open connection to %s:\n%s", char *msg = dupprintf("Unable to open connection to %s:\n%s",
@ -5079,13 +5077,11 @@ static void start_backend(struct gui_data *inst)
} }
sfree(realhost); sfree(realhost);
inst->back->provide_logctx(inst->backhandle, inst->logctx); backend_provide_logctx(inst->backend, inst->logctx);
term_provide_resize_fn(inst->term, inst->back->size, inst->backhandle); term_provide_backend(inst->term, inst->backend);
inst->ldisc = inst->ldisc = ldisc_create(inst->conf, inst->term, inst->backend, inst);
ldisc_create(inst->conf, inst->term, inst->back, inst->backhandle,
inst);
gtk_widget_set_sensitive(inst->restartitem, FALSE); gtk_widget_set_sensitive(inst->restartitem, FALSE);
} }

View File

@ -67,7 +67,7 @@ struct FontSpec *fontspec_new(const char *name);
typedef void *Context; /* FIXME: probably needs changing */ typedef void *Context; /* FIXME: probably needs changing */
extern Backend pty_backend; extern const struct Backend_vtable pty_backend;
#define BROKEN_PIPE_ERROR_CODE EPIPE /* used in sshshare.c */ #define BROKEN_PIPE_ERROR_CODE EPIPE /* used in sshshare.c */
@ -178,6 +178,8 @@ void window_setup_error(const char *errmsg);
GtkWidget *make_gtk_toplevel_window(void *frontend); GtkWidget *make_gtk_toplevel_window(void *frontend);
#endif #endif
const struct Backend_vtable *select_backend(Conf *conf);
/* Defined in gtkcomm.c */ /* Defined in gtkcomm.c */
void gtkcomm_setup(void); void gtkcomm_setup(void);
@ -324,9 +326,9 @@ void *sk_getxdmdata(Socket sock, int *lenp);
} while (0) } while (0)
/* /*
* Exports from winser.c. * Exports from uxser.c.
*/ */
extern Backend serial_backend; extern const struct Backend_vtable serial_backend;
/* /*
* uxpeer.c, wrapping getsockopt(SO_PEERCRED). * uxpeer.c, wrapping getsockopt(SO_PEERCRED).

View File

@ -91,8 +91,7 @@ void cmdline_error(const char *p, ...)
static int local_tty = FALSE; /* do we have a local tty? */ static int local_tty = FALSE; /* do we have a local tty? */
static Backend *back; static Backend *backend;
static void *backhandle;
static Conf *conf; static Conf *conf;
/* /*
@ -459,13 +458,13 @@ static void from_tty(void *vbuf, unsigned len)
} else { } else {
q = memchr(p, '\xff', end - p); q = memchr(p, '\xff', end - p);
if (q == NULL) q = end; if (q == NULL) q = end;
back->send(backhandle, p, q - p); backend_send(backend, p, q - p);
p = q; p = q;
} }
break; break;
case FF: case FF:
if (*p == '\xff') { if (*p == '\xff') {
back->send(backhandle, p, 1); backend_send(backend, p, 1);
p++; p++;
state = NORMAL; state = NORMAL;
} else if (*p == '\0') { } else if (*p == '\0') {
@ -475,7 +474,7 @@ static void from_tty(void *vbuf, unsigned len)
break; break;
case FF00: case FF00:
if (*p == '\0') { if (*p == '\0') {
back->special(backhandle, TS_BRK); backend_special(backend, TS_BRK);
} else { } else {
/* /*
* Pretend that PARMRK wasn't set. This involves * Pretend that PARMRK wasn't set. This involves
@ -494,11 +493,11 @@ static void from_tty(void *vbuf, unsigned len)
if (!(orig_termios.c_iflag & IGNPAR)) { if (!(orig_termios.c_iflag & IGNPAR)) {
/* PE/FE get passed on as NUL. */ /* PE/FE get passed on as NUL. */
*p = 0; *p = 0;
back->send(backhandle, p, 1); backend_send(backend, p, 1);
} }
} else { } else {
/* INPCK not set. Assume we got a parity error. */ /* INPCK not set. Assume we got a parity error. */
back->send(backhandle, p, 1); backend_send(backend, p, 1);
} }
} }
p++; p++;
@ -606,6 +605,7 @@ int main(int argc, char **argv)
int just_test_share_exists = FALSE; int just_test_share_exists = FALSE;
unsigned long now; unsigned long now;
struct winsize size; struct winsize size;
const struct Backend_vtable *backvt;
fdlist = NULL; fdlist = NULL;
fdcount = fdsize = 0; fdcount = fdsize = 0;
@ -643,10 +643,10 @@ int main(int argc, char **argv)
*/ */
char *p = getenv("PLINK_PROTOCOL"); char *p = getenv("PLINK_PROTOCOL");
if (p) { if (p) {
const Backend *b = backend_from_name(p); const struct Backend_vtable *vt = backend_vt_from_name(p);
if (b) { if (vt) {
default_protocol = b->protocol; default_protocol = vt->protocol;
default_port = b->default_port; default_port = vt->default_port;
conf_set_int(conf, CONF_protocol, default_protocol); conf_set_int(conf, CONF_protocol, default_protocol);
conf_set_int(conf, CONF_port, default_port); conf_set_int(conf, CONF_port, default_port);
} }
@ -766,8 +766,8 @@ int main(int argc, char **argv)
* Select protocol. This is farmed out into a table in a * Select protocol. This is farmed out into a table in a
* separate file to enable an ssh-free variant. * separate file to enable an ssh-free variant.
*/ */
back = backend_from_proto(conf_get_int(conf, CONF_protocol)); backvt = backend_vt_from_proto(conf_get_int(conf, CONF_protocol));
if (back == NULL) { if (!backvt) {
fprintf(stderr, fprintf(stderr,
"Internal fault: Unsupported protocol found\n"); "Internal fault: Unsupported protocol found\n");
return 1; return 1;
@ -817,13 +817,13 @@ int main(int argc, char **argv)
conf_set_int(conf, CONF_ssh_simple, TRUE); conf_set_int(conf, CONF_ssh_simple, TRUE);
if (just_test_share_exists) { if (just_test_share_exists) {
if (!back->test_for_upstream) { if (!backvt->test_for_upstream) {
fprintf(stderr, "Connection sharing not supported for connection " fprintf(stderr, "Connection sharing not supported for connection "
"type '%s'\n", back->name); "type '%s'\n", backvt->name);
return 1; return 1;
} }
if (back->test_for_upstream(conf_get_str(conf, CONF_host), if (backvt->test_for_upstream(conf_get_str(conf, CONF_host),
conf_get_int(conf, CONF_port), conf)) conf_get_int(conf, CONF_port), conf))
return 0; return 0;
else else
return 1; return 1;
@ -845,17 +845,17 @@ int main(int argc, char **argv)
__AFL_INIT(); __AFL_INIT();
#endif #endif
error = back->init(NULL, &backhandle, conf, error = backend_init(backvt, NULL, &backend, conf,
conf_get_str(conf, CONF_host), conf_get_str(conf, CONF_host),
conf_get_int(conf, CONF_port), conf_get_int(conf, CONF_port),
&realhost, nodelay, &realhost, nodelay,
conf_get_int(conf, CONF_tcp_keepalives)); conf_get_int(conf, CONF_tcp_keepalives));
if (error) { if (error) {
fprintf(stderr, "Unable to open connection:\n%s\n", error); fprintf(stderr, "Unable to open connection:\n%s\n", error);
return 1; return 1;
} }
back->provide_logctx(backhandle, logctx); backend_provide_logctx(backend, logctx);
ldisc_create(conf, NULL, back, backhandle, NULL); ldisc_create(conf, NULL, backend, NULL);
sfree(realhost); sfree(realhost);
} }
@ -885,9 +885,9 @@ int main(int argc, char **argv)
FD_SET_MAX(signalpipe[0], maxfd, rset); FD_SET_MAX(signalpipe[0], maxfd, rset);
if (!sending && if (!sending &&
back->connected(backhandle) && backend_connected(backend) &&
back->sendok(backhandle) && backend_sendok(backend) &&
back->sendbuffer(backhandle) < MAX_STDIN_BACKLOG) { backend_sendbuffer(backend) < MAX_STDIN_BACKLOG) {
/* If we're OK to send, then try to read from stdin. */ /* If we're OK to send, then try to read from stdin. */
FD_SET_MAX(STDIN_FILENO, maxfd, rset); FD_SET_MAX(STDIN_FILENO, maxfd, rset);
} }
@ -988,46 +988,46 @@ int main(int argc, char **argv)
/* ignore error */; /* ignore error */;
/* ignore its value; it'll be `x' */ /* ignore its value; it'll be `x' */
if (ioctl(STDIN_FILENO, TIOCGWINSZ, (void *)&size) >= 0) if (ioctl(STDIN_FILENO, TIOCGWINSZ, (void *)&size) >= 0)
back->size(backhandle, size.ws_col, size.ws_row); backend_size(backend, size.ws_col, size.ws_row);
} }
if (FD_ISSET(STDIN_FILENO, &rset)) { if (FD_ISSET(STDIN_FILENO, &rset)) {
char buf[4096]; char buf[4096];
int ret; int ret;
if (back->connected(backhandle)) { if (backend_connected(backend)) {
ret = read(STDIN_FILENO, buf, sizeof(buf)); ret = read(STDIN_FILENO, buf, sizeof(buf));
if (ret < 0) { if (ret < 0) {
perror("stdin: read"); perror("stdin: read");
exit(1); exit(1);
} else if (ret == 0) { } else if (ret == 0) {
back->special(backhandle, TS_EOF); backend_special(backend, TS_EOF);
sending = FALSE; /* send nothing further after this */ sending = FALSE; /* send nothing further after this */
} else { } else {
if (local_tty) if (local_tty)
from_tty(buf, ret); from_tty(buf, ret);
else else
back->send(backhandle, buf, ret); backend_send(backend, buf, ret);
} }
} }
} }
if (FD_ISSET(STDOUT_FILENO, &wset)) { if (FD_ISSET(STDOUT_FILENO, &wset)) {
back->unthrottle(backhandle, try_output(FALSE)); backend_unthrottle(backend, try_output(FALSE));
} }
if (FD_ISSET(STDERR_FILENO, &wset)) { if (FD_ISSET(STDERR_FILENO, &wset)) {
back->unthrottle(backhandle, try_output(TRUE)); backend_unthrottle(backend, try_output(TRUE));
} }
run_toplevel_callbacks(); run_toplevel_callbacks();
if (!back->connected(backhandle) && if (!backend_connected(backend) &&
bufchain_size(&stdout_data) == 0 && bufchain_size(&stdout_data) == 0 &&
bufchain_size(&stderr_data) == 0) bufchain_size(&stderr_data) == 0)
break; /* we closed the connection */ break; /* we closed the connection */
} }
exitcode = back->exitcode(backhandle); exitcode = backend_exitcode(backend);
if (exitcode < 0) { if (exitcode < 0) {
fprintf(stderr, "Remote process exit code unavailable\n"); fprintf(stderr, "Remote process exit code unavailable\n");
exitcode = 1; /* this is an error condition */ exitcode = 1; /* this is an error condition */

View File

@ -13,7 +13,7 @@ const int new_session = 0, saved_sessions = 0; /* or these */
const int dup_check_launchable = 0; /* no need to check host name in conf */ const int dup_check_launchable = 0; /* no need to check host name in conf */
const int use_pty_argv = TRUE; const int use_pty_argv = TRUE;
Backend *select_backend(Conf *conf) const struct Backend_vtable *select_backend(Conf *conf)
{ {
return &pty_backend; return &pty_backend;
} }

View File

@ -78,6 +78,7 @@ struct pty_tag {
int child_dead, finished; int child_dead, finished;
int exit_code; int exit_code;
bufchain output_data; bufchain output_data;
Backend backend;
}; };
/* /*
@ -728,9 +729,9 @@ static void pty_uxsel_setup(Pty pty)
* Also places the canonical host name into `realhost'. It must be * Also places the canonical host name into `realhost'. It must be
* freed by the caller. * freed by the caller.
*/ */
static const char *pty_init(void *frontend, void **backend_handle, Conf *conf, static const char *pty_init(void *frontend, Backend **backend_handle,
const char *host, int port, char **realhost, Conf *conf, const char *host, int port,
int nodelay, int keepalive) char **realhost, int nodelay, int keepalive)
{ {
int slavefd; int slavefd;
pid_t pid, pgrp; pid_t pid, pgrp;
@ -752,7 +753,8 @@ static const char *pty_init(void *frontend, void **backend_handle, Conf *conf,
} }
pty->frontend = frontend; pty->frontend = frontend;
*backend_handle = NULL; /* we can't sensibly use this, sadly */ pty->backend.vt = &pty_backend;
*backend_handle = &pty->backend;
pty->conf = conf_copy(conf); pty->conf = conf_copy(conf);
pty->term_width = conf_get_int(conf, CONF_width); pty->term_width = conf_get_int(conf, CONF_width);
@ -1025,16 +1027,14 @@ static const char *pty_init(void *frontend, void **backend_handle, Conf *conf,
} }
pty_uxsel_setup(pty); pty_uxsel_setup(pty);
*backend_handle = pty;
*realhost = dupstr(""); *realhost = dupstr("");
return NULL; return NULL;
} }
static void pty_reconfig(void *handle, Conf *conf) static void pty_reconfig(Backend *be, Conf *conf)
{ {
Pty pty = (Pty)handle; Pty pty = FROMFIELD(be, struct pty_tag, backend);
/* /*
* We don't have much need to reconfigure this backend, but * We don't have much need to reconfigure this backend, but
* unfortunately we do need to pick up the setting of Close On * unfortunately we do need to pick up the setting of Close On
@ -1046,9 +1046,9 @@ static void pty_reconfig(void *handle, Conf *conf)
/* /*
* Stub routine (never called in pterm). * Stub routine (never called in pterm).
*/ */
static void pty_free(void *handle) static void pty_free(Backend *be)
{ {
Pty pty = (Pty)handle; Pty pty = FROMFIELD(be, struct pty_tag, backend);
/* Either of these may fail `not found'. That's fine with us. */ /* Either of these may fail `not found'. That's fine with us. */
del234(ptys_by_pid, pty); del234(ptys_by_pid, pty);
@ -1099,9 +1099,9 @@ static void pty_try_write(Pty pty)
/* /*
* Called to send data down the pty. * Called to send data down the pty.
*/ */
static int pty_send(void *handle, const char *buf, int len) static int pty_send(Backend *be, const char *buf, int len)
{ {
Pty pty = (Pty)handle; Pty pty = FROMFIELD(be, struct pty_tag, backend);
if (pty->master_fd < 0) if (pty->master_fd < 0)
return 0; /* ignore all writes if fd closed */ return 0; /* ignore all writes if fd closed */
@ -1129,18 +1129,18 @@ static void pty_close(Pty pty)
/* /*
* Called to query the current socket sendability status. * Called to query the current socket sendability status.
*/ */
static int pty_sendbuffer(void *handle) static int pty_sendbuffer(Backend *be)
{ {
/* Pty pty = (Pty)handle; */ /* Pty pty = FROMFIELD(be, struct pty_tag, backend); */
return 0; return 0;
} }
/* /*
* Called to set the size of the window * Called to set the size of the window
*/ */
static void pty_size(void *handle, int width, int height) static void pty_size(Backend *be, int width, int height)
{ {
Pty pty = (Pty)handle; Pty pty = FROMFIELD(be, struct pty_tag, backend);
struct winsize size; struct winsize size;
pty->term_width = width; pty->term_width = width;
@ -1159,9 +1159,9 @@ static void pty_size(void *handle, int width, int height)
/* /*
* Send special codes. * Send special codes.
*/ */
static void pty_special(void *handle, Telnet_Special code) static void pty_special(Backend *be, Telnet_Special code)
{ {
/* Pty pty = (Pty)handle; */ /* Pty pty = FROMFIELD(be, struct pty_tag, backend); */
/* Do nothing! */ /* Do nothing! */
return; return;
} }
@ -1170,9 +1170,9 @@ static void pty_special(void *handle, Telnet_Special code)
* Return a list of the special codes that make sense in this * Return a list of the special codes that make sense in this
* protocol. * protocol.
*/ */
static const struct telnet_special *pty_get_specials(void *handle) static const struct telnet_special *pty_get_specials(Backend *be)
{ {
/* Pty pty = (Pty)handle; */ /* Pty pty = FROMFIELD(be, struct pty_tag, backend); */
/* /*
* Hmm. When I get round to having this actually usable, it * Hmm. When I get round to having this actually usable, it
* might be quite nice to have the ability to deliver a few * might be quite nice to have the ability to deliver a few
@ -1182,58 +1182,58 @@ static const struct telnet_special *pty_get_specials(void *handle)
return NULL; return NULL;
} }
static int pty_connected(void *handle) static int pty_connected(Backend *be)
{ {
/* Pty pty = (Pty)handle; */ /* Pty pty = FROMFIELD(be, struct pty_tag, backend); */
return TRUE; return TRUE;
} }
static int pty_sendok(void *handle) static int pty_sendok(Backend *be)
{ {
/* Pty pty = (Pty)handle; */ /* Pty pty = FROMFIELD(be, struct pty_tag, backend); */
return 1; return 1;
} }
static void pty_unthrottle(void *handle, int backlog) static void pty_unthrottle(Backend *be, int backlog)
{ {
/* Pty pty = (Pty)handle; */ /* Pty pty = FROMFIELD(be, struct pty_tag, backend); */
/* do nothing */ /* do nothing */
} }
static int pty_ldisc(void *handle, int option) static int pty_ldisc(Backend *be, int option)
{ {
/* Pty pty = (Pty)handle; */ /* Pty pty = FROMFIELD(be, struct pty_tag, backend); */
return 0; /* neither editing nor echoing */ return 0; /* neither editing nor echoing */
} }
static void pty_provide_ldisc(void *handle, Ldisc *ldisc) static void pty_provide_ldisc(Backend *be, Ldisc *ldisc)
{ {
/* Pty pty = (Pty)handle; */ /* Pty pty = FROMFIELD(be, struct pty_tag, backend); */
/* This is a stub. */ /* This is a stub. */
} }
static void pty_provide_logctx(void *handle, LogContext *logctx) static void pty_provide_logctx(Backend *be, LogContext *logctx)
{ {
/* Pty pty = (Pty)handle; */ /* Pty pty = FROMFIELD(be, struct pty_tag, backend); */
/* This is a stub. */ /* This is a stub. */
} }
static int pty_exitcode(void *handle) static int pty_exitcode(Backend *be)
{ {
Pty pty = (Pty)handle; Pty pty = FROMFIELD(be, struct pty_tag, backend);
if (!pty->finished) if (!pty->finished)
return -1; /* not dead yet */ return -1; /* not dead yet */
else else
return pty->exit_code; return pty->exit_code;
} }
static int pty_cfg_info(void *handle) static int pty_cfg_info(Backend *be)
{ {
/* Pty pty = (Pty)handle; */ /* Pty pty = FROMFIELD(be, struct pty_tag, backend); */
return 0; return 0;
} }
Backend pty_backend = { const struct Backend_vtable pty_backend = {
pty_init, pty_init,
pty_free, pty_free,
pty_reconfig, pty_reconfig,

View File

@ -37,11 +37,12 @@ void cleanup_exit(int code)
exit(code); exit(code);
} }
Backend *select_backend(Conf *conf) const struct Backend_vtable *select_backend(Conf *conf)
{ {
Backend *back = backend_from_proto(conf_get_int(conf, CONF_protocol)); const struct Backend_vtable *vt =
assert(back != NULL); backend_vt_from_proto(conf_get_int(conf, CONF_protocol));
return back; assert(vt != NULL);
return vt;
} }
void initial_config_box(Conf *conf, post_dialog_fn_t after, void *afterctx) void initial_config_box(Conf *conf, post_dialog_fn_t after, void *afterctx)
@ -83,9 +84,10 @@ void setup(int single)
default_protocol = be_default_protocol; default_protocol = be_default_protocol;
/* Find the appropriate default port. */ /* Find the appropriate default port. */
{ {
Backend *b = backend_from_proto(default_protocol); const struct Backend_vtable *vt =
backend_vt_from_proto(default_protocol);
default_port = 0; /* illegal */ default_port = 0; /* illegal */
if (b) if (vt)
default_port = b->default_port; default_port = vt->default_port;
} }
} }

View File

@ -23,6 +23,7 @@ typedef struct serial_backend_data {
int finished; int finished;
int inbufsize; int inbufsize;
bufchain output_data; bufchain output_data;
Backend backend;
} *Serial; } *Serial;
/* /*
@ -287,7 +288,7 @@ static const char *serial_configure(Serial serial, Conf *conf)
* Also places the canonical host name into `realhost'. It must be * Also places the canonical host name into `realhost'. It must be
* freed by the caller. * freed by the caller.
*/ */
static const char *serial_init(void *frontend_handle, void **backend_handle, static const char *serial_init(void *frontend_handle, Backend **backend_handle,
Conf *conf, Conf *conf,
const char *host, int port, char **realhost, const char *host, int port, char **realhost,
int nodelay, int keepalive) int nodelay, int keepalive)
@ -297,7 +298,8 @@ static const char *serial_init(void *frontend_handle, void **backend_handle,
char *line; char *line;
serial = snew(struct serial_backend_data); serial = snew(struct serial_backend_data);
*backend_handle = serial; serial->backend.vt = &serial_backend;
*backend_handle = &serial->backend;
serial->frontend = frontend_handle; serial->frontend = frontend_handle;
serial->finished = FALSE; serial->finished = FALSE;
@ -345,9 +347,9 @@ static void serial_close(Serial serial)
} }
} }
static void serial_free(void *handle) static void serial_free(Backend *be)
{ {
Serial serial = (Serial) handle; Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
serial_close(serial); serial_close(serial);
@ -356,9 +358,9 @@ static void serial_free(void *handle)
sfree(serial); sfree(serial);
} }
static void serial_reconfig(void *handle, Conf *conf) static void serial_reconfig(Backend *be, Conf *conf)
{ {
Serial serial = (Serial) handle; Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
/* /*
* FIXME: what should we do if this returns an error? * FIXME: what should we do if this returns an error?
@ -460,9 +462,9 @@ static void serial_try_write(Serial serial)
/* /*
* Called to send data down the serial connection. * Called to send data down the serial connection.
*/ */
static int serial_send(void *handle, const char *buf, int len) static int serial_send(Backend *be, const char *buf, int len)
{ {
Serial serial = (Serial) handle; Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
if (serial->fd < 0) if (serial->fd < 0)
return 0; return 0;
@ -476,16 +478,16 @@ static int serial_send(void *handle, const char *buf, int len)
/* /*
* Called to query the current sendability status. * Called to query the current sendability status.
*/ */
static int serial_sendbuffer(void *handle) static int serial_sendbuffer(Backend *be)
{ {
Serial serial = (Serial) handle; Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
return bufchain_size(&serial->output_data); return bufchain_size(&serial->output_data);
} }
/* /*
* Called to set the size of the window * Called to set the size of the window
*/ */
static void serial_size(void *handle, int width, int height) static void serial_size(Backend *be, int width, int height)
{ {
/* Do nothing! */ /* Do nothing! */
return; return;
@ -494,9 +496,9 @@ static void serial_size(void *handle, int width, int height)
/* /*
* Send serial special codes. * Send serial special codes.
*/ */
static void serial_special(void *handle, Telnet_Special code) static void serial_special(Backend *be, Telnet_Special code)
{ {
Serial serial = (Serial) handle; Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
if (serial->fd >= 0 && code == TS_BRK) { if (serial->fd >= 0 && code == TS_BRK) {
tcsendbreak(serial->fd, 0); tcsendbreak(serial->fd, 0);
@ -510,7 +512,7 @@ static void serial_special(void *handle, Telnet_Special code)
* Return a list of the special codes that make sense in this * Return a list of the special codes that make sense in this
* protocol. * protocol.
*/ */
static const struct telnet_special *serial_get_specials(void *handle) static const struct telnet_special *serial_get_specials(Backend *be)
{ {
static const struct telnet_special specials[] = { static const struct telnet_special specials[] = {
{"Break", TS_BRK}, {"Break", TS_BRK},
@ -519,24 +521,24 @@ static const struct telnet_special *serial_get_specials(void *handle)
return specials; return specials;
} }
static int serial_connected(void *handle) static int serial_connected(Backend *be)
{ {
return 1; /* always connected */ return 1; /* always connected */
} }
static int serial_sendok(void *handle) static int serial_sendok(Backend *be)
{ {
return 1; return 1;
} }
static void serial_unthrottle(void *handle, int backlog) static void serial_unthrottle(Backend *be, int backlog)
{ {
Serial serial = (Serial) handle; Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
serial->inbufsize = backlog; serial->inbufsize = backlog;
serial_uxsel_setup(serial); serial_uxsel_setup(serial);
} }
static int serial_ldisc(void *handle, int option) static int serial_ldisc(Backend *be, int option)
{ {
/* /*
* Local editing and local echo are off by default. * Local editing and local echo are off by default.
@ -544,19 +546,19 @@ static int serial_ldisc(void *handle, int option)
return 0; return 0;
} }
static void serial_provide_ldisc(void *handle, Ldisc *ldisc) static void serial_provide_ldisc(Backend *be, Ldisc *ldisc)
{ {
/* This is a stub. */ /* This is a stub. */
} }
static void serial_provide_logctx(void *handle, LogContext *logctx) static void serial_provide_logctx(Backend *be, LogContext *logctx)
{ {
/* This is a stub. */ /* This is a stub. */
} }
static int serial_exitcode(void *handle) static int serial_exitcode(Backend *be)
{ {
Serial serial = (Serial) handle; Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
if (serial->fd >= 0) if (serial->fd >= 0)
return -1; /* still connected */ return -1; /* still connected */
else else
@ -567,12 +569,12 @@ static int serial_exitcode(void *handle)
/* /*
* cfg_info for Serial does nothing at all. * cfg_info for Serial does nothing at all.
*/ */
static int serial_cfg_info(void *handle) static int serial_cfg_info(Backend *be)
{ {
return 0; return 0;
} }
Backend serial_backend = { const struct Backend_vtable serial_backend = {
serial_init, serial_init,
serial_free, serial_free,
serial_reconfig, serial_reconfig,

View File

@ -393,7 +393,7 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, int has_help,
* $XAUTHORITY is not reliable on Windows, so we provide a * $XAUTHORITY is not reliable on Windows, so we provide a
* means to override it. * means to override it.
*/ */
if (!midsession && backend_from_proto(PROT_SSH)) { if (!midsession && backend_vt_from_proto(PROT_SSH)) {
s = ctrl_getset(b, "Connection/SSH/X11", "x11", "X11 forwarding"); s = ctrl_getset(b, "Connection/SSH/X11", "x11", "X11 forwarding");
ctrl_filesel(s, "X authority file for local display", 't', ctrl_filesel(s, "X authority file for local display", 't',
NULL, FALSE, "Select X authority file", NULL, FALSE, "Select X authority file",

View File

@ -126,8 +126,7 @@ static int caret_x = -1, caret_y = -1;
static int kbd_codepage; static int kbd_codepage;
static Ldisc *ldisc; static Ldisc *ldisc;
static Backend *back; static Backend *backend;
static void *backhandle;
static struct unicode_data ucsdata; static struct unicode_data ucsdata;
static int session_closed; static int session_closed;
@ -248,6 +247,7 @@ char *get_ttymode(void *frontend, const char *mode)
static void start_backend(void) static void start_backend(void)
{ {
const struct Backend_vtable *vt;
const char *error; const char *error;
char msg[1024], *title; char msg[1024], *title;
char *realhost; char *realhost;
@ -257,8 +257,8 @@ static void start_backend(void)
* Select protocol. This is farmed out into a table in a * Select protocol. This is farmed out into a table in a
* separate file to enable an ssh-free variant. * separate file to enable an ssh-free variant.
*/ */
back = backend_from_proto(conf_get_int(conf, CONF_protocol)); vt = backend_vt_from_proto(conf_get_int(conf, CONF_protocol));
if (back == NULL) { if (!vt) {
char *str = dupprintf("%s Internal Error", appname); char *str = dupprintf("%s Internal Error", appname);
MessageBox(NULL, "Unsupported protocol number found", MessageBox(NULL, "Unsupported protocol number found",
str, MB_OK | MB_ICONEXCLAMATION); str, MB_OK | MB_ICONEXCLAMATION);
@ -266,13 +266,13 @@ static void start_backend(void)
cleanup_exit(1); cleanup_exit(1);
} }
error = back->init(NULL, &backhandle, conf, error = backend_init(vt, NULL, &backend, conf,
conf_get_str(conf, CONF_host), conf_get_str(conf, CONF_host),
conf_get_int(conf, CONF_port), conf_get_int(conf, CONF_port),
&realhost, &realhost,
conf_get_int(conf, CONF_tcp_nodelay), conf_get_int(conf, CONF_tcp_nodelay),
conf_get_int(conf, CONF_tcp_keepalives)); conf_get_int(conf, CONF_tcp_keepalives));
back->provide_logctx(backhandle, logctx); backend_provide_logctx(backend, logctx);
if (error) { if (error) {
char *str = dupprintf("%s Error", appname); char *str = dupprintf("%s Error", appname);
sprintf(msg, "Unable to open connection to\n" sprintf(msg, "Unable to open connection to\n"
@ -294,12 +294,12 @@ static void start_backend(void)
/* /*
* Connect the terminal to the backend for resize purposes. * Connect the terminal to the backend for resize purposes.
*/ */
term_provide_resize_fn(term, back->size, backhandle); term_provide_backend(term, backend);
/* /*
* Set up a line discipline. * Set up a line discipline.
*/ */
ldisc = ldisc_create(conf, term, back, backhandle, NULL); ldisc = ldisc_create(conf, term, backend, NULL);
/* /*
* Destroy the Restart Session menu item. (This will return * Destroy the Restart Session menu item. (This will return
@ -329,11 +329,10 @@ static void close_session(void *ignored_context)
ldisc_free(ldisc); ldisc_free(ldisc);
ldisc = NULL; ldisc = NULL;
} }
if (back) { if (backend) {
back->free(backhandle); backend_free(backend);
backhandle = NULL; backend = NULL;
back = NULL; term_provide_backend(term, NULL);
term_provide_resize_fn(term, NULL, NULL);
update_specials_menu(NULL); update_specials_menu(NULL);
} }
@ -413,10 +412,11 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
default_protocol = be_default_protocol; default_protocol = be_default_protocol;
/* Find the appropriate default port. */ /* Find the appropriate default port. */
{ {
Backend *b = backend_from_proto(default_protocol); const struct Backend_vtable *vt =
backend_vt_from_proto(default_protocol);
default_port = 0; /* illegal */ default_port = 0; /* illegal */
if (b) if (vt)
default_port = b->default_port; default_port = vt->default_port;
} }
conf_set_int(conf, CONF_logtype, LGTYP_NONE); conf_set_int(conf, CONF_logtype, LGTYP_NONE);
@ -951,8 +951,8 @@ void update_specials_menu(void *frontend)
HMENU new_menu; HMENU new_menu;
int i, j; int i, j;
if (back) if (backend)
specials = back->get_specials(backhandle); specials = backend_get_specials(backend);
else else
specials = NULL; specials = NULL;
@ -1975,7 +1975,7 @@ void notify_remote_exit(void *fe)
int exitcode, close_on_exit; int exitcode, close_on_exit;
if (!session_closed && if (!session_closed &&
(exitcode = back->exitcode(backhandle)) >= 0) { (exitcode = backend_exitcode(backend)) >= 0) {
close_on_exit = conf_get_int(conf, CONF_close_on_exit); close_on_exit = conf_get_int(conf, CONF_close_on_exit);
/* Abnormal exits will already have set session_closed and taken /* Abnormal exits will already have set session_closed and taken
* appropriate action. */ * appropriate action. */
@ -2161,7 +2161,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
} }
break; break;
case IDM_RESTART: case IDM_RESTART:
if (!back) { if (!backend) {
logevent(NULL, "----- Session restarted -----"); logevent(NULL, "----- Session restarted -----");
term_pwron(term, FALSE); term_pwron(term, FALSE);
start_backend(); start_backend();
@ -2190,7 +2190,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
prev_conf = conf_copy(conf); prev_conf = conf_copy(conf);
reconfig_result = reconfig_result =
do_reconfig(hwnd, back ? back->cfg_info(backhandle) : 0); do_reconfig(hwnd, backend ? backend_cfg_info(backend) : 0);
reconfiguring = FALSE; reconfiguring = FALSE;
if (!reconfig_result) { if (!reconfig_result) {
conf_free(prev_conf); conf_free(prev_conf);
@ -2237,8 +2237,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
setup_clipboards(term, conf); setup_clipboards(term, conf);
/* Pass new config data to the back end */ /* Pass new config data to the back end */
if (back) if (backend)
back->reconfig(backhandle, conf); backend_reconfig(backend, conf);
/* Screen size changed ? */ /* Screen size changed ? */
if (conf_get_int(conf, CONF_height) != if (conf_get_int(conf, CONF_height) !=
@ -2414,8 +2414,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
*/ */
if (i >= n_specials) if (i >= n_specials)
break; break;
if (back) if (backend)
back->special(backhandle, specials[i].code); backend_special(backend, specials[i].code);
} }
} }
break; break;
@ -4405,8 +4405,8 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
return p - output; return p - output;
} }
if (wParam == VK_CANCEL && shift_state == 2) { /* Ctrl-Break */ if (wParam == VK_CANCEL && shift_state == 2) { /* Ctrl-Break */
if (back) if (backend)
back->special(backhandle, TS_BRK); backend_special(backend, TS_BRK);
return 0; return 0;
} }
if (wParam == VK_PAUSE) { /* Break/Pause */ if (wParam == VK_PAUSE) { /* Break/Pause */

View File

@ -76,8 +76,7 @@ DWORD orig_console_mode;
WSAEVENT netevent; WSAEVENT netevent;
static Backend *back; static Backend *backend;
static void *backhandle;
static Conf *conf; static Conf *conf;
int term_ldisc(Terminal *term, int mode) int term_ldisc(Terminal *term, int mode)
@ -254,11 +253,11 @@ int stdin_gotdata(struct handle *h, void *data, int len)
cleanup_exit(0); cleanup_exit(0);
} }
noise_ultralight(len); noise_ultralight(len);
if (back->connected(backhandle)) { if (backend_connected(backend)) {
if (len > 0) { if (len > 0) {
return back->send(backhandle, data, len); return backend_send(backend, data, len);
} else { } else {
back->special(backhandle, TS_EOF); backend_special(backend, TS_EOF);
return 0; return 0;
} }
} else } else
@ -281,9 +280,9 @@ void stdouterr_sent(struct handle *h, int new_backlog)
(h == stdout_handle ? "output" : "error"), buf); (h == stdout_handle ? "output" : "error"), buf);
cleanup_exit(0); cleanup_exit(0);
} }
if (back->connected(backhandle)) { if (backend_connected(backend)) {
back->unthrottle(backhandle, (handle_backlog(stdout_handle) + backend_unthrottle(backend, (handle_backlog(stdout_handle) +
handle_backlog(stderr_handle))); handle_backlog(stderr_handle)));
} }
} }
@ -300,6 +299,7 @@ int main(int argc, char **argv)
int use_subsystem = 0; int use_subsystem = 0;
int just_test_share_exists = FALSE; int just_test_share_exists = FALSE;
unsigned long now, next, then; unsigned long now, next, then;
const struct Backend_vtable *vt;
dll_hijacking_protection(); dll_hijacking_protection();
@ -334,10 +334,10 @@ int main(int argc, char **argv)
*/ */
char *p = getenv("PLINK_PROTOCOL"); char *p = getenv("PLINK_PROTOCOL");
if (p) { if (p) {
const Backend *b = backend_from_name(p); const struct Backend_vtable *vt = backend_vt_from_name(p);
if (b) { if (vt) {
default_protocol = b->protocol; default_protocol = vt->protocol;
default_port = b->default_port; default_port = vt->default_port;
conf_set_int(conf, CONF_protocol, default_protocol); conf_set_int(conf, CONF_protocol, default_protocol);
conf_set_int(conf, CONF_port, default_port); conf_set_int(conf, CONF_port, default_port);
} }
@ -432,8 +432,8 @@ int main(int argc, char **argv)
* Select protocol. This is farmed out into a table in a * Select protocol. This is farmed out into a table in a
* separate file to enable an ssh-free variant. * separate file to enable an ssh-free variant.
*/ */
back = backend_from_proto(conf_get_int(conf, CONF_protocol)); vt = backend_vt_from_proto(conf_get_int(conf, CONF_protocol));
if (back == NULL) { if (vt == NULL) {
fprintf(stderr, fprintf(stderr,
"Internal fault: Unsupported protocol found\n"); "Internal fault: Unsupported protocol found\n");
return 1; return 1;
@ -460,13 +460,13 @@ int main(int argc, char **argv)
console_provide_logctx(logctx); console_provide_logctx(logctx);
if (just_test_share_exists) { if (just_test_share_exists) {
if (!back->test_for_upstream) { if (!vt->test_for_upstream) {
fprintf(stderr, "Connection sharing not supported for connection " fprintf(stderr, "Connection sharing not supported for connection "
"type '%s'\n", back->name); "type '%s'\n", vt->name);
return 1; return 1;
} }
if (back->test_for_upstream(conf_get_str(conf, CONF_host), if (vt->test_for_upstream(conf_get_str(conf, CONF_host),
conf_get_int(conf, CONF_port), conf)) conf_get_int(conf, CONF_port), conf))
return 0; return 0;
else else
return 1; return 1;
@ -487,16 +487,16 @@ int main(int argc, char **argv)
int nodelay = conf_get_int(conf, CONF_tcp_nodelay) && int nodelay = conf_get_int(conf, CONF_tcp_nodelay) &&
(GetFileType(GetStdHandle(STD_INPUT_HANDLE)) == FILE_TYPE_CHAR); (GetFileType(GetStdHandle(STD_INPUT_HANDLE)) == FILE_TYPE_CHAR);
error = back->init(NULL, &backhandle, conf, error = backend_init(vt, NULL, &backend, conf,
conf_get_str(conf, CONF_host), conf_get_str(conf, CONF_host),
conf_get_int(conf, CONF_port), conf_get_int(conf, CONF_port),
&realhost, nodelay, &realhost, nodelay,
conf_get_int(conf, CONF_tcp_keepalives)); conf_get_int(conf, CONF_tcp_keepalives));
if (error) { if (error) {
fprintf(stderr, "Unable to open connection:\n%s", error); fprintf(stderr, "Unable to open connection:\n%s", error);
return 1; return 1;
} }
back->provide_logctx(backhandle, logctx); backend_provide_logctx(backend, logctx);
sfree(realhost); sfree(realhost);
} }
@ -532,7 +532,7 @@ int main(int argc, char **argv)
int n; int n;
DWORD ticks; DWORD ticks;
if (!sending && back->sendok(backhandle)) { if (!sending && backend_sendok(backend)) {
stdin_handle = handle_input_new(inhandle, stdin_gotdata, NULL, stdin_handle = handle_input_new(inhandle, stdin_gotdata, NULL,
0); 0);
sending = TRUE; sending = TRUE;
@ -643,13 +643,13 @@ int main(int argc, char **argv)
sfree(handles); sfree(handles);
if (sending) if (sending)
handle_unthrottle(stdin_handle, back->sendbuffer(backhandle)); handle_unthrottle(stdin_handle, backend_sendbuffer(backend));
if (!back->connected(backhandle) && if (!backend_connected(backend) &&
handle_backlog(stdout_handle) + handle_backlog(stderr_handle) == 0) handle_backlog(stdout_handle) + handle_backlog(stderr_handle) == 0)
break; /* we closed the connection */ break; /* we closed the connection */
} }
exitcode = back->exitcode(backhandle); exitcode = backend_exitcode(backend);
if (exitcode < 0) { if (exitcode < 0) {
fprintf(stderr, "Remote process exit code unavailable\n"); fprintf(stderr, "Remote process exit code unavailable\n");
exitcode = 1; /* this is an error condition */ exitcode = 1; /* this is an error condition */

View File

@ -17,6 +17,7 @@ typedef struct serial_backend_data {
int bufsize; int bufsize;
long clearbreak_time; long clearbreak_time;
int break_in_progress; int break_in_progress;
Backend backend;
} *Serial; } *Serial;
static void serial_terminate(Serial serial) static void serial_terminate(Serial serial)
@ -198,7 +199,7 @@ static const char *serial_configure(Serial serial, HANDLE serport, Conf *conf)
* Also places the canonical host name into `realhost'. It must be * Also places the canonical host name into `realhost'. It must be
* freed by the caller. * freed by the caller.
*/ */
static const char *serial_init(void *frontend_handle, void **backend_handle, static const char *serial_init(void *frontend_handle, Backend **backend_handle,
Conf *conf, const char *host, int port, Conf *conf, const char *host, int port,
char **realhost, int nodelay, int keepalive) char **realhost, int nodelay, int keepalive)
{ {
@ -212,7 +213,8 @@ static const char *serial_init(void *frontend_handle, void **backend_handle,
serial->out = serial->in = NULL; serial->out = serial->in = NULL;
serial->bufsize = 0; serial->bufsize = 0;
serial->break_in_progress = FALSE; serial->break_in_progress = FALSE;
*backend_handle = serial; serial->backend.vt = &serial_backend;
*backend_handle = &serial->backend;
serial->frontend = frontend_handle; serial->frontend = frontend_handle;
@ -279,18 +281,18 @@ static const char *serial_init(void *frontend_handle, void **backend_handle,
return NULL; return NULL;
} }
static void serial_free(void *handle) static void serial_free(Backend *be)
{ {
Serial serial = (Serial) handle; Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
serial_terminate(serial); serial_terminate(serial);
expire_timer_context(serial); expire_timer_context(serial);
sfree(serial); sfree(serial);
} }
static void serial_reconfig(void *handle, Conf *conf) static void serial_reconfig(Backend *be, Conf *conf)
{ {
Serial serial = (Serial) handle; Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
serial_configure(serial, serial->port, conf); serial_configure(serial, serial->port, conf);
@ -303,9 +305,9 @@ static void serial_reconfig(void *handle, Conf *conf)
/* /*
* Called to send data down the serial connection. * Called to send data down the serial connection.
*/ */
static int serial_send(void *handle, const char *buf, int len) static int serial_send(Backend *be, const char *buf, int len)
{ {
Serial serial = (Serial) handle; Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
if (serial->out == NULL) if (serial->out == NULL)
return 0; return 0;
@ -317,16 +319,16 @@ static int serial_send(void *handle, const char *buf, int len)
/* /*
* Called to query the current sendability status. * Called to query the current sendability status.
*/ */
static int serial_sendbuffer(void *handle) static int serial_sendbuffer(Backend *be)
{ {
Serial serial = (Serial) handle; Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
return serial->bufsize; return serial->bufsize;
} }
/* /*
* Called to set the size of the window * Called to set the size of the window
*/ */
static void serial_size(void *handle, int width, int height) static void serial_size(Backend *be, int width, int height)
{ {
/* Do nothing! */ /* Do nothing! */
return; return;
@ -346,9 +348,9 @@ static void serbreak_timer(void *ctx, unsigned long now)
/* /*
* Send serial special codes. * Send serial special codes.
*/ */
static void serial_special(void *handle, Telnet_Special code) static void serial_special(Backend *be, Telnet_Special code)
{ {
Serial serial = (Serial) handle; Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
if (serial->port && code == TS_BRK) { if (serial->port && code == TS_BRK) {
logevent(serial->frontend, "Starting serial break at user request"); logevent(serial->frontend, "Starting serial break at user request");
@ -375,7 +377,7 @@ static void serial_special(void *handle, Telnet_Special code)
* Return a list of the special codes that make sense in this * Return a list of the special codes that make sense in this
* protocol. * protocol.
*/ */
static const struct telnet_special *serial_get_specials(void *handle) static const struct telnet_special *serial_get_specials(Backend *be)
{ {
static const struct telnet_special specials[] = { static const struct telnet_special specials[] = {
{"Break", TS_BRK}, {"Break", TS_BRK},
@ -384,24 +386,24 @@ static const struct telnet_special *serial_get_specials(void *handle)
return specials; return specials;
} }
static int serial_connected(void *handle) static int serial_connected(Backend *be)
{ {
return 1; /* always connected */ return 1; /* always connected */
} }
static int serial_sendok(void *handle) static int serial_sendok(Backend *be)
{ {
return 1; return 1;
} }
static void serial_unthrottle(void *handle, int backlog) static void serial_unthrottle(Backend *be, int backlog)
{ {
Serial serial = (Serial) handle; Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
if (serial->in) if (serial->in)
handle_unthrottle(serial->in, backlog); handle_unthrottle(serial->in, backlog);
} }
static int serial_ldisc(void *handle, int option) static int serial_ldisc(Backend *be, int option)
{ {
/* /*
* Local editing and local echo are off by default. * Local editing and local echo are off by default.
@ -409,19 +411,19 @@ static int serial_ldisc(void *handle, int option)
return 0; return 0;
} }
static void serial_provide_ldisc(void *handle, Ldisc *ldisc) static void serial_provide_ldisc(Backend *be, Ldisc *ldisc)
{ {
/* This is a stub. */ /* This is a stub. */
} }
static void serial_provide_logctx(void *handle, LogContext *logctx) static void serial_provide_logctx(Backend *be, LogContext *logctx)
{ {
/* This is a stub. */ /* This is a stub. */
} }
static int serial_exitcode(void *handle) static int serial_exitcode(Backend *be)
{ {
Serial serial = (Serial) handle; Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
if (serial->port != INVALID_HANDLE_VALUE) if (serial->port != INVALID_HANDLE_VALUE)
return -1; /* still connected */ return -1; /* still connected */
else else
@ -432,12 +434,12 @@ static int serial_exitcode(void *handle)
/* /*
* cfg_info for Serial does nothing at all. * cfg_info for Serial does nothing at all.
*/ */
static int serial_cfg_info(void *handle) static int serial_cfg_info(Backend *be)
{ {
return 0; return 0;
} }
Backend serial_backend = { const struct Backend_vtable serial_backend = {
serial_init, serial_init,
serial_free, serial_free,
serial_reconfig, serial_reconfig,

View File

@ -596,7 +596,7 @@ void agent_schedule_callback(void (*callback)(void *, void *, int),
/* /*
* Exports from winser.c. * Exports from winser.c.
*/ */
extern Backend serial_backend; extern const struct Backend_vtable serial_backend;
/* /*
* Exports from winjump.c. * Exports from winjump.c.