diff options
author | Damien Miller <djm@mindrot.org> | 2011-05-15 08:48:05 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2011-05-15 08:48:05 +1000 |
commit | 555f3b856f2681b46870a66386396b49426b9719 (patch) | |
tree | 88756b47f05c76c5afd5ce739aa26a7b3f124809 /clientloop.c | |
parent | f4b32aad05cb65caa6eabe09049750b3c8a29cf3 (diff) |
- djm@cvs.openbsd.org 2011/05/08 12:52:01
[PROTOCOL.mux clientloop.c clientloop.h mux.c]
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 'clientloop.c')
-rw-r--r-- | clientloop.c | 53 |
1 files changed, 39 insertions, 14 deletions
diff --git a/clientloop.c b/clientloop.c index 5bd757dfb..ed1d8a238 100644 --- a/clientloop.c +++ b/clientloop.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: clientloop.c,v 1.233 2011/05/06 21:34:32 djm Exp $ */ | 1 | /* $OpenBSD: clientloop.c,v 1.234 2011/05/08 12:52:01 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -174,9 +174,11 @@ struct escape_filter_ctx { | |||
174 | }; | 174 | }; |
175 | 175 | ||
176 | /* Context for channel confirmation replies */ | 176 | /* Context for channel confirmation replies */ |
177 | enum confirm_action { CONFIRM_WARN = 0, CONFIRM_CLOSE, CONFIRM_TTY }; | ||
177 | struct channel_reply_ctx { | 178 | struct channel_reply_ctx { |
178 | const char *request_type; | 179 | const char *request_type; |
179 | int id, do_close; | 180 | int id; |
181 | enum confirm_action action; | ||
180 | }; | 182 | }; |
181 | 183 | ||
182 | /* Global request success/failure callbacks */ | 184 | /* Global request success/failure callbacks */ |
@@ -739,6 +741,15 @@ client_status_confirm(int type, Channel *c, void *ctx) | |||
739 | char errmsg[256]; | 741 | char errmsg[256]; |
740 | int tochan; | 742 | int tochan; |
741 | 743 | ||
744 | /* | ||
745 | * If a TTY was explicitly requested, then a failure to allocate | ||
746 | * one is fatal. | ||
747 | */ | ||
748 | if (cr->action == CONFIRM_TTY && | ||
749 | (options.request_tty == REQUEST_TTY_FORCE || | ||
750 | options.request_tty == REQUEST_TTY_YES)) | ||
751 | cr->action = CONFIRM_CLOSE; | ||
752 | |||
742 | /* XXX supress on mux _client_ quietmode */ | 753 | /* XXX supress on mux _client_ quietmode */ |
743 | tochan = options.log_level >= SYSLOG_LEVEL_ERROR && | 754 | tochan = options.log_level >= SYSLOG_LEVEL_ERROR && |
744 | c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE; | 755 | c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE; |
@@ -756,14 +767,27 @@ client_status_confirm(int type, Channel *c, void *ctx) | |||
756 | cr->request_type, c->self); | 767 | cr->request_type, c->self); |
757 | } | 768 | } |
758 | /* If error occurred on primary session channel, then exit */ | 769 | /* If error occurred on primary session channel, then exit */ |
759 | if (cr->do_close && c->self == session_ident) | 770 | if (cr->action == CONFIRM_CLOSE && c->self == session_ident) |
760 | fatal("%s", errmsg); | 771 | fatal("%s", errmsg); |
761 | /* If error occurred on mux client, append to their stderr */ | 772 | /* |
762 | if (tochan) | 773 | * If error occurred on mux client, append to |
763 | buffer_append(&c->extended, errmsg, strlen(errmsg)); | 774 | * their stderr. |
764 | else | 775 | */ |
776 | if (tochan) { | ||
777 | buffer_append(&c->extended, errmsg, | ||
778 | strlen(errmsg)); | ||
779 | } else | ||
765 | error("%s", errmsg); | 780 | error("%s", errmsg); |
766 | if (cr->do_close) { | 781 | if (cr->action == CONFIRM_TTY) { |
782 | /* | ||
783 | * If a TTY allocation error occurred, then arrange | ||
784 | * for the correct TTY to leave raw mode. | ||
785 | */ | ||
786 | if (c->self == session_ident) | ||
787 | leave_raw_mode(0); | ||
788 | else | ||
789 | mux_tty_alloc_failed(c); | ||
790 | } else if (cr->action == CONFIRM_CLOSE) { | ||
767 | chan_read_failed(c); | 791 | chan_read_failed(c); |
768 | chan_write_failed(c); | 792 | chan_write_failed(c); |
769 | } | 793 | } |
@@ -778,12 +802,13 @@ client_abandon_status_confirm(Channel *c, void *ctx) | |||
778 | } | 802 | } |
779 | 803 | ||
780 | static void | 804 | static void |
781 | client_expect_confirm(int id, const char *request, int do_close) | 805 | client_expect_confirm(int id, const char *request, |
806 | enum confirm_action action) | ||
782 | { | 807 | { |
783 | struct channel_reply_ctx *cr = xmalloc(sizeof(*cr)); | 808 | struct channel_reply_ctx *cr = xmalloc(sizeof(*cr)); |
784 | 809 | ||
785 | cr->request_type = request; | 810 | cr->request_type = request; |
786 | cr->do_close = do_close; | 811 | cr->action = action; |
787 | 812 | ||
788 | channel_register_status_confirm(id, client_status_confirm, | 813 | channel_register_status_confirm(id, client_status_confirm, |
789 | client_abandon_status_confirm, cr); | 814 | client_abandon_status_confirm, cr); |
@@ -1983,7 +2008,7 @@ client_session2_setup(int id, int want_tty, int want_subsystem, | |||
1983 | memset(&ws, 0, sizeof(ws)); | 2008 | memset(&ws, 0, sizeof(ws)); |
1984 | 2009 | ||
1985 | channel_request_start(id, "pty-req", 1); | 2010 | channel_request_start(id, "pty-req", 1); |
1986 | client_expect_confirm(id, "PTY allocation", 1); | 2011 | client_expect_confirm(id, "PTY allocation", CONFIRM_TTY); |
1987 | packet_put_cstring(term != NULL ? term : ""); | 2012 | packet_put_cstring(term != NULL ? term : ""); |
1988 | packet_put_int((u_int)ws.ws_col); | 2013 | packet_put_int((u_int)ws.ws_col); |
1989 | packet_put_int((u_int)ws.ws_row); | 2014 | packet_put_int((u_int)ws.ws_row); |
@@ -2042,18 +2067,18 @@ client_session2_setup(int id, int want_tty, int want_subsystem, | |||
2042 | debug("Sending subsystem: %.*s", | 2067 | debug("Sending subsystem: %.*s", |
2043 | len, (u_char*)buffer_ptr(cmd)); | 2068 | len, (u_char*)buffer_ptr(cmd)); |
2044 | channel_request_start(id, "subsystem", 1); | 2069 | channel_request_start(id, "subsystem", 1); |
2045 | client_expect_confirm(id, "subsystem", 1); | 2070 | client_expect_confirm(id, "subsystem", CONFIRM_CLOSE); |
2046 | } else { | 2071 | } else { |
2047 | debug("Sending command: %.*s", | 2072 | debug("Sending command: %.*s", |
2048 | len, (u_char*)buffer_ptr(cmd)); | 2073 | len, (u_char*)buffer_ptr(cmd)); |
2049 | channel_request_start(id, "exec", 1); | 2074 | channel_request_start(id, "exec", 1); |
2050 | client_expect_confirm(id, "exec", 1); | 2075 | client_expect_confirm(id, "exec", CONFIRM_CLOSE); |
2051 | } | 2076 | } |
2052 | packet_put_string(buffer_ptr(cmd), buffer_len(cmd)); | 2077 | packet_put_string(buffer_ptr(cmd), buffer_len(cmd)); |
2053 | packet_send(); | 2078 | packet_send(); |
2054 | } else { | 2079 | } else { |
2055 | channel_request_start(id, "shell", 1); | 2080 | channel_request_start(id, "shell", 1); |
2056 | client_expect_confirm(id, "shell", 1); | 2081 | client_expect_confirm(id, "shell", CONFIRM_CLOSE); |
2057 | packet_send(); | 2082 | packet_send(); |
2058 | } | 2083 | } |
2059 | } | 2084 | } |