Cygwin: (mostly) drop NT4 and Samba < 3.0 support
[newlib-cygwin.git] / winsup / cygwin / termios.cc
blob1dfd57079d61781c4e85c9a78d454c8e8d2c33ef
1 /* termios.cc: termios for WIN32.
3 Written by Doug Evans and Steve Chamberlain of Cygnus Support
4 dje@cygnus.com, sac@cygnus.com
6 This file is part of Cygwin.
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
10 details. */
12 #include "winsup.h"
13 #include "cygwin/version.h"
14 #include <stdlib.h>
15 #include "cygerrno.h"
16 #include "security.h"
17 #include "path.h"
18 #include "fhandler.h"
19 #include "dtable.h"
20 #include "cygheap.h"
21 #include "perprocess.h"
22 #include "cygtls.h"
24 /* tcsendbreak: POSIX 7.2.2.1 */
25 extern "C" int
26 tcsendbreak (int fd, int duration)
28 int res = -1;
30 cygheap_fdget cfd (fd);
31 if (cfd < 0)
32 goto out;
34 if (!cfd->is_tty ())
35 set_errno (ENOTTY);
36 else if ((res = cfd->bg_check (-SIGTTOU)) > bg_eof)
37 res = cfd->tcsendbreak (duration);
39 out:
40 syscall_printf ("%R = tcsendbreak(%d, %d)", res, fd, duration);
41 return res;
44 /* tcdrain: POSIX 7.2.2.1 */
45 extern "C" int
46 tcdrain (int fd)
48 pthread_testcancel ();
50 int res = -1;
52 termios_printf ("tcdrain");
54 cygheap_fdget cfd (fd);
55 if (cfd < 0)
56 goto out;
58 if (!cfd->is_tty ())
59 set_errno (ENOTTY);
60 else if ((res = cfd->bg_check (-SIGTTOU)) > bg_eof)
61 res = cfd->tcdrain ();
63 out:
64 syscall_printf ("%R = tcdrain(%d)", res, fd);
65 return res;
68 /* tcflush: POSIX 7.2.2.1 */
69 extern "C" int
70 tcflush (int fd, int queue)
72 int res = -1;
74 cygheap_fdget cfd (fd);
75 if (cfd < 0)
76 goto out;
78 if (!cfd->is_tty ())
79 set_errno (ENOTTY);
80 else if (queue != TCIFLUSH && queue != TCOFLUSH && queue != TCIOFLUSH)
81 set_errno (EINVAL);
82 else if ((res = cfd->bg_check (-SIGTTOU)) > bg_eof)
83 res = cfd->tcflush (queue);
85 out:
86 termios_printf ("%R = tcflush(%d, %d)", res, fd, queue);
87 return res;
90 /* tcflow: POSIX 7.2.2.1 */
91 extern "C" int
92 tcflow (int fd, int action)
94 int res = -1;
96 cygheap_fdget cfd (fd);
97 if (cfd < 0)
98 goto out;
100 if (!cfd->is_tty ())
101 set_errno (ENOTTY);
102 else if ((res = cfd->bg_check (-SIGTTOU)) > bg_eof)
103 res = cfd->tcflow (action);
105 out:
106 syscall_printf ("%R = tcflow(%d, %d)", res, fd, action);
107 return res;
110 /* tcsetattr: POSIX96 7.2.1.1 */
111 extern "C" int
112 tcsetattr (int fd, int a, const struct termios *t)
114 int res;
115 int e = get_errno ();
117 while (1)
119 res = -1;
120 cygheap_fdget cfd (fd);
121 if (cfd < 0)
123 e = get_errno ();
124 break;
127 if (!cfd->is_tty ())
129 e = ENOTTY;
130 break;
133 res = cfd->bg_check (-SIGTTOU);
135 switch (res)
137 case bg_eof:
138 e = get_errno ();
139 break;
140 case bg_ok:
141 if (cfd.isopen ())
142 res = cfd->tcsetattr (a, t);
143 e = get_errno ();
144 break;
145 case bg_signalled:
146 if (_my_tls.call_signal_handler ())
147 continue;
148 res = -1;
149 fallthrough;
150 default:
151 e = get_errno ();
152 break;
154 break;
157 set_errno (e);
158 termios_printf ("iflag %y, oflag %y, cflag %y, lflag %y, VMIN %d, VTIME %d",
159 t->c_iflag, t->c_oflag, t->c_cflag, t->c_lflag, t->c_cc[VMIN],
160 t->c_cc[VTIME]);
161 termios_printf ("%R = tcsetattr(%d, %d, %p)", res, fd, a, t);
162 return res;
165 /* tcgetattr: POSIX 7.2.1.1 */
166 extern "C" int
167 tcgetattr (int fd, struct termios *t)
169 int res = -1;
171 cygheap_fdget cfd (fd);
172 if (cfd < 0)
173 /* saw an error */;
174 else if (!cfd->is_tty ())
175 set_errno (ENOTTY);
176 else
177 res = cfd->tcgetattr (t);
179 if (res)
180 termios_printf ("%R = tcgetattr(%d, %p)", res, fd, t);
181 else
182 termios_printf ("iflag %y, oflag %y, cflag %y, lflag %y, VMIN %d, VTIME %d",
183 t->c_iflag, t->c_oflag, t->c_cflag, t->c_lflag, t->c_cc[VMIN],
184 t->c_cc[VTIME]);
186 return res;
189 /* tcgetpgrp: POSIX 7.2.3.1 */
190 extern "C" int
191 tcgetpgrp (int fd)
193 int res;
195 cygheap_fdget cfd (fd);
196 if (cfd < 0)
197 res = -1;
198 else
199 res = cfd->tcgetpgrp ();
201 termios_printf ("%R = tcgetpgrp(%d)", res, fd);
202 return res;
205 extern "C" pid_t
206 tcgetsid (int fd)
208 int res;
210 cygheap_fdget cfd (fd);
211 if (cfd < 0)
212 res = -1;
213 else
214 res = cfd->tcgetsid ();
216 termios_printf ("%R = tcgetsid(%d)", res, fd);
217 return res;
220 /* tcsetpgrp: POSIX 7.2.4.1 */
221 extern "C" int
222 tcsetpgrp (int fd, pid_t pgid)
224 int res = -1;
226 cygheap_fdget cfd (fd);
227 if (cfd < 0)
228 /* saw an error */;
229 else if (!cfd->is_tty ())
230 set_errno (ENOTTY);
231 else
232 res = cfd->tcsetpgrp (pgid);
234 termios_printf ("%R = tcsetpgrp(%d, %d)", res, fd, pgid);
235 return res;
238 /* NIST PCTS requires not macro-only implementation */
239 #undef cfgetospeed
240 #undef cfgetispeed
241 #undef cfsetospeed
242 #undef cfsetispeed
244 /* cfgetospeed: POSIX96 7.1.3.1 */
245 extern "C" speed_t
246 cfgetospeed (const struct termios *tp)
248 return tp->c_ospeed;
251 /* cfgetispeed: POSIX96 7.1.3.1 */
252 extern "C" speed_t
253 cfgetispeed (const struct termios *tp)
255 return tp->c_ispeed;
258 static inline int
259 setspeed (speed_t &set_speed, speed_t from_speed)
261 int res;
262 switch (from_speed)
264 case B0:
265 case B50:
266 case B75:
267 case B110:
268 case B134:
269 case B150:
270 case B200:
271 case B300:
272 case B600:
273 case B1200:
274 case B1800:
275 case B2400:
276 case B4800:
277 case B9600:
278 case B19200:
279 case B38400:
280 case B57600:
281 case B115200:
282 case B128000:
283 case B230400:
284 case B256000:
285 case B460800:
286 case B500000:
287 case B576000:
288 case B921600:
289 case B1000000:
290 case B1152000:
291 case B1500000:
292 case B2000000:
293 case B2500000:
294 case B3000000:
295 set_speed = from_speed;
296 res = 0;
297 break;
298 default:
299 set_errno (EINVAL);
300 res = -1;
301 break;
303 return res;
306 /* cfsetospeed: POSIX96 7.1.3.1 */
307 extern "C" int
308 cfsetospeed (struct termios *tp, speed_t speed)
310 return setspeed (tp->c_ospeed, speed);
313 /* cfsetispeed: POSIX96 7.1.3.1 */
314 extern "C" int
315 cfsetispeed (struct termios *tp, speed_t speed)
317 return setspeed (tp->c_ispeed, speed);
320 struct speed_struct
322 speed_t value;
323 speed_t internal;
326 static const struct speed_struct speeds[] =
328 { 0, B0 },
329 { 50, B50 },
330 { 75, B75 },
331 { 110, B110 },
332 { 134, B134 },
333 { 150, B150 },
334 { 200, B200 },
335 { 300, B300 },
336 { 600, B600 },
337 { 1200, B1200 },
338 { 1800, B1800 },
339 { 2400, B2400 },
340 { 4800, B4800 },
341 { 9600, B9600 },
342 { 19200, B19200 },
343 { 38400, B38400 },
344 { 57600, B57600 },
345 { 115200, B115200 },
346 { 128000, B128000 },
347 { 230400, B230400 },
348 { 256000, B256000 },
349 { 460800, B460800 },
350 { 500000, B500000 },
351 { 576000, B576000 },
352 { 921600, B921600 },
353 { 1000000, B1000000 },
354 { 1152000, B1152000 },
355 { 1500000, B1500000 },
356 { 2000000, B2000000 },
357 { 2500000, B2500000 },
358 { 3000000, B3000000 },
361 /* Given a numerical baud rate (e.g., 9600), convert it to a Bnnn
362 constant (e.g., B9600). */
363 static speed_t
364 convert_speed (speed_t speed)
366 for (size_t i = 0; i < sizeof speeds / sizeof speeds[0]; i++)
368 if (speed == speeds[i].internal)
369 return speed;
370 else if (speed == speeds[i].value)
371 return speeds[i].internal;
373 return speed;
376 /* cfsetspeed: 4.4BSD */
377 /* Following Linux (undocumented), allow speed to be a numerical baud rate. */
378 extern "C" int
379 cfsetspeed (struct termios *tp, speed_t speed)
381 int res;
383 speed = convert_speed (speed);
384 /* errors come only from unsupported baud rates, so setspeed() would return
385 identical results in both calls */
386 if ((res = setspeed (tp->c_ospeed, speed)) == 0)
387 setspeed (tp->c_ispeed, speed);
388 return res;
391 extern "C" void
392 cfmakeraw(struct termios *tp)
394 tp->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
395 | INLCR | IGNCR | ICRNL | IXON);
396 tp->c_oflag &= ~OPOST;
397 tp->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
398 tp->c_cflag &= ~(CSIZE | PARENB);
399 tp->c_cflag |= CS8;