summaryrefslogtreecommitdiff
path: root/usr.bin/ssh/clientloop.c
diff options
context:
space:
mode:
authorDamien Miller <djm@cvs.openbsd.org>2011-05-08 12:52:02 +0000
committerDamien Miller <djm@cvs.openbsd.org>2011-05-08 12:52:02 +0000
commit5e6d68444563de018ac60e58c3cf114feee74501 (patch)
treef7baedafbb42333454a22431eac9327ddd054039 /usr.bin/ssh/clientloop.c
parent3dc8acfe369aa6bd6bdc4a05995ebe9bf18d6e8b (diff)
improve our behaviour when TTY allocation fails: if we are in
RequestTTY=auto mode (the default), then do not treat at TTY allocation error as fatal but rather just restore the local TTY to cooked mode and continue. This is more graceful on devices that never allocate TTYs. If RequestTTY is set to "yes" or "force", then failure to allocate a TTY is fatal. ok markus@
Diffstat (limited to 'usr.bin/ssh/clientloop.c')
-rw-r--r--usr.bin/ssh/clientloop.c53
1 files changed, 39 insertions, 14 deletions
diff --git a/usr.bin/ssh/clientloop.c b/usr.bin/ssh/clientloop.c
index 7df1fb652bc..5389be666a4 100644
--- a/usr.bin/ssh/clientloop.c
+++ b/usr.bin/ssh/clientloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.233 2011/05/06 21:34:32 djm Exp $ */
+/* $OpenBSD: clientloop.c,v 1.234 2011/05/08 12:52:01 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -166,9 +166,11 @@ struct escape_filter_ctx {
};
/* Context for channel confirmation replies */
+enum confirm_action { CONFIRM_WARN = 0, CONFIRM_CLOSE, CONFIRM_TTY };
struct channel_reply_ctx {
const char *request_type;
- int id, do_close;
+ int id;
+ enum confirm_action action;
};
/* Global request success/failure callbacks */
@@ -730,6 +732,15 @@ client_status_confirm(int type, Channel *c, void *ctx)
char errmsg[256];
int tochan;
+ /*
+ * If a TTY was explicitly requested, then a failure to allocate
+ * one is fatal.
+ */
+ if (cr->action == CONFIRM_TTY &&
+ (options.request_tty == REQUEST_TTY_FORCE ||
+ options.request_tty == REQUEST_TTY_YES))
+ cr->action = CONFIRM_CLOSE;
+
/* XXX supress on mux _client_ quietmode */
tochan = options.log_level >= SYSLOG_LEVEL_ERROR &&
c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE;
@@ -747,14 +758,27 @@ client_status_confirm(int type, Channel *c, void *ctx)
cr->request_type, c->self);
}
/* If error occurred on primary session channel, then exit */
- if (cr->do_close && c->self == session_ident)
+ if (cr->action == CONFIRM_CLOSE && c->self == session_ident)
fatal("%s", errmsg);
- /* If error occurred on mux client, append to their stderr */
- if (tochan)
- buffer_append(&c->extended, errmsg, strlen(errmsg));
- else
+ /*
+ * If error occurred on mux client, append to
+ * their stderr.
+ */
+ if (tochan) {
+ buffer_append(&c->extended, errmsg,
+ strlen(errmsg));
+ } else
error("%s", errmsg);
- if (cr->do_close) {
+ if (cr->action == CONFIRM_TTY) {
+ /*
+ * If a TTY allocation error occurred, then arrange
+ * for the correct TTY to leave raw mode.
+ */
+ if (c->self == session_ident)
+ leave_raw_mode(0);
+ else
+ mux_tty_alloc_failed(c);
+ } else if (cr->action == CONFIRM_CLOSE) {
chan_read_failed(c);
chan_write_failed(c);
}
@@ -769,12 +793,13 @@ client_abandon_status_confirm(Channel *c, void *ctx)
}
static void
-client_expect_confirm(int id, const char *request, int do_close)
+client_expect_confirm(int id, const char *request,
+ enum confirm_action action)
{
struct channel_reply_ctx *cr = xmalloc(sizeof(*cr));
cr->request_type = request;
- cr->do_close = do_close;
+ cr->action = action;
channel_register_status_confirm(id, client_status_confirm,
client_abandon_status_confirm, cr);
@@ -1965,7 +1990,7 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
memset(&ws, 0, sizeof(ws));
channel_request_start(id, "pty-req", 1);
- client_expect_confirm(id, "PTY allocation", 1);
+ client_expect_confirm(id, "PTY allocation", CONFIRM_TTY);
packet_put_cstring(term != NULL ? term : "");
packet_put_int((u_int)ws.ws_col);
packet_put_int((u_int)ws.ws_row);
@@ -2024,18 +2049,18 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
debug("Sending subsystem: %.*s",
len, (u_char*)buffer_ptr(cmd));
channel_request_start(id, "subsystem", 1);
- client_expect_confirm(id, "subsystem", 1);
+ client_expect_confirm(id, "subsystem", CONFIRM_CLOSE);
} else {
debug("Sending command: %.*s",
len, (u_char*)buffer_ptr(cmd));
channel_request_start(id, "exec", 1);
- client_expect_confirm(id, "exec", 1);
+ client_expect_confirm(id, "exec", CONFIRM_CLOSE);
}
packet_put_string(buffer_ptr(cmd), buffer_len(cmd));
packet_send();
} else {
channel_request_start(id, "shell", 1);
- client_expect_confirm(id, "shell", 1);
+ client_expect_confirm(id, "shell", CONFIRM_CLOSE);
packet_send();
}
}