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: }