1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 09:58:01 +00:00

Rework special-commands system to add an integer argument.

In order to list cross-certifiable host keys in the GUI specials menu,
the SSH backend has been inventing new values on the end of the
Telnet_Special enumeration, starting from the value TS_LOCALSTART.
This is inelegant, and also makes it awkward to break up special
handlers (e.g. to dispatch different specials to different SSH
layers), since if all you know about a special is that it's somewhere
in the TS_LOCALSTART+n space, you can't tell what _general kind_ of
thing it is. Also, if I ever need another open-ended set of specials
in future, I'll have to remember which TS_LOCALSTART+n codes are in
which set.

So here's a revamp that causes every special to take an extra integer
argument. For all previously numbered specials, this argument is
passed as zero and ignored, but there's a new main special code for
SSH host key cross-certification, in which the integer argument is an
index into the backend's list of available keys. TS_LOCALSTART is now
a thing of the past: if I need any other open-ended sets of specials
in future, I can add a new top-level code with a nicely separated
space of arguments.

While I'm at it, I've removed the legacy misnomer 'Telnet_Special'
from the code completely; the enum is now SessionSpecialCode, the
struct containing full details of a menu entry is SessionSpecial, and
the enum values now start SS_ rather than TS_.
This commit is contained in:
Simon Tatham 2018-09-24 09:35:52 +01:00
parent 26f7a2ac72
commit f4fbaa1bd9
19 changed files with 224 additions and 194 deletions

2
defs.h
View File

@ -70,6 +70,8 @@ typedef struct settings_w settings_w;
typedef struct settings_r settings_r; typedef struct settings_r settings_r;
typedef struct settings_e settings_e; typedef struct settings_e settings_e;
typedef struct SessionSpecial SessionSpecial;
/* 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

20
ldisc.c
View File

@ -217,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--;
} }
backend_special(ldisc->backend, TS_EL); backend_special(ldisc->backend, SS_EL, 0);
/* /*
* 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
@ -226,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'))
backend_special(ldisc->backend, TS_IP); backend_special(ldisc->backend, SS_IP, 0);
if (c == CTRL('Z')) if (c == CTRL('Z'))
backend_special(ldisc->backend, TS_SUSP); backend_special(ldisc->backend, SS_SUSP, 0);
if (c == CTRL('\\')) if (c == CTRL('\\'))
backend_special(ldisc->backend, TS_ABORT); backend_special(ldisc->backend, SS_ABORT, 0);
break; break;
case CTRL('R'): /* redraw line */ case CTRL('R'): /* redraw line */
if (ECHOING) { if (ECHOING) {
@ -245,7 +245,7 @@ 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) {
backend_special(ldisc->backend, TS_EOF); backend_special(ldisc->backend, SS_EOF, 0);
} else { } else {
backend_send(ldisc->backend, ldisc->buf, ldisc->buflen); backend_send(ldisc->backend, ldisc->buf, ldisc->buflen);
ldisc->buflen = 0; ldisc->buflen = 0;
@ -288,7 +288,7 @@ void ldisc_send(Ldisc *ldisc, const void *vbuf, int len, int interactive)
if (ldisc->protocol == PROT_RAW) if (ldisc->protocol == PROT_RAW)
backend_send(ldisc->backend, "\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)
backend_special(ldisc->backend, TS_EOL); backend_special(ldisc->backend, SS_EOL, 0);
else else
backend_send(ldisc->backend, "\r", 1); backend_send(ldisc->backend, "\r", 1);
if (ECHOING) if (ECHOING)
@ -325,24 +325,24 @@ 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)
backend_special(ldisc->backend, TS_EOL); backend_special(ldisc->backend, SS_EOL, 0);
else else
backend_send(ldisc->backend, "\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) {
backend_special(ldisc->backend, TS_EC); backend_special(ldisc->backend, SS_EC, 0);
break; break;
} }
case CTRL('C'): case CTRL('C'):
if (ldisc->telnet_keyboard) { if (ldisc->telnet_keyboard) {
backend_special(ldisc->backend, TS_IP); backend_special(ldisc->backend, SS_IP, 0);
break; break;
} }
case CTRL('Z'): case CTRL('Z'):
if (ldisc->telnet_keyboard) { if (ldisc->telnet_keyboard) {
backend_special(ldisc->backend, TS_SUSP); backend_special(ldisc->backend, SS_SUSP, 0);
break; break;
} }

View File

@ -1,5 +1,5 @@
/* /*
* pinger.c: centralised module that deals with sending TS_PING * pinger.c: centralised module that deals with sending SS_PING
* keepalives, to avoid replicating this code in multiple backends. * keepalives, to avoid replicating this code in multiple backends.
*/ */
@ -19,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) {
backend_special(pinger->backend, TS_PING); backend_special(pinger->backend, SS_PING, 0);
pinger->pending = FALSE; pinger->pending = FALSE;
pinger_schedule(pinger); pinger_schedule(pinger);
} }

4
pscp.c
View File

@ -293,7 +293,7 @@ static void bump(const char *fmt, ...)
if (backend && backend_connected(backend)) { if (backend && backend_connected(backend)) {
char ch; char ch;
backend_special(backend, TS_EOF); backend_special(backend, SS_EOF, 0);
sent_eof = TRUE; sent_eof = TRUE;
ssh_scp_recv(&ch, 1); ssh_scp_recv(&ch, 1);
} }
@ -2367,7 +2367,7 @@ int psftp_main(int argc, char *argv[])
if (backend && backend_connected(backend)) { if (backend && backend_connected(backend)) {
char ch; char ch;
backend_special(backend, TS_EOF); backend_special(backend, SS_EOF, 0);
sent_eof = TRUE; sent_eof = TRUE;
ssh_scp_recv(&ch, 1); ssh_scp_recv(&ch, 1);
} }

View File

@ -973,7 +973,7 @@ int sftp_cmd_close(struct sftp_command *cmd)
if (backend_connected(backend)) { if (backend_connected(backend)) {
char ch; char ch;
backend_special(backend, TS_EOF); backend_special(backend, SS_EOF, 0);
sent_eof = TRUE; sent_eof = TRUE;
sftp_recvdata(&ch, 1); sftp_recvdata(&ch, 1);
} }
@ -2355,7 +2355,7 @@ void do_sftp_cleanup()
{ {
char ch; char ch;
if (backend) { if (backend) {
backend_special(backend, TS_EOF); backend_special(backend, SS_EOF, 0);
sent_eof = TRUE; sent_eof = TRUE;
sftp_recvdata(&ch, 1); sftp_recvdata(&ch, 1);
backend_free(backend); backend_free(backend);
@ -2965,7 +2965,7 @@ int psftp_main(int argc, char *argv[])
if (backend && backend_connected(backend)) { if (backend && backend_connected(backend)) {
char ch; char ch;
backend_special(backend, TS_EOF); backend_special(backend, SS_EOF, 0);
sent_eof = TRUE; sent_eof = TRUE;
sftp_recvdata(&ch, 1); sftp_recvdata(&ch, 1);
} }

89
putty.h
View File

@ -172,34 +172,67 @@ struct unicode_data {
#define LGTYP_PACKETS 3 /* logmode: SSH data packets */ #define LGTYP_PACKETS 3 /* logmode: SSH data packets */
#define LGTYP_SSHRAW 4 /* logmode: SSH raw data */ #define LGTYP_SSHRAW 4 /* logmode: SSH raw data */
/*
* Enumeration of 'special commands' that can be sent during a
* session, separately from the byte stream of ordinary session data.
*/
typedef enum { typedef enum {
/* Actual special commands. Originally Telnet, but some codes have /*
* been re-used for similar specials in other protocols. */ * Commands that are generally useful in multiple backends.
TS_AYT, TS_BRK, TS_SYNCH, TS_EC, TS_EL, TS_GA, TS_NOP, TS_ABORT, */
TS_AO, TS_IP, TS_SUSP, TS_EOR, TS_EOF, TS_LECHO, TS_RECHO, TS_PING, SS_BRK, /* serial-line break */
TS_EOL, SS_EOF, /* end-of-file on session input */
/* Special command for SSH. */ SS_NOP, /* transmit data with no effect */
TS_REKEY, SS_PING, /* try to keep the session alive (probably, but not
/* POSIX-style signals. (not Telnet) */ * necessarily, implemented as SS_NOP) */
TS_SIGABRT, TS_SIGALRM, TS_SIGFPE, TS_SIGHUP, TS_SIGILL,
TS_SIGINT, TS_SIGKILL, TS_SIGPIPE, TS_SIGQUIT, TS_SIGSEGV,
TS_SIGTERM, TS_SIGUSR1, TS_SIGUSR2,
/* Pseudo-specials used for constructing the specials menu. */
TS_SEP, /* Separator */
TS_SUBMENU, /* Start a new submenu with specified name */
TS_EXITMENU, /* Exit current submenu or end of specials */
/* Starting point for protocols to invent special-action codes
* that can't live in this enum at all, e.g. because they change
* with every session.
*
* Of course, this must remain the last value in this
* enumeration. */
TS_LOCALSTART
} Telnet_Special;
struct telnet_special { /*
* Commands specific to Telnet.
*/
SS_AYT, /* Are You There */
SS_SYNCH, /* Synch */
SS_EC, /* Erase Character */
SS_EL, /* Erase Line */
SS_GA, /* Go Ahead */
SS_ABORT, /* Abort Process */
SS_AO, /* Abort Output */
SS_IP, /* Interrupt Process */
SS_SUSP, /* Suspend Process */
SS_EOR, /* End Of Record */
SS_EOL, /* Telnet end-of-line sequence (CRLF, as opposed to CR
* NUL that escapes a literal CR) */
/*
* Commands specific to SSH.
*/
SS_REKEY, /* trigger an immediate repeat key exchange */
SS_XCERT, /* cross-certify another host key ('arg' indicates which) */
/*
* Send a POSIX-style signal. (Useful in SSH and also pterm.)
*/
SS_SIGABRT, SS_SIGALRM, SS_SIGFPE, SS_SIGHUP, SS_SIGILL,
SS_SIGINT, SS_SIGKILL, SS_SIGPIPE, SS_SIGQUIT, SS_SIGSEGV,
SS_SIGTERM, SS_SIGUSR1, SS_SIGUSR2,
/*
* These aren't really special commands, but they appear in the
* enumeration because the list returned from
* backend_get_specials() will use them to specify the structure
* of the GUI specials menu.
*/
SS_SEP, /* Separator */
SS_SUBMENU, /* Start a new submenu with specified name */
SS_EXITMENU, /* Exit current submenu, or end of entire specials list */
} SessionSpecialCode;
/*
* The structure type returned from backend_get_specials.
*/
struct SessionSpecial {
const char *name; const char *name;
int code; SessionSpecialCode code;
int arg;
}; };
typedef enum { typedef enum {
@ -457,8 +490,8 @@ struct Backend_vtable {
/* sendbuffer() does the same thing but without attempting a send */ /* sendbuffer() does the same thing but without attempting a send */
int (*sendbuffer) (Backend *be); int (*sendbuffer) (Backend *be);
void (*size) (Backend *be, int width, int height); void (*size) (Backend *be, int width, int height);
void (*special) (Backend *be, Telnet_Special code); void (*special) (Backend *be, SessionSpecialCode code, int arg);
const struct telnet_special *(*get_specials) (Backend *be); const SessionSpecial *(*get_specials) (Backend *be);
int (*connected) (Backend *be); int (*connected) (Backend *be);
int (*exitcode) (Backend *be); int (*exitcode) (Backend *be);
/* If back->sendok() returns FALSE, the backend doesn't currently /* If back->sendok() returns FALSE, the backend doesn't currently
@ -488,7 +521,7 @@ struct Backend_vtable {
#define backend_send(be, buf, len) ((be)->vt->send(be, buf, len)) #define backend_send(be, buf, len) ((be)->vt->send(be, buf, len))
#define backend_sendbuffer(be) ((be)->vt->sendbuffer(be)) #define backend_sendbuffer(be) ((be)->vt->sendbuffer(be))
#define backend_size(be, w, h) ((be)->vt->size(be, w, h)) #define backend_size(be, w, h) ((be)->vt->size(be, w, h))
#define backend_special(be, code) ((be)->vt->special(be, code)) #define backend_special(be, code, arg) ((be)->vt->special(be, code, arg))
#define backend_get_specials(be) ((be)->vt->get_specials(be)) #define backend_get_specials(be) ((be)->vt->get_specials(be))
#define backend_connected(be) ((be)->vt->connected(be)) #define backend_connected(be) ((be)->vt->connected(be))
#define backend_exitcode(be) ((be)->vt->exitcode(be)) #define backend_exitcode(be) ((be)->vt->exitcode(be))

6
raw.c
View File

@ -231,10 +231,10 @@ static void raw_size(Backend *be, 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(Backend *be, Telnet_Special code) static void raw_special(Backend *be, SessionSpecialCode code, int arg)
{ {
Raw raw = FROMFIELD(be, struct raw_backend_data, backend); Raw raw = FROMFIELD(be, struct raw_backend_data, backend);
if (code == TS_EOF && raw->s) { if (code == SS_EOF && raw->s) {
sk_write_eof(raw->s); sk_write_eof(raw->s);
raw->sent_socket_eof= TRUE; raw->sent_socket_eof= TRUE;
raw_check_close(raw); raw_check_close(raw);
@ -247,7 +247,7 @@ static void raw_special(Backend *be, 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(Backend *be) static const SessionSpecial *raw_get_specials(Backend *be)
{ {
return NULL; return NULL;
} }

View File

@ -328,7 +328,7 @@ static void rlogin_size(Backend *be, int width, int height)
/* /*
* Send rlogin special codes. * Send rlogin special codes.
*/ */
static void rlogin_special(Backend *be, Telnet_Special code) static void rlogin_special(Backend *be, SessionSpecialCode code, int arg)
{ {
/* Do nothing! */ /* Do nothing! */
return; return;
@ -338,7 +338,7 @@ static void rlogin_special(Backend *be, 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(Backend *be) static const SessionSpecial *rlogin_get_specials(Backend *be)
{ {
return NULL; return NULL;
} }

119
ssh.c
View File

@ -313,7 +313,7 @@ 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(Backend *be, int width, int height); static void ssh_size(Backend *be, int width, int height);
static void ssh_special(Backend *be, Telnet_Special); static void ssh_special(Backend *be, SessionSpecialCode, int arg);
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);
@ -592,7 +592,7 @@ struct ssh_tag {
/* /*
* The last list returned from get_specials. * The last list returned from get_specials.
*/ */
struct telnet_special *specials; SessionSpecial *specials;
/* /*
* List of host key algorithms for which we _don't_ have a stored * List of host key algorithms for which we _don't_ have a stored
@ -3243,7 +3243,7 @@ static void do_ssh1_connection(void *vctx)
if (ssh->size_needed) if (ssh->size_needed)
backend_size(&ssh->backend, ssh->term_width, ssh->term_height); backend_size(&ssh->backend, ssh->term_width, ssh->term_height);
if (ssh->eof_needed) if (ssh->eof_needed)
backend_special(&ssh->backend, TS_EOF); backend_special(&ssh->backend, SS_EOF, 0);
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 */
@ -8524,7 +8524,7 @@ static void do_ssh2_connection(void *vctx)
if (ssh->size_needed) if (ssh->size_needed)
backend_size(&ssh->backend, ssh->term_width, ssh->term_height); backend_size(&ssh->backend, ssh->term_width, ssh->term_height);
if (ssh->eof_needed) if (ssh->eof_needed)
backend_special(&ssh->backend, TS_EOF); backend_special(&ssh->backend, SS_EOF, 0);
/* /*
* Transfer data! * Transfer data!
@ -9514,40 +9514,40 @@ static void ssh_size(Backend *be, 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(Backend *be) static const SessionSpecial *ssh_get_specials(Backend *be)
{ {
static const struct telnet_special ssh1_ignore_special[] = { static const SessionSpecial ssh1_ignore_special[] = {
{"IGNORE message", TS_NOP} {"IGNORE message", SS_NOP}
}; };
static const struct telnet_special ssh2_ignore_special[] = { static const SessionSpecial ssh2_ignore_special[] = {
{"IGNORE message", TS_NOP}, {"IGNORE message", SS_NOP},
}; };
static const struct telnet_special ssh2_rekey_special[] = { static const SessionSpecial ssh2_rekey_special[] = {
{"Repeat key exchange", TS_REKEY}, {"Repeat key exchange", SS_REKEY},
}; };
static const struct telnet_special ssh2_session_specials[] = { static const SessionSpecial ssh2_session_specials[] = {
{NULL, TS_SEP}, {NULL, SS_SEP},
{"Break", TS_BRK}, {"Break", SS_BRK},
/* These are the signal names defined by RFC 4254. /* These are the signal names defined by RFC 4254.
* They include all the ISO C signals, but are a subset of the POSIX * They include all the ISO C signals, but are a subset of the POSIX
* required signals. */ * required signals. */
{"SIGINT (Interrupt)", TS_SIGINT}, {"SIGINT (Interrupt)", SS_SIGINT},
{"SIGTERM (Terminate)", TS_SIGTERM}, {"SIGTERM (Terminate)", SS_SIGTERM},
{"SIGKILL (Kill)", TS_SIGKILL}, {"SIGKILL (Kill)", SS_SIGKILL},
{"SIGQUIT (Quit)", TS_SIGQUIT}, {"SIGQUIT (Quit)", SS_SIGQUIT},
{"SIGHUP (Hangup)", TS_SIGHUP}, {"SIGHUP (Hangup)", SS_SIGHUP},
{"More signals", TS_SUBMENU}, {"More signals", SS_SUBMENU},
{"SIGABRT", TS_SIGABRT}, {"SIGALRM", TS_SIGALRM}, {"SIGABRT", SS_SIGABRT}, {"SIGALRM", SS_SIGALRM},
{"SIGFPE", TS_SIGFPE}, {"SIGILL", TS_SIGILL}, {"SIGFPE", SS_SIGFPE}, {"SIGILL", SS_SIGILL},
{"SIGPIPE", TS_SIGPIPE}, {"SIGSEGV", TS_SIGSEGV}, {"SIGPIPE", SS_SIGPIPE}, {"SIGSEGV", SS_SIGSEGV},
{"SIGUSR1", TS_SIGUSR1}, {"SIGUSR2", TS_SIGUSR2}, {"SIGUSR1", SS_SIGUSR1}, {"SIGUSR2", SS_SIGUSR2},
{NULL, TS_EXITMENU} {NULL, SS_EXITMENU}
}; };
static const struct telnet_special specials_end[] = { static const SessionSpecial specials_end[] = {
{NULL, TS_EXITMENU} {NULL, SS_EXITMENU}
}; };
struct telnet_special *specials = NULL; SessionSpecial *specials = NULL;
int nspecials = 0, specialsize = 0; int nspecials = 0, specialsize = 0;
Ssh ssh = FROMFIELD(be, struct ssh_tag, backend); Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
@ -9559,9 +9559,9 @@ static const struct telnet_special *ssh_get_specials(Backend *be)
int len = lenof(name); \ int len = lenof(name); \
if (nspecials + len > specialsize) { \ if (nspecials + len > specialsize) { \
specialsize = (nspecials + len) * 5 / 4 + 32; \ specialsize = (nspecials + len) * 5 / 4 + 32; \
specials = sresize(specials, specialsize, struct telnet_special); \ specials = sresize(specials, specialsize, SessionSpecial); \
} \ } \
memcpy(specials+nspecials, name, len*sizeof(struct telnet_special)); \ memcpy(specials+nspecials, name, len*sizeof(SessionSpecial)); \
nspecials += len; \ nspecials += len; \
} while (0) } while (0)
@ -9580,22 +9580,23 @@ static const struct telnet_special *ssh_get_specials(Backend *be)
ADD_SPECIALS(ssh2_session_specials); ADD_SPECIALS(ssh2_session_specials);
if (ssh->n_uncert_hostkeys) { if (ssh->n_uncert_hostkeys) {
static const struct telnet_special uncert_start[] = { static const SessionSpecial uncert_start[] = {
{NULL, TS_SEP}, {NULL, SS_SEP},
{"Cache new host key type", TS_SUBMENU}, {"Cache new host key type", SS_SUBMENU},
}; };
static const struct telnet_special uncert_end[] = { static const SessionSpecial uncert_end[] = {
{NULL, TS_EXITMENU}, {NULL, SS_EXITMENU},
}; };
int i; int i;
ADD_SPECIALS(uncert_start); ADD_SPECIALS(uncert_start);
for (i = 0; i < ssh->n_uncert_hostkeys; i++) { for (i = 0; i < ssh->n_uncert_hostkeys; i++) {
struct telnet_special uncert[1]; SessionSpecial uncert[1];
const ssh_keyalg *alg = const ssh_keyalg *alg =
hostkey_algs[ssh->uncert_hostkeys[i]].alg; hostkey_algs[ssh->uncert_hostkeys[i]].alg;
uncert[0].name = alg->ssh_id; uncert[0].name = alg->ssh_id;
uncert[0].code = TS_LOCALSTART + ssh->uncert_hostkeys[i]; uncert[0].code = SS_XCERT;
uncert[0].arg = ssh->uncert_hostkeys[i];
ADD_SPECIALS(uncert); ADD_SPECIALS(uncert);
} }
ADD_SPECIALS(uncert_end); ADD_SPECIALS(uncert_end);
@ -9616,22 +9617,22 @@ static const struct telnet_special *ssh_get_specials(Backend *be)
} }
/* /*
* Send special codes. TS_EOF is useful for `plink', so you * Send special codes. SS_EOF is useful for `plink', so you
* 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(Backend *be, Telnet_Special code) static void ssh_special(Backend *be, SessionSpecialCode code, int arg)
{ {
Ssh ssh = FROMFIELD(be, struct ssh_tag, backend); Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
PktOut *pktout; PktOut *pktout;
if (code == TS_EOF) { if (code == SS_EOF) {
if (ssh->state != SSH_STATE_SESSION) { if (ssh->state != SSH_STATE_SESSION) {
/* /*
* Buffer the EOF in case we are pre-SESSION, so we can * Buffer the EOF in case we are pre-SESSION, so we can
* send it as soon as we reach SESSION. * send it as soon as we reach SESSION.
*/ */
if (code == TS_EOF) if (code == SS_EOF)
ssh->eof_needed = TRUE; ssh->eof_needed = TRUE;
return; return;
} }
@ -9643,7 +9644,7 @@ static void ssh_special(Backend *be, Telnet_Special code)
ssh->send_ok = 0; /* now stop trying to read from stdin */ ssh->send_ok = 0; /* now stop trying to read from stdin */
} }
logevent("Sent EOF message"); logevent("Sent EOF message");
} else if (code == TS_PING || code == TS_NOP) { } else if (code == SS_PING || code == SS_NOP) {
if (ssh->state == SSH_STATE_CLOSED if (ssh->state == SSH_STATE_CLOSED
|| ssh->state == SSH_STATE_PREPACKET) return; || ssh->state == SSH_STATE_PREPACKET) return;
if (ssh->version == 1) { if (ssh->version == 1) {
@ -9659,15 +9660,15 @@ static void ssh_special(Backend *be, Telnet_Special code)
ssh_pkt_write(ssh, pktout); ssh_pkt_write(ssh, pktout);
} }
} }
} else if (code == TS_REKEY) { } else if (code == SS_REKEY) {
if (!ssh->kex_in_progress && !ssh->bare_connection && if (!ssh->kex_in_progress && !ssh->bare_connection &&
ssh->version == 2) { ssh->version == 2) {
ssh->rekey_reason = "at user request"; ssh->rekey_reason = "at user request";
ssh->rekey_class = RK_NORMAL; ssh->rekey_class = RK_NORMAL;
queue_idempotent_callback(&ssh->ssh2_transport_icb); queue_idempotent_callback(&ssh->ssh2_transport_icb);
} }
} else if (code >= TS_LOCALSTART) { } else if (code == SS_XCERT) {
ssh->hostkey_alg = hostkey_algs[code - TS_LOCALSTART].alg; ssh->hostkey_alg = hostkey_algs[arg].alg;
ssh->cross_certifying = TRUE; ssh->cross_certifying = TRUE;
if (!ssh->kex_in_progress && !ssh->bare_connection && if (!ssh->kex_in_progress && !ssh->bare_connection &&
ssh->version == 2) { ssh->version == 2) {
@ -9675,7 +9676,7 @@ static void ssh_special(Backend *be, Telnet_Special code)
ssh->rekey_class = RK_NORMAL; ssh->rekey_class = RK_NORMAL;
queue_idempotent_callback(&ssh->ssh2_transport_icb); queue_idempotent_callback(&ssh->ssh2_transport_icb);
} }
} else if (code == TS_BRK) { } else if (code == SS_BRK) {
if (ssh->state == SSH_STATE_CLOSED if (ssh->state == SSH_STATE_CLOSED
|| ssh->state == SSH_STATE_PREPACKET) return; || ssh->state == SSH_STATE_PREPACKET) return;
if (ssh->version == 1) { if (ssh->version == 1) {
@ -9688,19 +9689,19 @@ static void ssh_special(Backend *be, Telnet_Special code)
} else { } else {
/* Is is a POSIX signal? */ /* Is is a POSIX signal? */
const char *signame = NULL; const char *signame = NULL;
if (code == TS_SIGABRT) signame = "ABRT"; if (code == SS_SIGABRT) signame = "ABRT";
if (code == TS_SIGALRM) signame = "ALRM"; if (code == SS_SIGALRM) signame = "ALRM";
if (code == TS_SIGFPE) signame = "FPE"; if (code == SS_SIGFPE) signame = "FPE";
if (code == TS_SIGHUP) signame = "HUP"; if (code == SS_SIGHUP) signame = "HUP";
if (code == TS_SIGILL) signame = "ILL"; if (code == SS_SIGILL) signame = "ILL";
if (code == TS_SIGINT) signame = "INT"; if (code == SS_SIGINT) signame = "INT";
if (code == TS_SIGKILL) signame = "KILL"; if (code == SS_SIGKILL) signame = "KILL";
if (code == TS_SIGPIPE) signame = "PIPE"; if (code == SS_SIGPIPE) signame = "PIPE";
if (code == TS_SIGQUIT) signame = "QUIT"; if (code == SS_SIGQUIT) signame = "QUIT";
if (code == TS_SIGSEGV) signame = "SEGV"; if (code == SS_SIGSEGV) signame = "SEGV";
if (code == TS_SIGTERM) signame = "TERM"; if (code == SS_SIGTERM) signame = "TERM";
if (code == TS_SIGUSR1) signame = "USR1"; if (code == SS_SIGUSR1) signame = "USR1";
if (code == TS_SIGUSR2) signame = "USR2"; if (code == SS_SIGUSR2) signame = "USR2";
/* The SSH-2 protocol does in principle support arbitrary named /* The SSH-2 protocol does in principle support arbitrary named
* signals, including signame@domain, but we don't support those. */ * signals, including signame@domain, but we don't support those. */
if (signame) { if (signame) {

View File

@ -914,7 +914,7 @@ static void telnet_size(Backend *be, int width, int height)
/* /*
* Send Telnet special codes. * Send Telnet special codes.
*/ */
static void telnet_special(Backend *be, Telnet_Special code) static void telnet_special(Backend *be, SessionSpecialCode code, int arg)
{ {
Telnet telnet = FROMFIELD(be, struct telnet_tag, backend); Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
unsigned char b[2]; unsigned char b[2];
@ -924,55 +924,55 @@ static void telnet_special(Backend *be, Telnet_Special code)
b[0] = IAC; b[0] = IAC;
switch (code) { switch (code) {
case TS_AYT: case SS_AYT:
b[1] = AYT; b[1] = AYT;
telnet->bufsize = sk_write(telnet->s, b, 2); telnet->bufsize = sk_write(telnet->s, b, 2);
break; break;
case TS_BRK: case SS_BRK:
b[1] = BREAK; b[1] = BREAK;
telnet->bufsize = sk_write(telnet->s, b, 2); telnet->bufsize = sk_write(telnet->s, b, 2);
break; break;
case TS_EC: case SS_EC:
b[1] = EC; b[1] = EC;
telnet->bufsize = sk_write(telnet->s, b, 2); telnet->bufsize = sk_write(telnet->s, b, 2);
break; break;
case TS_EL: case SS_EL:
b[1] = EL; b[1] = EL;
telnet->bufsize = sk_write(telnet->s, b, 2); telnet->bufsize = sk_write(telnet->s, b, 2);
break; break;
case TS_GA: case SS_GA:
b[1] = GA; b[1] = GA;
telnet->bufsize = sk_write(telnet->s, b, 2); telnet->bufsize = sk_write(telnet->s, b, 2);
break; break;
case TS_NOP: case SS_NOP:
b[1] = NOP; b[1] = NOP;
telnet->bufsize = sk_write(telnet->s, b, 2); telnet->bufsize = sk_write(telnet->s, b, 2);
break; break;
case TS_ABORT: case SS_ABORT:
b[1] = ABORT; b[1] = ABORT;
telnet->bufsize = sk_write(telnet->s, b, 2); telnet->bufsize = sk_write(telnet->s, b, 2);
break; break;
case TS_AO: case SS_AO:
b[1] = AO; b[1] = AO;
telnet->bufsize = sk_write(telnet->s, b, 2); telnet->bufsize = sk_write(telnet->s, b, 2);
break; break;
case TS_IP: case SS_IP:
b[1] = IP; b[1] = IP;
telnet->bufsize = sk_write(telnet->s, b, 2); telnet->bufsize = sk_write(telnet->s, b, 2);
break; break;
case TS_SUSP: case SS_SUSP:
b[1] = SUSP; b[1] = SUSP;
telnet->bufsize = sk_write(telnet->s, b, 2); telnet->bufsize = sk_write(telnet->s, b, 2);
break; break;
case TS_EOR: case SS_EOR:
b[1] = EOR; b[1] = EOR;
telnet->bufsize = sk_write(telnet->s, b, 2); telnet->bufsize = sk_write(telnet->s, b, 2);
break; break;
case TS_EOF: case SS_EOF:
b[1] = xEOF; b[1] = xEOF;
telnet->bufsize = sk_write(telnet->s, b, 2); telnet->bufsize = sk_write(telnet->s, b, 2);
break; break;
case TS_EOL: case SS_EOL:
/* In BINARY mode, CR-LF becomes just CR - /* In BINARY mode, CR-LF becomes just CR -
* and without the NUL suffix too. */ * and without the NUL suffix too. */
if (telnet->opt_states[o_we_bin.index] == ACTIVE) if (telnet->opt_states[o_we_bin.index] == ACTIVE)
@ -980,25 +980,12 @@ static void telnet_special(Backend *be, Telnet_Special code)
else else
telnet->bufsize = sk_write(telnet->s, "\r\n", 2); telnet->bufsize = sk_write(telnet->s, "\r\n", 2);
break; break;
case TS_SYNCH: case SS_SYNCH:
b[1] = DM; b[1] = DM;
telnet->bufsize = sk_write(telnet->s, b, 1); telnet->bufsize = sk_write(telnet->s, b, 1);
telnet->bufsize = sk_write_oob(telnet->s, b + 1, 1); telnet->bufsize = sk_write_oob(telnet->s, b + 1, 1);
break; break;
case TS_RECHO: case SS_PING:
if (telnet->opt_states[o_echo.index] == INACTIVE ||
telnet->opt_states[o_echo.index] == REALLY_INACTIVE) {
telnet->opt_states[o_echo.index] = REQUESTED;
send_opt(telnet, o_echo.send, o_echo.option);
}
break;
case TS_LECHO:
if (telnet->opt_states[o_echo.index] == ACTIVE) {
telnet->opt_states[o_echo.index] = REQUESTED;
send_opt(telnet, o_echo.nsend, o_echo.option);
}
break;
case TS_PING:
if (telnet->opt_states[o_they_sga.index] == ACTIVE) { if (telnet->opt_states[o_they_sga.index] == ACTIVE) {
b[1] = NOP; b[1] = NOP;
telnet->bufsize = sk_write(telnet->s, b, 2); telnet->bufsize = sk_write(telnet->s, b, 2);
@ -1009,25 +996,25 @@ static void telnet_special(Backend *be, Telnet_Special code)
} }
} }
static const struct telnet_special *telnet_get_specials(Backend *be) static const SessionSpecial *telnet_get_specials(Backend *be)
{ {
static const struct telnet_special specials[] = { static const SessionSpecial specials[] = {
{"Are You There", TS_AYT}, {"Are You There", SS_AYT},
{"Break", TS_BRK}, {"Break", SS_BRK},
{"Synch", TS_SYNCH}, {"Synch", SS_SYNCH},
{"Erase Character", TS_EC}, {"Erase Character", SS_EC},
{"Erase Line", TS_EL}, {"Erase Line", SS_EL},
{"Go Ahead", TS_GA}, {"Go Ahead", SS_GA},
{"No Operation", TS_NOP}, {"No Operation", SS_NOP},
{NULL, TS_SEP}, {NULL, SS_SEP},
{"Abort Process", TS_ABORT}, {"Abort Process", SS_ABORT},
{"Abort Output", TS_AO}, {"Abort Output", SS_AO},
{"Interrupt Process", TS_IP}, {"Interrupt Process", SS_IP},
{"Suspend Process", TS_SUSP}, {"Suspend Process", SS_SUSP},
{NULL, TS_SEP}, {NULL, SS_SEP},
{"End Of Record", TS_EOR}, {"End Of Record", SS_EOR},
{"End Of File", TS_EOF}, {"End Of File", SS_EOF},
{NULL, TS_EXITMENU} {NULL, SS_EXITMENU}
}; };
return specials; return specials;
} }

View File

@ -43,8 +43,8 @@ static int null_send(Backend *, const char *, int);
static int loop_send(Backend *, const char *, int); static int loop_send(Backend *, const char *, int);
static int null_sendbuffer(Backend *); static int null_sendbuffer(Backend *);
static void null_size(Backend *, int, int); static void null_size(Backend *, int, int);
static void null_special(Backend *, Telnet_Special); static void null_special(Backend *, SessionSpecialCode, int);
static const struct telnet_special *null_get_specials(Backend *); static const SessionSpecial *null_get_specials(Backend *);
static int null_connected(Backend *); static int null_connected(Backend *);
static int null_exitcode(Backend *); static int null_exitcode(Backend *);
static int null_sendok(Backend *); static int null_sendok(Backend *);
@ -126,11 +126,11 @@ static void null_size(Backend *be, int width, int height) {
} }
static void null_special(Backend *be, Telnet_Special code) { static void null_special(Backend *be, SessionSpecialCode code, int arg) {
} }
static const struct telnet_special *null_get_specials (Backend *be) { static const SessionSpecial *null_get_specials (Backend *be) {
return NULL; return NULL;
} }

View File

@ -33,6 +33,7 @@
#define g_signal_handler_disconnect gtk_signal_disconnect #define g_signal_handler_disconnect gtk_signal_disconnect
#define g_object_get_data gtk_object_get_data #define g_object_get_data gtk_object_get_data
#define g_object_set_data gtk_object_set_data #define g_object_set_data gtk_object_set_data
#define g_object_set_data_full gtk_object_set_data_full
#define g_object_ref_sink gtk_object_sink #define g_object_ref_sink gtk_object_sink
#define GDK_GRAB_SUCCESS GrabSuccess #define GDK_GRAB_SUCCESS GrabSuccess

View File

@ -1573,10 +1573,10 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
if (event->keyval == GDK_KEY_Break && if (event->keyval == GDK_KEY_Break &&
(event->state & GDK_CONTROL_MASK)) { (event->state & GDK_CONTROL_MASK)) {
#ifdef KEY_EVENT_DIAGNOSTICS #ifdef KEY_EVENT_DIAGNOSTICS
debug((" - Ctrl-Break special case, sending TS_BRK\n")); debug((" - Ctrl-Break special case, sending SS_BRK\n"));
#endif #endif
if (inst->backend) if (inst->backend)
backend_special(inst->backend, TS_BRK); backend_special(inst->backend, SS_BRK, 0);
return TRUE; return TRUE;
} }
@ -4414,11 +4414,10 @@ void copy_all_menuitem(GtkMenuItem *item, gpointer data)
void special_menuitem(GtkMenuItem *item, gpointer data) void special_menuitem(GtkMenuItem *item, gpointer data)
{ {
Frontend *inst = (Frontend *)data; Frontend *inst = (Frontend *)data;
int code = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(item), SessionSpecial *sc = g_object_get_data(G_OBJECT(item), "user-data");
"user-data"));
if (inst->backend) if (inst->backend)
backend_special(inst->backend, code); backend_special(inst->backend, sc->code, sc->arg);
} }
void about_menuitem(GtkMenuItem *item, gpointer data) void about_menuitem(GtkMenuItem *item, gpointer data)
@ -4915,9 +4914,11 @@ void set_window_icon(GtkWidget *window, const char *const *const *icon,
#endif #endif
} }
static void free_special_cmd(gpointer data) { sfree(data); }
void update_specials_menu(Frontend *inst) void update_specials_menu(Frontend *inst)
{ {
const struct telnet_special *specials; const SessionSpecial *specials;
if (inst->backend) if (inst->backend)
specials = backend_get_specials(inst->backend); specials = backend_get_specials(inst->backend);
@ -4936,7 +4937,7 @@ void update_specials_menu(Frontend *inst)
for (i = 0; nesting > 0; i++) { for (i = 0; nesting > 0; i++) {
GtkWidget *menuitem = NULL; GtkWidget *menuitem = NULL;
switch (specials[i].code) { switch (specials[i].code) {
case TS_SUBMENU: case SS_SUBMENU:
assert (nesting < 2); assert (nesting < 2);
saved_menu = menu; /* XXX lame stacking */ saved_menu = menu; /* XXX lame stacking */
menu = gtk_menu_new(); menu = gtk_menu_new();
@ -4947,20 +4948,24 @@ void update_specials_menu(Frontend *inst)
menuitem = NULL; menuitem = NULL;
nesting++; nesting++;
break; break;
case TS_EXITMENU: case SS_EXITMENU:
nesting--; nesting--;
if (nesting) { if (nesting) {
menu = saved_menu; /* XXX lame stacking */ menu = saved_menu; /* XXX lame stacking */
saved_menu = NULL; saved_menu = NULL;
} }
break; break;
case TS_SEP: case SS_SEP:
menuitem = gtk_menu_item_new(); menuitem = gtk_menu_item_new();
break; break;
default: default:
menuitem = gtk_menu_item_new_with_label(specials[i].name); menuitem = gtk_menu_item_new_with_label(specials[i].name);
g_object_set_data(G_OBJECT(menuitem), "user-data", {
GINT_TO_POINTER(specials[i].code)); SessionSpecial *sc = snew(SessionSpecial);
*sc = specials[i]; /* structure copy */
g_object_set_data_full(G_OBJECT(menuitem), "user-data",
sc, free_special_cmd);
}
g_signal_connect(G_OBJECT(menuitem), "activate", g_signal_connect(G_OBJECT(menuitem), "activate",
G_CALLBACK(special_menuitem), inst); G_CALLBACK(special_menuitem), inst);
break; break;

View File

@ -464,7 +464,7 @@ static void from_tty(void *vbuf, unsigned len)
break; break;
case FF00: case FF00:
if (*p == '\0') { if (*p == '\0') {
backend_special(backend, TS_BRK); backend_special(backend, SS_BRK, 0);
} else { } else {
/* /*
* Pretend that PARMRK wasn't set. This involves * Pretend that PARMRK wasn't set. This involves
@ -991,7 +991,7 @@ int main(int argc, char **argv)
perror("stdin: read"); perror("stdin: read");
exit(1); exit(1);
} else if (ret == 0) { } else if (ret == 0) {
backend_special(backend, TS_EOF); backend_special(backend, SS_EOF, 0);
sending = FALSE; /* send nothing further after this */ sending = FALSE; /* send nothing further after this */
} else { } else {
if (local_tty) if (local_tty)

View File

@ -1159,7 +1159,7 @@ static void pty_size(Backend *be, int width, int height)
/* /*
* Send special codes. * Send special codes.
*/ */
static void pty_special(Backend *be, Telnet_Special code) static void pty_special(Backend *be, SessionSpecialCode code, int arg)
{ {
/* Pty pty = FROMFIELD(be, struct pty_tag, backend); */ /* Pty pty = FROMFIELD(be, struct pty_tag, backend); */
/* Do nothing! */ /* Do nothing! */
@ -1170,7 +1170,7 @@ static void pty_special(Backend *be, 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(Backend *be) static const SessionSpecial *pty_get_specials(Backend *be)
{ {
/* Pty pty = FROMFIELD(be, struct pty_tag, backend); */ /* Pty pty = FROMFIELD(be, struct pty_tag, backend); */
/* /*

View File

@ -496,11 +496,11 @@ static void serial_size(Backend *be, int width, int height)
/* /*
* Send serial special codes. * Send serial special codes.
*/ */
static void serial_special(Backend *be, Telnet_Special code) static void serial_special(Backend *be, SessionSpecialCode code, int arg)
{ {
Serial serial = FROMFIELD(be, struct serial_backend_data, backend); Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
if (serial->fd >= 0 && code == TS_BRK) { if (serial->fd >= 0 && code == SS_BRK) {
tcsendbreak(serial->fd, 0); tcsendbreak(serial->fd, 0);
logevent(serial->frontend, "Sending serial break at user request"); logevent(serial->frontend, "Sending serial break at user request");
} }
@ -512,11 +512,11 @@ static void serial_special(Backend *be, 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(Backend *be) static const SessionSpecial *serial_get_specials(Backend *be)
{ {
static const struct telnet_special specials[] = { static const struct SessionSpecial specials[] = {
{"Break", TS_BRK}, {"Break", SS_BRK},
{NULL, TS_EXITMENU} {NULL, SS_EXITMENU}
}; };
return specials; return specials;
} }

View File

@ -132,7 +132,7 @@ static struct unicode_data ucsdata;
static int session_closed; static int session_closed;
static int reconfiguring = FALSE; static int reconfiguring = FALSE;
static const struct telnet_special *specials = NULL; static const SessionSpecial *specials = NULL;
static HMENU specials_menu = NULL; static HMENU specials_menu = NULL;
static int n_specials = 0; static int n_specials = 0;
@ -965,10 +965,10 @@ void update_specials_menu(Frontend *frontend)
for (i = 0; nesting > 0; i++) { for (i = 0; nesting > 0; i++) {
assert(IDM_SPECIAL_MIN + 0x10 * i < IDM_SPECIAL_MAX); assert(IDM_SPECIAL_MIN + 0x10 * i < IDM_SPECIAL_MAX);
switch (specials[i].code) { switch (specials[i].code) {
case TS_SEP: case SS_SEP:
AppendMenu(new_menu, MF_SEPARATOR, 0, 0); AppendMenu(new_menu, MF_SEPARATOR, 0, 0);
break; break;
case TS_SUBMENU: case SS_SUBMENU:
assert(nesting < 2); assert(nesting < 2);
nesting++; nesting++;
saved_menu = new_menu; /* XXX lame stacking */ saved_menu = new_menu; /* XXX lame stacking */
@ -976,7 +976,7 @@ void update_specials_menu(Frontend *frontend)
AppendMenu(saved_menu, MF_POPUP | MF_ENABLED, AppendMenu(saved_menu, MF_POPUP | MF_ENABLED,
(UINT_PTR) new_menu, specials[i].name); (UINT_PTR) new_menu, specials[i].name);
break; break;
case TS_EXITMENU: case SS_EXITMENU:
nesting--; nesting--;
if (nesting) { if (nesting) {
new_menu = saved_menu; /* XXX lame stacking */ new_menu = saved_menu; /* XXX lame stacking */
@ -2415,7 +2415,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
if (i >= n_specials) if (i >= n_specials)
break; break;
if (backend) if (backend)
backend_special(backend, specials[i].code); backend_special(
backend, specials[i].code, specials[i].arg);
} }
} }
break; break;
@ -4406,7 +4407,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
} }
if (wParam == VK_CANCEL && shift_state == 2) { /* Ctrl-Break */ if (wParam == VK_CANCEL && shift_state == 2) { /* Ctrl-Break */
if (backend) if (backend)
backend_special(backend, TS_BRK); backend_special(backend, SS_BRK, 0);
return 0; return 0;
} }
if (wParam == VK_PAUSE) { /* Break/Pause */ if (wParam == VK_PAUSE) { /* Break/Pause */

View File

@ -247,7 +247,7 @@ int stdin_gotdata(struct handle *h, void *data, int len)
if (len > 0) { if (len > 0) {
return backend_send(backend, data, len); return backend_send(backend, data, len);
} else { } else {
backend_special(backend, TS_EOF); backend_special(backend, SS_EOF, 0);
return 0; return 0;
} }
} else } else

View File

@ -348,11 +348,11 @@ static void serbreak_timer(void *ctx, unsigned long now)
/* /*
* Send serial special codes. * Send serial special codes.
*/ */
static void serial_special(Backend *be, Telnet_Special code) static void serial_special(Backend *be, SessionSpecialCode code, int arg)
{ {
Serial serial = FROMFIELD(be, struct serial_backend_data, backend); Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
if (serial->port && code == TS_BRK) { if (serial->port && code == SS_BRK) {
logevent(serial->frontend, "Starting serial break at user request"); logevent(serial->frontend, "Starting serial break at user request");
SetCommBreak(serial->port); SetCommBreak(serial->port);
/* /*
@ -377,11 +377,11 @@ static void serial_special(Backend *be, 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(Backend *be) static const SessionSpecial *serial_get_specials(Backend *be)
{ {
static const struct telnet_special specials[] = { static const SessionSpecial specials[] = {
{"Break", TS_BRK}, {"Break", SS_BRK},
{NULL, TS_EXITMENU} {NULL, SS_EXITMENU}
}; };
return specials; return specials;
} }