1 /* 2 * 3 * clientloop.c 4 * 5 * Author: Tatu Ylonen <ylo@cs.hut.fi> 6 * 7 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 8 * All rights reserved 9 * 10 * 11 * Created: Sat Sep 23 12:23:57 1995 ylo 12 * 13 * The main loop for the interactive session (client side). 14 * 15 */ 16 17 #include "includes.h" 18 RCSID("$Id: clientloop.c,v 1.14 1999/12/06 20:15:26 deraadt Exp $"); 19 20 #include "xmalloc.h" 21 #include "ssh.h" 22 #include "packet.h" 23 #include "buffer.h" 24 #include "authfd.h" 25 #include "readconf.h" 26 27 /* Flag indicating that stdin should be redirected from /dev/null. */ 28 extern int stdin_null_flag; 29 30 /* 31 * Name of the host we are connecting to. This is the name given on the 32 * command line, or the HostName specified for the user-supplied name in a 33 * configuration file. 34 */ 35 extern char *host; 36 37 /* 38 * Flag to indicate that we have received a window change signal which has 39 * not yet been processed. This will cause a message indicating the new 40 * window size to be sent to the server a little later. This is volatile 41 * because this is updated in a signal handler. 42 */ 43 static volatile int received_window_change_signal = 0; 44 45 /* Terminal modes, as saved by enter_raw_mode. */ 46 static struct termios saved_tio; 47 48 /* 49 * Flag indicating whether we are in raw mode. This is used by 50 * enter_raw_mode and leave_raw_mode. 51 */ 52 static int in_raw_mode = 0; 53 54 /* Flag indicating whether the user\'s terminal is in non-blocking mode. */ 55 static int in_non_blocking_mode = 0; 56 57 /* Common data for the client loop code. */ 58 static int escape_pending; /* Last character was the escape character */ 59 static int last_was_cr; /* Last character was a newline. */ 60 static int exit_status; /* Used to store the exit status of the command. */ 61 static int stdin_eof; /* EOF has been encountered on standard error. */ 62 static Buffer stdin_buffer; /* Buffer for stdin data. */ 63 static Buffer stdout_buffer; /* Buffer for stdout data. */ 64 static Buffer stderr_buffer; /* Buffer for stderr data. */ 65 static unsigned int buffer_high;/* Soft max buffer size. */ 66 static int max_fd; /* Maximum file descriptor number in select(). */ 67 static int connection_in; /* Connection to server (input). */ 68 static int connection_out; /* Connection to server (output). */ 69 static unsigned long stdin_bytes, stdout_bytes, stderr_bytes; 70 static int quit_pending; /* Set to non-zero to quit the client loop. */ 71 static int escape_char; /* Escape character. */ 72 73 /* Returns the user\'s terminal to normal mode if it had been put in raw mode. */ 74 75 void 76 leave_raw_mode() 77 { 78 if (!in_raw_mode) 79 return; 80 in_raw_mode = 0; 81 if (tcsetattr(fileno(stdin), TCSADRAIN, &saved_tio) < 0) 82 perror("tcsetattr"); 83 84 fatal_remove_cleanup((void (*) (void *)) leave_raw_mode, NULL); 85 } 86 87 /* Puts the user\'s terminal in raw mode. */ 88 89 void 90 enter_raw_mode() 91 { 92 struct termios tio; 93 94 if (tcgetattr(fileno(stdin), &tio) < 0) 95 perror("tcgetattr"); 96 saved_tio = tio; 97 tio.c_iflag |= IGNPAR; 98 tio.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF); 99 tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL); 100 #ifdef IEXTEN 101 tio.c_lflag &= ~IEXTEN; 102 #endif /* IEXTEN */ 103 tio.c_oflag &= ~OPOST; 104 tio.c_cc[VMIN] = 1; 105 tio.c_cc[VTIME] = 0; 106 if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) < 0) 107 perror("tcsetattr"); 108 in_raw_mode = 1; 109 110 fatal_add_cleanup((void (*) (void *)) leave_raw_mode, NULL); 111 } 112 113 /* Restores stdin to blocking mode. */ 114 115 void 116 leave_non_blocking() 117 { 118 if (in_non_blocking_mode) { 119 (void) fcntl(fileno(stdin), F_SETFL, 0); 120 in_non_blocking_mode = 0; 121 fatal_remove_cleanup((void (*) (void *)) leave_non_blocking, NULL); 122 } 123 } 124 125 /* Puts stdin terminal in non-blocking mode. */ 126 127 void 128 enter_non_blocking() 129 { 130 in_non_blocking_mode = 1; 131 (void) fcntl(fileno(stdin), F_SETFL, O_NONBLOCK); 132 fatal_add_cleanup((void (*) (void *)) leave_non_blocking, NULL); 133 } 134 135 /* 136 * Signal handler for the window change signal (SIGWINCH). This just sets a 137 * flag indicating that the window has changed. 138 */ 139 140 void 141 window_change_handler(int sig) 142 { 143 received_window_change_signal = 1; 144 signal(SIGWINCH, window_change_handler); 145 } 146 147 /* 148 * Signal handler for signals that cause the program to terminate. These 149 * signals must be trapped to restore terminal modes. 150 */ 151 152 void 153 signal_handler(int sig) 154 { 155 if (in_raw_mode) 156 leave_raw_mode(); 157 if (in_non_blocking_mode) 158 leave_non_blocking(); 159 channel_stop_listening(); 160 packet_close(); 161 fatal("Killed by signal %d.", sig); 162 } 163 164 /* 165 * Returns current time in seconds from Jan 1, 1970 with the maximum 166 * available resolution. 167 */ 168 169 double 170 get_current_time() 171 { 172 struct timeval tv; 173 gettimeofday(&tv, NULL); 174 return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0; 175 } 176 177 /* 178 * This is called when the interactive is entered. This checks if there is 179 * an EOF coming on stdin. We must check this explicitly, as select() does 180 * not appear to wake up when redirecting from /dev/null. 181 */ 182 183 void 184 client_check_initial_eof_on_stdin() 185 { 186 int len; 187 char buf[1]; 188 189 /* 190 * If standard input is to be "redirected from /dev/null", we simply 191 * mark that we have seen an EOF and send an EOF message to the 192 * server. Otherwise, we try to read a single character; it appears 193 * that for some files, such /dev/null, select() never wakes up for 194 * read for this descriptor, which means that we never get EOF. This 195 * way we will get the EOF if stdin comes from /dev/null or similar. 196 */ 197 if (stdin_null_flag) { 198 /* Fake EOF on stdin. */ 199 debug("Sending eof."); 200 stdin_eof = 1; 201 packet_start(SSH_CMSG_EOF); 202 packet_send(); 203 } else { 204 enter_non_blocking(); 205 206 /* Check for immediate EOF on stdin. */ 207 len = read(fileno(stdin), buf, 1); 208 if (len == 0) { 209 /* EOF. Record that we have seen it and send EOF to server. */ 210 debug("Sending eof."); 211 stdin_eof = 1; 212 packet_start(SSH_CMSG_EOF); 213 packet_send(); 214 } else if (len > 0) { 215 /* 216 * Got data. We must store the data in the buffer, 217 * and also process it as an escape character if 218 * appropriate. 219 */ 220 if ((unsigned char) buf[0] == escape_char) 221 escape_pending = 1; 222 else { 223 buffer_append(&stdin_buffer, buf, 1); 224 stdin_bytes += 1; 225 } 226 } 227 leave_non_blocking(); 228 } 229 } 230 231 /* 232 * Get packets from the connection input buffer, and process them as long as 233 * there are packets available. 234 */ 235 236 void 237 client_process_buffered_input_packets() 238 { 239 int type; 240 char *data; 241 unsigned int data_len; 242 int payload_len; 243 244 /* Process any buffered packets from the server. */ 245 while (!quit_pending && 246 (type = packet_read_poll(&payload_len)) != SSH_MSG_NONE) { 247 switch (type) { 248 249 case SSH_SMSG_STDOUT_DATA: 250 data = packet_get_string(&data_len); 251 packet_integrity_check(payload_len, 4 + data_len, type); 252 buffer_append(&stdout_buffer, data, data_len); 253 stdout_bytes += data_len; 254 memset(data, 0, data_len); 255 xfree(data); 256 break; 257 258 case SSH_SMSG_STDERR_DATA: 259 data = packet_get_string(&data_len); 260 packet_integrity_check(payload_len, 4 + data_len, type); 261 buffer_append(&stderr_buffer, data, data_len); 262 stdout_bytes += data_len; 263 memset(data, 0, data_len); 264 xfree(data); 265 break; 266 267 case SSH_SMSG_EXITSTATUS: 268 packet_integrity_check(payload_len, 4, type); 269 exit_status = packet_get_int(); 270 /* Acknowledge the exit. */ 271 packet_start(SSH_CMSG_EXIT_CONFIRMATION); 272 packet_send(); 273 /* 274 * Must wait for packet to be sent since we are 275 * exiting the loop. 276 */ 277 packet_write_wait(); 278 /* Flag that we want to exit. */ 279 quit_pending = 1; 280 break; 281 282 case SSH_SMSG_X11_OPEN: 283 x11_input_open(payload_len); 284 break; 285 286 case SSH_MSG_PORT_OPEN: 287 channel_input_port_open(payload_len); 288 break; 289 290 case SSH_SMSG_AGENT_OPEN: 291 packet_integrity_check(payload_len, 4, type); 292 auth_input_open_request(); 293 break; 294 295 case SSH_MSG_CHANNEL_OPEN_CONFIRMATION: 296 packet_integrity_check(payload_len, 4 + 4, type); 297 channel_input_open_confirmation(); 298 break; 299 300 case SSH_MSG_CHANNEL_OPEN_FAILURE: 301 packet_integrity_check(payload_len, 4, type); 302 channel_input_open_failure(); 303 break; 304 305 case SSH_MSG_CHANNEL_DATA: 306 channel_input_data(payload_len); 307 break; 308 309 case SSH_MSG_CHANNEL_CLOSE: 310 packet_integrity_check(payload_len, 4, type); 311 channel_input_close(); 312 break; 313 314 case SSH_MSG_CHANNEL_CLOSE_CONFIRMATION: 315 packet_integrity_check(payload_len, 4, type); 316 channel_input_close_confirmation(); 317 break; 318 319 default: 320 /* 321 * Any unknown packets received during the actual 322 * session cause the session to terminate. This is 323 * intended to make debugging easier since no 324 * confirmations are sent. Any compatible protocol 325 * extensions must be negotiated during the 326 * preparatory phase. 327 */ 328 packet_disconnect("Protocol error during session: type %d", 329 type); 330 } 331 } 332 } 333 334 /* 335 * Make packets from buffered stdin data, and buffer them for sending to the 336 * connection. 337 */ 338 339 void 340 client_make_packets_from_stdin_data() 341 { 342 unsigned int len; 343 344 /* Send buffered stdin data to the server. */ 345 while (buffer_len(&stdin_buffer) > 0 && 346 packet_not_very_much_data_to_write()) { 347 len = buffer_len(&stdin_buffer); 348 /* Keep the packets at reasonable size. */ 349 if (len > packet_get_maxsize()) 350 len = packet_get_maxsize(); 351 packet_start(SSH_CMSG_STDIN_DATA); 352 packet_put_string(buffer_ptr(&stdin_buffer), len); 353 packet_send(); 354 buffer_consume(&stdin_buffer, len); 355 /* If we have a pending EOF, send it now. */ 356 if (stdin_eof && buffer_len(&stdin_buffer) == 0) { 357 packet_start(SSH_CMSG_EOF); 358 packet_send(); 359 } 360 } 361 } 362 363 /* 364 * Checks if the client window has changed, and sends a packet about it to 365 * the server if so. The actual change is detected elsewhere (by a software 366 * interrupt on Unix); this just checks the flag and sends a message if 367 * appropriate. 368 */ 369 370 void 371 client_check_window_change() 372 { 373 /* Send possible window change message to the server. */ 374 if (received_window_change_signal) { 375 struct winsize ws; 376 377 /* Clear the window change indicator. */ 378 received_window_change_signal = 0; 379 380 /* Read new window size. */ 381 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) >= 0) { 382 /* Successful, send the packet now. */ 383 packet_start(SSH_CMSG_WINDOW_SIZE); 384 packet_put_int(ws.ws_row); 385 packet_put_int(ws.ws_col); 386 packet_put_int(ws.ws_xpixel); 387 packet_put_int(ws.ws_ypixel); 388 packet_send(); 389 } 390 } 391 } 392 393 /* 394 * Waits until the client can do something (some data becomes available on 395 * one of the file descriptors). 396 */ 397 398 void 399 client_wait_until_can_do_something(fd_set * readset, fd_set * writeset) 400 { 401 /* Initialize select masks. */ 402 FD_ZERO(readset); 403 404 /* Read from the connection, unless our buffers are full. */ 405 if (buffer_len(&stdout_buffer) < buffer_high && 406 buffer_len(&stderr_buffer) < buffer_high && 407 channel_not_very_much_buffered_data()) 408 FD_SET(connection_in, readset); 409 410 /* 411 * Read from stdin, unless we have seen EOF or have very much 412 * buffered data to send to the server. 413 */ 414 if (!stdin_eof && packet_not_very_much_data_to_write()) 415 FD_SET(fileno(stdin), readset); 416 417 FD_ZERO(writeset); 418 419 /* Add any selections by the channel mechanism. */ 420 channel_prepare_select(readset, writeset); 421 422 /* Select server connection if have data to write to the server. */ 423 if (packet_have_data_to_write()) 424 FD_SET(connection_out, writeset); 425 426 /* Select stdout if have data in buffer. */ 427 if (buffer_len(&stdout_buffer) > 0) 428 FD_SET(fileno(stdout), writeset); 429 430 /* Select stderr if have data in buffer. */ 431 if (buffer_len(&stderr_buffer) > 0) 432 FD_SET(fileno(stderr), writeset); 433 434 /* Update maximum file descriptor number, if appropriate. */ 435 if (channel_max_fd() > max_fd) 436 max_fd = channel_max_fd(); 437 438 /* 439 * Wait for something to happen. This will suspend the process until 440 * some selected descriptor can be read, written, or has some other 441 * event pending. Note: if you want to implement SSH_MSG_IGNORE 442 * messages to fool traffic analysis, this might be the place to do 443 * it: just have a random timeout for the select, and send a random 444 * SSH_MSG_IGNORE packet when the timeout expires. 445 */ 446 447 if (select(max_fd + 1, readset, writeset, NULL, NULL) < 0) { 448 char buf[100]; 449 /* Some systems fail to clear these automatically. */ 450 FD_ZERO(readset); 451 FD_ZERO(writeset); 452 if (errno == EINTR) 453 return; 454 /* Note: we might still have data in the buffers. */ 455 snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno)); 456 buffer_append(&stderr_buffer, buf, strlen(buf)); 457 stderr_bytes += strlen(buf); 458 quit_pending = 1; 459 } 460 } 461 462 void 463 client_suspend_self() 464 { 465 struct winsize oldws, newws; 466 467 /* Flush stdout and stderr buffers. */ 468 if (buffer_len(&stdout_buffer) > 0) 469 atomicio(write, fileno(stdout), buffer_ptr(&stdout_buffer), 470 buffer_len(&stdout_buffer)); 471 if (buffer_len(&stderr_buffer) > 0) 472 atomicio(write, fileno(stderr), buffer_ptr(&stderr_buffer), 473 buffer_len(&stderr_buffer)); 474 475 leave_raw_mode(); 476 477 /* 478 * Free (and clear) the buffer to reduce the amount of data that gets 479 * written to swap. 480 */ 481 buffer_free(&stdin_buffer); 482 buffer_free(&stdout_buffer); 483 buffer_free(&stderr_buffer); 484 485 /* Save old window size. */ 486 ioctl(fileno(stdin), TIOCGWINSZ, &oldws); 487 488 /* Send the suspend signal to the program itself. */ 489 kill(getpid(), SIGTSTP); 490 491 /* Check if the window size has changed. */ 492 if (ioctl(fileno(stdin), TIOCGWINSZ, &newws) >= 0 && 493 (oldws.ws_row != newws.ws_row || 494 oldws.ws_col != newws.ws_col || 495 oldws.ws_xpixel != newws.ws_xpixel || 496 oldws.ws_ypixel != newws.ws_ypixel)) 497 received_window_change_signal = 1; 498 499 /* OK, we have been continued by the user. Reinitialize buffers. */ 500 buffer_init(&stdin_buffer); 501 buffer_init(&stdout_buffer); 502 buffer_init(&stderr_buffer); 503 504 enter_raw_mode(); 505 } 506 507 void 508 client_process_input(fd_set * readset) 509 { 510 int len, pid; 511 char buf[8192], *s; 512 513 /* 514 * Read input from the server, and add any such data to the buffer of 515 * the packet subsystem. 516 */ 517 if (FD_ISSET(connection_in, readset)) { 518 /* Read as much as possible. */ 519 len = read(connection_in, buf, sizeof(buf)); 520 if (len == 0) { 521 /* Received EOF. The remote host has closed the connection. */ 522 snprintf(buf, sizeof buf, "Connection to %.300s closed by remote host.\r\n", 523 host); 524 buffer_append(&stderr_buffer, buf, strlen(buf)); 525 stderr_bytes += strlen(buf); 526 quit_pending = 1; 527 return; 528 } 529 /* 530 * There is a kernel bug on Solaris that causes select to 531 * sometimes wake up even though there is no data available. 532 */ 533 if (len < 0 && errno == EAGAIN) 534 len = 0; 535 536 if (len < 0) { 537 /* An error has encountered. Perhaps there is a network problem. */ 538 snprintf(buf, sizeof buf, "Read from remote host %.300s: %.100s\r\n", 539 host, strerror(errno)); 540 buffer_append(&stderr_buffer, buf, strlen(buf)); 541 stderr_bytes += strlen(buf); 542 quit_pending = 1; 543 return; 544 } 545 packet_process_incoming(buf, len); 546 } 547 /* Read input from stdin. */ 548 if (FD_ISSET(fileno(stdin), readset)) { 549 /* Read as much as possible. */ 550 len = read(fileno(stdin), buf, sizeof(buf)); 551 if (len <= 0) { 552 /* 553 * Received EOF or error. They are treated 554 * similarly, except that an error message is printed 555 * if it was an error condition. 556 */ 557 if (len < 0) { 558 snprintf(buf, sizeof buf, "read: %.100s\r\n", strerror(errno)); 559 buffer_append(&stderr_buffer, buf, strlen(buf)); 560 stderr_bytes += strlen(buf); 561 } 562 /* Mark that we have seen EOF. */ 563 stdin_eof = 1; 564 /* 565 * Send an EOF message to the server unless there is 566 * data in the buffer. If there is data in the 567 * buffer, no message will be sent now. Code 568 * elsewhere will send the EOF when the buffer 569 * becomes empty if stdin_eof is set. 570 */ 571 if (buffer_len(&stdin_buffer) == 0) { 572 packet_start(SSH_CMSG_EOF); 573 packet_send(); 574 } 575 } else if (escape_char == -1) { 576 /* 577 * Normal successful read, and no escape character. 578 * Just append the data to buffer. 579 */ 580 buffer_append(&stdin_buffer, buf, len); 581 stdin_bytes += len; 582 } else { 583 /* 584 * Normal, successful read. But we have an escape character 585 * and have to process the characters one by one. 586 */ 587 unsigned int i; 588 for (i = 0; i < len; i++) { 589 unsigned char ch; 590 /* Get one character at a time. */ 591 ch = buf[i]; 592 593 if (escape_pending) { 594 /* We have previously seen an escape character. */ 595 /* Clear the flag now. */ 596 escape_pending = 0; 597 /* Process the escaped character. */ 598 switch (ch) { 599 case '.': 600 /* Terminate the connection. */ 601 snprintf(buf, sizeof buf, "%c.\r\n", escape_char); 602 buffer_append(&stderr_buffer, buf, strlen(buf)); 603 stderr_bytes += strlen(buf); 604 quit_pending = 1; 605 return; 606 607 case 'Z' - 64: 608 /* Suspend the program. */ 609 /* Print a message to that effect to the user. */ 610 snprintf(buf, sizeof buf, "%c^Z\r\n", escape_char); 611 buffer_append(&stderr_buffer, buf, strlen(buf)); 612 stderr_bytes += strlen(buf); 613 614 /* Restore terminal modes and suspend. */ 615 client_suspend_self(); 616 617 /* We have been continued. */ 618 continue; 619 620 case '&': 621 /* 622 * Detach the program (continue to serve connections, 623 * but put in background and no more new connections). 624 */ 625 if (!stdin_eof) { 626 /* 627 * Sending SSH_CMSG_EOF alone does not always appear 628 * to be enough. So we try to send an EOF character 629 * first. 630 */ 631 packet_start(SSH_CMSG_STDIN_DATA); 632 packet_put_string("\004", 1); 633 packet_send(); 634 /* Close stdin. */ 635 stdin_eof = 1; 636 if (buffer_len(&stdin_buffer) == 0) { 637 packet_start(SSH_CMSG_EOF); 638 packet_send(); 639 } 640 } 641 /* Restore tty modes. */ 642 leave_raw_mode(); 643 644 /* Stop listening for new connections. */ 645 channel_stop_listening(); 646 647 printf("%c& [backgrounded]\n", escape_char); 648 649 /* Fork into background. */ 650 pid = fork(); 651 if (pid < 0) { 652 error("fork: %.100s", strerror(errno)); 653 continue; 654 } 655 if (pid != 0) { /* This is the parent. */ 656 /* The parent just exits. */ 657 exit(0); 658 } 659 /* The child continues serving connections. */ 660 continue; 661 662 case '?': 663 snprintf(buf, sizeof buf, 664 "%c?\r\n\ 665 Supported escape sequences:\r\n\ 666 ~. - terminate connection\r\n\ 667 ~^Z - suspend ssh\r\n\ 668 ~# - list forwarded connections\r\n\ 669 ~& - background ssh (when waiting for connections to terminate)\r\n\ 670 ~? - this message\r\n\ 671 ~~ - send the escape character by typing it twice\r\n\ 672 (Note that escapes are only recognized immediately after newline.)\r\n", 673 escape_char); 674 buffer_append(&stderr_buffer, buf, strlen(buf)); 675 continue; 676 677 case '#': 678 snprintf(buf, sizeof buf, "%c#\r\n", escape_char); 679 buffer_append(&stderr_buffer, buf, strlen(buf)); 680 s = channel_open_message(); 681 buffer_append(&stderr_buffer, s, strlen(s)); 682 xfree(s); 683 continue; 684 685 default: 686 if (ch != escape_char) { 687 /* 688 * Escape character followed by non-special character. 689 * Append both to the input buffer. 690 */ 691 buf[0] = escape_char; 692 buf[1] = ch; 693 buffer_append(&stdin_buffer, buf, 2); 694 stdin_bytes += 2; 695 continue; 696 } 697 /* 698 * Note that escape character typed twice 699 * falls through here; the latter gets processed 700 * as a normal character below. 701 */ 702 break; 703 } 704 } else { 705 /* 706 * The previous character was not an escape char. Check if this 707 * is an escape. 708 */ 709 if (last_was_cr && ch == escape_char) { 710 /* It is. Set the flag and continue to next character. */ 711 escape_pending = 1; 712 continue; 713 } 714 } 715 716 /* 717 * Normal character. Record whether it was a newline, 718 * and append it to the buffer. 719 */ 720 last_was_cr = (ch == '\r' || ch == '\n'); 721 buf[0] = ch; 722 buffer_append(&stdin_buffer, buf, 1); 723 stdin_bytes += 1; 724 continue; 725 } 726 } 727 } 728 } 729 730 void 731 client_process_output(fd_set * writeset) 732 { 733 int len; 734 char buf[100]; 735 736 /* Write buffered output to stdout. */ 737 if (FD_ISSET(fileno(stdout), writeset)) { 738 /* Write as much data as possible. */ 739 len = write(fileno(stdout), buffer_ptr(&stdout_buffer), 740 buffer_len(&stdout_buffer)); 741 if (len <= 0) { 742 if (errno == EAGAIN) 743 len = 0; 744 else { 745 /* 746 * An error or EOF was encountered. Put an 747 * error message to stderr buffer. 748 */ 749 snprintf(buf, sizeof buf, "write stdout: %.50s\r\n", strerror(errno)); 750 buffer_append(&stderr_buffer, buf, strlen(buf)); 751 stderr_bytes += strlen(buf); 752 quit_pending = 1; 753 return; 754 } 755 } 756 /* Consume printed data from the buffer. */ 757 buffer_consume(&stdout_buffer, len); 758 } 759 /* Write buffered output to stderr. */ 760 if (FD_ISSET(fileno(stderr), writeset)) { 761 /* Write as much data as possible. */ 762 len = write(fileno(stderr), buffer_ptr(&stderr_buffer), 763 buffer_len(&stderr_buffer)); 764 if (len <= 0) { 765 if (errno == EAGAIN) 766 len = 0; 767 else { 768 /* EOF or error, but can't even print error message. */ 769 quit_pending = 1; 770 return; 771 } 772 } 773 /* Consume printed characters from the buffer. */ 774 buffer_consume(&stderr_buffer, len); 775 } 776 } 777 778 /* 779 * Implements the interactive session with the server. This is called after 780 * the user has been authenticated, and a command has been started on the 781 * remote host. If escape_char != -1, it is the character used as an escape 782 * character for terminating or suspending the session. 783 */ 784 785 int 786 client_loop(int have_pty, int escape_char_arg) 787 { 788 extern Options options; 789 double start_time, total_time; 790 int len; 791 char buf[100]; 792 793 debug("Entering interactive session."); 794 795 start_time = get_current_time(); 796 797 /* Initialize variables. */ 798 escape_pending = 0; 799 last_was_cr = 1; 800 exit_status = -1; 801 stdin_eof = 0; 802 buffer_high = 64 * 1024; 803 connection_in = packet_get_connection_in(); 804 connection_out = packet_get_connection_out(); 805 max_fd = connection_in; 806 if (connection_out > max_fd) 807 max_fd = connection_out; 808 stdin_bytes = 0; 809 stdout_bytes = 0; 810 stderr_bytes = 0; 811 quit_pending = 0; 812 escape_char = escape_char_arg; 813 814 /* Initialize buffers. */ 815 buffer_init(&stdin_buffer); 816 buffer_init(&stdout_buffer); 817 buffer_init(&stderr_buffer); 818 819 /* Set signal handlers to restore non-blocking mode. */ 820 signal(SIGINT, signal_handler); 821 signal(SIGQUIT, signal_handler); 822 signal(SIGTERM, signal_handler); 823 signal(SIGPIPE, SIG_IGN); 824 if (have_pty) 825 signal(SIGWINCH, window_change_handler); 826 827 if (have_pty) 828 enter_raw_mode(); 829 830 /* Check if we should immediately send of on stdin. */ 831 client_check_initial_eof_on_stdin(); 832 833 /* Main loop of the client for the interactive session mode. */ 834 while (!quit_pending) { 835 fd_set readset, writeset; 836 837 /* Process buffered packets sent by the server. */ 838 client_process_buffered_input_packets(); 839 840 /* 841 * Make packets of buffered stdin data, and buffer them for 842 * sending to the server. 843 */ 844 client_make_packets_from_stdin_data(); 845 846 /* 847 * Make packets from buffered channel data, and buffer them 848 * for sending to the server. 849 */ 850 if (packet_not_very_much_data_to_write()) 851 channel_output_poll(); 852 853 /* 854 * Check if the window size has changed, and buffer a message 855 * about it to the server if so. 856 */ 857 client_check_window_change(); 858 859 if (quit_pending) 860 break; 861 862 /* 863 * Wait until we have something to do (something becomes 864 * available on one of the descriptors). 865 */ 866 client_wait_until_can_do_something(&readset, &writeset); 867 868 if (quit_pending) 869 break; 870 871 /* Do channel operations. */ 872 channel_after_select(&readset, &writeset); 873 874 /* 875 * Process input from the connection and from stdin. Buffer 876 * any data that is available. 877 */ 878 client_process_input(&readset); 879 880 /* 881 * Process output to stdout and stderr. Output to the 882 * connection is processed elsewhere (above). 883 */ 884 client_process_output(&writeset); 885 886 /* Send as much buffered packet data as possible to the sender. */ 887 if (FD_ISSET(connection_out, &writeset)) 888 packet_write_poll(); 889 } 890 891 /* Terminate the session. */ 892 893 /* Stop watching for window change. */ 894 if (have_pty) 895 signal(SIGWINCH, SIG_DFL); 896 897 /* Stop listening for connections. */ 898 channel_stop_listening(); 899 900 /* 901 * In interactive mode (with pseudo tty) display a message indicating 902 * that the connection has been closed. 903 */ 904 if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) { 905 snprintf(buf, sizeof buf, "Connection to %.64s closed.\r\n", host); 906 buffer_append(&stderr_buffer, buf, strlen(buf)); 907 stderr_bytes += strlen(buf); 908 } 909 /* Output any buffered data for stdout. */ 910 while (buffer_len(&stdout_buffer) > 0) { 911 len = write(fileno(stdout), buffer_ptr(&stdout_buffer), 912 buffer_len(&stdout_buffer)); 913 if (len <= 0) { 914 error("Write failed flushing stdout buffer."); 915 break; 916 } 917 buffer_consume(&stdout_buffer, len); 918 } 919 920 /* Output any buffered data for stderr. */ 921 while (buffer_len(&stderr_buffer) > 0) { 922 len = write(fileno(stderr), buffer_ptr(&stderr_buffer), 923 buffer_len(&stderr_buffer)); 924 if (len <= 0) { 925 error("Write failed flushing stderr buffer."); 926 break; 927 } 928 buffer_consume(&stderr_buffer, len); 929 } 930 931 if (have_pty) 932 leave_raw_mode(); 933 934 /* Clear and free any buffers. */ 935 memset(buf, 0, sizeof(buf)); 936 buffer_free(&stdin_buffer); 937 buffer_free(&stdout_buffer); 938 buffer_free(&stderr_buffer); 939 940 /* Report bytes transferred, and transfer rates. */ 941 total_time = get_current_time() - start_time; 942 debug("Transferred: stdin %lu, stdout %lu, stderr %lu bytes in %.1f seconds", 943 stdin_bytes, stdout_bytes, stderr_bytes, total_time); 944 if (total_time > 0) 945 debug("Bytes per second: stdin %.1f, stdout %.1f, stderr %.1f", 946 stdin_bytes / total_time, stdout_bytes / total_time, 947 stderr_bytes / total_time); 948 949 /* Return the exit status of the program. */ 950 debug("Exit status %d", exit_status); 951 return exit_status; 952 } 953