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