]> andersk Git - openssh.git/blob - ttymodes.c
Initial revision
[openssh.git] / ttymodes.c
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$");
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 }
This page took 0.358496 seconds and 5 git commands to generate.