diff options
Diffstat (limited to 'clientloop.c')
-rw-r--r-- | clientloop.c | 317 |
1 files changed, 189 insertions, 128 deletions
diff --git a/clientloop.c b/clientloop.c index c49346c2c..679180f58 100644 --- a/clientloop.c +++ b/clientloop.c | |||
@@ -15,7 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "includes.h" | 17 | #include "includes.h" |
18 | RCSID("$Id: clientloop.c,v 1.5 1999/11/24 13:26:22 damien Exp $"); | 18 | RCSID("$Id: clientloop.c,v 1.6 1999/11/25 00:54:58 damien Exp $"); |
19 | 19 | ||
20 | #include "xmalloc.h" | 20 | #include "xmalloc.h" |
21 | #include "ssh.h" | 21 | #include "ssh.h" |
@@ -27,22 +27,28 @@ RCSID("$Id: clientloop.c,v 1.5 1999/11/24 13:26:22 damien Exp $"); | |||
27 | /* Flag indicating that stdin should be redirected from /dev/null. */ | 27 | /* Flag indicating that stdin should be redirected from /dev/null. */ |
28 | extern int stdin_null_flag; | 28 | extern int stdin_null_flag; |
29 | 29 | ||
30 | /* Name of the host we are connecting to. This is the name given on the | 30 | /* |
31 | command line, or the HostName specified for the user-supplied name | 31 | * Name of the host we are connecting to. This is the name given on the |
32 | in a configuration file. */ | 32 | * command line, or the HostName specified for the user-supplied name in a |
33 | * configuration file. | ||
34 | */ | ||
33 | extern char *host; | 35 | extern char *host; |
34 | 36 | ||
35 | /* Flag to indicate that we have received a window change signal which has | 37 | /* |
36 | not yet been processed. This will cause a message indicating the new | 38 | * Flag to indicate that we have received a window change signal which has |
37 | window size to be sent to the server a little later. This is volatile | 39 | * not yet been processed. This will cause a message indicating the new |
38 | because this is updated in a signal handler. */ | 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 | */ | ||
39 | static volatile int received_window_change_signal = 0; | 43 | static volatile int received_window_change_signal = 0; |
40 | 44 | ||
41 | /* Terminal modes, as saved by enter_raw_mode. */ | 45 | /* Terminal modes, as saved by enter_raw_mode. */ |
42 | static struct termios saved_tio; | 46 | static struct termios saved_tio; |
43 | 47 | ||
44 | /* Flag indicating whether we are in raw mode. This is used by enter_raw_mode | 48 | /* |
45 | and leave_raw_mode. */ | 49 | * Flag indicating whether we are in raw mode. This is used by |
50 | * enter_raw_mode and leave_raw_mode. | ||
51 | */ | ||
46 | static int in_raw_mode = 0; | 52 | static int in_raw_mode = 0; |
47 | 53 | ||
48 | /* Flag indicating whether the user\'s terminal is in non-blocking mode. */ | 54 | /* Flag indicating whether the user\'s terminal is in non-blocking mode. */ |
@@ -64,8 +70,7 @@ static unsigned long stdin_bytes, stdout_bytes, stderr_bytes; | |||
64 | static int quit_pending; /* Set to non-zero to quit the client loop. */ | 70 | static int quit_pending; /* Set to non-zero to quit the client loop. */ |
65 | static int escape_char; /* Escape character. */ | 71 | static int escape_char; /* Escape character. */ |
66 | 72 | ||
67 | /* Returns the user\'s terminal to normal mode if it had been put in raw | 73 | /* Returns the user\'s terminal to normal mode if it had been put in raw mode. */ |
68 | mode. */ | ||
69 | 74 | ||
70 | void | 75 | void |
71 | leave_raw_mode() | 76 | leave_raw_mode() |
@@ -127,8 +132,10 @@ enter_non_blocking() | |||
127 | fatal_add_cleanup((void (*) (void *)) leave_non_blocking, NULL); | 132 | fatal_add_cleanup((void (*) (void *)) leave_non_blocking, NULL); |
128 | } | 133 | } |
129 | 134 | ||
130 | /* Signal handler for the window change signal (SIGWINCH). This just | 135 | /* |
131 | sets a flag indicating that the window has changed. */ | 136 | * Signal handler for the window change signal (SIGWINCH). This just sets a |
137 | * flag indicating that the window has changed. | ||
138 | */ | ||
132 | 139 | ||
133 | void | 140 | void |
134 | window_change_handler(int sig) | 141 | window_change_handler(int sig) |
@@ -137,8 +144,10 @@ window_change_handler(int sig) | |||
137 | signal(SIGWINCH, window_change_handler); | 144 | signal(SIGWINCH, window_change_handler); |
138 | } | 145 | } |
139 | 146 | ||
140 | /* Signal handler for signals that cause the program to terminate. These | 147 | /* |
141 | signals must be trapped to restore terminal modes. */ | 148 | * Signal handler for signals that cause the program to terminate. These |
149 | * signals must be trapped to restore terminal modes. | ||
150 | */ | ||
142 | 151 | ||
143 | void | 152 | void |
144 | signal_handler(int sig) | 153 | signal_handler(int sig) |
@@ -152,8 +161,10 @@ signal_handler(int sig) | |||
152 | fatal("Killed by signal %d.", sig); | 161 | fatal("Killed by signal %d.", sig); |
153 | } | 162 | } |
154 | 163 | ||
155 | /* Returns current time in seconds from Jan 1, 1970 with the maximum available | 164 | /* |
156 | resolution. */ | 165 | * Returns current time in seconds from Jan 1, 1970 with the maximum |
166 | * available resolution. | ||
167 | */ | ||
157 | 168 | ||
158 | double | 169 | double |
159 | get_current_time() | 170 | get_current_time() |
@@ -163,9 +174,11 @@ get_current_time() | |||
163 | return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0; | 174 | return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0; |
164 | } | 175 | } |
165 | 176 | ||
166 | /* This is called when the interactive is entered. This checks if there | 177 | /* |
167 | is an EOF coming on stdin. We must check this explicitly, as select() | 178 | * This is called when the interactive is entered. This checks if there is |
168 | does not appear to wake up when redirecting from /dev/null. */ | 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 | */ | ||
169 | 182 | ||
170 | void | 183 | void |
171 | client_check_initial_eof_on_stdin() | 184 | client_check_initial_eof_on_stdin() |
@@ -173,13 +186,14 @@ client_check_initial_eof_on_stdin() | |||
173 | int len; | 186 | int len; |
174 | char buf[1]; | 187 | char buf[1]; |
175 | 188 | ||
176 | /* If standard input is to be "redirected from /dev/null", we | 189 | /* |
177 | simply mark that we have seen an EOF and send an EOF message to | 190 | * If standard input is to be "redirected from /dev/null", we simply |
178 | the server. Otherwise, we try to read a single character; it | 191 | * mark that we have seen an EOF and send an EOF message to the |
179 | appears that for some files, such /dev/null, select() never | 192 | * server. Otherwise, we try to read a single character; it appears |
180 | wakes up for read for this descriptor, which means that we | 193 | * that for some files, such /dev/null, select() never wakes up for |
181 | never get EOF. This way we will get the EOF if stdin comes | 194 | * read for this descriptor, which means that we never get EOF. This |
182 | from /dev/null or similar. */ | 195 | * way we will get the EOF if stdin comes from /dev/null or similar. |
196 | */ | ||
183 | if (stdin_null_flag) { | 197 | if (stdin_null_flag) { |
184 | /* Fake EOF on stdin. */ | 198 | /* Fake EOF on stdin. */ |
185 | debug("Sending eof."); | 199 | debug("Sending eof."); |
@@ -187,22 +201,22 @@ client_check_initial_eof_on_stdin() | |||
187 | packet_start(SSH_CMSG_EOF); | 201 | packet_start(SSH_CMSG_EOF); |
188 | packet_send(); | 202 | packet_send(); |
189 | } else { | 203 | } else { |
190 | /* Enter non-blocking mode for stdin. */ | ||
191 | enter_non_blocking(); | 204 | enter_non_blocking(); |
192 | 205 | ||
193 | /* Check for immediate EOF on stdin. */ | 206 | /* Check for immediate EOF on stdin. */ |
194 | len = read(fileno(stdin), buf, 1); | 207 | len = read(fileno(stdin), buf, 1); |
195 | if (len == 0) { | 208 | if (len == 0) { |
196 | /* EOF. Record that we have seen it and send EOF | 209 | /* EOF. Record that we have seen it and send EOF to server. */ |
197 | to server. */ | ||
198 | debug("Sending eof."); | 210 | debug("Sending eof."); |
199 | stdin_eof = 1; | 211 | stdin_eof = 1; |
200 | packet_start(SSH_CMSG_EOF); | 212 | packet_start(SSH_CMSG_EOF); |
201 | packet_send(); | 213 | packet_send(); |
202 | } else if (len > 0) { | 214 | } else if (len > 0) { |
203 | /* Got data. We must store the data in the | 215 | /* |
204 | buffer, and also process it as an escape | 216 | * Got data. We must store the data in the buffer, |
205 | character if appropriate. */ | 217 | * and also process it as an escape character if |
218 | * appropriate. | ||
219 | */ | ||
206 | if ((unsigned char) buf[0] == escape_char) | 220 | if ((unsigned char) buf[0] == escape_char) |
207 | escape_pending = 1; | 221 | escape_pending = 1; |
208 | else { | 222 | else { |
@@ -210,13 +224,14 @@ client_check_initial_eof_on_stdin() | |||
210 | stdin_bytes += 1; | 224 | stdin_bytes += 1; |
211 | } | 225 | } |
212 | } | 226 | } |
213 | /* Leave non-blocking mode. */ | ||
214 | leave_non_blocking(); | 227 | leave_non_blocking(); |
215 | } | 228 | } |
216 | } | 229 | } |
217 | 230 | ||
218 | /* Get packets from the connection input buffer, and process them as long | 231 | /* |
219 | as there are packets available. */ | 232 | * Get packets from the connection input buffer, and process them as long as |
233 | * there are packets available. | ||
234 | */ | ||
220 | 235 | ||
221 | void | 236 | void |
222 | client_process_buffered_input_packets() | 237 | client_process_buffered_input_packets() |
@@ -255,8 +270,10 @@ client_process_buffered_input_packets() | |||
255 | /* Acknowledge the exit. */ | 270 | /* Acknowledge the exit. */ |
256 | packet_start(SSH_CMSG_EXIT_CONFIRMATION); | 271 | packet_start(SSH_CMSG_EXIT_CONFIRMATION); |
257 | packet_send(); | 272 | packet_send(); |
258 | /* Must wait for packet to be sent since we are | 273 | /* |
259 | exiting the loop. */ | 274 | * Must wait for packet to be sent since we are |
275 | * exiting the loop. | ||
276 | */ | ||
260 | packet_write_wait(); | 277 | packet_write_wait(); |
261 | /* Flag that we want to exit. */ | 278 | /* Flag that we want to exit. */ |
262 | quit_pending = 1; | 279 | quit_pending = 1; |
@@ -300,20 +317,24 @@ client_process_buffered_input_packets() | |||
300 | break; | 317 | break; |
301 | 318 | ||
302 | default: | 319 | default: |
303 | /* Any unknown packets received during the actual | 320 | /* |
304 | session cause the session to terminate. This | 321 | * Any unknown packets received during the actual |
305 | is intended to make debugging easier since no | 322 | * session cause the session to terminate. This is |
306 | confirmations are sent. Any compatible | 323 | * intended to make debugging easier since no |
307 | protocol extensions must be negotiated during | 324 | * confirmations are sent. Any compatible protocol |
308 | the preparatory phase. */ | 325 | * extensions must be negotiated during the |
326 | * preparatory phase. | ||
327 | */ | ||
309 | packet_disconnect("Protocol error during session: type %d", | 328 | packet_disconnect("Protocol error during session: type %d", |
310 | type); | 329 | type); |
311 | } | 330 | } |
312 | } | 331 | } |
313 | } | 332 | } |
314 | 333 | ||
315 | /* Make packets from buffered stdin data, and buffer them for sending to | 334 | /* |
316 | the connection. */ | 335 | * Make packets from buffered stdin data, and buffer them for sending to the |
336 | * connection. | ||
337 | */ | ||
317 | 338 | ||
318 | void | 339 | void |
319 | client_make_packets_from_stdin_data() | 340 | client_make_packets_from_stdin_data() |
@@ -339,10 +360,12 @@ client_make_packets_from_stdin_data() | |||
339 | } | 360 | } |
340 | } | 361 | } |
341 | 362 | ||
342 | /* Checks if the client window has changed, and sends a packet about it to | 363 | /* |
343 | the server if so. The actual change is detected elsewhere (by a software | 364 | * Checks if the client window has changed, and sends a packet about it to |
344 | interrupt on Unix); this just checks the flag and sends a message if | 365 | * the server if so. The actual change is detected elsewhere (by a software |
345 | appropriate. */ | 366 | * interrupt on Unix); this just checks the flag and sends a message if |
367 | * appropriate. | ||
368 | */ | ||
346 | 369 | ||
347 | void | 370 | void |
348 | client_check_window_change() | 371 | client_check_window_change() |
@@ -367,8 +390,10 @@ client_check_window_change() | |||
367 | } | 390 | } |
368 | } | 391 | } |
369 | 392 | ||
370 | /* Waits until the client can do something (some data becomes available on | 393 | /* |
371 | one of the file descriptors). */ | 394 | * Waits until the client can do something (some data becomes available on |
395 | * one of the file descriptors). | ||
396 | */ | ||
372 | 397 | ||
373 | void | 398 | void |
374 | client_wait_until_can_do_something(fd_set * readset, fd_set * writeset) | 399 | client_wait_until_can_do_something(fd_set * readset, fd_set * writeset) |
@@ -382,8 +407,10 @@ client_wait_until_can_do_something(fd_set * readset, fd_set * writeset) | |||
382 | channel_not_very_much_buffered_data()) | 407 | channel_not_very_much_buffered_data()) |
383 | FD_SET(connection_in, readset); | 408 | FD_SET(connection_in, readset); |
384 | 409 | ||
385 | /* Read from stdin, unless we have seen EOF or have very much | 410 | /* |
386 | buffered data to send to the server. */ | 411 | * Read from stdin, unless we have seen EOF or have very much |
412 | * buffered data to send to the server. | ||
413 | */ | ||
387 | if (!stdin_eof && packet_not_very_much_data_to_write()) | 414 | if (!stdin_eof && packet_not_very_much_data_to_write()) |
388 | FD_SET(fileno(stdin), readset); | 415 | FD_SET(fileno(stdin), readset); |
389 | 416 | ||
@@ -408,13 +435,14 @@ client_wait_until_can_do_something(fd_set * readset, fd_set * writeset) | |||
408 | if (channel_max_fd() > max_fd) | 435 | if (channel_max_fd() > max_fd) |
409 | max_fd = channel_max_fd(); | 436 | max_fd = channel_max_fd(); |
410 | 437 | ||
411 | /* Wait for something to happen. This will suspend the process | 438 | /* |
412 | until some selected descriptor can be read, written, or has | 439 | * Wait for something to happen. This will suspend the process until |
413 | some other event pending. | 440 | * some selected descriptor can be read, written, or has some other |
414 | Note: if you want to implement SSH_MSG_IGNORE messages to fool | 441 | * event pending. Note: if you want to implement SSH_MSG_IGNORE |
415 | traffic analysis, this might be the place to do it: | 442 | * messages to fool traffic analysis, this might be the place to do |
416 | just have a random timeout for the select, and send a random | 443 | * it: just have a random timeout for the select, and send a random |
417 | SSH_MSG_IGNORE packet when the timeout expires. */ | 444 | * SSH_MSG_IGNORE packet when the timeout expires. |
445 | */ | ||
418 | 446 | ||
419 | if (select(max_fd + 1, readset, writeset, NULL, NULL) < 0) { | 447 | if (select(max_fd + 1, readset, writeset, NULL, NULL) < 0) { |
420 | char buf[100]; | 448 | char buf[100]; |
@@ -446,11 +474,12 @@ client_suspend_self() | |||
446 | buffer_ptr(&stderr_buffer), | 474 | buffer_ptr(&stderr_buffer), |
447 | buffer_len(&stderr_buffer)); | 475 | buffer_len(&stderr_buffer)); |
448 | 476 | ||
449 | /* Leave raw mode. */ | ||
450 | leave_raw_mode(); | 477 | leave_raw_mode(); |
451 | 478 | ||
452 | /* Free (and clear) the buffer to reduce the amount of data that | 479 | /* |
453 | gets written to swap. */ | 480 | * Free (and clear) the buffer to reduce the amount of data that gets |
481 | * written to swap. | ||
482 | */ | ||
454 | buffer_free(&stdin_buffer); | 483 | buffer_free(&stdin_buffer); |
455 | buffer_free(&stdout_buffer); | 484 | buffer_free(&stdout_buffer); |
456 | buffer_free(&stderr_buffer); | 485 | buffer_free(&stderr_buffer); |
@@ -474,7 +503,6 @@ client_suspend_self() | |||
474 | buffer_init(&stdout_buffer); | 503 | buffer_init(&stdout_buffer); |
475 | buffer_init(&stderr_buffer); | 504 | buffer_init(&stderr_buffer); |
476 | 505 | ||
477 | /* Re-enter raw mode. */ | ||
478 | enter_raw_mode(); | 506 | enter_raw_mode(); |
479 | } | 507 | } |
480 | 508 | ||
@@ -484,8 +512,10 @@ client_process_input(fd_set * readset) | |||
484 | int len, pid; | 512 | int len, pid; |
485 | char buf[8192], *s; | 513 | char buf[8192], *s; |
486 | 514 | ||
487 | /* Read input from the server, and add any such data to the buffer | 515 | /* |
488 | of the packet subsystem. */ | 516 | * Read input from the server, and add any such data to the buffer of |
517 | * the packet subsystem. | ||
518 | */ | ||
489 | if (FD_ISSET(connection_in, readset)) { | 519 | if (FD_ISSET(connection_in, readset)) { |
490 | /* Read as much as possible. */ | 520 | /* Read as much as possible. */ |
491 | len = read(connection_in, buf, sizeof(buf)); | 521 | len = read(connection_in, buf, sizeof(buf)); |
@@ -498,9 +528,10 @@ client_process_input(fd_set * readset) | |||
498 | quit_pending = 1; | 528 | quit_pending = 1; |
499 | return; | 529 | return; |
500 | } | 530 | } |
501 | /* There is a kernel bug on Solaris that causes select to | 531 | /* |
502 | sometimes wake up even though there is no data | 532 | * There is a kernel bug on Solaris that causes select to |
503 | available. */ | 533 | * sometimes wake up even though there is no data available. |
534 | */ | ||
504 | if (len < 0 && errno == EAGAIN) | 535 | if (len < 0 && errno == EAGAIN) |
505 | len = 0; | 536 | len = 0; |
506 | 537 | ||
@@ -520,9 +551,11 @@ client_process_input(fd_set * readset) | |||
520 | /* Read as much as possible. */ | 551 | /* Read as much as possible. */ |
521 | len = read(fileno(stdin), buf, sizeof(buf)); | 552 | len = read(fileno(stdin), buf, sizeof(buf)); |
522 | if (len <= 0) { | 553 | if (len <= 0) { |
523 | /* Received EOF or error. They are treated | 554 | /* |
524 | similarly, except that an error message is | 555 | * Received EOF or error. They are treated |
525 | printed if it was an error condition. */ | 556 | * similarly, except that an error message is printed |
557 | * if it was an error condition. | ||
558 | */ | ||
526 | if (len < 0) { | 559 | if (len < 0) { |
527 | snprintf(buf, sizeof buf, "read: %.100s\r\n", strerror(errno)); | 560 | snprintf(buf, sizeof buf, "read: %.100s\r\n", strerror(errno)); |
528 | buffer_append(&stderr_buffer, buf, strlen(buf)); | 561 | buffer_append(&stderr_buffer, buf, strlen(buf)); |
@@ -530,32 +563,35 @@ client_process_input(fd_set * readset) | |||
530 | } | 563 | } |
531 | /* Mark that we have seen EOF. */ | 564 | /* Mark that we have seen EOF. */ |
532 | stdin_eof = 1; | 565 | stdin_eof = 1; |
533 | /* Send an EOF message to the server unless there | 566 | /* |
534 | is data in the buffer. If there is data in the | 567 | * Send an EOF message to the server unless there is |
535 | buffer, no message will be sent now. Code | 568 | * data in the buffer. If there is data in the |
536 | elsewhere will send the EOF when the buffer | 569 | * buffer, no message will be sent now. Code |
537 | becomes empty if stdin_eof is set. */ | 570 | * elsewhere will send the EOF when the buffer |
571 | * becomes empty if stdin_eof is set. | ||
572 | */ | ||
538 | if (buffer_len(&stdin_buffer) == 0) { | 573 | if (buffer_len(&stdin_buffer) == 0) { |
539 | packet_start(SSH_CMSG_EOF); | 574 | packet_start(SSH_CMSG_EOF); |
540 | packet_send(); | 575 | packet_send(); |
541 | } | 576 | } |
542 | } else if (escape_char == -1) { | 577 | } else if (escape_char == -1) { |
543 | /* Normal successful read, and no escape | 578 | /* |
544 | character. Just append the data to buffer. */ | 579 | * Normal successful read, and no escape character. |
580 | * Just append the data to buffer. | ||
581 | */ | ||
545 | buffer_append(&stdin_buffer, buf, len); | 582 | buffer_append(&stdin_buffer, buf, len); |
546 | stdin_bytes += len; | 583 | stdin_bytes += len; |
547 | } else { | 584 | } else { |
548 | /* Normal, successful read. But we have an escape | 585 | /* |
549 | character and have to process the characters | 586 | * Normal, successful read. But we have an escape character |
550 | one by one. */ | 587 | * and have to process the characters one by one. |
588 | */ | ||
551 | unsigned int i; | 589 | unsigned int i; |
552 | for (i = 0; i < len; i++) { | 590 | for (i = 0; i < len; i++) { |
553 | unsigned char ch; | 591 | unsigned char ch; |
554 | /* Get one character at a time. */ | 592 | /* Get one character at a time. */ |
555 | ch = buf[i]; | 593 | ch = buf[i]; |
556 | 594 | ||
557 | /* Check if we have a pending escape | ||
558 | character. */ | ||
559 | if (escape_pending) { | 595 | if (escape_pending) { |
560 | /* We have previously seen an escape character. */ | 596 | /* We have previously seen an escape character. */ |
561 | /* Clear the flag now. */ | 597 | /* Clear the flag now. */ |
@@ -584,12 +620,16 @@ client_process_input(fd_set * readset) | |||
584 | continue; | 620 | continue; |
585 | 621 | ||
586 | case '&': | 622 | case '&': |
587 | /* Detach the program (continue to serve connections, | 623 | /* |
588 | but put in background and no more new connections). */ | 624 | * Detach the program (continue to serve connections, |
625 | * but put in background and no more new connections). | ||
626 | */ | ||
589 | if (!stdin_eof) { | 627 | if (!stdin_eof) { |
590 | /* Sending SSH_CMSG_EOF alone does not always appear | 628 | /* |
591 | to be enough. So we try to send an EOF character | 629 | * Sending SSH_CMSG_EOF alone does not always appear |
592 | first. */ | 630 | * to be enough. So we try to send an EOF character |
631 | * first. | ||
632 | */ | ||
593 | packet_start(SSH_CMSG_STDIN_DATA); | 633 | packet_start(SSH_CMSG_STDIN_DATA); |
594 | packet_put_string("\004", 1); | 634 | packet_put_string("\004", 1); |
595 | packet_send(); | 635 | packet_send(); |
@@ -646,22 +686,28 @@ Supported escape sequences:\r\n\ | |||
646 | 686 | ||
647 | default: | 687 | default: |
648 | if (ch != escape_char) { | 688 | if (ch != escape_char) { |
649 | /* Escape character followed by non-special character. | 689 | /* |
650 | Append both to the input buffer. */ | 690 | * Escape character followed by non-special character. |
691 | * Append both to the input buffer. | ||
692 | */ | ||
651 | buf[0] = escape_char; | 693 | buf[0] = escape_char; |
652 | buf[1] = ch; | 694 | buf[1] = ch; |
653 | buffer_append(&stdin_buffer, buf, 2); | 695 | buffer_append(&stdin_buffer, buf, 2); |
654 | stdin_bytes += 2; | 696 | stdin_bytes += 2; |
655 | continue; | 697 | continue; |
656 | } | 698 | } |
657 | /* Note that escape character typed twice | 699 | /* |
658 | falls through here; the latter gets processed | 700 | * Note that escape character typed twice |
659 | as a normal character below. */ | 701 | * falls through here; the latter gets processed |
702 | * as a normal character below. | ||
703 | */ | ||
660 | break; | 704 | break; |
661 | } | 705 | } |
662 | } else { | 706 | } else { |
663 | /* The previous character was not an escape char. Check if this | 707 | /* |
664 | is an escape. */ | 708 | * The previous character was not an escape char. Check if this |
709 | * is an escape. | ||
710 | */ | ||
665 | if (last_was_cr && ch == escape_char) { | 711 | if (last_was_cr && ch == escape_char) { |
666 | /* It is. Set the flag and continue to next character. */ | 712 | /* It is. Set the flag and continue to next character. */ |
667 | escape_pending = 1; | 713 | escape_pending = 1; |
@@ -669,8 +715,10 @@ Supported escape sequences:\r\n\ | |||
669 | } | 715 | } |
670 | } | 716 | } |
671 | 717 | ||
672 | /* Normal character. Record whether it was a newline, and append it to the | 718 | /* |
673 | buffer. */ | 719 | * Normal character. Record whether it was a newline, |
720 | * and append it to the buffer. | ||
721 | */ | ||
674 | last_was_cr = (ch == '\r' || ch == '\n'); | 722 | last_was_cr = (ch == '\r' || ch == '\n'); |
675 | buf[0] = ch; | 723 | buf[0] = ch; |
676 | buffer_append(&stdin_buffer, buf, 1); | 724 | buffer_append(&stdin_buffer, buf, 1); |
@@ -696,8 +744,10 @@ client_process_output(fd_set * writeset) | |||
696 | if (errno == EAGAIN) | 744 | if (errno == EAGAIN) |
697 | len = 0; | 745 | len = 0; |
698 | else { | 746 | else { |
699 | /* An error or EOF was encountered. Put | 747 | /* |
700 | an error message to stderr buffer. */ | 748 | * An error or EOF was encountered. Put an |
749 | * error message to stderr buffer. | ||
750 | */ | ||
701 | snprintf(buf, sizeof buf, "write stdout: %.50s\r\n", strerror(errno)); | 751 | snprintf(buf, sizeof buf, "write stdout: %.50s\r\n", strerror(errno)); |
702 | buffer_append(&stderr_buffer, buf, strlen(buf)); | 752 | buffer_append(&stderr_buffer, buf, strlen(buf)); |
703 | stderr_bytes += strlen(buf); | 753 | stderr_bytes += strlen(buf); |
@@ -717,8 +767,7 @@ client_process_output(fd_set * writeset) | |||
717 | if (errno == EAGAIN) | 767 | if (errno == EAGAIN) |
718 | len = 0; | 768 | len = 0; |
719 | else { | 769 | else { |
720 | /* EOF or error, but can't even print | 770 | /* EOF or error, but can't even print error message. */ |
721 | error message. */ | ||
722 | quit_pending = 1; | 771 | quit_pending = 1; |
723 | return; | 772 | return; |
724 | } | 773 | } |
@@ -728,11 +777,12 @@ client_process_output(fd_set * writeset) | |||
728 | } | 777 | } |
729 | } | 778 | } |
730 | 779 | ||
731 | /* Implements the interactive session with the server. This is called | 780 | /* |
732 | after the user has been authenticated, and a command has been | 781 | * Implements the interactive session with the server. This is called after |
733 | started on the remote host. If escape_char != -1, it is the character | 782 | * the user has been authenticated, and a command has been started on the |
734 | used as an escape character for terminating or suspending the | 783 | * remote host. If escape_char != -1, it is the character used as an escape |
735 | session. */ | 784 | * character for terminating or suspending the session. |
785 | */ | ||
736 | 786 | ||
737 | int | 787 | int |
738 | client_loop(int have_pty, int escape_char_arg) | 788 | client_loop(int have_pty, int escape_char_arg) |
@@ -776,7 +826,6 @@ client_loop(int have_pty, int escape_char_arg) | |||
776 | if (have_pty) | 826 | if (have_pty) |
777 | signal(SIGWINCH, window_change_handler); | 827 | signal(SIGWINCH, window_change_handler); |
778 | 828 | ||
779 | /* Enter raw mode if have a pseudo terminal. */ | ||
780 | if (have_pty) | 829 | if (have_pty) |
781 | enter_raw_mode(); | 830 | enter_raw_mode(); |
782 | 831 | ||
@@ -787,27 +836,35 @@ client_loop(int have_pty, int escape_char_arg) | |||
787 | while (!quit_pending) { | 836 | while (!quit_pending) { |
788 | fd_set readset, writeset; | 837 | fd_set readset, writeset; |
789 | 838 | ||
790 | /* Precess buffered packets sent by the server. */ | 839 | /* Process buffered packets sent by the server. */ |
791 | client_process_buffered_input_packets(); | 840 | client_process_buffered_input_packets(); |
792 | 841 | ||
793 | /* Make packets of buffered stdin data, and buffer them | 842 | /* |
794 | for sending to the server. */ | 843 | * Make packets of buffered stdin data, and buffer them for |
844 | * sending to the server. | ||
845 | */ | ||
795 | client_make_packets_from_stdin_data(); | 846 | client_make_packets_from_stdin_data(); |
796 | 847 | ||
797 | /* Make packets from buffered channel data, and buffer | 848 | /* |
798 | them for sending to the server. */ | 849 | * Make packets from buffered channel data, and buffer them |
850 | * for sending to the server. | ||
851 | */ | ||
799 | if (packet_not_very_much_data_to_write()) | 852 | if (packet_not_very_much_data_to_write()) |
800 | channel_output_poll(); | 853 | channel_output_poll(); |
801 | 854 | ||
802 | /* Check if the window size has changed, and buffer a | 855 | /* |
803 | message about it to the server if so. */ | 856 | * Check if the window size has changed, and buffer a message |
857 | * about it to the server if so. | ||
858 | */ | ||
804 | client_check_window_change(); | 859 | client_check_window_change(); |
805 | 860 | ||
806 | if (quit_pending) | 861 | if (quit_pending) |
807 | break; | 862 | break; |
808 | 863 | ||
809 | /* Wait until we have something to do (something becomes | 864 | /* |
810 | available on one of the descriptors). */ | 865 | * Wait until we have something to do (something becomes |
866 | * available on one of the descriptors). | ||
867 | */ | ||
811 | client_wait_until_can_do_something(&readset, &writeset); | 868 | client_wait_until_can_do_something(&readset, &writeset); |
812 | 869 | ||
813 | if (quit_pending) | 870 | if (quit_pending) |
@@ -816,16 +873,19 @@ client_loop(int have_pty, int escape_char_arg) | |||
816 | /* Do channel operations. */ | 873 | /* Do channel operations. */ |
817 | channel_after_select(&readset, &writeset); | 874 | channel_after_select(&readset, &writeset); |
818 | 875 | ||
819 | /* Process input from the connection and from stdin. | 876 | /* |
820 | Buffer any data that is available. */ | 877 | * Process input from the connection and from stdin. Buffer |
878 | * any data that is available. | ||
879 | */ | ||
821 | client_process_input(&readset); | 880 | client_process_input(&readset); |
822 | 881 | ||
823 | /* Process output to stdout and stderr. Output to the | 882 | /* |
824 | connection is processed elsewhere (above). */ | 883 | * Process output to stdout and stderr. Output to the |
884 | * connection is processed elsewhere (above). | ||
885 | */ | ||
825 | client_process_output(&writeset); | 886 | client_process_output(&writeset); |
826 | 887 | ||
827 | /* Send as much buffered packet data as possible to the | 888 | /* Send as much buffered packet data as possible to the sender. */ |
828 | sender. */ | ||
829 | if (FD_ISSET(connection_out, &writeset)) | 889 | if (FD_ISSET(connection_out, &writeset)) |
830 | packet_write_poll(); | 890 | packet_write_poll(); |
831 | } | 891 | } |
@@ -839,8 +899,10 @@ client_loop(int have_pty, int escape_char_arg) | |||
839 | /* Stop listening for connections. */ | 899 | /* Stop listening for connections. */ |
840 | channel_stop_listening(); | 900 | channel_stop_listening(); |
841 | 901 | ||
842 | /* In interactive mode (with pseudo tty) display a message | 902 | /* |
843 | indicating that the connection has been closed. */ | 903 | * In interactive mode (with pseudo tty) display a message indicating |
904 | * that the connection has been closed. | ||
905 | */ | ||
844 | if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) { | 906 | if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) { |
845 | snprintf(buf, sizeof buf, "Connection to %.64s closed.\r\n", host); | 907 | snprintf(buf, sizeof buf, "Connection to %.64s closed.\r\n", host); |
846 | buffer_append(&stderr_buffer, buf, strlen(buf)); | 908 | buffer_append(&stderr_buffer, buf, strlen(buf)); |
@@ -868,7 +930,6 @@ client_loop(int have_pty, int escape_char_arg) | |||
868 | buffer_consume(&stderr_buffer, len); | 930 | buffer_consume(&stderr_buffer, len); |
869 | } | 931 | } |
870 | 932 | ||
871 | /* Leave raw mode. */ | ||
872 | if (have_pty) | 933 | if (have_pty) |
873 | leave_raw_mode(); | 934 | leave_raw_mode(); |
874 | 935 | ||