=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/clientloop.c,v retrieving revision 1.233 retrieving revision 1.234 diff -u -r1.233 -r1.234 --- src/usr.bin/ssh/clientloop.c 2011/05/06 21:34:32 1.233 +++ src/usr.bin/ssh/clientloop.c 2011/05/08 12:52:01 1.234 @@ -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 * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -166,9 +166,11 @@ }; /* 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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ 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(); } }