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

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.3     ! markus     20: RCSID("$Id: ttymodes.c,v 1.2 1999/09/30 05:03:05 deraadt Exp $");
1.1       deraadt    21:
                     22: #include "packet.h"
                     23: #include "ssh.h"
                     24:
                     25: #define TTY_OP_END     0
1.3     ! markus     26: #define TTY_OP_ISPEED  192     /* int follows */
        !            27: #define TTY_OP_OSPEED  193     /* int follows */
1.1       deraadt    28:
                     29: /* Converts POSIX speed_t to a baud rate.  The values of the constants
                     30:    for speed_t are not themselves portable. */
                     31:
1.3     ! markus     32: static int
        !            33: speed_to_baud(speed_t speed)
1.1       deraadt    34: {
1.3     ! markus     35:        switch (speed) {
        !            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;
1.1       deraadt    64:
                     65: #ifdef B19200
1.3     ! markus     66:        case B19200:
        !            67:                return 19200;
1.1       deraadt    68: #else /* B19200 */
                     69: #ifdef EXTA
1.3     ! markus     70:        case EXTA:
        !            71:                return 19200;
1.1       deraadt    72: #endif /* EXTA */
                     73: #endif /* B19200 */
                     74:
                     75: #ifdef B38400
1.3     ! markus     76:        case B38400:
        !            77:                return 38400;
1.1       deraadt    78: #else /* B38400 */
                     79: #ifdef EXTB
1.3     ! markus     80:        case EXTB:
        !            81:                return 38400;
1.1       deraadt    82: #endif /* EXTB */
                     83: #endif /* B38400 */
                     84:
                     85: #ifdef B7200
1.3     ! markus     86:        case B7200:
        !            87:                return 7200;
1.1       deraadt    88: #endif /* B7200 */
                     89: #ifdef B14400
1.3     ! markus     90:        case B14400:
        !            91:                return 14400;
1.1       deraadt    92: #endif /* B14400 */
                     93: #ifdef B28800
1.3     ! markus     94:        case B28800:
        !            95:                return 28800;
1.1       deraadt    96: #endif /* B28800 */
                     97: #ifdef B57600
1.3     ! markus     98:        case B57600:
        !            99:                return 57600;
1.1       deraadt   100: #endif /* B57600 */
                    101: #ifdef B76800
1.3     ! markus    102:        case B76800:
        !           103:                return 76800;
1.1       deraadt   104: #endif /* B76800 */
                    105: #ifdef B115200
1.3     ! markus    106:        case B115200:
        !           107:                return 115200;
1.1       deraadt   108: #endif /* B115200 */
                    109: #ifdef B230400
1.3     ! markus    110:        case B230400:
        !           111:                return 230400;
1.1       deraadt   112: #endif /* B230400 */
1.3     ! markus    113:        default:
        !           114:                return 9600;
        !           115:        }
1.1       deraadt   116: }
                    117:
                    118: /* Converts a numeric baud rate to a POSIX speed_t. */
                    119:
1.3     ! markus    120: static speed_t
        !           121: baud_to_speed(int baud)
1.1       deraadt   122: {
1.3     ! markus    123:        switch (baud) {
        !           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;
1.1       deraadt   152:
                    153: #ifdef B19200
1.3     ! markus    154:        case 19200:
        !           155:                return B19200;
1.1       deraadt   156: #else /* B19200 */
                    157: #ifdef EXTA
1.3     ! markus    158:        case 19200:
        !           159:                return EXTA;
1.1       deraadt   160: #endif /* EXTA */
                    161: #endif /* B19200 */
                    162:
                    163: #ifdef B38400
1.3     ! markus    164:        case 38400:
        !           165:                return B38400;
1.1       deraadt   166: #else /* B38400 */
                    167: #ifdef EXTB
1.3     ! markus    168:        case 38400:
        !           169:                return EXTB;
1.1       deraadt   170: #endif /* EXTB */
                    171: #endif /* B38400 */
                    172:
                    173: #ifdef B7200
1.3     ! markus    174:        case 7200:
        !           175:                return B7200;
1.1       deraadt   176: #endif /* B7200 */
                    177: #ifdef B14400
1.3     ! markus    178:        case 14400:
        !           179:                return B14400;
1.1       deraadt   180: #endif /* B14400 */
                    181: #ifdef B28800
1.3     ! markus    182:        case 28800:
        !           183:                return B28800;
1.1       deraadt   184: #endif /* B28800 */
                    185: #ifdef B57600
1.3     ! markus    186:        case 57600:
        !           187:                return B57600;
1.1       deraadt   188: #endif /* B57600 */
                    189: #ifdef B76800
1.3     ! markus    190:        case 76800:
        !           191:                return B76800;
1.1       deraadt   192: #endif /* B76800 */
                    193: #ifdef B115200
1.3     ! markus    194:        case 115200:
        !           195:                return B115200;
1.1       deraadt   196: #endif /* B115200 */
                    197: #ifdef B230400
1.3     ! markus    198:        case 230400:
        !           199:                return B230400;
1.1       deraadt   200: #endif /* B230400 */
1.3     ! markus    201:        default:
        !           202:                return B9600;
        !           203:        }
1.1       deraadt   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:
1.3     ! markus    209: void
        !           210: tty_make_modes(int fd)
1.1       deraadt   211: {
1.3     ! markus    212:        struct termios tio;
        !           213:        int baud;
1.1       deraadt   214:
1.3     ! markus    215:        /* Get the modes. */
        !           216:        if (tcgetattr(fd, &tio) < 0) {
        !           217:                packet_put_char(TTY_OP_END);
        !           218:                log("tcgetattr: %.100s", strerror(errno));
        !           219:                return;
        !           220:        }
        !           221:        /* Store input and output baud rates. */
        !           222:        baud = speed_to_baud(cfgetospeed(&tio));
        !           223:        packet_put_char(TTY_OP_OSPEED);
        !           224:        packet_put_int(baud);
        !           225:        baud = speed_to_baud(cfgetispeed(&tio));
        !           226:        packet_put_char(TTY_OP_ISPEED);
        !           227:        packet_put_int(baud);
1.1       deraadt   228:
1.3     ! markus    229:        /* Store values of mode flags. */
1.1       deraadt   230: #define TTYCHAR(NAME, OP) \
                    231:   packet_put_char(OP); packet_put_char(tio.c_cc[NAME]);
                    232: #define TTYMODE(NAME, FIELD, OP) \
                    233:   packet_put_char(OP); packet_put_char((tio.FIELD & NAME) != 0);
                    234: #define SGTTYCHAR(NAME, OP)
                    235: #define SGTTYMODE(NAME, FIELD, OP)
                    236: #define SGTTYMODEN(NAME, FIELD, OP)
                    237:
                    238: #include "ttymodes.h"
                    239:
                    240: #undef TTYCHAR
                    241: #undef TTYMODE
                    242: #undef SGTTYCHAR
                    243: #undef SGTTYMODE
                    244: #undef SGTTYMODEN
                    245:
1.3     ! markus    246:        /* Mark end of mode data. */
        !           247:        packet_put_char(TTY_OP_END);
1.1       deraadt   248: }
                    249:
                    250: /* Decodes terminal modes for the terminal referenced by fd in a portable
                    251:    manner from a packet being read. */
                    252:
1.3     ! markus    253: void
        !           254: tty_parse_modes(int fd, int *n_bytes_ptr)
1.1       deraadt   255: {
1.3     ! markus    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
        !           262:           flags. I am hoping that if there are any machine-specific
        !           263:           modes, they will initially have reasonable values. */
        !           264:        if (tcgetattr(fd, &tio) < 0)
        !           265:                failure = -1;
        !           266:
        !           267:        for (;;) {
        !           268:                n_bytes += 1;
        !           269:                opcode = packet_get_char();
        !           270:                switch (opcode) {
        !           271:                case TTY_OP_END:
        !           272:                        goto set;
        !           273:
        !           274:                case TTY_OP_ISPEED:
        !           275:                        n_bytes += 4;
        !           276:                        baud = packet_get_int();
        !           277:                        if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) < 0)
        !           278:                                error("cfsetispeed failed for %d", baud);
        !           279:                        break;
        !           280:
        !           281:                case TTY_OP_OSPEED:
        !           282:                        n_bytes += 4;
        !           283:                        baud = packet_get_int();
        !           284:                        if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) < 0)
        !           285:                                error("cfsetospeed failed for %d", baud);
        !           286:                        break;
1.1       deraadt   287:
                    288: #define TTYCHAR(NAME, OP)                              \
                    289:        case OP:                                        \
                    290:          n_bytes += 1;                                 \
                    291:          tio.c_cc[NAME] = packet_get_char();           \
                    292:          break;
                    293: #define TTYMODE(NAME, FIELD, OP)                       \
                    294:        case OP:                                        \
                    295:          n_bytes += 1;                                 \
                    296:          if (packet_get_char())                        \
                    297:            tio.FIELD |= NAME;                          \
                    298:          else                                          \
                    299:            tio.FIELD &= ~NAME;                         \
                    300:          break;
                    301: #define SGTTYCHAR(NAME, OP)
                    302: #define SGTTYMODE(NAME, FIELD, OP)
                    303: #define SGTTYMODEN(NAME, FIELD, OP)
                    304:
                    305: #include "ttymodes.h"
                    306:
                    307: #undef TTYCHAR
                    308: #undef TTYMODE
                    309: #undef SGTTYCHAR
                    310: #undef SGTTYMODE
                    311: #undef SGTTYMODEN
                    312:
1.3     ! markus    313:                default:
        !           314:                        debug("Ignoring unsupported tty mode opcode %d (0x%x)",
        !           315:                              opcode, opcode);
        !           316:                        /* Opcodes 0 to 127 are defined to have a one-byte argument. */
        !           317:                        if (opcode >= 0 && opcode < 128) {
        !           318:                                n_bytes += 1;
        !           319:                                (void) packet_get_char();
        !           320:                                break;
        !           321:                        } else {
        !           322:                                /* Opcodes 128 to 159 are defined to have an integer argument. */
        !           323:                                if (opcode >= 128 && opcode < 160) {
        !           324:                                        n_bytes += 4;
        !           325:                                        (void) packet_get_int();
        !           326:                                        break;
        !           327:                                }
        !           328:                        }
        !           329:                        /* It is a truly undefined opcode (160 to 255).
        !           330:                           We have no idea about its arguments.  So we
        !           331:                           must stop parsing.  Note that some data may be
        !           332:                           left in the packet; hopefully there is nothing
        !           333:                           more coming after the mode data. */
        !           334:                        log("parse_tty_modes: unknown opcode %d", opcode);
        !           335:                        packet_integrity_check(0, 1, SSH_CMSG_REQUEST_PTY);
        !           336:                        goto set;
1.1       deraadt   337:                }
                    338:        }
                    339:
1.3     ! markus    340: set:
        !           341:        if (*n_bytes_ptr != n_bytes) {
        !           342:                *n_bytes_ptr = n_bytes;
        !           343:                return;         /* Don't process bytes passed */
        !           344:        }
        !           345:        if (failure == -1)
        !           346:                return;         /* Packet parsed ok but tty stuff failed */
        !           347:
        !           348:        /* Set the new modes for the terminal. */
        !           349:        if (tcsetattr(fd, TCSANOW, &tio) < 0)
        !           350:                log("Setting tty modes failed: %.100s", strerror(errno));
        !           351:        return;
1.1       deraadt   352: }