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;
}
} 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);
}
ssh2_channel_got_eof(c);
/*
+ * And we also send an outgoing EOF, if we haven't already, on the
+ * assumption that CLOSE is a pretty forceful announcement that
+ * the remote side is doing away with the entire channel. (If it
+ * had wanted to send us EOF and continue receiving data from us,
+ * it would have just sent CHANNEL_EOF.)
+ */
+ if (!(c->closes & CLOSES_SENT_EOF)) {
+ /*
+ * Make sure we don't read any more from whatever our local
+ * data source is for this channel.
+ */
+ switch (c->type) {
+ case CHAN_MAINSESSION:
+ ssh->send_ok = 0; /* stop trying to read from stdin */
+ break;
+ case CHAN_X11:
+ x11_override_throttle(c->u.x11.s, 1);
+ break;
+ case CHAN_SOCKDATA:
+ pfd_override_throttle(c->u.pfd.s, 1);
+ break;
+ }
+
+ /*
+ * Send outgoing EOF.
+ */
+ sshfwd_write_eof(ssh->mainchan);
+ }
+
+ /*
* Now process the actual close.
*/
if (!(c->closes & CLOSES_RCVD_CLOSE)) {
} 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;