struct Packet *pktin);
static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
struct Packet *pktin);
+static void ssh2_channel_check_close(struct ssh_channel *c);
static void ssh_channel_destroy(struct ssh_channel *c);
/*
int size_needed, eof_needed;
int sent_console_eof;
+ int got_pty; /* affects EOF behaviour on main channel */
struct Packet **queue;
int queuelen, queuesize;
} else if (pktin->type == SSH1_SMSG_FAILURE) {
c_write_str(ssh, "Server refused to allocate pty\r\n");
ssh->editing = ssh->echoing = 1;
- }
- logeventf(ssh, "Allocated pty (ospeed %dbps, ispeed %dbps)",
- ssh->ospeed, ssh->ispeed);
+ } else {
+ logeventf(ssh, "Allocated pty (ospeed %dbps, ispeed %dbps)",
+ ssh->ospeed, ssh->ispeed);
+ ssh->got_pty = TRUE;
+ }
} else {
ssh->editing = ssh->echoing = 1;
}
*/
if (c->v.v2.throttle_state == UNTHROTTLING)
c->v.v2.throttle_state = UNTHROTTLED;
+ /*
+ * We may now initiate channel-closing procedures, if that winadj
+ * was the last thing outstanding before we send CHANNEL_CLOSE.
+ */
+ ssh2_channel_check_close(c);
return TRUE;
}
struct Packet *pktout;
if ((c->closes & (CLOSES_SENT_EOF | CLOSES_RCVD_EOF | CLOSES_SENT_CLOSE))
- == (CLOSES_SENT_EOF | CLOSES_RCVD_EOF)) {
+ == (CLOSES_SENT_EOF | CLOSES_RCVD_EOF) && !c->v.v2.winadj_head) {
/*
- * We have both sent and received EOF, which means the channel
- * is in final wind-up. But we haven't sent CLOSE, so let's.
+ * We have both sent and received EOF, and we have no
+ * outstanding winadj channel requests, which means the
+ * channel is in final wind-up. But we haven't sent CLOSE, so
+ * let's do so now.
*/
pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_CLOSE);
ssh2_pkt_adduint32(pktout, c->remoteid);
} else if (c->type == CHAN_MAINSESSION) {
Ssh ssh = c->ssh;
- if (!ssh->sent_console_eof && from_backend_eof(ssh->frontend)) {
+ if (!ssh->sent_console_eof &&
+ (from_backend_eof(ssh->frontend) || ssh->got_pty)) {
/*
- * The front end wants us to close the outgoing side of the
- * connection as soon as we see EOF from the far end.
+ * Either from_backend_eof told us that the front end
+ * wants us to close the outgoing side of the connection
+ * as soon as we see EOF from the far end, or else we've
+ * unilaterally decided to do that because we've allocated
+ * a remote pty and hence EOF isn't a particularly
+ * meaningful concept.
*/
sshfwd_write_eof(c);
}
} else {
logeventf(ssh, "Allocated pty (ospeed %dbps, ispeed %dbps)",
ssh->ospeed, ssh->ispeed);
+ ssh->got_pty = TRUE;
}
} else {
ssh->editing = ssh->echoing = 1;
ssh->frozen = FALSE;
ssh->username = NULL;
ssh->sent_console_eof = FALSE;
+ ssh->got_pty = FALSE;
*backend_handle = ssh;