mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-07-14 09:37:34 -05:00
New system for handling SSH terminal modes.
I've introduced a new POD struct type 'ssh_ttymodes' which stores an encoding of everything you can specify in the "pty-req" packet or the SSH-1 equivalent. This allows me to split up write_ttymodes_to_packet_from_conf() into two separate functions, one to parse all the ttymode data out of a Conf (and a Seat for fallback) and return one of those structures, and the other to write it into an SSH packet. While I'm at it, I've moved the special case of terminal speeds into the same mechanism, simplifying the call sites in both versions of the SSH protocol. The new master definition of all terminal modes lives in a header file, with an ifdef around each item, so that later on I'll be able to include it in a context that only enumerates the modes supported by the particular target Unix platform.
This commit is contained in:
172
sshcommon.c
172
sshcommon.c
@ -367,101 +367,47 @@ void chan_no_request_response(Channel *chan, int success)
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Common routine to marshal tty modes into an SSH packet.
|
||||
* Common routines for handling SSH tty modes.
|
||||
*/
|
||||
|
||||
void write_ttymodes_to_packet_from_conf(
|
||||
BinarySink *bs, Seat *seat, Conf *conf,
|
||||
int ssh_version, int ospeed, int ispeed)
|
||||
static unsigned real_ttymode_opcode(unsigned our_opcode, int ssh_version)
|
||||
{
|
||||
int i;
|
||||
switch (our_opcode) {
|
||||
case TTYMODE_ISPEED:
|
||||
return ssh_version == 1 ? TTYMODE_ISPEED_SSH1 : TTYMODE_ISPEED_SSH2;
|
||||
case TTYMODE_OSPEED:
|
||||
return ssh_version == 1 ? TTYMODE_OSPEED_SSH1 : TTYMODE_OSPEED_SSH2;
|
||||
default:
|
||||
return our_opcode;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Codes for terminal modes.
|
||||
* Most of these are the same in SSH-1 and SSH-2.
|
||||
* This list is derived from RFC 4254 and
|
||||
* SSH-1 RFC-1.2.31.
|
||||
*/
|
||||
static const struct ssh_ttymode {
|
||||
struct ssh_ttymodes get_ttymodes_from_conf(Seat *seat, Conf *conf)
|
||||
{
|
||||
struct ssh_ttymodes modes;
|
||||
size_t i;
|
||||
|
||||
static const struct mode_name_type {
|
||||
const char *mode;
|
||||
int opcode;
|
||||
enum { TTY_OP_CHAR, TTY_OP_BOOL } type;
|
||||
} ssh_ttymodes[] = {
|
||||
/* "V" prefix discarded for special characters relative to SSH specs */
|
||||
{ "INTR", 1, TTY_OP_CHAR },
|
||||
{ "QUIT", 2, TTY_OP_CHAR },
|
||||
{ "ERASE", 3, TTY_OP_CHAR },
|
||||
{ "KILL", 4, TTY_OP_CHAR },
|
||||
{ "EOF", 5, TTY_OP_CHAR },
|
||||
{ "EOL", 6, TTY_OP_CHAR },
|
||||
{ "EOL2", 7, TTY_OP_CHAR },
|
||||
{ "START", 8, TTY_OP_CHAR },
|
||||
{ "STOP", 9, TTY_OP_CHAR },
|
||||
{ "SUSP", 10, TTY_OP_CHAR },
|
||||
{ "DSUSP", 11, TTY_OP_CHAR },
|
||||
{ "REPRINT", 12, TTY_OP_CHAR },
|
||||
{ "WERASE", 13, TTY_OP_CHAR },
|
||||
{ "LNEXT", 14, TTY_OP_CHAR },
|
||||
{ "FLUSH", 15, TTY_OP_CHAR },
|
||||
{ "SWTCH", 16, TTY_OP_CHAR },
|
||||
{ "STATUS", 17, TTY_OP_CHAR },
|
||||
{ "DISCARD", 18, TTY_OP_CHAR },
|
||||
{ "IGNPAR", 30, TTY_OP_BOOL },
|
||||
{ "PARMRK", 31, TTY_OP_BOOL },
|
||||
{ "INPCK", 32, TTY_OP_BOOL },
|
||||
{ "ISTRIP", 33, TTY_OP_BOOL },
|
||||
{ "INLCR", 34, TTY_OP_BOOL },
|
||||
{ "IGNCR", 35, TTY_OP_BOOL },
|
||||
{ "ICRNL", 36, TTY_OP_BOOL },
|
||||
{ "IUCLC", 37, TTY_OP_BOOL },
|
||||
{ "IXON", 38, TTY_OP_BOOL },
|
||||
{ "IXANY", 39, TTY_OP_BOOL },
|
||||
{ "IXOFF", 40, TTY_OP_BOOL },
|
||||
{ "IMAXBEL", 41, TTY_OP_BOOL },
|
||||
{ "IUTF8", 42, TTY_OP_BOOL },
|
||||
{ "ISIG", 50, TTY_OP_BOOL },
|
||||
{ "ICANON", 51, TTY_OP_BOOL },
|
||||
{ "XCASE", 52, TTY_OP_BOOL },
|
||||
{ "ECHO", 53, TTY_OP_BOOL },
|
||||
{ "ECHOE", 54, TTY_OP_BOOL },
|
||||
{ "ECHOK", 55, TTY_OP_BOOL },
|
||||
{ "ECHONL", 56, TTY_OP_BOOL },
|
||||
{ "NOFLSH", 57, TTY_OP_BOOL },
|
||||
{ "TOSTOP", 58, TTY_OP_BOOL },
|
||||
{ "IEXTEN", 59, TTY_OP_BOOL },
|
||||
{ "ECHOCTL", 60, TTY_OP_BOOL },
|
||||
{ "ECHOKE", 61, TTY_OP_BOOL },
|
||||
{ "PENDIN", 62, TTY_OP_BOOL }, /* XXX is this a real mode? */
|
||||
{ "OPOST", 70, TTY_OP_BOOL },
|
||||
{ "OLCUC", 71, TTY_OP_BOOL },
|
||||
{ "ONLCR", 72, TTY_OP_BOOL },
|
||||
{ "OCRNL", 73, TTY_OP_BOOL },
|
||||
{ "ONOCR", 74, TTY_OP_BOOL },
|
||||
{ "ONLRET", 75, TTY_OP_BOOL },
|
||||
{ "CS7", 90, TTY_OP_BOOL },
|
||||
{ "CS8", 91, TTY_OP_BOOL },
|
||||
{ "PARENB", 92, TTY_OP_BOOL },
|
||||
{ "PARODD", 93, TTY_OP_BOOL }
|
||||
enum { TYPE_CHAR, TYPE_BOOL } type;
|
||||
} modes_names_types[] = {
|
||||
#define TTYMODE_CHAR(name, val, index) { #name, val, TYPE_CHAR },
|
||||
#define TTYMODE_FLAG(name, val, field, mask) { #name, val, TYPE_BOOL },
|
||||
#include "sshttymodes.h"
|
||||
#undef TTYMODE_CHAR
|
||||
#undef TTYMODE_FLAG
|
||||
};
|
||||
|
||||
/* Miscellaneous other tty-related constants. */
|
||||
enum {
|
||||
/* The opcodes for ISPEED/OSPEED differ between SSH-1 and SSH-2. */
|
||||
SSH1_TTY_OP_ISPEED = 192,
|
||||
SSH1_TTY_OP_OSPEED = 193,
|
||||
SSH2_TTY_OP_ISPEED = 128,
|
||||
SSH2_TTY_OP_OSPEED = 129,
|
||||
memset(&modes, 0, sizeof(modes));
|
||||
|
||||
SSH_TTY_OP_END = 0
|
||||
};
|
||||
|
||||
for (i = 0; i < lenof(ssh_ttymodes); i++) {
|
||||
const struct ssh_ttymode *mode = ssh_ttymodes + i;
|
||||
for (i = 0; i < lenof(modes_names_types); i++) {
|
||||
const struct mode_name_type *mode = &modes_names_types[i];
|
||||
const char *sval = conf_get_str_str(conf, CONF_ttymodes, mode->mode);
|
||||
char *to_free = NULL;
|
||||
|
||||
/* Every mode known to the current version of the code should be
|
||||
* mentioned; this was ensured when settings were loaded. */
|
||||
if (!sval)
|
||||
sval = "N"; /* just in case */
|
||||
|
||||
/*
|
||||
* sval[0] can be
|
||||
@ -488,7 +434,7 @@ void write_ttymodes_to_packet_from_conf(
|
||||
unsigned ival = 0;
|
||||
|
||||
switch (mode->type) {
|
||||
case TTY_OP_CHAR:
|
||||
case TYPE_CHAR:
|
||||
if (*sval) {
|
||||
char *next = NULL;
|
||||
/* We know ctrlparse won't write to the string, so
|
||||
@ -500,7 +446,7 @@ void write_ttymodes_to_packet_from_conf(
|
||||
ival = 255; /* special value meaning "don't set" */
|
||||
}
|
||||
break;
|
||||
case TTY_OP_BOOL:
|
||||
case TYPE_BOOL:
|
||||
if (stricmp(sval, "yes") == 0 ||
|
||||
stricmp(sval, "on") == 0 ||
|
||||
stricmp(sval, "true") == 0 ||
|
||||
@ -518,30 +464,48 @@ void write_ttymodes_to_packet_from_conf(
|
||||
assert(0 && "Bad mode->type");
|
||||
}
|
||||
|
||||
/*
|
||||
* And write it into the output packet. The parameter
|
||||
* value is formatted as a byte in SSH-1, but a uint32
|
||||
* in SSH-2.
|
||||
*/
|
||||
put_byte(bs, mode->opcode);
|
||||
if (ssh_version == 1)
|
||||
put_byte(bs, ival);
|
||||
else
|
||||
put_uint32(bs, ival);
|
||||
modes.have_mode[mode->opcode] = TRUE;
|
||||
modes.mode_val[mode->opcode] = ival;
|
||||
}
|
||||
|
||||
sfree(to_free);
|
||||
}
|
||||
|
||||
/*
|
||||
* Finish off with the terminal speeds (which are formatted as
|
||||
* uint32 in both protocol versions) and the end marker.
|
||||
*/
|
||||
put_byte(bs, ssh_version == 1 ? SSH1_TTY_OP_ISPEED : SSH2_TTY_OP_ISPEED);
|
||||
put_uint32(bs, ispeed);
|
||||
put_byte(bs, ssh_version == 1 ? SSH1_TTY_OP_OSPEED : SSH2_TTY_OP_OSPEED);
|
||||
put_uint32(bs, ospeed);
|
||||
put_byte(bs, SSH_TTY_OP_END);
|
||||
{
|
||||
unsigned ospeed, ispeed;
|
||||
|
||||
/* Unpick the terminal-speed config string. */
|
||||
ospeed = ispeed = 38400; /* last-resort defaults */
|
||||
sscanf(conf_get_str(conf, CONF_termspeed), "%u,%u", &ospeed, &ispeed);
|
||||
/* Currently we unconditionally set these */
|
||||
modes.have_mode[TTYMODE_ISPEED] = TRUE;
|
||||
modes.mode_val[TTYMODE_ISPEED] = ispeed;
|
||||
modes.have_mode[TTYMODE_OSPEED] = TRUE;
|
||||
modes.mode_val[TTYMODE_OSPEED] = ospeed;
|
||||
}
|
||||
|
||||
return modes;
|
||||
}
|
||||
|
||||
void write_ttymodes_to_packet(BinarySink *bs, int ssh_version,
|
||||
struct ssh_ttymodes modes)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < TTYMODE_LIMIT; i++) {
|
||||
if (modes.have_mode[i]) {
|
||||
unsigned val = modes.mode_val[i];
|
||||
unsigned opcode = real_ttymode_opcode(i, ssh_version);
|
||||
|
||||
put_byte(bs, opcode);
|
||||
if (ssh_version == 1 && opcode >= 1 && opcode <= 127)
|
||||
put_byte(bs, val);
|
||||
else
|
||||
put_uint32(bs, val);
|
||||
}
|
||||
}
|
||||
|
||||
put_byte(bs, TTYMODE_END_OF_LIST);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
|
Reference in New Issue
Block a user