Clean up the parse_ssh_ttymodes system.

There's no reason to pass a 'void *' through and then cast it back to
a packet. All those functions are really doing is serialising a pile
of output on to an arbitrary receiver, so it's nicer to use the new
abstract BinarySink type, and then the do_mode function doesn't have
to cast it at all.

This also removes one lingering ugliness from the previous commit, in
the form of the variable 'stringstart' I introduced in ssh2_setup_pty
to work around the removal of the addstring_start system. Now that's
done the sensible way, by constructing the subsidiary terminal-modes
string in a strbuf (taking advantage of the new type-genericity
meaning I can pass that to the underlying functions just as easily as
a struct Packet), and then putting that into the final packet
afterwards.
This commit is contained in:
Simon Tatham 2018-05-24 10:39:07 +01:00
Родитель 98dce3b291
Коммит 472fddf011
1 изменённых файлов: 24 добавлений и 32 удалений

56
ssh.c
Просмотреть файл

@ -1172,11 +1172,9 @@ static void bomb_out(Ssh ssh, char *text)
#define bombout(msg) bomb_out(ssh, dupprintf msg) #define bombout(msg) bomb_out(ssh, dupprintf msg)
/* Helper function for common bits of parsing ttymodes. */ /* Helper function for common bits of parsing ttymodes. */
static void parse_ttymodes(Ssh ssh, static void parse_ttymodes(
void (*do_mode)(void *data, BinarySink *bs, Ssh ssh,
const struct ssh_ttymode *mode, void (*do_mode)(BinarySink *, const struct ssh_ttymode *, char *))
char *val),
void *data)
{ {
int i; int i;
const struct ssh_ttymode *mode; const struct ssh_ttymode *mode;
@ -1199,11 +1197,11 @@ static void parse_ttymodes(Ssh ssh,
if (val[0] == 'A') { if (val[0] == 'A') {
val = get_ttymode(ssh->frontend, mode->mode); val = get_ttymode(ssh->frontend, mode->mode);
if (val) { if (val) {
do_mode(data, mode, val); do_mode(bs, mode, val);
sfree(val); sfree(val);
} }
} else if (val[0] == 'V') { } else if (val[0] == 'V') {
do_mode(data, mode, val + 1); /* skip the 'V' */ do_mode(bs, mode, val + 1); /* skip the 'V' */
} /* else 'N', or something from the future we don't understand */ } /* else 'N', or something from the future we don't understand */
} }
} }
@ -5979,22 +5977,19 @@ static void ssh1_smsg_exit_status(Ssh ssh, struct Packet *pktin)
} }
/* Helper function to deal with sending tty modes for REQUEST_PTY */ /* Helper function to deal with sending tty modes for REQUEST_PTY */
static void ssh1_send_ttymode(void *data, static void ssh1_send_ttymode(BinarySink *bs,
const struct ssh_ttymode *mode, char *val) const struct ssh_ttymode *mode, char *val)
{ {
struct Packet *pktout = (struct Packet *)data; put_byte(bs, mode->opcode);
unsigned int arg = 0;
switch (mode->type) { switch (mode->type) {
case TTY_OP_CHAR: case TTY_OP_CHAR:
arg = ssh_tty_parse_specchar(val); put_byte(bs, ssh_tty_parse_specchar(val));
break; break;
case TTY_OP_BOOL: case TTY_OP_BOOL:
arg = ssh_tty_parse_boolean(val); put_byte(bs, ssh_tty_parse_boolean(val));
break; break;
} }
put_byte(pktout, mode->opcode);
put_byte(pktout, arg);
} }
int ssh_agent_forwarding_permitted(Ssh ssh) int ssh_agent_forwarding_permitted(Ssh ssh)
@ -6098,7 +6093,7 @@ static void do_ssh1_connection(void *vctx)
put_uint32(pkt, ssh->term_width); put_uint32(pkt, ssh->term_width);
put_uint32(pkt, 0); /* width in pixels */ put_uint32(pkt, 0); /* width in pixels */
put_uint32(pkt, 0); /* height in pixels */ put_uint32(pkt, 0); /* height in pixels */
parse_ttymodes(ssh, ssh1_send_ttymode, (void *)pkt); parse_ttymodes(BinarySink_UPCAST(pkt), ssh, ssh1_send_ttymode);
put_byte(pkt, SSH1_TTY_OP_ISPEED); put_byte(pkt, SSH1_TTY_OP_ISPEED);
put_uint32(pkt, ssh->ispeed); put_uint32(pkt, ssh->ispeed);
put_byte(pkt, SSH1_TTY_OP_OSPEED); put_byte(pkt, SSH1_TTY_OP_OSPEED);
@ -9711,22 +9706,19 @@ static void ssh2_msg_userauth_banner(Ssh ssh, struct Packet *pktin)
} }
/* Helper function to deal with sending tty modes for "pty-req" */ /* Helper function to deal with sending tty modes for "pty-req" */
static void ssh2_send_ttymode(void *data, static void ssh2_send_ttymode(BinarySink *bs,
const struct ssh_ttymode *mode, char *val) const struct ssh_ttymode *mode, char *val)
{ {
struct Packet *pktout = (struct Packet *)data; put_byte(bs, mode->opcode);
unsigned int arg = 0;
switch (mode->type) { switch (mode->type) {
case TTY_OP_CHAR: case TTY_OP_CHAR:
arg = ssh_tty_parse_specchar(val); put_uint32(bs, ssh_tty_parse_specchar(val));
break; break;
case TTY_OP_BOOL: case TTY_OP_BOOL:
arg = ssh_tty_parse_boolean(val); put_uint32(bs, ssh_tty_parse_boolean(val));
break; break;
} }
put_byte(pktout, mode->opcode);
put_uint32(pktout, arg);
} }
static void ssh2_setup_x11(struct ssh_channel *c, struct Packet *pktin, static void ssh2_setup_x11(struct ssh_channel *c, struct Packet *pktin,
@ -9805,7 +9797,6 @@ static void ssh2_setup_pty(struct ssh_channel *c, struct Packet *pktin,
}; };
Ssh ssh = c->ssh; Ssh ssh = c->ssh;
struct Packet *pktout; struct Packet *pktout;
int stringstart;
crStateP(ssh2_setup_pty_state, ctx); crStateP(ssh2_setup_pty_state, ctx);
crBeginState; crBeginState;
@ -9822,15 +9813,16 @@ static void ssh2_setup_pty(struct ssh_channel *c, struct Packet *pktin,
put_uint32(pktout, ssh->term_height); put_uint32(pktout, ssh->term_height);
put_uint32(pktout, 0); /* pixel width */ put_uint32(pktout, 0); /* pixel width */
put_uint32(pktout, 0); /* pixel height */ put_uint32(pktout, 0); /* pixel height */
put_uint32(pktout, 0); /* string length to fill in later */ {
stringstart = pktout->length; strbuf *modebuf = strbuf_new();
parse_ttymodes(ssh, ssh2_send_ttymode, (void *)pktout); parse_ttymodes(BinarySink_UPCAST(modebuf), ssh, ssh2_send_ttymode);
put_byte(pktout, SSH2_TTY_OP_ISPEED); put_byte(modebuf, SSH2_TTY_OP_ISPEED);
put_uint32(pktout, ssh->ispeed); put_uint32(modebuf, ssh->ispeed);
put_byte(pktout, SSH2_TTY_OP_OSPEED); put_byte(modebuf, SSH2_TTY_OP_OSPEED);
put_uint32(pktout, ssh->ospeed); put_uint32(modebuf, ssh->ospeed);
put_byte(pktout, SSH_TTY_OP_END); put_byte(modebuf, SSH_TTY_OP_END);
PUT_32BIT(pktout->data + stringstart - 4, pktout->length - stringstart); put_stringsb(pktout, modebuf);
}
ssh2_pkt_send(ssh, pktout); ssh2_pkt_send(ssh, pktout);
ssh->state = SSH_STATE_INTERMED; ssh->state = SSH_STATE_INTERMED;