[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 and 1.8.2.6

version 1.8, 2000/09/07 20:27:55 version 1.8.2.6, 2002/03/08 17:04:43
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 14 
Line 10 
  * 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 "ssh.h"  #include "log.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 */  /*
 #define TTY_OP_OSPEED   193     /* int follows */   * uint32 (u_int) follows speed in SSH1 and SSH2
    */
   #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 121 
Line 158 
 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 205 
Line 242 
   
 /*  /*
  * Encodes terminal modes for the terminal referenced by fd   * Encodes terminal modes for the terminal referenced by fd
  * in a portable manner, and appends the modes to a packet   * or tiop in a portable manner, and appends the modes to a packet
  * being constructed.   * being constructed.
  */   */
 void  void
 tty_make_modes(int fd)  tty_make_modes(int fd, struct termios *tiop)
 {  {
         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);
   
         if (tcgetattr(fd, &tio) < 0) {          buffer_init(&buf);
                 packet_put_char(TTY_OP_END);          if (compat20) {
                 log("tcgetattr: %.100s", strerror(errno));                  tty_op_ospeed = TTY_OP_OSPEED_PROTO2;
                 return;                  tty_op_ispeed = TTY_OP_ISPEED_PROTO2;
                   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));
         packet_put_char(TTY_OP_OSPEED);          debug3("tty_make_modes: ospeed %d", baud);
         packet_put_int(baud);          buffer_put_char(&buf, tty_op_ospeed);
           buffer_put_int(&buf, baud);
         baud = speed_to_baud(cfgetispeed(&tio));          baud = speed_to_baud(cfgetispeed(&tio));
         packet_put_char(TTY_OP_ISPEED);          debug3("tty_make_modes: ispeed %d", baud);
         packet_put_int(baud);          buffer_put_char(&buf, tty_op_ispeed);
           buffer_put_int(&buf, baud);
   
         /* Store values of mode flags. */          /* Store values of mode flags. */
 #define TTYCHAR(NAME, OP) \  #define TTYCHAR(NAME, OP) \
   packet_put_char(OP); packet_put_char(tio.c_cc[NAME]);          debug3("tty_make_modes: %d %d", OP, 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) \
   packet_put_char(OP); packet_put_char((tio.FIELD & NAME) != 0);          debug3("tty_make_modes: %d %d", OP, ((tio.FIELD & NAME) != 0)); \
 #define SGTTYCHAR(NAME, OP)          buffer_put_char(&buf, OP); \
 #define SGTTYMODE(NAME, FIELD, OP)          put_arg(&buf, ((tio.FIELD & NAME) != 0));
 #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. */
         packet_put_char(TTY_OP_END);          buffer_put_char(&buf, 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 259 
Line 321 
         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) < 0)          if (tcgetattr(fd, &tio) == -1) {
                   log("tcgetattr: %.100s", strerror(errno));
                 failure = -1;                  failure = -1;
           }
   
         for (;;) {          for (;;) {
                 n_bytes += 1;                  n_bytes += 1;
Line 275 
Line 353 
                 case TTY_OP_END:                  case TTY_OP_END:
                         goto set;                          goto set;
   
                 case TTY_OP_ISPEED:                  /* XXX: future conflict possible */
                   case TTY_OP_ISPEED_PROTO1:
                   case TTY_OP_ISPEED_PROTO2:
                         n_bytes += 4;                          n_bytes += 4;
                         baud = packet_get_int();                          baud = packet_get_int();
                         if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) < 0)                          debug3("tty_parse_modes: ispeed %d", baud);
                           if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) == -1)
                                 error("cfsetispeed failed for %d", baud);                                  error("cfsetispeed failed for %d", baud);
                         break;                          break;
   
                 case TTY_OP_OSPEED:                  /* XXX: future conflict possible */
                   case TTY_OP_OSPEED_PROTO1:
                   case TTY_OP_OSPEED_PROTO2:
                         n_bytes += 4;                          n_bytes += 4;
                         baud = packet_get_int();                          baud = packet_get_int();
                         if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) < 0)                          debug3("tty_parse_modes: ospeed %d", baud);
                           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 += 1;                                 \            n_bytes += arg_size; \
           tio.c_cc[NAME] = packet_get_char();           \            tio.c_cc[NAME] = get_arg(); \
             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 += 1;                                 \            n_bytes += arg_size; \
           if (packet_get_char())                        \            if ((arg = get_arg())) \
             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                                  /*
                          * a one-byte argument.                                   * SSH1:
                          */                                   * Opcodes 1 to 127 are defined to have
                         if (opcode >= 0 && opcode < 128) {                                   * a one-byte argument.
                                 n_bytes += 1;                                   * Opcodes 128 to 159 are defined to have
                                 (void) packet_get_char();                                   * an integer argument.
                                 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 {
                                 /*                                  /*
                                  * Opcodes 128 to 159 are defined to have                                   * SSH2:
                                  * an integer argument.                                   * Opcodes 1 to 159 are defined to have
                                    * a uint32 argument.
                                    * Opcodes 160 to 255 are undefined and
                                    * cause parsing to stop.
                                  */                                   */
                                 if (opcode >= 128 && opcode < 160) {                                  if (opcode > 0 && 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 tty stuff failed */                  return;         /* Packet parsed ok but tcgetattr() failed */
   
         /* Set the new modes for the terminal. */          /* Set the new modes for the terminal. */
         if (tcsetattr(fd, TCSANOW, &tio) < 0)          if (tcsetattr(fd, TCSANOW, &tio) == -1)
                 log("Setting tty modes failed: %.100s", strerror(errno));                  log("Setting tty modes failed: %.100s", strerror(errno));
         return;          return;
 }  }

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