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.)
+ *
+ * For the moment, this policy applies to the main session channel
+ * only, because we have a convenient mechanism (ssh->send_ok) for
+ * ceasing to read from our local data source. Ideally I think
+ * we'd do this for auxiliary channels too, which would need an
+ * extra API call in the forwarding modules.
+ */
+ if (c->type == CHAN_MAINSESSION && !(c->closes & CLOSES_SENT_EOF)) {
+ sshfwd_write_eof(ssh->mainchan);
+ ssh->send_ok = 0; /* now stop trying to read from stdin */
+ }
+
+ /*
* 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;