[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.1

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"
        !            20: RCSID("$Id: ttymodes.c,v 1.3 1999/05/04 11:59:25 bg Exp $");
        !            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: /* Speed extraction & setting macros for sgtty. */
        !            30:
        !            31: #ifdef USING_SGTTY
        !            32: #define cfgetospeed(tio)       ((tio)->sg_ospeed)
        !            33: #define cfgetispeed(tio)       ((tio)->sg_ispeed)
        !            34: #define cfsetospeed(tio, spd)  ((tio)->sg_ospeed = (spd), 0)
        !            35: #define cfsetispeed(tio, spd)  ((tio)->sg_ispeed = (spd), 0)
        !            36: #ifndef SPEED_T_IN_STDTYPES_H
        !            37: typedef char speed_t;
        !            38: #endif
        !            39: #endif
        !            40:
        !            41: /* Converts POSIX speed_t to a baud rate.  The values of the constants
        !            42:    for speed_t are not themselves portable. */
        !            43:
        !            44: static int speed_to_baud(speed_t speed)
        !            45: {
        !            46:   switch (speed)
        !            47:     {
        !            48:     case B0:
        !            49:       return 0;
        !            50:     case B50:
        !            51:       return 50;
        !            52:     case B75:
        !            53:       return 75;
        !            54:     case B110:
        !            55:       return 110;
        !            56:     case B134:
        !            57:       return 134;
        !            58:     case B150:
        !            59:       return 150;
        !            60:     case B200:
        !            61:       return 200;
        !            62:     case B300:
        !            63:       return 300;
        !            64:     case B600:
        !            65:       return 600;
        !            66:     case B1200:
        !            67:       return 1200;
        !            68:     case B1800:
        !            69:       return 1800;
        !            70:     case B2400:
        !            71:       return 2400;
        !            72:     case B4800:
        !            73:       return 4800;
        !            74:     case B9600:
        !            75:       return 9600;
        !            76:
        !            77: #ifdef B19200
        !            78:     case B19200:
        !            79:       return 19200;
        !            80: #else /* B19200 */
        !            81: #ifdef EXTA
        !            82:     case EXTA:
        !            83:       return 19200;
        !            84: #endif /* EXTA */
        !            85: #endif /* B19200 */
        !            86:
        !            87: #ifdef B38400
        !            88:     case B38400:
        !            89:       return 38400;
        !            90: #else /* B38400 */
        !            91: #ifdef EXTB
        !            92:     case EXTB:
        !            93:       return 38400;
        !            94: #endif /* EXTB */
        !            95: #endif /* B38400 */
        !            96:
        !            97: #ifdef B7200
        !            98:     case B7200:
        !            99:       return 7200;
        !           100: #endif /* B7200 */
        !           101: #ifdef B14400
        !           102:     case B14400:
        !           103:       return 14400;
        !           104: #endif /* B14400 */
        !           105: #ifdef B28800
        !           106:     case B28800:
        !           107:       return 28800;
        !           108: #endif /* B28800 */
        !           109: #ifdef B57600
        !           110:     case B57600:
        !           111:       return 57600;
        !           112: #endif /* B57600 */
        !           113: #ifdef B76800
        !           114:     case B76800:
        !           115:       return 76800;
        !           116: #endif /* B76800 */
        !           117: #ifdef B115200
        !           118:     case B115200:
        !           119:       return 115200;
        !           120: #endif /* B115200 */
        !           121: #ifdef B230400
        !           122:     case B230400:
        !           123:       return 230400;
        !           124: #endif /* B230400 */
        !           125:     default:
        !           126:       return 9600;
        !           127:     }
        !           128: }
        !           129:
        !           130: /* Converts a numeric baud rate to a POSIX speed_t. */
        !           131:
        !           132: static speed_t baud_to_speed(int baud)
        !           133: {
        !           134:   switch (baud)
        !           135:     {
        !           136:     case 0:
        !           137:       return B0;
        !           138:     case 50:
        !           139:       return B50;
        !           140:     case 75:
        !           141:       return B75;
        !           142:     case 110:
        !           143:       return B110;
        !           144:     case 134:
        !           145:       return B134;
        !           146:     case 150:
        !           147:       return B150;
        !           148:     case 200:
        !           149:       return B200;
        !           150:     case 300:
        !           151:       return B300;
        !           152:     case 600:
        !           153:       return B600;
        !           154:     case 1200:
        !           155:       return B1200;
        !           156:     case 1800:
        !           157:       return B1800;
        !           158:     case 2400:
        !           159:       return B2400;
        !           160:     case 4800:
        !           161:       return B4800;
        !           162:     case 9600:
        !           163:       return B9600;
        !           164:
        !           165: #ifdef B19200
        !           166:     case 19200:
        !           167:       return B19200;
        !           168: #else /* B19200 */
        !           169: #ifdef EXTA
        !           170:     case 19200:
        !           171:       return EXTA;
        !           172: #endif /* EXTA */
        !           173: #endif /* B19200 */
        !           174:
        !           175: #ifdef B38400
        !           176:     case 38400:
        !           177:       return B38400;
        !           178: #else /* B38400 */
        !           179: #ifdef EXTB
        !           180:     case 38400:
        !           181:       return EXTB;
        !           182: #endif /* EXTB */
        !           183: #endif /* B38400 */
        !           184:
        !           185: #ifdef B7200
        !           186:     case 7200:
        !           187:       return B7200;
        !           188: #endif /* B7200 */
        !           189: #ifdef B14400
        !           190:     case 14400:
        !           191:       return B14400;
        !           192: #endif /* B14400 */
        !           193: #ifdef B28800
        !           194:     case 28800:
        !           195:       return B28800;
        !           196: #endif /* B28800 */
        !           197: #ifdef B57600
        !           198:     case 57600:
        !           199:       return B57600;
        !           200: #endif /* B57600 */
        !           201: #ifdef B76800
        !           202:     case 76800:
        !           203:       return B76800;
        !           204: #endif /* B76800 */
        !           205: #ifdef B115200
        !           206:     case 115200:
        !           207:       return B115200;
        !           208: #endif /* B115200 */
        !           209: #ifdef B230400
        !           210:     case 230400:
        !           211:       return B230400;
        !           212: #endif /* B230400 */
        !           213:     default:
        !           214:       return B9600;
        !           215:     }
        !           216: }
        !           217:
        !           218: /* Encodes terminal modes for the terminal referenced by fd in a portable
        !           219:    manner, and appends the modes to a packet being constructed. */
        !           220:
        !           221: void tty_make_modes(int fd)
        !           222: {
        !           223: #ifdef USING_TERMIOS
        !           224:   struct termios tio;
        !           225: #endif
        !           226: #ifdef USING_SGTTY
        !           227:   struct sgttyb tio;
        !           228:   struct tchars tiotc;
        !           229:   struct ltchars tioltc;
        !           230:   int tiolm;
        !           231: #ifdef TIOCGSTAT
        !           232:   struct tstatus tiots;
        !           233: #endif /* TIOCGSTAT */
        !           234: #endif /* USING_SGTTY */
        !           235:   int baud;
        !           236:
        !           237:   /* Get the modes. */
        !           238: #ifdef USING_TERMIOS
        !           239:   if (tcgetattr(fd, &tio) < 0)
        !           240:     {
        !           241:       packet_put_char(TTY_OP_END);
        !           242:       log("tcgetattr: %.100s", strerror(errno));
        !           243:       return;
        !           244:     }
        !           245: #endif /* USING_TERMIOS */
        !           246: #ifdef USING_SGTTY
        !           247:   if (ioctl(fd, TIOCGETP, &tio) < 0)
        !           248:     {
        !           249:       packet_put_char(TTY_OP_END);
        !           250:       log("ioctl(fd, TIOCGETP, ...): %.100s", strerror(errno));
        !           251:       return;
        !           252:     }
        !           253:   if (ioctl(fd, TIOCGETC, &tiotc) < 0)
        !           254:     {
        !           255:       packet_put_char(TTY_OP_END);
        !           256:       log("ioctl(fd, TIOCGETC, ...): %.100s", strerror(errno));
        !           257:       return;
        !           258:     }
        !           259:   if (ioctl(fd, TIOCLGET, &tiolm) < 0)
        !           260:     {
        !           261:       packet_put_char(TTY_OP_END);
        !           262:       log("ioctl(fd, TIOCLGET, ...): %.100s", strerror(errno));
        !           263:       return;
        !           264:     }
        !           265:   if (ioctl(fd, TIOCGLTC, &tioltc) < 0)
        !           266:     {
        !           267:       packet_put_char(TTY_OP_END);
        !           268:       log("ioctl(fd, TIOCGLTC, ...): %.100s", strerror(errno));
        !           269:       return;
        !           270:     }
        !           271: #ifdef TIOCGSTAT
        !           272:   if (ioctl(fd, TIOCGSTAT, &tiots) < 0)
        !           273:     {
        !           274:       packet_put_char(TTY_OP_END);
        !           275:       log("ioctl(fd, TIOCGSTAT, ...): %.100s", strerror(errno));
        !           276:       return;
        !           277:     }
        !           278: #endif /* TIOCGSTAT */
        !           279: #endif /* USING_SGTTY */
        !           280:
        !           281:   /* Store input and output baud rates. */
        !           282:   baud = speed_to_baud(cfgetospeed(&tio));
        !           283:   packet_put_char(TTY_OP_OSPEED);
        !           284:   packet_put_int(baud);
        !           285:   baud = speed_to_baud(cfgetispeed(&tio));
        !           286:   packet_put_char(TTY_OP_ISPEED);
        !           287:   packet_put_int(baud);
        !           288:
        !           289:   /* Store values of mode flags. */
        !           290: #ifdef USING_TERMIOS
        !           291: #define TTYCHAR(NAME, OP) \
        !           292:   packet_put_char(OP); packet_put_char(tio.c_cc[NAME]);
        !           293: #define TTYMODE(NAME, FIELD, OP) \
        !           294:   packet_put_char(OP); packet_put_char((tio.FIELD & NAME) != 0);
        !           295: #define SGTTYCHAR(NAME, OP)
        !           296: #define SGTTYMODE(NAME, FIELD, OP)
        !           297: #define SGTTYMODEN(NAME, FIELD, OP)
        !           298: #endif /* USING_TERMIOS */
        !           299:
        !           300: #ifdef USING_SGTTY
        !           301: #define TTYCHAR(NAME, OP)
        !           302: #define TTYMODE(NAME, FIELD, OP)
        !           303: #define SGTTYCHAR(NAME, OP) \
        !           304:   packet_put_char(OP); packet_put_char(NAME);
        !           305: #define SGTTYMODE(NAME, FIELD, OP) \
        !           306:   packet_put_char(OP); packet_put_char((FIELD & NAME) != 0);
        !           307: #define SGTTYMODEN(NAME, FIELD, OP) \
        !           308:   packet_put_char(OP); packet_put_char((FIELD & NAME) == 0);
        !           309: #endif /* USING_SGTTY */
        !           310:
        !           311: #include "ttymodes.h"
        !           312:
        !           313: #undef TTYCHAR
        !           314: #undef TTYMODE
        !           315: #undef SGTTYCHAR
        !           316: #undef SGTTYMODE
        !           317: #undef SGTTYMODEN
        !           318:
        !           319:   /* Mark end of mode data. */
        !           320:   packet_put_char(TTY_OP_END);
        !           321: }
        !           322:
        !           323: /* Decodes terminal modes for the terminal referenced by fd in a portable
        !           324:    manner from a packet being read. */
        !           325:
        !           326: void tty_parse_modes(int fd, int *n_bytes_ptr)
        !           327: {
        !           328: #ifdef USING_TERMIOS
        !           329:   struct termios tio;
        !           330: #endif /* USING_TERMIOS */
        !           331: #ifdef USING_SGTTY
        !           332:   struct sgttyb tio;
        !           333:   struct tchars tiotc;
        !           334:   struct ltchars tioltc;
        !           335:   int tiolm;
        !           336: #ifdef TIOCGSTAT
        !           337:   struct tstatus tiots;
        !           338: #endif /* TIOCGSTAT */
        !           339: #endif
        !           340:   int opcode, baud;
        !           341:   int n_bytes = 0;
        !           342:   int failure = 0;
        !           343:
        !           344:   /* Get old attributes for the terminal.  We will modify these flags.
        !           345:      I am hoping that if there are any machine-specific modes, they will
        !           346:      initially have reasonable values. */
        !           347: #ifdef USING_TERMIOS
        !           348:   if (tcgetattr(fd, &tio) < 0)
        !           349:     failure = -1;
        !           350: #endif /* USING_TERMIOS */
        !           351: #ifdef USING_SGTTY
        !           352:   if (ioctl(fd, TIOCGETP, &tio) < 0)
        !           353:     failure = -1;
        !           354:   if (ioctl(fd, TIOCGETC, &tiotc) < 0)
        !           355:     failure = -1;
        !           356:   if (ioctl(fd, TIOCLGET, &tiolm) < 0)
        !           357:     failure = -1;
        !           358:   if (ioctl(fd, TIOCGLTC, &tioltc) < 0)
        !           359:     failure = -1;
        !           360: #ifdef TIOCGSTAT
        !           361:   if (ioctl(fd, TIOCGSTAT, &tiots) < 0)
        !           362:     failure = -1;
        !           363: #endif /* TIOCGSTAT */
        !           364: #endif /* USING_SGTTY */
        !           365:
        !           366:   for (;;)
        !           367:     {
        !           368:       n_bytes += 1;
        !           369:       opcode = packet_get_char();
        !           370:       switch (opcode)
        !           371:        {
        !           372:        case TTY_OP_END:
        !           373:          goto set;
        !           374:
        !           375:        case TTY_OP_ISPEED:
        !           376:          n_bytes += 4;
        !           377:          baud = packet_get_int();
        !           378:          if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) < 0)
        !           379:            error("cfsetispeed failed for %d", baud);
        !           380:          break;
        !           381:
        !           382:        case TTY_OP_OSPEED:
        !           383:          n_bytes += 4;
        !           384:          baud = packet_get_int();
        !           385:          if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) < 0)
        !           386:            error("cfsetospeed failed for %d", baud);
        !           387:          break;
        !           388:
        !           389: #ifdef USING_TERMIOS
        !           390: #define TTYCHAR(NAME, OP)                              \
        !           391:        case OP:                                        \
        !           392:          n_bytes += 1;                                 \
        !           393:          tio.c_cc[NAME] = packet_get_char();           \
        !           394:          break;
        !           395: #define TTYMODE(NAME, FIELD, OP)                       \
        !           396:        case OP:                                        \
        !           397:          n_bytes += 1;                                 \
        !           398:          if (packet_get_char())                        \
        !           399:            tio.FIELD |= NAME;                          \
        !           400:          else                                          \
        !           401:            tio.FIELD &= ~NAME;                         \
        !           402:          break;
        !           403: #define SGTTYCHAR(NAME, OP)
        !           404: #define SGTTYMODE(NAME, FIELD, OP)
        !           405: #define SGTTYMODEN(NAME, FIELD, OP)
        !           406: #endif /* USING_TERMIOS */
        !           407:
        !           408: #ifdef USING_SGTTY
        !           409: #define TTYCHAR(NAME, OP)
        !           410: #define TTYMODE(NAME, FIELD, OP)
        !           411: #define SGTTYCHAR(NAME, OP)                            \
        !           412:        case OP:                                        \
        !           413:          n_bytes += 1;                                 \
        !           414:          NAME = packet_get_char();                     \
        !           415:          break;
        !           416: #define SGTTYMODE(NAME, FIELD, OP)                     \
        !           417:        case OP:                                        \
        !           418:          n_bytes += 1;                                 \
        !           419:          if (packet_get_char())                        \
        !           420:            FIELD |= NAME;                              \
        !           421:          else                                          \
        !           422:            FIELD &= ~NAME;                             \
        !           423:          break;
        !           424: #define SGTTYMODEN(NAME, FIELD, OP)                    \
        !           425:        case OP:                                        \
        !           426:          n_bytes += 1;                                 \
        !           427:          if (packet_get_char())                        \
        !           428:            FIELD &= ~NAME;                             \
        !           429:          else                                          \
        !           430:            FIELD |= NAME;                              \
        !           431:          break;
        !           432: #endif /* USING_SGTTY */
        !           433:
        !           434: #include "ttymodes.h"
        !           435:
        !           436: #undef TTYCHAR
        !           437: #undef TTYMODE
        !           438: #undef SGTTYCHAR
        !           439: #undef SGTTYMODE
        !           440: #undef SGTTYMODEN
        !           441:
        !           442:        default:
        !           443:          debug("Ignoring unsupported tty mode opcode %d (0x%x)",
        !           444:                opcode, opcode);
        !           445:          /* Opcodes 0 to 127 are defined to have a one-byte argument. */
        !           446:          if (opcode >= 0 && opcode < 128)
        !           447:            {
        !           448:              n_bytes += 1;
        !           449:              (void)packet_get_char();
        !           450:              break;
        !           451:            }
        !           452:          else
        !           453:            {
        !           454:              /* Opcodes 128 to 159 are defined to have an integer argument. */
        !           455:              if (opcode >= 128 && opcode < 160)
        !           456:                {
        !           457:                  n_bytes += 4;
        !           458:                  (void)packet_get_int();
        !           459:                  break;
        !           460:                }
        !           461:            }
        !           462:          /* It is a truly undefined opcode (160 to 255).  We have no idea
        !           463:             about its arguments.  So we must stop parsing.  Note that some
        !           464:             data may be left in the packet; hopefully there is nothing more
        !           465:             coming after the mode data. */
        !           466:          log("parse_tty_modes: unknown opcode %d", opcode);
        !           467:          packet_integrity_check(0, 1, SSH_CMSG_REQUEST_PTY);
        !           468:          goto set;
        !           469:        }
        !           470:     }
        !           471:
        !           472:  set:
        !           473:   if (*n_bytes_ptr != n_bytes)
        !           474:     {
        !           475:       *n_bytes_ptr = n_bytes;
        !           476:       return;                  /* Don't process bytes passed */
        !           477:     }
        !           478:
        !           479:   if (failure == -1)
        !           480:     return;                    /* Packet parsed ok but tty stuff failed */
        !           481:
        !           482:   /* Set the new modes for the terminal. */
        !           483: #ifdef USING_TERMIOS
        !           484:   if (tcsetattr(fd, TCSANOW, &tio) < 0)
        !           485:     log("Setting tty modes failed: %.100s", strerror(errno));
        !           486: #endif /* USING_TERMIOS */
        !           487: #ifdef USING_SGTTY
        !           488:   if (ioctl(fd, TIOCSETP, &tio) < 0
        !           489:       || ioctl(fd, TIOCSETC, &tiotc) < 0
        !           490:       || ioctl(fd, TIOCLSET, &tiolm) < 0
        !           491:       || ioctl(fd, TIOCSLTC, &tioltc) < 0
        !           492: #ifdef TIOCSSTAT
        !           493:       || ioctl(fd, TIOCSSTAT, &tiots) < 0
        !           494: #endif /* TIOCSSTAT */
        !           495:      )
        !           496:     log("Setting tty modes failed: %.100s", strerror(errno));
        !           497: #endif /* USING_SGTTY */
        !           498:   return;
        !           499: }