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

Annotation of src/usr.bin/ssh/ttymodes.c, Revision 1.2

1.1       deraadt     1: /*
                      2:
                      3: ttymodes.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: Created: Tue Mar 21 15:59:15 1995 ylo
                     11:
                     12: Encoding and decoding of terminal modes in a portable way.
                     13: Much of the format is defined in ttymodes.h; it is included multiple times
                     14: into this file with the appropriate macro definitions to generate the
                     15: suitable code.
                     16:
                     17: */
                     18:
                     19: #include "includes.h"
1.2     ! deraadt    20: RCSID("$Id: ttymodes.c,v 1.1 1999/09/26 20:53:38 deraadt Exp $");
1.1       deraadt    21:
                     22: #include "packet.h"
                     23: #include "ssh.h"
                     24:
                     25: #define TTY_OP_END     0
                     26: #define TTY_OP_ISPEED  192 /* int follows */
                     27: #define TTY_OP_OSPEED  193 /* int follows */
                     28:
                     29: /* Converts POSIX speed_t to a baud rate.  The values of the constants
                     30:    for speed_t are not themselves portable. */
                     31:
                     32: static int speed_to_baud(speed_t speed)
                     33: {
                     34:   switch (speed)
                     35:     {
                     36:     case B0:
                     37:       return 0;
                     38:     case B50:
                     39:       return 50;
                     40:     case B75:
                     41:       return 75;
                     42:     case B110:
                     43:       return 110;
                     44:     case B134:
                     45:       return 134;
                     46:     case B150:
                     47:       return 150;
                     48:     case B200:
                     49:       return 200;
                     50:     case B300:
                     51:       return 300;
                     52:     case B600:
                     53:       return 600;
                     54:     case B1200:
                     55:       return 1200;
                     56:     case B1800:
                     57:       return 1800;
                     58:     case B2400:
                     59:       return 2400;
                     60:     case B4800:
                     61:       return 4800;
                     62:     case B9600:
                     63:       return 9600;
                     64:
                     65: #ifdef B19200
                     66:     case B19200:
                     67:       return 19200;
                     68: #else /* B19200 */
                     69: #ifdef EXTA
                     70:     case EXTA:
                     71:       return 19200;
                     72: #endif /* EXTA */
                     73: #endif /* B19200 */
                     74:
                     75: #ifdef B38400
                     76:     case B38400:
                     77:       return 38400;
                     78: #else /* B38400 */
                     79: #ifdef EXTB
                     80:     case EXTB:
                     81:       return 38400;
                     82: #endif /* EXTB */
                     83: #endif /* B38400 */
                     84:
                     85: #ifdef B7200
                     86:     case B7200:
                     87:       return 7200;
                     88: #endif /* B7200 */
                     89: #ifdef B14400
                     90:     case B14400:
                     91:       return 14400;
                     92: #endif /* B14400 */
                     93: #ifdef B28800
                     94:     case B28800:
                     95:       return 28800;
                     96: #endif /* B28800 */
                     97: #ifdef B57600
                     98:     case B57600:
                     99:       return 57600;
                    100: #endif /* B57600 */
                    101: #ifdef B76800
                    102:     case B76800:
                    103:       return 76800;
                    104: #endif /* B76800 */
                    105: #ifdef B115200
                    106:     case B115200:
                    107:       return 115200;
                    108: #endif /* B115200 */
                    109: #ifdef B230400
                    110:     case B230400:
                    111:       return 230400;
                    112: #endif /* B230400 */
                    113:     default:
                    114:       return 9600;
                    115:     }
                    116: }
                    117:
                    118: /* Converts a numeric baud rate to a POSIX speed_t. */
                    119:
                    120: static speed_t baud_to_speed(int baud)
                    121: {
                    122:   switch (baud)
                    123:     {
                    124:     case 0:
                    125:       return B0;
                    126:     case 50:
                    127:       return B50;
                    128:     case 75:
                    129:       return B75;
                    130:     case 110:
                    131:       return B110;
                    132:     case 134:
                    133:       return B134;
                    134:     case 150:
                    135:       return B150;
                    136:     case 200:
                    137:       return B200;
                    138:     case 300:
                    139:       return B300;
                    140:     case 600:
                    141:       return B600;
                    142:     case 1200:
                    143:       return B1200;
                    144:     case 1800:
                    145:       return B1800;
                    146:     case 2400:
                    147:       return B2400;
                    148:     case 4800:
                    149:       return B4800;
                    150:     case 9600:
                    151:       return B9600;
                    152:
                    153: #ifdef B19200
                    154:     case 19200:
                    155:       return B19200;
                    156: #else /* B19200 */
                    157: #ifdef EXTA
                    158:     case 19200:
                    159:       return EXTA;
                    160: #endif /* EXTA */
                    161: #endif /* B19200 */
                    162:
                    163: #ifdef B38400
                    164:     case 38400:
                    165:       return B38400;
                    166: #else /* B38400 */
                    167: #ifdef EXTB
                    168:     case 38400:
                    169:       return EXTB;
                    170: #endif /* EXTB */
                    171: #endif /* B38400 */
                    172:
                    173: #ifdef B7200
                    174:     case 7200:
                    175:       return B7200;
                    176: #endif /* B7200 */
                    177: #ifdef B14400
                    178:     case 14400:
                    179:       return B14400;
                    180: #endif /* B14400 */
                    181: #ifdef B28800
                    182:     case 28800:
                    183:       return B28800;
                    184: #endif /* B28800 */
                    185: #ifdef B57600
                    186:     case 57600:
                    187:       return B57600;
                    188: #endif /* B57600 */
                    189: #ifdef B76800
                    190:     case 76800:
                    191:       return B76800;
                    192: #endif /* B76800 */
                    193: #ifdef B115200
                    194:     case 115200:
                    195:       return B115200;
                    196: #endif /* B115200 */
                    197: #ifdef B230400
                    198:     case 230400:
                    199:       return B230400;
                    200: #endif /* B230400 */
                    201:     default:
                    202:       return B9600;
                    203:     }
                    204: }
                    205:
                    206: /* Encodes terminal modes for the terminal referenced by fd in a portable
                    207:    manner, and appends the modes to a packet being constructed. */
                    208:
                    209: void tty_make_modes(int fd)
                    210: {
                    211:   struct termios tio;
                    212:   int baud;
                    213:
                    214:   /* Get the modes. */
                    215:   if (tcgetattr(fd, &tio) < 0)
                    216:     {
                    217:       packet_put_char(TTY_OP_END);
                    218:       log("tcgetattr: %.100s", strerror(errno));
                    219:       return;
                    220:     }
                    221:
                    222:   /* Store input and output baud rates. */
                    223:   baud = speed_to_baud(cfgetospeed(&tio));
                    224:   packet_put_char(TTY_OP_OSPEED);
                    225:   packet_put_int(baud);
                    226:   baud = speed_to_baud(cfgetispeed(&tio));
                    227:   packet_put_char(TTY_OP_ISPEED);
                    228:   packet_put_int(baud);
                    229:
                    230:   /* Store values of mode flags. */
                    231: #define TTYCHAR(NAME, OP) \
                    232:   packet_put_char(OP); packet_put_char(tio.c_cc[NAME]);
                    233: #define TTYMODE(NAME, FIELD, OP) \
                    234:   packet_put_char(OP); packet_put_char((tio.FIELD & NAME) != 0);
                    235: #define SGTTYCHAR(NAME, OP)
                    236: #define SGTTYMODE(NAME, FIELD, OP)
                    237: #define SGTTYMODEN(NAME, FIELD, OP)
                    238:
                    239: #include "ttymodes.h"
                    240:
                    241: #undef TTYCHAR
                    242: #undef TTYMODE
                    243: #undef SGTTYCHAR
                    244: #undef SGTTYMODE
                    245: #undef SGTTYMODEN
                    246:
                    247:   /* Mark end of mode data. */
                    248:   packet_put_char(TTY_OP_END);
                    249: }
                    250:
                    251: /* Decodes terminal modes for the terminal referenced by fd in a portable
                    252:    manner from a packet being read. */
                    253:
                    254: void tty_parse_modes(int fd, int *n_bytes_ptr)
                    255: {
                    256:   struct termios tio;
                    257:   int opcode, baud;
                    258:   int n_bytes = 0;
                    259:   int failure = 0;
                    260:
                    261:   /* Get old attributes for the terminal.  We will modify these flags.
                    262:      I am hoping that if there are any machine-specific modes, they will
                    263:      initially have reasonable values. */
                    264:   if (tcgetattr(fd, &tio) < 0)
                    265:     failure = -1;
                    266:
                    267:   for (;;)
                    268:     {
                    269:       n_bytes += 1;
                    270:       opcode = packet_get_char();
                    271:       switch (opcode)
                    272:        {
                    273:        case TTY_OP_END:
                    274:          goto set;
                    275:
                    276:        case TTY_OP_ISPEED:
                    277:          n_bytes += 4;
                    278:          baud = packet_get_int();
                    279:          if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) < 0)
                    280:            error("cfsetispeed failed for %d", baud);
                    281:          break;
                    282:
                    283:        case TTY_OP_OSPEED:
                    284:          n_bytes += 4;
                    285:          baud = packet_get_int();
                    286:          if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) < 0)
                    287:            error("cfsetospeed failed for %d", baud);
                    288:          break;
                    289:
                    290: #define TTYCHAR(NAME, OP)                              \
                    291:        case OP:                                        \
                    292:          n_bytes += 1;                                 \
                    293:          tio.c_cc[NAME] = packet_get_char();           \
                    294:          break;
                    295: #define TTYMODE(NAME, FIELD, OP)                       \
                    296:        case OP:                                        \
                    297:          n_bytes += 1;                                 \
                    298:          if (packet_get_char())                        \
                    299:            tio.FIELD |= NAME;                          \
                    300:          else                                          \
                    301:            tio.FIELD &= ~NAME;                         \
                    302:          break;
                    303: #define SGTTYCHAR(NAME, OP)
                    304: #define SGTTYMODE(NAME, FIELD, OP)
                    305: #define SGTTYMODEN(NAME, FIELD, OP)
                    306:
                    307: #include "ttymodes.h"
                    308:
                    309: #undef TTYCHAR
                    310: #undef TTYMODE
                    311: #undef SGTTYCHAR
                    312: #undef SGTTYMODE
                    313: #undef SGTTYMODEN
                    314:
                    315:        default:
                    316:          debug("Ignoring unsupported tty mode opcode %d (0x%x)",
                    317:                opcode, opcode);
                    318:          /* Opcodes 0 to 127 are defined to have a one-byte argument. */
                    319:          if (opcode >= 0 && opcode < 128)
                    320:            {
                    321:              n_bytes += 1;
                    322:              (void)packet_get_char();
                    323:              break;
                    324:            }
                    325:          else
                    326:            {
                    327:              /* Opcodes 128 to 159 are defined to have an integer argument. */
                    328:              if (opcode >= 128 && opcode < 160)
                    329:                {
                    330:                  n_bytes += 4;
                    331:                  (void)packet_get_int();
                    332:                  break;
                    333:                }
                    334:            }
                    335:          /* It is a truly undefined opcode (160 to 255).  We have no idea
                    336:             about its arguments.  So we must stop parsing.  Note that some
                    337:             data may be left in the packet; hopefully there is nothing more
                    338:             coming after the mode data. */
                    339:          log("parse_tty_modes: unknown opcode %d", opcode);
                    340:          packet_integrity_check(0, 1, SSH_CMSG_REQUEST_PTY);
                    341:          goto set;
                    342:        }
                    343:     }
                    344:
                    345:  set:
                    346:   if (*n_bytes_ptr != n_bytes)
                    347:     {
                    348:       *n_bytes_ptr = n_bytes;
                    349:       return;                  /* Don't process bytes passed */
                    350:     }
                    351:
                    352:   if (failure == -1)
                    353:     return;                    /* Packet parsed ok but tty stuff failed */
                    354:
                    355:   /* Set the new modes for the terminal. */
                    356:   if (tcsetattr(fd, TCSANOW, &tio) < 0)
                    357:     log("Setting tty modes failed: %.100s", strerror(errno));
                    358:   return;
                    359: }