source: trunk/third/ssh/clientloop.c @ 12646

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