=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/clientloop.c,v retrieving revision 1.15 retrieving revision 1.16 diff -u -r1.15 -r1.16 --- src/usr.bin/ssh/clientloop.c 2000/03/28 20:31:26 1.15 +++ src/usr.bin/ssh/clientloop.c 2000/04/04 15:19:42 1.16 @@ -12,10 +12,11 @@ * * The main loop for the interactive session (client side). * + * SSH2 support added by Markus Friedl. */ #include "includes.h" -RCSID("$Id: clientloop.c,v 1.15 2000/03/28 20:31:26 markus Exp $"); +RCSID("$Id: clientloop.c,v 1.16 2000/04/04 15:19:42 markus Exp $"); #include "xmalloc.h" #include "ssh.h" @@ -24,6 +25,7 @@ #include "authfd.h" #include "readconf.h" +#include "ssh2.h" #include "compat.h" #include "channels.h" #include "dispatch.h" @@ -75,6 +77,10 @@ static int quit_pending; /* Set to non-zero to quit the client loop. */ static int escape_char; /* Escape character. */ + +void client_init_dispatch(void); +int session_ident = -1; + /* Returns the user\'s terminal to normal mode if it had been put in raw mode. */ void @@ -273,23 +279,32 @@ void client_check_window_change() { - /* Send possible window change message to the server. */ - if (received_window_change_signal) { - struct winsize ws; + struct winsize ws; - /* Clear the window change indicator. */ - received_window_change_signal = 0; + if (! received_window_change_signal) + return; + /** XXX race */ + received_window_change_signal = 0; - /* Read new window size. */ - if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) >= 0) { - /* Successful, send the packet now. */ - packet_start(SSH_CMSG_WINDOW_SIZE); - packet_put_int(ws.ws_row); - packet_put_int(ws.ws_col); - packet_put_int(ws.ws_xpixel); - packet_put_int(ws.ws_ypixel); - packet_send(); - } + if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) + return; + + debug("client_check_window_change: changed"); + + if (compat20) { + channel_request_start(session_ident, "window-change", 0); + packet_put_int(ws.ws_col); + packet_put_int(ws.ws_row); + packet_put_int(ws.ws_xpixel); + packet_put_int(ws.ws_ypixel); + packet_send(); + } else { + packet_start(SSH_CMSG_WINDOW_SIZE); + packet_put_int(ws.ws_row); + packet_put_int(ws.ws_col); + packet_put_int(ws.ws_xpixel); + packet_put_int(ws.ws_ypixel); + packet_send(); } } @@ -301,21 +316,28 @@ void client_wait_until_can_do_something(fd_set * readset, fd_set * writeset) { + /*debug("client_wait_until_can_do_something"); */ + /* Initialize select masks. */ FD_ZERO(readset); /* Read from the connection, unless our buffers are full. */ - if (buffer_len(&stdout_buffer) < buffer_high && - buffer_len(&stderr_buffer) < buffer_high && - channel_not_very_much_buffered_data()) + if (!compat20) { + if (buffer_len(&stdout_buffer) < buffer_high && + buffer_len(&stderr_buffer) < buffer_high && + channel_not_very_much_buffered_data()) + FD_SET(connection_in, readset); + } else { FD_SET(connection_in, readset); + } /* * Read from stdin, unless we have seen EOF or have very much * buffered data to send to the server. */ - if (!stdin_eof && packet_not_very_much_data_to_write()) - FD_SET(fileno(stdin), readset); + if (!compat20) + if (!stdin_eof && packet_not_very_much_data_to_write()) + FD_SET(fileno(stdin), readset); FD_ZERO(writeset); @@ -326,14 +348,17 @@ if (packet_have_data_to_write()) FD_SET(connection_out, writeset); - /* Select stdout if have data in buffer. */ - if (buffer_len(&stdout_buffer) > 0) - FD_SET(fileno(stdout), writeset); + if (!compat20) { + /* Select stdout if have data in buffer. */ + if (buffer_len(&stdout_buffer) > 0) + FD_SET(fileno(stdout), writeset); - /* Select stderr if have data in buffer. */ - if (buffer_len(&stderr_buffer) > 0) - FD_SET(fileno(stderr), writeset); + /* Select stderr if have data in buffer. */ + if (buffer_len(&stderr_buffer) > 0) + FD_SET(fileno(stderr), writeset); + } +/* move UP XXX */ /* Update maximum file descriptor number, if appropriate. */ if (channel_max_fd() > max_fd) max_fd = channel_max_fd(); @@ -420,6 +445,7 @@ if (FD_ISSET(connection_in, readset)) { /* Read as much as possible. */ len = read(connection_in, buf, sizeof(buf)); +/*debug("read connection_in len %d", len); XXX */ if (len == 0) { /* Received EOF. The remote host has closed the connection. */ snprintf(buf, sizeof buf, "Connection to %.300s closed by remote host.\r\n", @@ -447,6 +473,10 @@ } packet_process_incoming(buf, len); } + + if (compat20) + return; + /* Read input from stdin. */ if (FD_ISSET(fileno(stdin), readset)) { /* Read as much as possible. */ @@ -703,8 +733,6 @@ * character for terminating or suspending the session. */ -void client_init_dispatch(void); - int client_loop(int have_pty, int escape_char_arg) { @@ -753,7 +781,8 @@ enter_raw_mode(); /* Check if we should immediately send of on stdin. */ - client_check_initial_eof_on_stdin(); + if(!compat20) + client_check_initial_eof_on_stdin(); /* Main loop of the client for the interactive session mode. */ while (!quit_pending) { @@ -762,11 +791,17 @@ /* Process buffered packets sent by the server. */ client_process_buffered_input_packets(); + if (compat20 && !channel_still_open()) { + debug("!channel_still_open."); + break; + } + /* * Make packets of buffered stdin data, and buffer them for * sending to the server. */ - client_make_packets_from_stdin_data(); + if(!compat20) + client_make_packets_from_stdin_data(); /* * Make packets from buffered channel data, and buffer them @@ -806,7 +841,8 @@ * Process output to stdout and stderr. Output to the * connection is processed elsewhere (above). */ - client_process_output(&writeset); + if(!compat20) + client_process_output(&writeset); /* Send as much buffered packet data as possible to the sender. */ if (FD_ISSET(connection_out, &writeset)) @@ -918,6 +954,19 @@ } void +client_init_dispatch_20() +{ + dispatch_init(&dispatch_protocol_error); + dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose); + dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data); + dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof); + dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data); + dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation); + dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); + dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request); + dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust); +} +void client_init_dispatch_13() { dispatch_init(NULL); @@ -944,8 +993,55 @@ void client_init_dispatch() { - if (compat13) + if (compat20) + client_init_dispatch_20(); + else if (compat13) client_init_dispatch_13(); else client_init_dispatch_15(); +} + +void +client_input_channel_req(int id, void *arg) +{ + Channel *c = NULL; + unsigned int len; + int success = 0; + int reply; + char *rtype; + + rtype = packet_get_string(&len); + reply = packet_get_char(); + + log("session_input_channel_req: rtype %s reply %d", rtype, reply); + + c = channel_lookup(id); + if (c == NULL) + fatal("session_input_channel_req: channel %d: bad channel", id); + + if (session_ident == -1) { + error("client_input_channel_req: no channel %d", id); + } else if (id != session_ident) { + error("client_input_channel_req: bad channel %d != %d", + id, session_ident); + } else if (strcmp(rtype, "exit-status") == 0) { + success = 1; + exit_status = packet_get_int(); + } + if (reply) { + packet_start(success ? + SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); + packet_put_int(c->remote_id); + packet_send(); + } + xfree(rtype); +} + +void +client_set_session_ident(int id) +{ + debug("client_set_session_ident: id %d", id); + session_ident = id; + channel_register_callback(id, SSH2_MSG_CHANNEL_REQUEST, + client_input_channel_req, (void *)0); }