]> andersk Git - openssh.git/blob - ttymodes.c
- (djm) Merge OpenBSD changes:
[openssh.git] / ttymodes.c
1 /*
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.
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".
15  */
16
17 #include "includes.h"
18 RCSID("$OpenBSD: ttymodes.c,v 1.8 2000/09/07 20:27:55 deraadt Exp $");
19
20 #include "packet.h"
21 #include "ssh.h"
22
23 #define TTY_OP_END      0
24 #define TTY_OP_ISPEED   192     /* int follows */
25 #define TTY_OP_OSPEED   193     /* int follows */
26
27 /*
28  * Converts POSIX speed_t to a baud rate.  The values of the
29  * constants for speed_t are not themselves portable.
30  */
31 static int
32 speed_to_baud(speed_t speed)
33 {
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;
63
64 #ifdef B19200
65         case B19200:
66                 return 19200;
67 #else /* B19200 */
68 #ifdef EXTA
69         case EXTA:
70                 return 19200;
71 #endif /* EXTA */
72 #endif /* B19200 */
73
74 #ifdef B38400
75         case B38400:
76                 return 38400;
77 #else /* B38400 */
78 #ifdef EXTB
79         case EXTB:
80                 return 38400;
81 #endif /* EXTB */
82 #endif /* B38400 */
83
84 #ifdef B7200
85         case B7200:
86                 return 7200;
87 #endif /* B7200 */
88 #ifdef B14400
89         case B14400:
90                 return 14400;
91 #endif /* B14400 */
92 #ifdef B28800
93         case B28800:
94                 return 28800;
95 #endif /* B28800 */
96 #ifdef B57600
97         case B57600:
98                 return 57600;
99 #endif /* B57600 */
100 #ifdef B76800
101         case B76800:
102                 return 76800;
103 #endif /* B76800 */
104 #ifdef B115200
105         case B115200:
106                 return 115200;
107 #endif /* B115200 */
108 #ifdef B230400
109         case B230400:
110                 return 230400;
111 #endif /* B230400 */
112         default:
113                 return 9600;
114         }
115 }
116
117 /*
118  * Converts a numeric baud rate to a POSIX speed_t.
119  */
120 static speed_t
121 baud_to_speed(int baud)
122 {
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;
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 /*
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  */
211 void
212 tty_make_modes(int fd)
213 {
214         struct termios tio;
215         int baud;
216
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);
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 /*
252  * Decodes terminal modes for the terminal referenced by fd in a portable
253  * manner from a packet being read.
254  */
255 void
256 tty_parse_modes(int fd, int *n_bytes_ptr)
257 {
258         struct termios tio;
259         int opcode, baud;
260         int n_bytes = 0;
261         int failure = 0;
262
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          */
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;
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
317                 default:
318                         debug("Ignoring unsupported tty mode opcode %d (0x%x)",
319                               opcode, opcode);
320                         /*
321                          * Opcodes 0 to 127 are defined to have
322                          * a one-byte argument.
323                          */
324                         if (opcode >= 0 && opcode < 128) {
325                                 n_bytes += 1;
326                                 (void) packet_get_char();
327                                 break;
328                         } else {
329                                 /*
330                                  * Opcodes 128 to 159 are defined to have
331                                  * an integer argument.
332                                  */
333                                 if (opcode >= 128 && opcode < 160) {
334                                         n_bytes += 4;
335                                         (void) packet_get_int();
336                                         break;
337                                 }
338                         }
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                          */
346                         log("parse_tty_modes: unknown opcode %d", opcode);
347                         packet_integrity_check(0, 1, SSH_CMSG_REQUEST_PTY);
348                         goto set;
349                 }
350         }
351
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;
364 }
This page took 0.060729 seconds and 5 git commands to generate.