[BACK]Return to clientloop.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Diff for /src/usr.bin/ssh/clientloop.c between version 1.194 and 1.195

version 1.194, 2008/05/19 20:53:52 version 1.195, 2008/06/12 03:40:52
Line 136 
Line 136 
   
 /* Common data for the client loop code. */  /* Common data for the client loop code. */
 static volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */  static volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */
 static int escape_char;         /* Escape character. */  static int escape_char1;        /* Escape character. (proto1 only) */
 static int escape_pending;      /* Last character was the escape character */  static int escape_pending1;     /* Last character was an escape (proto1 only) */
 static int last_was_cr;         /* Last character was a newline. */  static int last_was_cr;         /* Last character was a newline. */
 static int exit_status;         /* Used to store the exit status of the command. */  static int exit_status;         /* Used to store the exit status of the command. */
 static int stdin_eof;           /* EOF has been encountered on standard error. */  static int stdin_eof;           /* EOF has been encountered on standard error. */
Line 154 
Line 154 
 static void client_init_dispatch(void);  static void client_init_dispatch(void);
 int     session_ident = -1;  int     session_ident = -1;
   
   /* Track escape per proto2 channel */
   struct escape_filter_ctx {
           int escape_pending;
           int escape_char;
   };
   
   /* Context for channel confirmation replies */
 struct channel_reply_ctx {  struct channel_reply_ctx {
         const char *request_type;          const char *request_type;
         int id, do_close;          int id, do_close;
Line 377 
Line 384 
                          * and also process it as an escape character if                           * and also process it as an escape character if
                          * appropriate.                           * appropriate.
                          */                           */
                         if ((u_char) buf[0] == escape_char)                          if ((u_char) buf[0] == escape_char1)
                                 escape_pending = 1;                                  escape_pending1 = 1;
                         else                          else
                                 buffer_append(&stdin_buffer, buf, 1);                                  buffer_append(&stdin_buffer, buf, 1);
                 }                  }
Line 805 
Line 812 
                 xfree(fwd.connect_host);                  xfree(fwd.connect_host);
 }  }
   
 /* process the characters one by one */  /*
    * Process the characters one by one, call with c==NULL for proto1 case.
    */
 static int  static int
 process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)  process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
       char *buf, int len)
 {  {
         char string[1024];          char string[1024];
         pid_t pid;          pid_t pid;
Line 815 
Line 825 
         u_int i;          u_int i;
         u_char ch;          u_char ch;
         char *s;          char *s;
           int *escape_pendingp, escape_char;
           struct escape_filter_ctx *efc;
   
           if (c == NULL) {
                   escape_pendingp = &escape_pending1;
                   escape_char = escape_char1;
           } else {
                   if (c->filter_ctx == NULL)
                           return 0;
                   efc = (struct escape_filter_ctx *)c->filter_ctx;
                   escape_pendingp = &efc->escape_pending;
                   escape_char = efc->escape_char;
           }
   
         if (len <= 0)          if (len <= 0)
                 return (0);                  return (0);
   
Line 823 
Line 846 
                 /* Get one character at a time. */                  /* Get one character at a time. */
                 ch = buf[i];                  ch = buf[i];
   
                 if (escape_pending) {                  if (*escape_pendingp) {
                         /* We have previously seen an escape character. */                          /* We have previously seen an escape character. */
                         /* Clear the flag now. */                          /* Clear the flag now. */
                         escape_pending = 0;                          *escape_pendingp = 0;
   
                         /* Process the escaped character. */                          /* Process the escaped character. */
                         switch (ch) {                          switch (ch) {
                         case '.':                          case '.':
                                 /* Terminate the connection. */                                  /* Terminate the connection. */
                                 snprintf(string, sizeof string, "%c.\r\n", escape_char);                                  snprintf(string, sizeof string, "%c.\r\n",
                                       escape_char);
                                 buffer_append(berr, string, strlen(string));                                  buffer_append(berr, string, strlen(string));
   
                                 quit_pending = 1;                                  if (c && c->ctl_fd != -1) {
                                           chan_read_failed(c);
                                           chan_write_failed(c);
                                           return 0;
                                   } else
                                           quit_pending = 1;
                                 return -1;                                  return -1;
   
                         case 'Z' - 64:                          case 'Z' - 64:
                                   /* XXX support this for mux clients */
                                   if (c && c->ctl_fd != -1) {
    noescape:
                                           snprintf(string, sizeof string,
                                               "%c%c escape not available to "
                                               "multiplexed sessions\r\n",
                                               escape_char, ch);
                                           buffer_append(berr, string,
                                               strlen(string));
                                           continue;
                                   }
                                 /* Suspend the program. */                                  /* Suspend the program. */
                                 /* Print a message to that effect to the user. */                                  /* Print a message to that effect to the user. */
                                 snprintf(string, sizeof string, "%c^Z [suspend ssh]\r\n", escape_char);                                  snprintf(string, sizeof string,
                                       "%c^Z [suspend ssh]\r\n", escape_char);
                                 buffer_append(berr, string, strlen(string));                                  buffer_append(berr, string, strlen(string));
   
                                 /* Restore terminal modes and suspend. */                                  /* Restore terminal modes and suspend. */
Line 873 
Line 914 
                                 continue;                                  continue;
   
                         case '&':                          case '&':
                                   if (c && c->ctl_fd != -1)
                                           goto noescape;
                                 /*                                  /*
                                  * Detach the program (continue to serve connections,                                   * Detach the program (continue to serve connections,
                                  * but put in background and no more new connections).                                   * but put in background and no more new connections).
Line 921 
Line 964 
                                 continue;                                  continue;
   
                         case '?':                          case '?':
                                 snprintf(string, sizeof string,                                  if (c && c->ctl_fd != -1) {
                                           snprintf(string, sizeof string,
 "%c?\r\n\  "%c?\r\n\
 Supported escape sequences:\r\n\  Supported escape sequences:\r\n\
 %c.  - terminate connection\r\n\    %c.  - terminate session\r\n\
 %cB  - send a BREAK to the remote system\r\n\    %cB  - send a BREAK to the remote system\r\n\
 %cC  - open a command line\r\n\    %cC  - open a command line\r\n\
 %cR  - Request rekey (SSH protocol 2 only)\r\n\    %cR  - Request rekey (SSH protocol 2 only)\r\n\
 %c^Z - suspend ssh\r\n\    %c#  - list forwarded connections\r\n\
 %c#  - list forwarded connections\r\n\    %c?  - this message\r\n\
 %c&  - background ssh (when waiting for connections to terminate)\r\n\    %c%c  - send the escape character by typing it twice\r\n\
 %c?  - this message\r\n\  
 %c%c  - send the escape character by typing it twice\r\n\  
 (Note that escapes are only recognized immediately after newline.)\r\n",  (Note that escapes are only recognized immediately after newline.)\r\n",
                                     escape_char, escape_char, escape_char, escape_char,                                              escape_char, escape_char,
                                     escape_char, escape_char, escape_char, escape_char,                                              escape_char, escape_char,
                                     escape_char, escape_char, escape_char);                                              escape_char, escape_char,
                                               escape_char, escape_char,
                                               escape_char);
                                   } else {
                                           snprintf(string, sizeof string,
   "%c?\r\n\
   Supported escape sequences:\r\n\
     %c.  - terminate connection (and any multiplexed sessions)\r\n\
     %cB  - send a BREAK to the remote system\r\n\
     %cC  - open a command line\r\n\
     %cR  - Request rekey (SSH protocol 2 only)\r\n\
     %c^Z - suspend ssh\r\n\
     %c#  - list forwarded connections\r\n\
     %c&  - background ssh (when waiting for connections to terminate)\r\n\
     %c?  - this message\r\n\
     %c%c  - send the escape character by typing it twice\r\n\
   (Note that escapes are only recognized immediately after newline.)\r\n",
                                               escape_char, escape_char,
                                               escape_char, escape_char,
                                               escape_char, escape_char,
                                               escape_char, escape_char,
                                               escape_char, escape_char,
                                               escape_char);
                                   }
                                 buffer_append(berr, string, strlen(string));                                  buffer_append(berr, string, strlen(string));
                                 continue;                                  continue;
   
                         case '#':                          case '#':
                                 snprintf(string, sizeof string, "%c#\r\n", escape_char);                                  snprintf(string, sizeof string, "%c#\r\n",
                                       escape_char);
                                 buffer_append(berr, string, strlen(string));                                  buffer_append(berr, string, strlen(string));
                                 s = channel_open_message();                                  s = channel_open_message();
                                 buffer_append(berr, s, strlen(s));                                  buffer_append(berr, s, strlen(s));
Line 967 
Line 1033 
                          */                           */
                         if (last_was_cr && ch == escape_char) {                          if (last_was_cr && ch == escape_char) {
                                 /* It is. Set the flag and continue to next character. */                                  /* It is. Set the flag and continue to next character. */
                                 escape_pending = 1;                                  *escape_pendingp = 1;
                                 continue;                                  continue;
                         }                          }
                 }                  }
Line 1018 
Line 1084 
                                 packet_start(SSH_CMSG_EOF);                                  packet_start(SSH_CMSG_EOF);
                                 packet_send();                                  packet_send();
                         }                          }
                 } else if (escape_char == SSH_ESCAPECHAR_NONE) {                  } else if (escape_char1 == SSH_ESCAPECHAR_NONE) {
                         /*                          /*
                          * Normal successful read, and no escape character.                           * Normal successful read, and no escape character.
                          * Just append the data to buffer.                           * Just append the data to buffer.
Line 1029 
Line 1095 
                          * Normal, successful read.  But we have an escape character                           * Normal, successful read.  But we have an escape character
                          * and have to process the characters one by one.                           * and have to process the characters one by one.
                          */                           */
                         if (process_escapes(&stdin_buffer, &stdout_buffer,                          if (process_escapes(NULL, &stdin_buffer,
                             &stderr_buffer, buf, len) == -1)                              &stdout_buffer, &stderr_buffer, buf, len) == -1)
                                 return;                                  return;
                 }                  }
         }          }
Line 1105 
Line 1171 
   
 /* scan buf[] for '~' before sending data to the peer */  /* scan buf[] for '~' before sending data to the peer */
   
 static int  /* Helper: allocate a new escape_filter_ctx and fill in its escape char */
 simple_escape_filter(Channel *c, char *buf, int len)  void *
   client_new_escape_filter_ctx(int escape_char)
 {  {
           struct escape_filter_ctx *ret;
   
           ret = xmalloc(sizeof(*ret));
           ret->escape_pending = 0;
           ret->escape_char = escape_char;
           return (void *)ret;
   }
   
   int
   client_simple_escape_filter(Channel *c, char *buf, int len)
   {
         if (c->extended_usage != CHAN_EXTENDED_WRITE)          if (c->extended_usage != CHAN_EXTENDED_WRITE)
                 return 0;                  return 0;
   
         return process_escapes(&c->input, &c->output, &c->extended, buf, len);          return process_escapes(c, &c->input, &c->output, &c->extended,
               buf, len);
 }  }
   
 static void  static void
Line 1143 
Line 1222 
         start_time = get_current_time();          start_time = get_current_time();
   
         /* Initialize variables. */          /* Initialize variables. */
         escape_pending = 0;          escape_pending1 = 0;
         last_was_cr = 1;          last_was_cr = 1;
         exit_status = -1;          exit_status = -1;
         stdin_eof = 0;          stdin_eof = 0;
Line 1170 
Line 1249 
         stdout_bytes = 0;          stdout_bytes = 0;
         stderr_bytes = 0;          stderr_bytes = 0;
         quit_pending = 0;          quit_pending = 0;
         escape_char = escape_char_arg;          escape_char1 = escape_char_arg;
   
         /* Initialize buffers. */          /* Initialize buffers. */
         buffer_init(&stdin_buffer);          buffer_init(&stdin_buffer);
Line 1198 
Line 1277 
   
         if (compat20) {          if (compat20) {
                 session_ident = ssh2_chan_id;                  session_ident = ssh2_chan_id;
                 if (escape_char != SSH_ESCAPECHAR_NONE)                  if (escape_char_arg != SSH_ESCAPECHAR_NONE)
                         channel_register_filter(session_ident,                          channel_register_filter(session_ident,
                             simple_escape_filter, NULL);                              client_simple_escape_filter, NULL,
                               client_new_escape_filter_ctx(escape_char_arg));
                 if (session_ident != -1)                  if (session_ident != -1)
                         channel_register_cleanup(session_ident,                          channel_register_cleanup(session_ident,
                             client_channel_closed, 0);                              client_channel_closed, 0);

Legend:
Removed from v.1.194  
changed lines
  Added in v.1.195