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

Diff for /src/usr.bin/ssh/ttymodes.c between version 1.8.2.6 and 1.9

version 1.8.2.6, 2002/03/08 17:04:43 version 1.9, 2001/01/19 15:55:12
Line 2 
Line 2 
  * Author: Tatu Ylonen <ylo@cs.hut.fi>   * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland   * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
  *                    All rights reserved   *                    All rights reserved
    * Encoding and decoding of terminal modes in a portable way.
    * Much of the format is defined in ttymodes.h; it is included multiple times
    * into this file with the appropriate macro definitions to generate the
    * suitable code.
  *   *
  * As far as I am concerned, the code I have written for this software   * As far as I am concerned, the code I have written for this software
  * can be used freely for any purpose.  Any derived versions of this   * can be used freely for any purpose.  Any derived versions of this
Line 10 
Line 14 
  * called by a name other than "ssh" or "Secure Shell".   * called by a name other than "ssh" or "Secure Shell".
  */   */
   
 /*  
  * SSH2 tty modes support by Kevin Steves.  
  * Copyright (c) 2001 Kevin Steves.  All rights reserved.  
  *  
  * Redistribution and use in source and binary forms, with or without  
  * modification, are permitted provided that the following conditions  
  * are met:  
  * 1. Redistributions of source code must retain the above copyright  
  *    notice, this list of conditions and the following disclaimer.  
  * 2. Redistributions in binary form must reproduce the above copyright  
  *    notice, this list of conditions and the following disclaimer in the  
  *    documentation and/or other materials provided with the distribution.  
  *  
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR  
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES  
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,  
  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT  
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,  
  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY  
  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT  
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF  
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
  */  
   
 /*  
  * Encoding and decoding of terminal modes in a portable way.  
  * Much of the format is defined in ttymodes.h; it is included multiple times  
  * into this file with the appropriate macro definitions to generate the  
  * suitable code.  
  */  
   
 #include "includes.h"  #include "includes.h"
 RCSID("$OpenBSD$");  RCSID("$OpenBSD$");
   
 #include "packet.h"  #include "packet.h"
 #include "log.h"  #include "ssh.h"
 #include "ssh1.h"  #include "ssh1.h"
 #include "compat.h"  
 #include "buffer.h"  
 #include "bufaux.h"  
   
 #define TTY_OP_END              0  #define TTY_OP_END      0
 /*  #define TTY_OP_ISPEED   192     /* int follows */
  * uint32 (u_int) follows speed in SSH1 and SSH2  #define TTY_OP_OSPEED   193     /* int follows */
  */  
 #define TTY_OP_ISPEED_PROTO1    192  
 #define TTY_OP_OSPEED_PROTO1    193  
 #define TTY_OP_ISPEED_PROTO2    128  
 #define TTY_OP_OSPEED_PROTO2    129  
   
 /*  /*
  * Converts POSIX speed_t to a baud rate.  The values of the   * Converts POSIX speed_t to a baud rate.  The values of the
Line 158 
Line 122 
 baud_to_speed(int baud)  baud_to_speed(int baud)
 {  {
         switch (baud) {          switch (baud) {
         case 0:                  case 0:
                 return B0;                  return B0;
         case 50:          case 50:
                 return B50;                  return B50;
Line 242 
Line 206 
   
 /*  /*
  * Encodes terminal modes for the terminal referenced by fd   * Encodes terminal modes for the terminal referenced by fd
  * or tiop in a portable manner, and appends the modes to a packet   * in a portable manner, and appends the modes to a packet
  * being constructed.   * being constructed.
  */   */
 void  void
 tty_make_modes(int fd, struct termios *tiop)  tty_make_modes(int fd)
 {  {
         struct termios tio;          struct termios tio;
         int baud;          int baud;
         Buffer buf;  
         int tty_op_ospeed, tty_op_ispeed;  
         void (*put_arg)(Buffer *, u_int);  
   
         buffer_init(&buf);          if (tcgetattr(fd, &tio) < 0) {
         if (compat20) {                  packet_put_char(TTY_OP_END);
                 tty_op_ospeed = TTY_OP_OSPEED_PROTO2;                  log("tcgetattr: %.100s", strerror(errno));
                 tty_op_ispeed = TTY_OP_ISPEED_PROTO2;                  return;
                 put_arg = buffer_put_int;  
         } else {  
                 tty_op_ospeed = TTY_OP_OSPEED_PROTO1;  
                 tty_op_ispeed = TTY_OP_ISPEED_PROTO1;  
                 put_arg = (void (*)(Buffer *, u_int)) buffer_put_char;  
         }          }
   
         if (tiop == NULL) {  
                 if (tcgetattr(fd, &tio) == -1) {  
                         log("tcgetattr: %.100s", strerror(errno));  
                         goto end;  
                 }  
         } else  
                 tio = *tiop;  
   
         /* Store input and output baud rates. */          /* Store input and output baud rates. */
         baud = speed_to_baud(cfgetospeed(&tio));          baud = speed_to_baud(cfgetospeed(&tio));
         debug3("tty_make_modes: ospeed %d", baud);          packet_put_char(TTY_OP_OSPEED);
         buffer_put_char(&buf, tty_op_ospeed);          packet_put_int(baud);
         buffer_put_int(&buf, baud);  
         baud = speed_to_baud(cfgetispeed(&tio));          baud = speed_to_baud(cfgetispeed(&tio));
         debug3("tty_make_modes: ispeed %d", baud);          packet_put_char(TTY_OP_ISPEED);
         buffer_put_char(&buf, tty_op_ispeed);          packet_put_int(baud);
         buffer_put_int(&buf, baud);  
   
         /* Store values of mode flags. */          /* Store values of mode flags. */
 #define TTYCHAR(NAME, OP) \  #define TTYCHAR(NAME, OP) \
         debug3("tty_make_modes: %d %d", OP, tio.c_cc[NAME]); \    packet_put_char(OP); packet_put_char(tio.c_cc[NAME]);
         buffer_put_char(&buf, OP); \  
         put_arg(&buf, tio.c_cc[NAME]);  
   
 #define TTYMODE(NAME, FIELD, OP) \  #define TTYMODE(NAME, FIELD, OP) \
         debug3("tty_make_modes: %d %d", OP, ((tio.FIELD & NAME) != 0)); \    packet_put_char(OP); packet_put_char((tio.FIELD & NAME) != 0);
         buffer_put_char(&buf, OP); \  #define SGTTYCHAR(NAME, OP)
         put_arg(&buf, ((tio.FIELD & NAME) != 0));  #define SGTTYMODE(NAME, FIELD, OP)
   #define SGTTYMODEN(NAME, FIELD, OP)
   
 #include "ttymodes.h"  #include "ttymodes.h"
   
 #undef TTYCHAR  #undef TTYCHAR
 #undef TTYMODE  #undef TTYMODE
   #undef SGTTYCHAR
   #undef SGTTYMODE
   #undef SGTTYMODEN
   
 end:  
         /* Mark end of mode data. */          /* Mark end of mode data. */
         buffer_put_char(&buf, TTY_OP_END);          packet_put_char(TTY_OP_END);
         if (compat20)  
                 packet_put_string(buffer_ptr(&buf), buffer_len(&buf));  
         else  
                 packet_put_raw(buffer_ptr(&buf), buffer_len(&buf));  
         buffer_free(&buf);  
         return;  
 }  }
   
 /*  /*
Line 321 
Line 260 
         int opcode, baud;          int opcode, baud;
         int n_bytes = 0;          int n_bytes = 0;
         int failure = 0;          int failure = 0;
         u_int (*get_arg)(void);  
         int arg, arg_size;  
   
         if (compat20) {  
                 *n_bytes_ptr = packet_get_int();  
                 debug3("tty_parse_modes: SSH2 n_bytes %d", *n_bytes_ptr);  
                 if (*n_bytes_ptr == 0)  
                         return;  
                 get_arg = packet_get_int;  
                 arg_size = 4;  
         } else {  
                 get_arg = packet_get_char;  
                 arg_size = 1;  
         }  
   
         /*          /*
          * Get old attributes for the terminal.  We will modify these           * Get old attributes for the terminal.  We will modify these
          * flags. I am hoping that if there are any machine-specific           * flags. I am hoping that if there are any machine-specific
          * modes, they will initially have reasonable values.           * modes, they will initially have reasonable values.
          */           */
         if (tcgetattr(fd, &tio) == -1) {          if (tcgetattr(fd, &tio) < 0)
                 log("tcgetattr: %.100s", strerror(errno));  
                 failure = -1;                  failure = -1;
         }  
   
         for (;;) {          for (;;) {
                 n_bytes += 1;                  n_bytes += 1;
Line 353 
Line 276 
                 case TTY_OP_END:                  case TTY_OP_END:
                         goto set;                          goto set;
   
                 /* XXX: future conflict possible */                  case TTY_OP_ISPEED:
                 case TTY_OP_ISPEED_PROTO1:  
                 case TTY_OP_ISPEED_PROTO2:  
                         n_bytes += 4;                          n_bytes += 4;
                         baud = packet_get_int();                          baud = packet_get_int();
                         debug3("tty_parse_modes: ispeed %d", baud);                          if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) < 0)
                         if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) == -1)  
                                 error("cfsetispeed failed for %d", baud);                                  error("cfsetispeed failed for %d", baud);
                         break;                          break;
   
                 /* XXX: future conflict possible */                  case TTY_OP_OSPEED:
                 case TTY_OP_OSPEED_PROTO1:  
                 case TTY_OP_OSPEED_PROTO2:  
                         n_bytes += 4;                          n_bytes += 4;
                         baud = packet_get_int();                          baud = packet_get_int();
                         debug3("tty_parse_modes: ospeed %d", baud);                          if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) < 0)
                         if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) == -1)  
                                 error("cfsetospeed failed for %d", baud);                                  error("cfsetospeed failed for %d", baud);
                         break;                          break;
   
 #define TTYCHAR(NAME, OP) \  #define TTYCHAR(NAME, OP)                               \
         case OP: \          case OP:                                        \
           n_bytes += arg_size; \            n_bytes += 1;                                 \
           tio.c_cc[NAME] = get_arg(); \            tio.c_cc[NAME] = packet_get_char();           \
           debug3("tty_parse_modes: %d %d", OP, tio.c_cc[NAME]); \  
           break;            break;
 #define TTYMODE(NAME, FIELD, OP) \  #define TTYMODE(NAME, FIELD, OP)                        \
         case OP: \          case OP:                                        \
           n_bytes += arg_size; \            n_bytes += 1;                                 \
           if ((arg = get_arg())) \            if (packet_get_char())                        \
             tio.FIELD |= NAME; \              tio.FIELD |= NAME;                          \
           else \            else                                          \
             tio.FIELD &= ~NAME; \              tio.FIELD &= ~NAME;                         \
           debug3("tty_parse_modes: %d %d", OP, arg); \  
           break;            break;
   #define SGTTYCHAR(NAME, OP)
   #define SGTTYMODE(NAME, FIELD, OP)
   #define SGTTYMODEN(NAME, FIELD, OP)
   
 #include "ttymodes.h"  #include "ttymodes.h"
   
 #undef TTYCHAR  #undef TTYCHAR
 #undef TTYMODE  #undef TTYMODE
   #undef SGTTYCHAR
   #undef SGTTYMODE
   #undef SGTTYMODEN
   
                 default:                  default:
                         debug("Ignoring unsupported tty mode opcode %d (0x%x)",                          debug("Ignoring unsupported tty mode opcode %d (0x%x)",
                             opcode, opcode);                                opcode, opcode);
                         if (!compat20) {                          /*
                                 /*                           * Opcodes 0 to 127 are defined to have
                                  * SSH1:                           * a one-byte argument.
                                  * Opcodes 1 to 127 are defined to have                           */
                                  * a one-byte argument.                          if (opcode >= 0 && opcode < 128) {
                                  * Opcodes 128 to 159 are defined to have                                  n_bytes += 1;
                                  * an integer argument.                                  (void) packet_get_char();
                                  */                                  break;
                                 if (opcode > 0 && opcode < 128) {  
                                         n_bytes += 1;  
                                         (void) packet_get_char();  
                                         break;  
                                 } else if (opcode >= 128 && opcode < 160) {  
                                         n_bytes += 4;  
                                         (void) packet_get_int();  
                                         break;  
                                 } else {  
                                         /*  
                                          * It is a truly undefined opcode (160 to 255).  
                                          * We have no idea about its arguments.  So we  
                                          * must stop parsing.  Note that some data may be  
                                          * left in the packet; hopefully there is nothing  
                                          * more coming after the mode data.  
                                          */  
                                         log("parse_tty_modes: unknown opcode %d", opcode);  
                                         goto set;  
                                 }  
                         } else {                          } else {
                                 /*                                  /*
                                  * SSH2:                                   * Opcodes 128 to 159 are defined to have
                                  * Opcodes 1 to 159 are defined to have                                   * an integer argument.
                                  * a uint32 argument.  
                                  * Opcodes 160 to 255 are undefined and  
                                  * cause parsing to stop.  
                                  */                                   */
                                 if (opcode > 0 && opcode < 160) {                                  if (opcode >= 128 && opcode < 160) {
                                         n_bytes += 4;                                          n_bytes += 4;
                                         (void) packet_get_int();                                          (void) packet_get_int();
                                         break;                                          break;
                                 } else {  
                                         log("parse_tty_modes: unknown opcode %d", opcode);  
                                         goto set;  
                                 }                                  }
                         }                          }
                           /*
                            * It is a truly undefined opcode (160 to 255).
                            * We have no idea about its arguments.  So we
                            * must stop parsing.  Note that some data may be
                            * left in the packet; hopefully there is nothing
                            * more coming after the mode data.
                            */
                           log("parse_tty_modes: unknown opcode %d", opcode);
                           packet_integrity_check(0, 1, SSH_CMSG_REQUEST_PTY);
                           goto set;
                 }                  }
         }          }
   
 set:  set:
         if (*n_bytes_ptr != n_bytes) {          if (*n_bytes_ptr != n_bytes) {
                 *n_bytes_ptr = n_bytes;                  *n_bytes_ptr = n_bytes;
                 log("parse_tty_modes: n_bytes_ptr != n_bytes: %d %d",  
                     *n_bytes_ptr, n_bytes);  
                 return;         /* Don't process bytes passed */                  return;         /* Don't process bytes passed */
         }          }
         if (failure == -1)          if (failure == -1)
                 return;         /* Packet parsed ok but tcgetattr() failed */                  return;         /* Packet parsed ok but tty stuff failed */
   
         /* Set the new modes for the terminal. */          /* Set the new modes for the terminal. */
         if (tcsetattr(fd, TCSANOW, &tio) == -1)          if (tcsetattr(fd, TCSANOW, &tio) < 0)
                 log("Setting tty modes failed: %.100s", strerror(errno));                  log("Setting tty modes failed: %.100s", strerror(errno));
         return;          return;
 }  }

Legend:
Removed from v.1.8.2.6  
changed lines
  Added in v.1.9