diff --git a/defs.h b/defs.h index 47f7c9ba..f45abfec 100644 --- a/defs.h +++ b/defs.h @@ -70,6 +70,8 @@ typedef struct settings_w settings_w; typedef struct settings_r settings_r; typedef struct settings_e settings_e; +typedef struct SessionSpecial SessionSpecial; + /* 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 * 'Socket', not 'Socket *'. So an implementation of Socket or Plug diff --git a/ldisc.c b/ldisc.c index e17b13c7..f411174a 100644 --- a/ldisc.c +++ b/ldisc.c @@ -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])); 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 * 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) goto default_case; if (c == CTRL('C')) - backend_special(ldisc->backend, TS_IP); + backend_special(ldisc->backend, SS_IP, 0); if (c == CTRL('Z')) - backend_special(ldisc->backend, TS_SUSP); + backend_special(ldisc->backend, SS_SUSP, 0); if (c == CTRL('\\')) - backend_special(ldisc->backend, TS_ABORT); + backend_special(ldisc->backend, SS_ABORT, 0); break; case CTRL('R'): /* redraw line */ if (ECHOING) { @@ -245,7 +245,7 @@ void ldisc_send(Ldisc *ldisc, const void *vbuf, int len, int interactive) break; case CTRL('D'): /* logout or send */ if (ldisc->buflen == 0) { - backend_special(ldisc->backend, TS_EOF); + backend_special(ldisc->backend, SS_EOF, 0); } else { backend_send(ldisc->backend, ldisc->buf, ldisc->buflen); ldisc->buflen = 0; @@ -288,7 +288,7 @@ void ldisc_send(Ldisc *ldisc, const void *vbuf, int len, int interactive) if (ldisc->protocol == PROT_RAW) backend_send(ldisc->backend, "\r\n", 2); else if (ldisc->protocol == PROT_TELNET && ldisc->telnet_newline) - backend_special(ldisc->backend, TS_EOL); + backend_special(ldisc->backend, SS_EOL, 0); else backend_send(ldisc->backend, "\r", 1); if (ECHOING) @@ -325,24 +325,24 @@ void ldisc_send(Ldisc *ldisc, const void *vbuf, int len, int interactive) switch (buf[0]) { case CTRL('M'): if (ldisc->protocol == PROT_TELNET && ldisc->telnet_newline) - backend_special(ldisc->backend, TS_EOL); + backend_special(ldisc->backend, SS_EOL, 0); else backend_send(ldisc->backend, "\r", 1); break; case CTRL('?'): case CTRL('H'): if (ldisc->telnet_keyboard) { - backend_special(ldisc->backend, TS_EC); + backend_special(ldisc->backend, SS_EC, 0); break; } case CTRL('C'): if (ldisc->telnet_keyboard) { - backend_special(ldisc->backend, TS_IP); + backend_special(ldisc->backend, SS_IP, 0); break; } case CTRL('Z'): if (ldisc->telnet_keyboard) { - backend_special(ldisc->backend, TS_SUSP); + backend_special(ldisc->backend, SS_SUSP, 0); break; } diff --git a/pinger.c b/pinger.c index c83b71d2..672e86f9 100644 --- a/pinger.c +++ b/pinger.c @@ -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. */ @@ -19,7 +19,7 @@ static void pinger_timer(void *ctx, unsigned long now) Pinger pinger = (Pinger)ctx; if (pinger->pending && now == pinger->next) { - backend_special(pinger->backend, TS_PING); + backend_special(pinger->backend, SS_PING, 0); pinger->pending = FALSE; pinger_schedule(pinger); } diff --git a/pscp.c b/pscp.c index 6a76b798..2ae32826 100644 --- a/pscp.c +++ b/pscp.c @@ -293,7 +293,7 @@ static void bump(const char *fmt, ...) if (backend && backend_connected(backend)) { char ch; - backend_special(backend, TS_EOF); + backend_special(backend, SS_EOF, 0); sent_eof = TRUE; ssh_scp_recv(&ch, 1); } @@ -2367,7 +2367,7 @@ int psftp_main(int argc, char *argv[]) if (backend && backend_connected(backend)) { char ch; - backend_special(backend, TS_EOF); + backend_special(backend, SS_EOF, 0); sent_eof = TRUE; ssh_scp_recv(&ch, 1); } diff --git a/psftp.c b/psftp.c index 4d9ce87d..c20bfb44 100644 --- a/psftp.c +++ b/psftp.c @@ -973,7 +973,7 @@ int sftp_cmd_close(struct sftp_command *cmd) if (backend_connected(backend)) { char ch; - backend_special(backend, TS_EOF); + backend_special(backend, SS_EOF, 0); sent_eof = TRUE; sftp_recvdata(&ch, 1); } @@ -2355,7 +2355,7 @@ void do_sftp_cleanup() { char ch; if (backend) { - backend_special(backend, TS_EOF); + backend_special(backend, SS_EOF, 0); sent_eof = TRUE; sftp_recvdata(&ch, 1); backend_free(backend); @@ -2965,7 +2965,7 @@ int psftp_main(int argc, char *argv[]) if (backend && backend_connected(backend)) { char ch; - backend_special(backend, TS_EOF); + backend_special(backend, SS_EOF, 0); sent_eof = TRUE; sftp_recvdata(&ch, 1); } diff --git a/putty.h b/putty.h index 4b02c06f..db39f2aa 100644 --- a/putty.h +++ b/putty.h @@ -172,34 +172,67 @@ struct unicode_data { #define LGTYP_PACKETS 3 /* logmode: SSH data packets */ #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 { - /* Actual special commands. Originally Telnet, but some codes have - * been re-used for similar specials in other protocols. */ - 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, - TS_EOL, - /* Special command for SSH. */ - TS_REKEY, - /* POSIX-style signals. (not Telnet) */ - 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; + /* + * Commands that are generally useful in multiple backends. + */ + SS_BRK, /* serial-line break */ + SS_EOF, /* end-of-file on session input */ + SS_NOP, /* transmit data with no effect */ + SS_PING, /* try to keep the session alive (probably, but not + * necessarily, implemented as SS_NOP) */ -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; - int code; + SessionSpecialCode code; + int arg; }; typedef enum { @@ -457,8 +490,8 @@ struct Backend_vtable { /* sendbuffer() does the same thing but without attempting a send */ int (*sendbuffer) (Backend *be); void (*size) (Backend *be, int width, int height); - void (*special) (Backend *be, Telnet_Special code); - const struct telnet_special *(*get_specials) (Backend *be); + void (*special) (Backend *be, SessionSpecialCode code, int arg); + const SessionSpecial *(*get_specials) (Backend *be); int (*connected) (Backend *be); int (*exitcode) (Backend *be); /* 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_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_special(be, code, arg) ((be)->vt->special(be, code, arg)) #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)) diff --git a/raw.c b/raw.c index df280139..fea38a9a 100644 --- a/raw.c +++ b/raw.c @@ -231,10 +231,10 @@ static void raw_size(Backend *be, int width, int height) /* * 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); - if (code == TS_EOF && raw->s) { + if (code == SS_EOF && raw->s) { sk_write_eof(raw->s); raw->sent_socket_eof= TRUE; 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 * protocol. */ -static const struct telnet_special *raw_get_specials(Backend *be) +static const SessionSpecial *raw_get_specials(Backend *be) { return NULL; } diff --git a/rlogin.c b/rlogin.c index 05dd7dbb..3055ee7f 100644 --- a/rlogin.c +++ b/rlogin.c @@ -328,7 +328,7 @@ static void rlogin_size(Backend *be, int width, int height) /* * 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! */ 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 * protocol. */ -static const struct telnet_special *rlogin_get_specials(Backend *be) +static const SessionSpecial *rlogin_get_specials(Backend *be) { return NULL; } diff --git a/ssh.c b/ssh.c index 1e22cb8f..bc153887 100644 --- a/ssh.c +++ b/ssh.c @@ -313,7 +313,7 @@ static void ssh1_protocol_setup(Ssh ssh); static void ssh2_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_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 ssh_send_channel_data(struct ssh_channel *c, const char *buf, int len); @@ -592,7 +592,7 @@ struct ssh_tag { /* * 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 @@ -3243,7 +3243,7 @@ static void do_ssh1_connection(void *vctx) if (ssh->size_needed) backend_size(&ssh->backend, ssh->term_width, ssh->term_height); if (ssh->eof_needed) - backend_special(&ssh->backend, TS_EOF); + backend_special(&ssh->backend, SS_EOF, 0); if (ssh->ldisc) 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) backend_size(&ssh->backend, ssh->term_width, ssh->term_height); if (ssh->eof_needed) - backend_special(&ssh->backend, TS_EOF); + backend_special(&ssh->backend, SS_EOF, 0); /* * 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 * 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[] = { - {"IGNORE message", TS_NOP} + static const SessionSpecial ssh1_ignore_special[] = { + {"IGNORE message", SS_NOP} }; - static const struct telnet_special ssh2_ignore_special[] = { - {"IGNORE message", TS_NOP}, + static const SessionSpecial ssh2_ignore_special[] = { + {"IGNORE message", SS_NOP}, }; - static const struct telnet_special ssh2_rekey_special[] = { - {"Repeat key exchange", TS_REKEY}, + static const SessionSpecial ssh2_rekey_special[] = { + {"Repeat key exchange", SS_REKEY}, }; - static const struct telnet_special ssh2_session_specials[] = { - {NULL, TS_SEP}, - {"Break", TS_BRK}, + static const SessionSpecial ssh2_session_specials[] = { + {NULL, SS_SEP}, + {"Break", SS_BRK}, /* These are the signal names defined by RFC 4254. * They include all the ISO C signals, but are a subset of the POSIX * required signals. */ - {"SIGINT (Interrupt)", TS_SIGINT}, - {"SIGTERM (Terminate)", TS_SIGTERM}, - {"SIGKILL (Kill)", TS_SIGKILL}, - {"SIGQUIT (Quit)", TS_SIGQUIT}, - {"SIGHUP (Hangup)", TS_SIGHUP}, - {"More signals", TS_SUBMENU}, - {"SIGABRT", TS_SIGABRT}, {"SIGALRM", TS_SIGALRM}, - {"SIGFPE", TS_SIGFPE}, {"SIGILL", TS_SIGILL}, - {"SIGPIPE", TS_SIGPIPE}, {"SIGSEGV", TS_SIGSEGV}, - {"SIGUSR1", TS_SIGUSR1}, {"SIGUSR2", TS_SIGUSR2}, - {NULL, TS_EXITMENU} + {"SIGINT (Interrupt)", SS_SIGINT}, + {"SIGTERM (Terminate)", SS_SIGTERM}, + {"SIGKILL (Kill)", SS_SIGKILL}, + {"SIGQUIT (Quit)", SS_SIGQUIT}, + {"SIGHUP (Hangup)", SS_SIGHUP}, + {"More signals", SS_SUBMENU}, + {"SIGABRT", SS_SIGABRT}, {"SIGALRM", SS_SIGALRM}, + {"SIGFPE", SS_SIGFPE}, {"SIGILL", SS_SIGILL}, + {"SIGPIPE", SS_SIGPIPE}, {"SIGSEGV", SS_SIGSEGV}, + {"SIGUSR1", SS_SIGUSR1}, {"SIGUSR2", SS_SIGUSR2}, + {NULL, SS_EXITMENU} }; - static const struct telnet_special specials_end[] = { - {NULL, TS_EXITMENU} + static const SessionSpecial specials_end[] = { + {NULL, SS_EXITMENU} }; - struct telnet_special *specials = NULL; + SessionSpecial *specials = NULL; int nspecials = 0, specialsize = 0; 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); \ if (nspecials + len > specialsize) { \ 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; \ } while (0) @@ -9580,22 +9580,23 @@ static const struct telnet_special *ssh_get_specials(Backend *be) ADD_SPECIALS(ssh2_session_specials); if (ssh->n_uncert_hostkeys) { - static const struct telnet_special uncert_start[] = { - {NULL, TS_SEP}, - {"Cache new host key type", TS_SUBMENU}, + static const SessionSpecial uncert_start[] = { + {NULL, SS_SEP}, + {"Cache new host key type", SS_SUBMENU}, }; - static const struct telnet_special uncert_end[] = { - {NULL, TS_EXITMENU}, + static const SessionSpecial uncert_end[] = { + {NULL, SS_EXITMENU}, }; int i; ADD_SPECIALS(uncert_start); for (i = 0; i < ssh->n_uncert_hostkeys; i++) { - struct telnet_special uncert[1]; + SessionSpecial uncert[1]; const ssh_keyalg *alg = hostkey_algs[ssh->uncert_hostkeys[i]].alg; 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_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 * 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); PktOut *pktout; - if (code == TS_EOF) { + if (code == SS_EOF) { if (ssh->state != SSH_STATE_SESSION) { /* * Buffer the EOF in case we are pre-SESSION, so we can * send it as soon as we reach SESSION. */ - if (code == TS_EOF) + if (code == SS_EOF) ssh->eof_needed = TRUE; 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 */ } 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 || ssh->state == SSH_STATE_PREPACKET) return; if (ssh->version == 1) { @@ -9659,15 +9660,15 @@ static void ssh_special(Backend *be, Telnet_Special code) ssh_pkt_write(ssh, pktout); } } - } else if (code == TS_REKEY) { + } else if (code == SS_REKEY) { if (!ssh->kex_in_progress && !ssh->bare_connection && ssh->version == 2) { ssh->rekey_reason = "at user request"; ssh->rekey_class = RK_NORMAL; queue_idempotent_callback(&ssh->ssh2_transport_icb); } - } else if (code >= TS_LOCALSTART) { - ssh->hostkey_alg = hostkey_algs[code - TS_LOCALSTART].alg; + } else if (code == SS_XCERT) { + ssh->hostkey_alg = hostkey_algs[arg].alg; ssh->cross_certifying = TRUE; if (!ssh->kex_in_progress && !ssh->bare_connection && ssh->version == 2) { @@ -9675,7 +9676,7 @@ static void ssh_special(Backend *be, Telnet_Special code) ssh->rekey_class = RK_NORMAL; queue_idempotent_callback(&ssh->ssh2_transport_icb); } - } else if (code == TS_BRK) { + } else if (code == SS_BRK) { if (ssh->state == SSH_STATE_CLOSED || ssh->state == SSH_STATE_PREPACKET) return; if (ssh->version == 1) { @@ -9688,19 +9689,19 @@ static void ssh_special(Backend *be, Telnet_Special code) } else { /* Is is a POSIX signal? */ const char *signame = NULL; - if (code == TS_SIGABRT) signame = "ABRT"; - if (code == TS_SIGALRM) signame = "ALRM"; - if (code == TS_SIGFPE) signame = "FPE"; - if (code == TS_SIGHUP) signame = "HUP"; - if (code == TS_SIGILL) signame = "ILL"; - if (code == TS_SIGINT) signame = "INT"; - if (code == TS_SIGKILL) signame = "KILL"; - if (code == TS_SIGPIPE) signame = "PIPE"; - if (code == TS_SIGQUIT) signame = "QUIT"; - if (code == TS_SIGSEGV) signame = "SEGV"; - if (code == TS_SIGTERM) signame = "TERM"; - if (code == TS_SIGUSR1) signame = "USR1"; - if (code == TS_SIGUSR2) signame = "USR2"; + if (code == SS_SIGABRT) signame = "ABRT"; + if (code == SS_SIGALRM) signame = "ALRM"; + if (code == SS_SIGFPE) signame = "FPE"; + if (code == SS_SIGHUP) signame = "HUP"; + if (code == SS_SIGILL) signame = "ILL"; + if (code == SS_SIGINT) signame = "INT"; + if (code == SS_SIGKILL) signame = "KILL"; + if (code == SS_SIGPIPE) signame = "PIPE"; + if (code == SS_SIGQUIT) signame = "QUIT"; + if (code == SS_SIGSEGV) signame = "SEGV"; + if (code == SS_SIGTERM) signame = "TERM"; + if (code == SS_SIGUSR1) signame = "USR1"; + if (code == SS_SIGUSR2) signame = "USR2"; /* The SSH-2 protocol does in principle support arbitrary named * signals, including signame@domain, but we don't support those. */ if (signame) { diff --git a/telnet.c b/telnet.c index 7e62e301..171b4210 100644 --- a/telnet.c +++ b/telnet.c @@ -914,7 +914,7 @@ static void telnet_size(Backend *be, int width, int height) /* * 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); unsigned char b[2]; @@ -924,55 +924,55 @@ static void telnet_special(Backend *be, Telnet_Special code) b[0] = IAC; switch (code) { - case TS_AYT: + case SS_AYT: b[1] = AYT; telnet->bufsize = sk_write(telnet->s, b, 2); break; - case TS_BRK: + case SS_BRK: b[1] = BREAK; telnet->bufsize = sk_write(telnet->s, b, 2); break; - case TS_EC: + case SS_EC: b[1] = EC; telnet->bufsize = sk_write(telnet->s, b, 2); break; - case TS_EL: + case SS_EL: b[1] = EL; telnet->bufsize = sk_write(telnet->s, b, 2); break; - case TS_GA: + case SS_GA: b[1] = GA; telnet->bufsize = sk_write(telnet->s, b, 2); break; - case TS_NOP: + case SS_NOP: b[1] = NOP; telnet->bufsize = sk_write(telnet->s, b, 2); break; - case TS_ABORT: + case SS_ABORT: b[1] = ABORT; telnet->bufsize = sk_write(telnet->s, b, 2); break; - case TS_AO: + case SS_AO: b[1] = AO; telnet->bufsize = sk_write(telnet->s, b, 2); break; - case TS_IP: + case SS_IP: b[1] = IP; telnet->bufsize = sk_write(telnet->s, b, 2); break; - case TS_SUSP: + case SS_SUSP: b[1] = SUSP; telnet->bufsize = sk_write(telnet->s, b, 2); break; - case TS_EOR: + case SS_EOR: b[1] = EOR; telnet->bufsize = sk_write(telnet->s, b, 2); break; - case TS_EOF: + case SS_EOF: b[1] = xEOF; telnet->bufsize = sk_write(telnet->s, b, 2); break; - case TS_EOL: + case SS_EOL: /* In BINARY mode, CR-LF becomes just CR - * and without the NUL suffix too. */ if (telnet->opt_states[o_we_bin.index] == ACTIVE) @@ -980,25 +980,12 @@ static void telnet_special(Backend *be, Telnet_Special code) else telnet->bufsize = sk_write(telnet->s, "\r\n", 2); break; - case TS_SYNCH: + case SS_SYNCH: b[1] = DM; telnet->bufsize = sk_write(telnet->s, b, 1); telnet->bufsize = sk_write_oob(telnet->s, b + 1, 1); break; - case TS_RECHO: - 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: + case SS_PING: if (telnet->opt_states[o_they_sga.index] == ACTIVE) { b[1] = NOP; 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[] = { - {"Are You There", TS_AYT}, - {"Break", TS_BRK}, - {"Synch", TS_SYNCH}, - {"Erase Character", TS_EC}, - {"Erase Line", TS_EL}, - {"Go Ahead", TS_GA}, - {"No Operation", TS_NOP}, - {NULL, TS_SEP}, - {"Abort Process", TS_ABORT}, - {"Abort Output", TS_AO}, - {"Interrupt Process", TS_IP}, - {"Suspend Process", TS_SUSP}, - {NULL, TS_SEP}, - {"End Of Record", TS_EOR}, - {"End Of File", TS_EOF}, - {NULL, TS_EXITMENU} + static const SessionSpecial specials[] = { + {"Are You There", SS_AYT}, + {"Break", SS_BRK}, + {"Synch", SS_SYNCH}, + {"Erase Character", SS_EC}, + {"Erase Line", SS_EL}, + {"Go Ahead", SS_GA}, + {"No Operation", SS_NOP}, + {NULL, SS_SEP}, + {"Abort Process", SS_ABORT}, + {"Abort Output", SS_AO}, + {"Interrupt Process", SS_IP}, + {"Suspend Process", SS_SUSP}, + {NULL, SS_SEP}, + {"End Of Record", SS_EOR}, + {"End Of File", SS_EOF}, + {NULL, SS_EXITMENU} }; return specials; } diff --git a/testback.c b/testback.c index 01a7e6e0..dfddf93f 100644 --- a/testback.c +++ b/testback.c @@ -43,8 +43,8 @@ static int null_send(Backend *, const char *, int); static int loop_send(Backend *, const char *, int); static int null_sendbuffer(Backend *); static void null_size(Backend *, int, int); -static void null_special(Backend *, Telnet_Special); -static const struct telnet_special *null_get_specials(Backend *); +static void null_special(Backend *, SessionSpecialCode, int); +static const SessionSpecial *null_get_specials(Backend *); static int null_connected(Backend *); static int null_exitcode(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; } diff --git a/unix/gtkcompat.h b/unix/gtkcompat.h index c0341c34..03947a79 100644 --- a/unix/gtkcompat.h +++ b/unix/gtkcompat.h @@ -33,6 +33,7 @@ #define g_signal_handler_disconnect gtk_signal_disconnect #define g_object_get_data gtk_object_get_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 GDK_GRAB_SUCCESS GrabSuccess diff --git a/unix/gtkwin.c b/unix/gtkwin.c index eb3f201f..a391f361 100644 --- a/unix/gtkwin.c +++ b/unix/gtkwin.c @@ -1573,10 +1573,10 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) if (event->keyval == GDK_KEY_Break && (event->state & GDK_CONTROL_MASK)) { #ifdef KEY_EVENT_DIAGNOSTICS - debug((" - Ctrl-Break special case, sending TS_BRK\n")); + debug((" - Ctrl-Break special case, sending SS_BRK\n")); #endif if (inst->backend) - backend_special(inst->backend, TS_BRK); + backend_special(inst->backend, SS_BRK, 0); return TRUE; } @@ -4414,11 +4414,10 @@ void copy_all_menuitem(GtkMenuItem *item, gpointer data) void special_menuitem(GtkMenuItem *item, gpointer data) { Frontend *inst = (Frontend *)data; - int code = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(item), - "user-data")); + SessionSpecial *sc = g_object_get_data(G_OBJECT(item), "user-data"); if (inst->backend) - backend_special(inst->backend, code); + backend_special(inst->backend, sc->code, sc->arg); } void about_menuitem(GtkMenuItem *item, gpointer data) @@ -4915,9 +4914,11 @@ void set_window_icon(GtkWidget *window, const char *const *const *icon, #endif } +static void free_special_cmd(gpointer data) { sfree(data); } + void update_specials_menu(Frontend *inst) { - const struct telnet_special *specials; + const SessionSpecial *specials; if (inst->backend) specials = backend_get_specials(inst->backend); @@ -4936,7 +4937,7 @@ void update_specials_menu(Frontend *inst) for (i = 0; nesting > 0; i++) { GtkWidget *menuitem = NULL; switch (specials[i].code) { - case TS_SUBMENU: + case SS_SUBMENU: assert (nesting < 2); saved_menu = menu; /* XXX lame stacking */ menu = gtk_menu_new(); @@ -4947,20 +4948,24 @@ void update_specials_menu(Frontend *inst) menuitem = NULL; nesting++; break; - case TS_EXITMENU: + case SS_EXITMENU: nesting--; if (nesting) { menu = saved_menu; /* XXX lame stacking */ saved_menu = NULL; } break; - case TS_SEP: + case SS_SEP: menuitem = gtk_menu_item_new(); break; default: 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_CALLBACK(special_menuitem), inst); break; diff --git a/unix/uxplink.c b/unix/uxplink.c index 9ef5841b..c211309b 100644 --- a/unix/uxplink.c +++ b/unix/uxplink.c @@ -464,7 +464,7 @@ static void from_tty(void *vbuf, unsigned len) break; case FF00: if (*p == '\0') { - backend_special(backend, TS_BRK); + backend_special(backend, SS_BRK, 0); } else { /* * Pretend that PARMRK wasn't set. This involves @@ -991,7 +991,7 @@ int main(int argc, char **argv) perror("stdin: read"); exit(1); } else if (ret == 0) { - backend_special(backend, TS_EOF); + backend_special(backend, SS_EOF, 0); sending = FALSE; /* send nothing further after this */ } else { if (local_tty) diff --git a/unix/uxpty.c b/unix/uxpty.c index a5c770d4..a8429d76 100644 --- a/unix/uxpty.c +++ b/unix/uxpty.c @@ -1159,7 +1159,7 @@ static void pty_size(Backend *be, int width, int height) /* * 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); */ /* 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 * 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); */ /* diff --git a/unix/uxser.c b/unix/uxser.c index b02eb320..f2064680 100644 --- a/unix/uxser.c +++ b/unix/uxser.c @@ -496,11 +496,11 @@ static void serial_size(Backend *be, int width, int height) /* * 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); - if (serial->fd >= 0 && code == TS_BRK) { + if (serial->fd >= 0 && code == SS_BRK) { tcsendbreak(serial->fd, 0); 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 * 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[] = { - {"Break", TS_BRK}, - {NULL, TS_EXITMENU} + static const struct SessionSpecial specials[] = { + {"Break", SS_BRK}, + {NULL, SS_EXITMENU} }; return specials; } diff --git a/windows/window.c b/windows/window.c index b73de782..40836435 100644 --- a/windows/window.c +++ b/windows/window.c @@ -132,7 +132,7 @@ static struct unicode_data ucsdata; static int session_closed; static int reconfiguring = FALSE; -static const struct telnet_special *specials = NULL; +static const SessionSpecial *specials = NULL; static HMENU specials_menu = NULL; static int n_specials = 0; @@ -965,10 +965,10 @@ void update_specials_menu(Frontend *frontend) for (i = 0; nesting > 0; i++) { assert(IDM_SPECIAL_MIN + 0x10 * i < IDM_SPECIAL_MAX); switch (specials[i].code) { - case TS_SEP: + case SS_SEP: AppendMenu(new_menu, MF_SEPARATOR, 0, 0); break; - case TS_SUBMENU: + case SS_SUBMENU: assert(nesting < 2); nesting++; saved_menu = new_menu; /* XXX lame stacking */ @@ -976,7 +976,7 @@ void update_specials_menu(Frontend *frontend) AppendMenu(saved_menu, MF_POPUP | MF_ENABLED, (UINT_PTR) new_menu, specials[i].name); break; - case TS_EXITMENU: + case SS_EXITMENU: nesting--; if (nesting) { new_menu = saved_menu; /* XXX lame stacking */ @@ -2415,7 +2415,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, if (i >= n_specials) break; if (backend) - backend_special(backend, specials[i].code); + backend_special( + backend, specials[i].code, specials[i].arg); } } break; @@ -4406,7 +4407,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, } if (wParam == VK_CANCEL && shift_state == 2) { /* Ctrl-Break */ if (backend) - backend_special(backend, TS_BRK); + backend_special(backend, SS_BRK, 0); return 0; } if (wParam == VK_PAUSE) { /* Break/Pause */ diff --git a/windows/winplink.c b/windows/winplink.c index e8da54ec..c215ec19 100644 --- a/windows/winplink.c +++ b/windows/winplink.c @@ -247,7 +247,7 @@ int stdin_gotdata(struct handle *h, void *data, int len) if (len > 0) { return backend_send(backend, data, len); } else { - backend_special(backend, TS_EOF); + backend_special(backend, SS_EOF, 0); return 0; } } else diff --git a/windows/winser.c b/windows/winser.c index 2a42ce21..e427f358 100644 --- a/windows/winser.c +++ b/windows/winser.c @@ -348,11 +348,11 @@ static void serbreak_timer(void *ctx, unsigned long now) /* * 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); - if (serial->port && code == TS_BRK) { + if (serial->port && code == SS_BRK) { logevent(serial->frontend, "Starting serial break at user request"); 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 * 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[] = { - {"Break", TS_BRK}, - {NULL, TS_EXITMENU} + static const SessionSpecial specials[] = { + {"Break", SS_BRK}, + {NULL, SS_EXITMENU} }; return specials; }