summaryrefslogtreecommitdiff
path: root/clientloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'clientloop.c')
-rw-r--r--clientloop.c210
1 files changed, 153 insertions, 57 deletions
diff --git a/clientloop.c b/clientloop.c
index 1bc6d7e67..4f2e5037d 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -12,10 +12,11 @@
12 * 12 *
13 * The main loop for the interactive session (client side). 13 * The main loop for the interactive session (client side).
14 * 14 *
15 * SSH2 support added by Markus Friedl.
15 */ 16 */
16 17
17#include "includes.h" 18#include "includes.h"
18RCSID("$Id: clientloop.c,v 1.8 2000/04/01 01:09:23 damien Exp $"); 19RCSID("$Id: clientloop.c,v 1.9 2000/04/06 02:32:39 damien Exp $");
19 20
20#include "xmalloc.h" 21#include "xmalloc.h"
21#include "ssh.h" 22#include "ssh.h"
@@ -24,6 +25,7 @@ RCSID("$Id: clientloop.c,v 1.8 2000/04/01 01:09:23 damien Exp $");
24#include "authfd.h" 25#include "authfd.h"
25#include "readconf.h" 26#include "readconf.h"
26 27
28#include "ssh2.h"
27#include "compat.h" 29#include "compat.h"
28#include "channels.h" 30#include "channels.h"
29#include "dispatch.h" 31#include "dispatch.h"
@@ -75,6 +77,10 @@ static unsigned long stdin_bytes, stdout_bytes, stderr_bytes;
75static int quit_pending; /* Set to non-zero to quit the client loop. */ 77static int quit_pending; /* Set to non-zero to quit the client loop. */
76static int escape_char; /* Escape character. */ 78static int escape_char; /* Escape character. */
77 79
80
81void client_init_dispatch(void);
82int session_ident = -1;
83
78/* Returns the user\'s terminal to normal mode if it had been put in raw mode. */ 84/* Returns the user\'s terminal to normal mode if it had been put in raw mode. */
79 85
80void 86void
@@ -273,23 +279,32 @@ client_make_packets_from_stdin_data()
273void 279void
274client_check_window_change() 280client_check_window_change()
275{ 281{
276 /* Send possible window change message to the server. */ 282 struct winsize ws;
277 if (received_window_change_signal) { 283
278 struct winsize ws; 284 if (! received_window_change_signal)
279 285 return;
280 /* Clear the window change indicator. */ 286 /** XXX race */
281 received_window_change_signal = 0; 287 received_window_change_signal = 0;
282 288
283 /* Read new window size. */ 289 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
284 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) >= 0) { 290 return;
285 /* Successful, send the packet now. */ 291
286 packet_start(SSH_CMSG_WINDOW_SIZE); 292 debug("client_check_window_change: changed");
287 packet_put_int(ws.ws_row); 293
288 packet_put_int(ws.ws_col); 294 if (compat20) {
289 packet_put_int(ws.ws_xpixel); 295 channel_request_start(session_ident, "window-change", 0);
290 packet_put_int(ws.ws_ypixel); 296 packet_put_int(ws.ws_col);
291 packet_send(); 297 packet_put_int(ws.ws_row);
292 } 298 packet_put_int(ws.ws_xpixel);
299 packet_put_int(ws.ws_ypixel);
300 packet_send();
301 } else {
302 packet_start(SSH_CMSG_WINDOW_SIZE);
303 packet_put_int(ws.ws_row);
304 packet_put_int(ws.ws_col);
305 packet_put_int(ws.ws_xpixel);
306 packet_put_int(ws.ws_ypixel);
307 packet_send();
293 } 308 }
294} 309}
295 310
@@ -301,23 +316,33 @@ client_check_window_change()
301void 316void
302client_wait_until_can_do_something(fd_set * readset, fd_set * writeset) 317client_wait_until_can_do_something(fd_set * readset, fd_set * writeset)
303{ 318{
319 /*debug("client_wait_until_can_do_something"); */
320
304 /* Initialize select masks. */ 321 /* Initialize select masks. */
305 FD_ZERO(readset); 322 FD_ZERO(readset);
323 FD_ZERO(writeset);
306 324
307 /* Read from the connection, unless our buffers are full. */ 325 if (!compat20) {
308 if (buffer_len(&stdout_buffer) < buffer_high && 326 /* Read from the connection, unless our buffers are full. */
309 buffer_len(&stderr_buffer) < buffer_high && 327 if (buffer_len(&stdout_buffer) < buffer_high &&
310 channel_not_very_much_buffered_data()) 328 buffer_len(&stderr_buffer) < buffer_high &&
329 channel_not_very_much_buffered_data())
330 FD_SET(connection_in, readset);
331 /*
332 * Read from stdin, unless we have seen EOF or have very much
333 * buffered data to send to the server.
334 */
335 if (!stdin_eof && packet_not_very_much_data_to_write())
336 FD_SET(fileno(stdin), readset);
337
338 /* Select stdout/stderr if have data in buffer. */
339 if (buffer_len(&stdout_buffer) > 0)
340 FD_SET(fileno(stdout), writeset);
341 if (buffer_len(&stderr_buffer) > 0)
342 FD_SET(fileno(stderr), writeset);
343 } else {
311 FD_SET(connection_in, readset); 344 FD_SET(connection_in, readset);
312 345 }
313 /*
314 * Read from stdin, unless we have seen EOF or have very much
315 * buffered data to send to the server.
316 */
317 if (!stdin_eof && packet_not_very_much_data_to_write())
318 FD_SET(fileno(stdin), readset);
319
320 FD_ZERO(writeset);
321 346
322 /* Add any selections by the channel mechanism. */ 347 /* Add any selections by the channel mechanism. */
323 channel_prepare_select(readset, writeset); 348 channel_prepare_select(readset, writeset);
@@ -326,14 +351,7 @@ client_wait_until_can_do_something(fd_set * readset, fd_set * writeset)
326 if (packet_have_data_to_write()) 351 if (packet_have_data_to_write())
327 FD_SET(connection_out, writeset); 352 FD_SET(connection_out, writeset);
328 353
329 /* Select stdout if have data in buffer. */ 354/* move UP XXX */
330 if (buffer_len(&stdout_buffer) > 0)
331 FD_SET(fileno(stdout), writeset);
332
333 /* Select stderr if have data in buffer. */
334 if (buffer_len(&stderr_buffer) > 0)
335 FD_SET(fileno(stderr), writeset);
336
337 /* Update maximum file descriptor number, if appropriate. */ 355 /* Update maximum file descriptor number, if appropriate. */
338 if (channel_max_fd() > max_fd) 356 if (channel_max_fd() > max_fd)
339 max_fd = channel_max_fd(); 357 max_fd = channel_max_fd();
@@ -408,10 +426,10 @@ client_suspend_self()
408} 426}
409 427
410void 428void
411client_process_input(fd_set * readset) 429client_process_net_input(fd_set * readset)
412{ 430{
413 int len, pid; 431 int len;
414 char buf[8192], *s; 432 char buf[8192];
415 433
416 /* 434 /*
417 * Read input from the server, and add any such data to the buffer of 435 * Read input from the server, and add any such data to the buffer of
@@ -420,6 +438,7 @@ client_process_input(fd_set * readset)
420 if (FD_ISSET(connection_in, readset)) { 438 if (FD_ISSET(connection_in, readset)) {
421 /* Read as much as possible. */ 439 /* Read as much as possible. */
422 len = read(connection_in, buf, sizeof(buf)); 440 len = read(connection_in, buf, sizeof(buf));
441/*debug("read connection_in len %d", len); XXX */
423 if (len == 0) { 442 if (len == 0) {
424 /* Received EOF. The remote host has closed the connection. */ 443 /* Received EOF. The remote host has closed the connection. */
425 snprintf(buf, sizeof buf, "Connection to %.300s closed by remote host.\r\n", 444 snprintf(buf, sizeof buf, "Connection to %.300s closed by remote host.\r\n",
@@ -447,6 +466,14 @@ client_process_input(fd_set * readset)
447 } 466 }
448 packet_process_incoming(buf, len); 467 packet_process_incoming(buf, len);
449 } 468 }
469}
470
471void
472client_process_input(fd_set * readset)
473{
474 int len, pid;
475 char buf[8192], *s;
476
450 /* Read input from stdin. */ 477 /* Read input from stdin. */
451 if (FD_ISSET(fileno(stdin), readset)) { 478 if (FD_ISSET(fileno(stdin), readset)) {
452 /* Read as much as possible. */ 479 /* Read as much as possible. */
@@ -703,8 +730,6 @@ client_process_buffered_input_packets()
703 * character for terminating or suspending the session. 730 * character for terminating or suspending the session.
704 */ 731 */
705 732
706void client_init_dispatch(void);
707
708int 733int
709client_loop(int have_pty, int escape_char_arg) 734client_loop(int have_pty, int escape_char_arg)
710{ 735{
@@ -753,7 +778,8 @@ client_loop(int have_pty, int escape_char_arg)
753 enter_raw_mode(); 778 enter_raw_mode();
754 779
755 /* Check if we should immediately send of on stdin. */ 780 /* Check if we should immediately send of on stdin. */
756 client_check_initial_eof_on_stdin(); 781 if (!compat20)
782 client_check_initial_eof_on_stdin();
757 783
758 /* Main loop of the client for the interactive session mode. */ 784 /* Main loop of the client for the interactive session mode. */
759 while (!quit_pending) { 785 while (!quit_pending) {
@@ -762,11 +788,17 @@ client_loop(int have_pty, int escape_char_arg)
762 /* Process buffered packets sent by the server. */ 788 /* Process buffered packets sent by the server. */
763 client_process_buffered_input_packets(); 789 client_process_buffered_input_packets();
764 790
791 if (compat20 && !channel_still_open()) {
792 debug("!channel_still_open.");
793 break;
794 }
795
765 /* 796 /*
766 * Make packets of buffered stdin data, and buffer them for 797 * Make packets of buffered stdin data, and buffer them for
767 * sending to the server. 798 * sending to the server.
768 */ 799 */
769 client_make_packets_from_stdin_data(); 800 if (!compat20)
801 client_make_packets_from_stdin_data();
770 802
771 /* 803 /*
772 * Make packets from buffered channel data, and buffer them 804 * Make packets from buffered channel data, and buffer them
@@ -796,17 +828,21 @@ client_loop(int have_pty, int escape_char_arg)
796 /* Do channel operations. */ 828 /* Do channel operations. */
797 channel_after_select(&readset, &writeset); 829 channel_after_select(&readset, &writeset);
798 830
799 /* 831 /* Buffer input from the connection. */
800 * Process input from the connection and from stdin. Buffer 832 client_process_net_input(&readset);
801 * any data that is available.
802 */
803 client_process_input(&readset);
804 833
805 /* 834 if (quit_pending)
806 * Process output to stdout and stderr. Output to the 835 break;
807 * connection is processed elsewhere (above). 836
808 */ 837 if (!compat20) {
809 client_process_output(&writeset); 838 /* Buffer data from stdin */
839 client_process_input(&readset);
840 /*
841 * Process output to stdout and stderr. Output to
842 * the connection is processed elsewhere (above).
843 */
844 client_process_output(&writeset);
845 }
810 846
811 /* Send as much buffered packet data as possible to the sender. */ 847 /* Send as much buffered packet data as possible to the sender. */
812 if (FD_ISSET(connection_out, &writeset)) 848 if (FD_ISSET(connection_out, &writeset))
@@ -918,6 +954,19 @@ client_input_exit_status(int type, int plen)
918} 954}
919 955
920void 956void
957client_init_dispatch_20()
958{
959 dispatch_init(&dispatch_protocol_error);
960 dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
961 dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
962 dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
963 dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
964 dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
965 dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
966 dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request);
967 dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
968}
969void
921client_init_dispatch_13() 970client_init_dispatch_13()
922{ 971{
923 dispatch_init(NULL); 972 dispatch_init(NULL);
@@ -944,8 +993,55 @@ client_init_dispatch_15()
944void 993void
945client_init_dispatch() 994client_init_dispatch()
946{ 995{
947 if (compat13) 996 if (compat20)
997 client_init_dispatch_20();
998 else if (compat13)
948 client_init_dispatch_13(); 999 client_init_dispatch_13();
949 else 1000 else
950 client_init_dispatch_15(); 1001 client_init_dispatch_15();
951} 1002}
1003
1004void
1005client_input_channel_req(int id, void *arg)
1006{
1007 Channel *c = NULL;
1008 unsigned int len;
1009 int success = 0;
1010 int reply;
1011 char *rtype;
1012
1013 rtype = packet_get_string(&len);
1014 reply = packet_get_char();
1015
1016 log("session_input_channel_req: rtype %s reply %d", rtype, reply);
1017
1018 c = channel_lookup(id);
1019 if (c == NULL)
1020 fatal("session_input_channel_req: channel %d: bad channel", id);
1021
1022 if (session_ident == -1) {
1023 error("client_input_channel_req: no channel %d", id);
1024 } else if (id != session_ident) {
1025 error("client_input_channel_req: bad channel %d != %d",
1026 id, session_ident);
1027 } else if (strcmp(rtype, "exit-status") == 0) {
1028 success = 1;
1029 exit_status = packet_get_int();
1030 }
1031 if (reply) {
1032 packet_start(success ?
1033 SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
1034 packet_put_int(c->remote_id);
1035 packet_send();
1036 }
1037 xfree(rtype);
1038}
1039
1040void
1041client_set_session_ident(int id)
1042{
1043 debug("client_set_session_ident: id %d", id);
1044 session_ident = id;
1045 channel_register_callback(id, SSH2_MSG_CHANNEL_REQUEST,
1046 client_input_channel_req, (void *)0);
1047}