Annotation of src/usr.bin/ssh/ttymodes.c, Revision 1.6.2.2
1.1 deraadt 1: /*
1.4 deraadt 2: * Author: Tatu Ylonen <ylo@cs.hut.fi>
3: * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4: * All rights reserved
5: * Encoding and decoding of terminal modes in a portable way.
6: * Much of the format is defined in ttymodes.h; it is included multiple times
7: * into this file with the appropriate macro definitions to generate the
8: * suitable code.
1.6.2.2 ! jason 9: *
! 10: * As far as I am concerned, the code I have written for this software
! 11: * can be used freely for any purpose. Any derived versions of this
! 12: * software must be clearly marked as such, and if the derived work is
! 13: * incompatible with the protocol description in the RFC file, it must be
! 14: * called by a name other than "ssh" or "Secure Shell".
1.4 deraadt 15: */
1.1 deraadt 16:
17: #include "includes.h"
1.6.2.2 ! jason 18: RCSID("$OpenBSD: ttymodes.c,v 1.8 2000/09/07 20:27:55 deraadt Exp $");
1.1 deraadt 19:
20: #include "packet.h"
21: #include "ssh.h"
22:
23: #define TTY_OP_END 0
1.3 markus 24: #define TTY_OP_ISPEED 192 /* int follows */
25: #define TTY_OP_OSPEED 193 /* int follows */
1.1 deraadt 26:
1.4 deraadt 27: /*
28: * Converts POSIX speed_t to a baud rate. The values of the
29: * constants for speed_t are not themselves portable.
30: */
1.6 markus 31: static int
1.3 markus 32: speed_to_baud(speed_t speed)
1.1 deraadt 33: {
1.3 markus 34: switch (speed) {
35: case B0:
36: return 0;
37: case B50:
38: return 50;
39: case B75:
40: return 75;
41: case B110:
42: return 110;
43: case B134:
44: return 134;
45: case B150:
46: return 150;
47: case B200:
48: return 200;
49: case B300:
50: return 300;
51: case B600:
52: return 600;
53: case B1200:
54: return 1200;
55: case B1800:
56: return 1800;
57: case B2400:
58: return 2400;
59: case B4800:
60: return 4800;
61: case B9600:
62: return 9600;
1.1 deraadt 63:
64: #ifdef B19200
1.3 markus 65: case B19200:
66: return 19200;
1.1 deraadt 67: #else /* B19200 */
68: #ifdef EXTA
1.3 markus 69: case EXTA:
70: return 19200;
1.1 deraadt 71: #endif /* EXTA */
72: #endif /* B19200 */
73:
74: #ifdef B38400
1.3 markus 75: case B38400:
76: return 38400;
1.1 deraadt 77: #else /* B38400 */
78: #ifdef EXTB
1.3 markus 79: case EXTB:
80: return 38400;
1.1 deraadt 81: #endif /* EXTB */
82: #endif /* B38400 */
83:
84: #ifdef B7200
1.3 markus 85: case B7200:
86: return 7200;
1.1 deraadt 87: #endif /* B7200 */
88: #ifdef B14400
1.3 markus 89: case B14400:
90: return 14400;
1.1 deraadt 91: #endif /* B14400 */
92: #ifdef B28800
1.3 markus 93: case B28800:
94: return 28800;
1.1 deraadt 95: #endif /* B28800 */
96: #ifdef B57600
1.3 markus 97: case B57600:
98: return 57600;
1.1 deraadt 99: #endif /* B57600 */
100: #ifdef B76800
1.3 markus 101: case B76800:
102: return 76800;
1.1 deraadt 103: #endif /* B76800 */
104: #ifdef B115200
1.3 markus 105: case B115200:
106: return 115200;
1.1 deraadt 107: #endif /* B115200 */
108: #ifdef B230400
1.3 markus 109: case B230400:
110: return 230400;
1.1 deraadt 111: #endif /* B230400 */
1.3 markus 112: default:
113: return 9600;
114: }
1.1 deraadt 115: }
116:
1.4 deraadt 117: /*
118: * Converts a numeric baud rate to a POSIX speed_t.
119: */
1.6 markus 120: static speed_t
1.3 markus 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:
1.4 deraadt 206: /*
207: * Encodes terminal modes for the terminal referenced by fd
208: * in a portable manner, and appends the modes to a packet
209: * being constructed.
210: */
1.6 markus 211: void
1.3 markus 212: tty_make_modes(int fd)
1.1 deraadt 213: {
1.3 markus 214: struct termios tio;
215: int baud;
1.1 deraadt 216:
1.3 markus 217: if (tcgetattr(fd, &tio) < 0) {
218: packet_put_char(TTY_OP_END);
219: log("tcgetattr: %.100s", strerror(errno));
220: return;
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);
1.1 deraadt 229:
1.3 markus 230: /* Store values of mode flags. */
1.1 deraadt 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:
1.3 markus 247: /* Mark end of mode data. */
248: packet_put_char(TTY_OP_END);
1.1 deraadt 249: }
250:
1.4 deraadt 251: /*
252: * Decodes terminal modes for the terminal referenced by fd in a portable
253: * manner from a packet being read.
254: */
1.6 markus 255: void
1.3 markus 256: tty_parse_modes(int fd, int *n_bytes_ptr)
1.1 deraadt 257: {
1.3 markus 258: struct termios tio;
259: int opcode, baud;
260: int n_bytes = 0;
261: int failure = 0;
262:
1.4 deraadt 263: /*
264: * Get old attributes for the terminal. We will modify these
265: * flags. I am hoping that if there are any machine-specific
266: * modes, they will initially have reasonable values.
267: */
1.3 markus 268: if (tcgetattr(fd, &tio) < 0)
269: failure = -1;
270:
271: for (;;) {
272: n_bytes += 1;
273: opcode = packet_get_char();
274: switch (opcode) {
275: case TTY_OP_END:
276: goto set;
277:
278: case TTY_OP_ISPEED:
279: n_bytes += 4;
280: baud = packet_get_int();
281: if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) < 0)
282: error("cfsetispeed failed for %d", baud);
283: break;
284:
285: case TTY_OP_OSPEED:
286: n_bytes += 4;
287: baud = packet_get_int();
288: if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) < 0)
289: error("cfsetospeed failed for %d", baud);
290: break;
1.1 deraadt 291:
292: #define TTYCHAR(NAME, OP) \
293: case OP: \
294: n_bytes += 1; \
295: tio.c_cc[NAME] = packet_get_char(); \
296: break;
297: #define TTYMODE(NAME, FIELD, OP) \
298: case OP: \
299: n_bytes += 1; \
300: if (packet_get_char()) \
301: tio.FIELD |= NAME; \
302: else \
303: tio.FIELD &= ~NAME; \
304: break;
305: #define SGTTYCHAR(NAME, OP)
306: #define SGTTYMODE(NAME, FIELD, OP)
307: #define SGTTYMODEN(NAME, FIELD, OP)
308:
309: #include "ttymodes.h"
310:
311: #undef TTYCHAR
312: #undef TTYMODE
313: #undef SGTTYCHAR
314: #undef SGTTYMODE
315: #undef SGTTYMODEN
316:
1.3 markus 317: default:
318: debug("Ignoring unsupported tty mode opcode %d (0x%x)",
319: opcode, opcode);
1.4 deraadt 320: /*
321: * Opcodes 0 to 127 are defined to have
322: * a one-byte argument.
323: */
1.3 markus 324: if (opcode >= 0 && opcode < 128) {
325: n_bytes += 1;
326: (void) packet_get_char();
327: break;
328: } else {
1.4 deraadt 329: /*
330: * Opcodes 128 to 159 are defined to have
331: * an integer argument.
332: */
1.3 markus 333: if (opcode >= 128 && opcode < 160) {
334: n_bytes += 4;
335: (void) packet_get_int();
336: break;
337: }
338: }
1.4 deraadt 339: /*
340: * It is a truly undefined opcode (160 to 255).
341: * We have no idea about its arguments. So we
342: * must stop parsing. Note that some data may be
343: * left in the packet; hopefully there is nothing
344: * more coming after the mode data.
345: */
1.3 markus 346: log("parse_tty_modes: unknown opcode %d", opcode);
347: packet_integrity_check(0, 1, SSH_CMSG_REQUEST_PTY);
348: goto set;
1.1 deraadt 349: }
350: }
351:
1.3 markus 352: set:
353: if (*n_bytes_ptr != n_bytes) {
354: *n_bytes_ptr = n_bytes;
355: return; /* Don't process bytes passed */
356: }
357: if (failure == -1)
358: return; /* Packet parsed ok but tty stuff failed */
359:
360: /* Set the new modes for the terminal. */
361: if (tcsetattr(fd, TCSANOW, &tio) < 0)
362: log("Setting tty modes failed: %.100s", strerror(errno));
363: return;
1.1 deraadt 364: }