1 /* termios.c -- POSIX terminal I/O module implementation. */
2
3 #include "Python.h"
4
5 /* Apparently, on SGI, termios.h won't define CTRL if _XOPEN_SOURCE
6 is defined, so we define it here. */
7 #if defined(__sgi)
8 #define CTRL(c) ((c)&037)
9 #endif
10
11 #if defined(__sun)
12 /* We could do better. Check issue-32660 */
13 #include <sys/filio.h>
14 #include <sys/sockio.h>
15 #endif
16
17 #include <termios.h>
18 #include <sys/ioctl.h>
19
20 /* HP-UX requires that this be included to pick up MDCD, MCTS, MDSR,
21 * MDTR, MRI, and MRTS (apparently used internally by some things
22 * defined as macros; these are not used here directly).
23 */
24 #ifdef HAVE_SYS_MODEM_H
25 #include <sys/modem.h>
26 #endif
27 /* HP-UX requires that this be included to pick up TIOCGPGRP and friends */
28 #ifdef HAVE_SYS_BSDTTY_H
29 #include <sys/bsdtty.h>
30 #endif
31
32 /*[clinic input]
33 module termios
34 [clinic start generated code]*/
35 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=01105c85d0ca7252]*/
36
37 #include "clinic/termios.c.h"
38
39 PyDoc_STRVAR(termios__doc__,
40 "This module provides an interface to the Posix calls for tty I/O control.\n\
41 For a complete description of these calls, see the Posix or Unix manual\n\
42 pages. It is only available for those Unix versions that support Posix\n\
43 termios style tty I/O control.\n\
44 \n\
45 All functions in this module take a file descriptor fd as their first\n\
46 argument. This can be an integer file descriptor, such as returned by\n\
47 sys.stdin.fileno(), or a file object, such as sys.stdin itself.");
48
49 typedef struct {
50 PyObject *TermiosError;
51 } termiosmodulestate;
52
53 static inline termiosmodulestate*
54 get_termios_state(PyObject *module)
55 {
56 void *state = PyModule_GetState(module);
57 assert(state != NULL);
58 return (termiosmodulestate *)state;
59 }
60
61 static struct PyModuleDef termiosmodule;
62
63 /*[clinic input]
64 termios.tcgetattr
65
66 fd: fildes
67 /
68
69 Get the tty attributes for file descriptor fd.
70
71 Returns a list [iflag, oflag, cflag, lflag, ispeed, ospeed, cc]
72 where cc is a list of the tty special characters (each a string of
73 length 1, except the items with indices VMIN and VTIME, which are
74 integers when these fields are defined). The interpretation of the
75 flags and the speeds as well as the indexing in the cc array must be
76 done using the symbolic constants defined in this module.
77 [clinic start generated code]*/
78
79 static PyObject *
80 termios_tcgetattr_impl(PyObject *module, int fd)
81 /*[clinic end generated code: output=2b3da39db870e629 input=54dad9779ebe74b1]*/
82 {
83 termiosmodulestate *state = PyModule_GetState(module);
84 struct termios mode;
85 int r;
86
87 Py_BEGIN_ALLOW_THREADS
88 r = tcgetattr(fd, &mode);
89 Py_END_ALLOW_THREADS
90 if (r == -1) {
91 return PyErr_SetFromErrno(state->TermiosError);
92 }
93
94 speed_t ispeed = cfgetispeed(&mode);
95 speed_t ospeed = cfgetospeed(&mode);
96
97 PyObject *cc = PyList_New(NCCS);
98 if (cc == NULL) {
99 return NULL;
100 }
101
102 PyObject *v;
103 int i;
104 for (i = 0; i < NCCS; i++) {
105 char ch = (char)mode.c_cc[i];
106 v = PyBytes_FromStringAndSize(&ch, 1);
107 if (v == NULL)
108 goto err;
109 PyList_SetItem(cc, i, v);
110 }
111
112 /* Convert the MIN and TIME slots to integer. On some systems, the
113 MIN and TIME slots are the same as the EOF and EOL slots. So we
114 only do this in noncanonical input mode. */
115 if ((mode.c_lflag & ICANON) == 0) {
116 v = PyLong_FromLong((long)mode.c_cc[VMIN]);
117 if (v == NULL)
118 goto err;
119 PyList_SetItem(cc, VMIN, v);
120 v = PyLong_FromLong((long)mode.c_cc[VTIME]);
121 if (v == NULL)
122 goto err;
123 PyList_SetItem(cc, VTIME, v);
124 }
125
126 if (!(v = PyList_New(7)))
127 goto err;
128
129 PyList_SetItem(v, 0, PyLong_FromLong((long)mode.c_iflag));
130 PyList_SetItem(v, 1, PyLong_FromLong((long)mode.c_oflag));
131 PyList_SetItem(v, 2, PyLong_FromLong((long)mode.c_cflag));
132 PyList_SetItem(v, 3, PyLong_FromLong((long)mode.c_lflag));
133 PyList_SetItem(v, 4, PyLong_FromLong((long)ispeed));
134 PyList_SetItem(v, 5, PyLong_FromLong((long)ospeed));
135 if (PyErr_Occurred()) {
136 Py_DECREF(v);
137 goto err;
138 }
139 PyList_SetItem(v, 6, cc);
140 return v;
141 err:
142 Py_DECREF(cc);
143 return NULL;
144 }
145
146 /*[clinic input]
147 termios.tcsetattr
148
149 fd: fildes
150 when: int
151 attributes as term: object
152 /
153
154 Set the tty attributes for file descriptor fd.
155
156 The attributes to be set are taken from the attributes argument, which
157 is a list like the one returned by tcgetattr(). The when argument
158 determines when the attributes are changed: termios.TCSANOW to
159 change immediately, termios.TCSADRAIN to change after transmitting all
160 queued output, or termios.TCSAFLUSH to change after transmitting all
161 queued output and discarding all queued input.
162 [clinic start generated code]*/
163
164 static PyObject *
165 termios_tcsetattr_impl(PyObject *module, int fd, int when, PyObject *term)
166 /*[clinic end generated code: output=bcd2b0a7b98a4bf5 input=5dafabdd5a08f018]*/
167 {
168 if (!PyList_Check(term) || PyList_Size(term) != 7) {
169 PyErr_SetString(PyExc_TypeError,
170 "tcsetattr, arg 3: must be 7 element list");
171 return NULL;
172 }
173
174 /* Get the old mode, in case there are any hidden fields... */
175 termiosmodulestate *state = PyModule_GetState(module);
176 struct termios mode;
177 int r;
178
179 Py_BEGIN_ALLOW_THREADS
180 r = tcgetattr(fd, &mode);
181 Py_END_ALLOW_THREADS
182 if (r == -1) {
183 return PyErr_SetFromErrno(state->TermiosError);
184 }
185
186 speed_t ispeed, ospeed;
187 #define SET_FROM_LIST(TYPE, VAR, LIST, N) do { \
188 PyObject *item = PyList_GET_ITEM(LIST, N); \
189 long num = PyLong_AsLong(item); \
190 if (num == -1 && PyErr_Occurred()) { \
191 return NULL; \
192 } \
193 VAR = (TYPE)num; \
194 } while (0)
195
196 SET_FROM_LIST(tcflag_t, mode.c_iflag, term, 0);
197 SET_FROM_LIST(tcflag_t, mode.c_oflag, term, 1);
198 SET_FROM_LIST(tcflag_t, mode.c_cflag, term, 2);
199 SET_FROM_LIST(tcflag_t, mode.c_lflag, term, 3);
200 SET_FROM_LIST(speed_t, ispeed, term, 4);
201 SET_FROM_LIST(speed_t, ospeed, term, 5);
202 #undef SET_FROM_LIST
203
204 PyObject *cc = PyList_GET_ITEM(term, 6);
205 if (!PyList_Check(cc) || PyList_Size(cc) != NCCS) {
206 PyErr_Format(PyExc_TypeError,
207 "tcsetattr: attributes[6] must be %d element list",
208 NCCS);
209 return NULL;
210 }
211
212 int i;
213 PyObject *v;
214 for (i = 0; i < NCCS; i++) {
215 v = PyList_GetItem(cc, i);
216
217 if (PyBytes_Check(v) && PyBytes_Size(v) == 1)
218 mode.c_cc[i] = (cc_t) * PyBytes_AsString(v);
219 else if (PyLong_Check(v)) {
220 long num = PyLong_AsLong(v);
221 if (num == -1 && PyErr_Occurred()) {
222 return NULL;
223 }
224 mode.c_cc[i] = (cc_t)num;
225 }
226 else {
227 PyErr_SetString(PyExc_TypeError,
228 "tcsetattr: elements of attributes must be characters or integers");
229 return NULL;
230 }
231 }
232
233 if (cfsetispeed(&mode, (speed_t) ispeed) == -1)
234 return PyErr_SetFromErrno(state->TermiosError);
235 if (cfsetospeed(&mode, (speed_t) ospeed) == -1)
236 return PyErr_SetFromErrno(state->TermiosError);
237
238 Py_BEGIN_ALLOW_THREADS
239 r = tcsetattr(fd, when, &mode);
240 Py_END_ALLOW_THREADS
241
242 if (r == -1)
243 return PyErr_SetFromErrno(state->TermiosError);
244
245 Py_RETURN_NONE;
246 }
247
248 /*[clinic input]
249 termios.tcsendbreak
250
251 fd: fildes
252 duration: int
253 /
254
255 Send a break on file descriptor fd.
256
257 A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration
258 has a system dependent meaning.
259 [clinic start generated code]*/
260
261 static PyObject *
262 termios_tcsendbreak_impl(PyObject *module, int fd, int duration)
263 /*[clinic end generated code: output=5945f589b5d3ac66 input=dc2f32417691f8ed]*/
264 {
265 termiosmodulestate *state = PyModule_GetState(module);
266 int r;
267
268 Py_BEGIN_ALLOW_THREADS
269 r = tcsendbreak(fd, duration);
270 Py_END_ALLOW_THREADS
271
272 if (r == -1) {
273 return PyErr_SetFromErrno(state->TermiosError);
274 }
275
276 Py_RETURN_NONE;
277 }
278
279 /*[clinic input]
280 termios.tcdrain
281
282 fd: fildes
283 /
284
285 Wait until all output written to file descriptor fd has been transmitted.
286 [clinic start generated code]*/
287
288 static PyObject *
289 termios_tcdrain_impl(PyObject *module, int fd)
290 /*[clinic end generated code: output=5fd86944c6255955 input=c99241b140b32447]*/
291 {
292 termiosmodulestate *state = PyModule_GetState(module);
293 int r;
294
295 Py_BEGIN_ALLOW_THREADS
296 r = tcdrain(fd);
297 Py_END_ALLOW_THREADS
298
299 if (r == -1) {
300 return PyErr_SetFromErrno(state->TermiosError);
301 }
302
303 Py_RETURN_NONE;
304 }
305
306 /*[clinic input]
307 termios.tcflush
308
309 fd: fildes
310 queue: int
311 /
312
313 Discard queued data on file descriptor fd.
314
315 The queue selector specifies which queue: termios.TCIFLUSH for the input
316 queue, termios.TCOFLUSH for the output queue, or termios.TCIOFLUSH for
317 both queues.
318 [clinic start generated code]*/
319
320 static PyObject *
321 termios_tcflush_impl(PyObject *module, int fd, int queue)
322 /*[clinic end generated code: output=2424f80312ec2f21 input=0f7d08122ddc07b5]*/
323 {
324 termiosmodulestate *state = PyModule_GetState(module);
325 int r;
326
327 Py_BEGIN_ALLOW_THREADS
328 r = tcflush(fd, queue);
329 Py_END_ALLOW_THREADS
330
331 if (r == -1) {
332 return PyErr_SetFromErrno(state->TermiosError);
333 }
334
335 Py_RETURN_NONE;
336 }
337
338 /*[clinic input]
339 termios.tcflow
340
341 fd: fildes
342 action: int
343 /
344
345 Suspend or resume input or output on file descriptor fd.
346
347 The action argument can be termios.TCOOFF to suspend output,
348 termios.TCOON to restart output, termios.TCIOFF to suspend input,
349 or termios.TCION to restart input.
350 [clinic start generated code]*/
351
352 static PyObject *
353 termios_tcflow_impl(PyObject *module, int fd, int action)
354 /*[clinic end generated code: output=afd10928e6ea66eb input=c6aff0640b6efd9c]*/
355 {
356 termiosmodulestate *state = PyModule_GetState(module);
357 int r;
358
359 Py_BEGIN_ALLOW_THREADS
360 r = tcflow(fd, action);
361 Py_END_ALLOW_THREADS
362
363 if (r == -1) {
364 return PyErr_SetFromErrno(state->TermiosError);
365 }
366
367 Py_RETURN_NONE;
368 }
369
370 /*[clinic input]
371 termios.tcgetwinsize
372
373 fd: fildes
374 /
375
376 Get the tty winsize for file descriptor fd.
377
378 Returns a tuple (ws_row, ws_col).
379 [clinic start generated code]*/
380
381 static PyObject *
382 termios_tcgetwinsize_impl(PyObject *module, int fd)
383 /*[clinic end generated code: output=31825977d5325fb6 input=5706c379d7fd984d]*/
384 {
385 #if defined(TIOCGWINSZ)
386 termiosmodulestate *state = PyModule_GetState(module);
387 struct winsize w;
388 int r;
389
390 Py_BEGIN_ALLOW_THREADS
391 r = ioctl(fd, TIOCGWINSZ, &w);
392 Py_END_ALLOW_THREADS
393
394 if (r == -1) {
395 return PyErr_SetFromErrno(state->TermiosError);
396 }
397
398 PyObject *v;
399 if (!(v = PyTuple_New(2))) {
400 return NULL;
401 }
402
403 PyTuple_SetItem(v, 0, PyLong_FromLong((long)w.ws_row));
404 PyTuple_SetItem(v, 1, PyLong_FromLong((long)w.ws_col));
405 if (PyErr_Occurred()) {
406 Py_DECREF(v);
407 return NULL;
408 }
409 return v;
410 #elif defined(TIOCGSIZE)
411 termiosmodulestate *state = PyModule_GetState(module);
412 struct ttysize s;
413 int r;
414
415 Py_BEGIN_ALLOW_THREADS
416 r = ioctl(fd, TIOCGSIZE, &s);
417 Py_END_ALLOW_THREADS
418 if (r == -1) {
419 return PyErr_SetFromErrno(state->TermiosError);
420 }
421
422 PyObject *v;
423 if (!(v = PyTuple_New(2))) {
424 return NULL;
425 }
426
427 PyTuple_SetItem(v, 0, PyLong_FromLong((long)s.ts_lines));
428 PyTuple_SetItem(v, 1, PyLong_FromLong((long)s.ts_cols));
429 if (PyErr_Occurred()) {
430 Py_DECREF(v);
431 return NULL;
432 }
433 return v;
434 #else
435 PyErr_SetString(PyExc_NotImplementedError,
436 "requires termios.TIOCGWINSZ and/or termios.TIOCGSIZE");
437 return NULL;
438 #endif /* defined(TIOCGWINSZ) */
439 }
440
441 /*[clinic input]
442 termios.tcsetwinsize
443
444 fd: fildes
445 winsize as winsz: object
446 /
447
448 Set the tty winsize for file descriptor fd.
449
450 The winsize to be set is taken from the winsize argument, which
451 is a two-item tuple (ws_row, ws_col) like the one returned by tcgetwinsize().
452 [clinic start generated code]*/
453
454 static PyObject *
455 termios_tcsetwinsize_impl(PyObject *module, int fd, PyObject *winsz)
456 /*[clinic end generated code: output=2ac3c9bb6eda83e1 input=4a06424465b24aee]*/
457 {
458 if (!PySequence_Check(winsz) || PySequence_Size(winsz) != 2) {
459 PyErr_SetString(PyExc_TypeError,
460 "tcsetwinsize, arg 2: must be a two-item sequence");
461 return NULL;
462 }
463
464 PyObject *tmp_item;
465 long winsz_0, winsz_1;
466 tmp_item = PySequence_GetItem(winsz, 0);
467 winsz_0 = PyLong_AsLong(tmp_item);
468 if (winsz_0 == -1 && PyErr_Occurred()) {
469 Py_XDECREF(tmp_item);
470 return NULL;
471 }
472 Py_XDECREF(tmp_item);
473 tmp_item = PySequence_GetItem(winsz, 1);
474 winsz_1 = PyLong_AsLong(tmp_item);
475 if (winsz_1 == -1 && PyErr_Occurred()) {
476 Py_XDECREF(tmp_item);
477 return NULL;
478 }
479 Py_XDECREF(tmp_item);
480
481 termiosmodulestate *state = PyModule_GetState(module);
482
483 #if defined(TIOCGWINSZ) && defined(TIOCSWINSZ)
484 struct winsize w;
485 /* Get the old winsize because it might have
486 more fields such as xpixel, ypixel. */
487 if (ioctl(fd, TIOCGWINSZ, &w) == -1) {
488 return PyErr_SetFromErrno(state->TermiosError);
489 }
490
491 w.ws_row = (unsigned short) winsz_0;
492 w.ws_col = (unsigned short) winsz_1;
493 if ((((long)w.ws_row) != winsz_0) || (((long)w.ws_col) != winsz_1)) {
494 PyErr_SetString(PyExc_OverflowError,
495 "winsize value(s) out of range.");
496 return NULL;
497 }
498
499 int r;
500 Py_BEGIN_ALLOW_THREADS
501 r = ioctl(fd, TIOCSWINSZ, &w);
502 Py_END_ALLOW_THREADS
503
504 if (r == -1) {
505 return PyErr_SetFromErrno(state->TermiosError);
506 }
507
508 Py_RETURN_NONE;
509 #elif defined(TIOCGSIZE) && defined(TIOCSSIZE)
510 struct ttysize s;
511 int r;
512 /* Get the old ttysize because it might have more fields. */
513 Py_BEGIN_ALLOW_THREADS
514 r = ioctl(fd, TIOCGSIZE, &s);
515 Py_END_ALLOW_THREADS
516
517 if (r == -1) {
518 return PyErr_SetFromErrno(state->TermiosError);
519 }
520
521 s.ts_lines = (int) winsz_0;
522 s.ts_cols = (int) winsz_1;
523 if ((((long)s.ts_lines) != winsz_0) || (((long)s.ts_cols) != winsz_1)) {
524 PyErr_SetString(PyExc_OverflowError,
525 "winsize value(s) out of range.");
526 return NULL;
527 }
528
529 Py_BEGIN_ALLOW_THREADS
530 r = ioctl(fd, TIOCSSIZE, &s);
531 Py_END_ALLOW_THREADS
532
533 if (r == -1) {
534 return PyErr_SetFromErrno(state->TermiosError);
535 }
536
537 Py_RETURN_NONE;
538 #else
539 PyErr_SetString(PyExc_NotImplementedError,
540 "requires termios.TIOCGWINSZ, termios.TIOCSWINSZ and/or termios.TIOCGSIZE, termios.TIOCSSIZE");
541 return NULL;
542 #endif /* defined(TIOCGWINSZ) && defined(TIOCSWINSZ) */
543 }
544
545 static PyMethodDef termios_methods[] =
546 {
547 TERMIOS_TCGETATTR_METHODDEF
548 TERMIOS_TCSETATTR_METHODDEF
549 TERMIOS_TCSENDBREAK_METHODDEF
550 TERMIOS_TCDRAIN_METHODDEF
551 TERMIOS_TCFLUSH_METHODDEF
552 TERMIOS_TCFLOW_METHODDEF
553 TERMIOS_TCGETWINSIZE_METHODDEF
554 TERMIOS_TCSETWINSIZE_METHODDEF
555 {NULL, NULL}
556 };
557
558
559 #if defined(VSWTCH) && !defined(VSWTC)
560 #define VSWTC VSWTCH
561 #endif
562
563 #if defined(VSWTC) && !defined(VSWTCH)
564 #define VSWTCH VSWTC
565 #endif
566
567 static struct constant {
568 char *name;
569 long value;
570 } termios_constants[] = {
571 /* cfgetospeed(), cfsetospeed() constants */
572 {"B0", B0},
573 {"B50", B50},
574 {"B75", B75},
575 {"B110", B110},
576 {"B134", B134},
577 {"B150", B150},
578 {"B200", B200},
579 {"B300", B300},
580 {"B600", B600},
581 {"B1200", B1200},
582 {"B1800", B1800},
583 {"B2400", B2400},
584 {"B4800", B4800},
585 {"B9600", B9600},
586 {"B19200", B19200},
587 {"B38400", B38400},
588 #ifdef B57600
589 {"B57600", B57600},
590 #endif
591 #ifdef B115200
592 {"B115200", B115200},
593 #endif
594 #ifdef B230400
595 {"B230400", B230400},
596 #endif
597 #ifdef B460800
598 {"B460800", B460800},
599 #endif
600 #ifdef B500000
601 {"B500000", B500000},
602 #endif
603 #ifdef B576000
604 {"B576000", B576000},
605 #endif
606 #ifdef B921600
607 {"B921600", B921600},
608 #endif
609 #ifdef B1000000
610 {"B1000000", B1000000},
611 #endif
612 #ifdef B1152000
613 {"B1152000", B1152000},
614 #endif
615 #ifdef B1500000
616 {"B1500000", B1500000},
617 #endif
618 #ifdef B2000000
619 {"B2000000", B2000000},
620 #endif
621 #ifdef B2500000
622 {"B2500000", B2500000},
623 #endif
624 #ifdef B3000000
625 {"B3000000", B3000000},
626 #endif
627 #ifdef B3500000
628 {"B3500000", B3500000},
629 #endif
630 #ifdef B4000000
631 {"B4000000", B4000000},
632 #endif
633
634 #ifdef CBAUDEX
635 {"CBAUDEX", CBAUDEX},
636 #endif
637
638 /* tcsetattr() constants */
639 {"TCSANOW", TCSANOW},
640 {"TCSADRAIN", TCSADRAIN},
641 {"TCSAFLUSH", TCSAFLUSH},
642 #ifdef TCSASOFT
643 {"TCSASOFT", TCSASOFT},
644 #endif
645
646 /* tcflush() constants */
647 {"TCIFLUSH", TCIFLUSH},
648 {"TCOFLUSH", TCOFLUSH},
649 {"TCIOFLUSH", TCIOFLUSH},
650
651 /* tcflow() constants */
652 {"TCOOFF", TCOOFF},
653 {"TCOON", TCOON},
654 {"TCIOFF", TCIOFF},
655 {"TCION", TCION},
656
657 /* struct termios.c_iflag constants */
658 {"IGNBRK", IGNBRK},
659 {"BRKINT", BRKINT},
660 {"IGNPAR", IGNPAR},
661 {"PARMRK", PARMRK},
662 {"INPCK", INPCK},
663 {"ISTRIP", ISTRIP},
664 {"INLCR", INLCR},
665 {"IGNCR", IGNCR},
666 {"ICRNL", ICRNL},
667 #ifdef IUCLC
668 {"IUCLC", IUCLC},
669 #endif
670 {"IXON", IXON},
671 {"IXANY", IXANY},
672 {"IXOFF", IXOFF},
673 #ifdef IMAXBEL
674 {"IMAXBEL", IMAXBEL},
675 #endif
676
677 /* struct termios.c_oflag constants */
678 {"OPOST", OPOST},
679 #ifdef OLCUC
680 {"OLCUC", OLCUC},
681 #endif
682 #ifdef ONLCR
683 {"ONLCR", ONLCR},
684 #endif
685 #ifdef OCRNL
686 {"OCRNL", OCRNL},
687 #endif
688 #ifdef ONOCR
689 {"ONOCR", ONOCR},
690 #endif
691 #ifdef ONLRET
692 {"ONLRET", ONLRET},
693 #endif
694 #ifdef OFILL
695 {"OFILL", OFILL},
696 #endif
697 #ifdef OFDEL
698 {"OFDEL", OFDEL},
699 #endif
700 #ifdef NLDLY
701 {"NLDLY", NLDLY},
702 #endif
703 #ifdef CRDLY
704 {"CRDLY", CRDLY},
705 #endif
706 #ifdef TABDLY
707 {"TABDLY", TABDLY},
708 #endif
709 #ifdef BSDLY
710 {"BSDLY", BSDLY},
711 #endif
712 #ifdef VTDLY
713 {"VTDLY", VTDLY},
714 #endif
715 #ifdef FFDLY
716 {"FFDLY", FFDLY},
717 #endif
718
719 /* struct termios.c_oflag-related values (delay mask) */
720 #ifdef NL0
721 {"NL0", NL0},
722 #endif
723 #ifdef NL1
724 {"NL1", NL1},
725 #endif
726 #ifdef CR0
727 {"CR0", CR0},
728 #endif
729 #ifdef CR1
730 {"CR1", CR1},
731 #endif
732 #ifdef CR2
733 {"CR2", CR2},
734 #endif
735 #ifdef CR3
736 {"CR3", CR3},
737 #endif
738 #ifdef TAB0
739 {"TAB0", TAB0},
740 #endif
741 #ifdef TAB1
742 {"TAB1", TAB1},
743 #endif
744 #ifdef TAB2
745 {"TAB2", TAB2},
746 #endif
747 #ifdef TAB3
748 {"TAB3", TAB3},
749 #endif
750 #ifdef XTABS
751 {"XTABS", XTABS},
752 #endif
753 #ifdef BS0
754 {"BS0", BS0},
755 #endif
756 #ifdef BS1
757 {"BS1", BS1},
758 #endif
759 #ifdef VT0
760 {"VT0", VT0},
761 #endif
762 #ifdef VT1
763 {"VT1", VT1},
764 #endif
765 #ifdef FF0
766 {"FF0", FF0},
767 #endif
768 #ifdef FF1
769 {"FF1", FF1},
770 #endif
771
772 /* struct termios.c_cflag constants */
773 {"CSIZE", CSIZE},
774 {"CSTOPB", CSTOPB},
775 {"CREAD", CREAD},
776 {"PARENB", PARENB},
777 {"PARODD", PARODD},
778 {"HUPCL", HUPCL},
779 {"CLOCAL", CLOCAL},
780 #ifdef CIBAUD
781 {"CIBAUD", CIBAUD},
782 #endif
783 #ifdef CRTSCTS
784 {"CRTSCTS", (long)CRTSCTS},
785 #endif
786
787 /* struct termios.c_cflag-related values (character size) */
788 {"CS5", CS5},
789 {"CS6", CS6},
790 {"CS7", CS7},
791 {"CS8", CS8},
792
793 /* struct termios.c_lflag constants */
794 {"ISIG", ISIG},
795 {"ICANON", ICANON},
796 #ifdef XCASE
797 {"XCASE", XCASE},
798 #endif
799 {"ECHO", ECHO},
800 {"ECHOE", ECHOE},
801 {"ECHOK", ECHOK},
802 {"ECHONL", ECHONL},
803 #ifdef ECHOCTL
804 {"ECHOCTL", ECHOCTL},
805 #endif
806 #ifdef ECHOPRT
807 {"ECHOPRT", ECHOPRT},
808 #endif
809 #ifdef ECHOKE
810 {"ECHOKE", ECHOKE},
811 #endif
812 #ifdef FLUSHO
813 {"FLUSHO", FLUSHO},
814 #endif
815 {"NOFLSH", NOFLSH},
816 {"TOSTOP", TOSTOP},
817 #ifdef PENDIN
818 {"PENDIN", PENDIN},
819 #endif
820 {"IEXTEN", IEXTEN},
821
822 /* indexes into the control chars array returned by tcgetattr() */
823 {"VINTR", VINTR},
824 {"VQUIT", VQUIT},
825 {"VERASE", VERASE},
826 {"VKILL", VKILL},
827 {"VEOF", VEOF},
828 {"VTIME", VTIME},
829 {"VMIN", VMIN},
830 #ifdef VSWTC
831 /* The #defines above ensure that if either is defined, both are,
832 * but both may be omitted by the system headers. ;-( */
833 {"VSWTC", VSWTC},
834 {"VSWTCH", VSWTCH},
835 #endif
836 {"VSTART", VSTART},
837 {"VSTOP", VSTOP},
838 {"VSUSP", VSUSP},
839 {"VEOL", VEOL},
840 #ifdef VREPRINT
841 {"VREPRINT", VREPRINT},
842 #endif
843 #ifdef VDISCARD
844 {"VDISCARD", VDISCARD},
845 #endif
846 #ifdef VWERASE
847 {"VWERASE", VWERASE},
848 #endif
849 #ifdef VLNEXT
850 {"VLNEXT", VLNEXT},
851 #endif
852 #ifdef VEOL2
853 {"VEOL2", VEOL2},
854 #endif
855
856
857 #ifdef B460800
858 {"B460800", B460800},
859 #endif
860 #ifdef B500000
861 {"B500000", B500000},
862 #endif
863 #ifdef B576000
864 { "B576000", B576000},
865 #endif
866 #ifdef B921600
867 { "B921600", B921600},
868 #endif
869 #ifdef B1000000
870 { "B1000000", B1000000},
871 #endif
872 #ifdef B1152000
873 { "B1152000", B1152000},
874 #endif
875 #ifdef B1500000
876 { "B1500000", B1500000},
877 #endif
878 #ifdef B2000000
879 { "B2000000", B2000000},
880 #endif
881 #ifdef B2500000
882 { "B2500000", B2500000},
883 #endif
884 #ifdef B3000000
885 { "B3000000", B3000000},
886 #endif
887 #ifdef B3500000
888 { "B3500000", B3500000},
889 #endif
890 #ifdef B4000000
891 { "B4000000", B4000000},
892 #endif
893 #ifdef CBAUD
894 {"CBAUD", CBAUD},
895 #endif
896 #ifdef CDEL
897 {"CDEL", CDEL},
898 #endif
899 #ifdef CDSUSP
900 {"CDSUSP", CDSUSP},
901 #endif
902 #ifdef CEOF
903 {"CEOF", CEOF},
904 #endif
905 #ifdef CEOL
906 {"CEOL", CEOL},
907 #endif
908 #ifdef CEOL2
909 {"CEOL2", CEOL2},
910 #endif
911 #ifdef CEOT
912 {"CEOT", CEOT},
913 #endif
914 #ifdef CERASE
915 {"CERASE", CERASE},
916 #endif
917 #ifdef CESC
918 {"CESC", CESC},
919 #endif
920 #ifdef CFLUSH
921 {"CFLUSH", CFLUSH},
922 #endif
923 #ifdef CINTR
924 {"CINTR", CINTR},
925 #endif
926 #ifdef CKILL
927 {"CKILL", CKILL},
928 #endif
929 #ifdef CLNEXT
930 {"CLNEXT", CLNEXT},
931 #endif
932 #ifdef CNUL
933 {"CNUL", CNUL},
934 #endif
935 #ifdef COMMON
936 {"COMMON", COMMON},
937 #endif
938 #ifdef CQUIT
939 {"CQUIT", CQUIT},
940 #endif
941 #ifdef CRPRNT
942 {"CRPRNT", CRPRNT},
943 #endif
944 #ifdef CSTART
945 {"CSTART", CSTART},
946 #endif
947 #ifdef CSTOP
948 {"CSTOP", CSTOP},
949 #endif
950 #ifdef CSUSP
951 {"CSUSP", CSUSP},
952 #endif
953 #ifdef CSWTCH
954 {"CSWTCH", CSWTCH},
955 #endif
956 #ifdef CWERASE
957 {"CWERASE", CWERASE},
958 #endif
959 #ifdef EXTA
960 {"EXTA", EXTA},
961 #endif
962 #ifdef EXTB
963 {"EXTB", EXTB},
964 #endif
965 #ifdef FIOASYNC
966 {"FIOASYNC", FIOASYNC},
967 #endif
968 #ifdef FIOCLEX
969 {"FIOCLEX", FIOCLEX},
970 #endif
971 #ifdef FIONBIO
972 {"FIONBIO", FIONBIO},
973 #endif
974 #ifdef FIONCLEX
975 {"FIONCLEX", FIONCLEX},
976 #endif
977 #ifdef FIONREAD
978 {"FIONREAD", FIONREAD},
979 #endif
980 #ifdef IBSHIFT
981 {"IBSHIFT", IBSHIFT},
982 #endif
983 #ifdef INIT_C_CC
984 {"INIT_C_CC", INIT_C_CC},
985 #endif
986 #ifdef IOCSIZE_MASK
987 {"IOCSIZE_MASK", IOCSIZE_MASK},
988 #endif
989 #ifdef IOCSIZE_SHIFT
990 {"IOCSIZE_SHIFT", IOCSIZE_SHIFT},
991 #endif
992 #ifdef NCC
993 {"NCC", NCC},
994 #endif
995 #ifdef NCCS
996 {"NCCS", NCCS},
997 #endif
998 #ifdef NSWTCH
999 {"NSWTCH", NSWTCH},
1000 #endif
1001 #ifdef N_MOUSE
1002 {"N_MOUSE", N_MOUSE},
1003 #endif
1004 #ifdef N_PPP
1005 {"N_PPP", N_PPP},
1006 #endif
1007 #ifdef N_SLIP
1008 {"N_SLIP", N_SLIP},
1009 #endif
1010 #ifdef N_STRIP
1011 {"N_STRIP", N_STRIP},
1012 #endif
1013 #ifdef N_TTY
1014 {"N_TTY", N_TTY},
1015 #endif
1016 #ifdef TCFLSH
1017 {"TCFLSH", TCFLSH},
1018 #endif
1019 #ifdef TCGETA
1020 {"TCGETA", TCGETA},
1021 #endif
1022 #ifdef TCGETS
1023 {"TCGETS", TCGETS},
1024 #endif
1025 #ifdef TCSBRK
1026 {"TCSBRK", TCSBRK},
1027 #endif
1028 #ifdef TCSBRKP
1029 {"TCSBRKP", TCSBRKP},
1030 #endif
1031 #ifdef TCSETA
1032 {"TCSETA", TCSETA},
1033 #endif
1034 #ifdef TCSETAF
1035 {"TCSETAF", TCSETAF},
1036 #endif
1037 #ifdef TCSETAW
1038 {"TCSETAW", TCSETAW},
1039 #endif
1040 #ifdef TCSETS
1041 {"TCSETS", TCSETS},
1042 #endif
1043 #ifdef TCSETSF
1044 {"TCSETSF", TCSETSF},
1045 #endif
1046 #ifdef TCSETSW
1047 {"TCSETSW", TCSETSW},
1048 #endif
1049 #ifdef TCXONC
1050 {"TCXONC", TCXONC},
1051 #endif
1052 #ifdef TIOCCONS
1053 {"TIOCCONS", TIOCCONS},
1054 #endif
1055 #ifdef TIOCEXCL
1056 {"TIOCEXCL", TIOCEXCL},
1057 #endif
1058 #ifdef TIOCGETD
1059 {"TIOCGETD", TIOCGETD},
1060 #endif
1061 #ifdef TIOCGICOUNT
1062 {"TIOCGICOUNT", TIOCGICOUNT},
1063 #endif
1064 #ifdef TIOCGLCKTRMIOS
1065 {"TIOCGLCKTRMIOS", TIOCGLCKTRMIOS},
1066 #endif
1067 #ifdef TIOCGPGRP
1068 {"TIOCGPGRP", TIOCGPGRP},
1069 #endif
1070 #ifdef TIOCGSERIAL
1071 {"TIOCGSERIAL", TIOCGSERIAL},
1072 #endif
1073 #ifdef TIOCGSIZE
1074 {"TIOCGSIZE", TIOCGSIZE},
1075 #endif
1076 #ifdef TIOCGSOFTCAR
1077 {"TIOCGSOFTCAR", TIOCGSOFTCAR},
1078 #endif
1079 #ifdef TIOCGWINSZ
1080 {"TIOCGWINSZ", TIOCGWINSZ},
1081 #endif
1082 #ifdef TIOCINQ
1083 {"TIOCINQ", TIOCINQ},
1084 #endif
1085 #ifdef TIOCLINUX
1086 {"TIOCLINUX", TIOCLINUX},
1087 #endif
1088 #ifdef TIOCMBIC
1089 {"TIOCMBIC", TIOCMBIC},
1090 #endif
1091 #ifdef TIOCMBIS
1092 {"TIOCMBIS", TIOCMBIS},
1093 #endif
1094 #ifdef TIOCMGET
1095 {"TIOCMGET", TIOCMGET},
1096 #endif
1097 #ifdef TIOCMIWAIT
1098 {"TIOCMIWAIT", TIOCMIWAIT},
1099 #endif
1100 #ifdef TIOCMSET
1101 {"TIOCMSET", TIOCMSET},
1102 #endif
1103 #ifdef TIOCM_CAR
1104 {"TIOCM_CAR", TIOCM_CAR},
1105 #endif
1106 #ifdef TIOCM_CD
1107 {"TIOCM_CD", TIOCM_CD},
1108 #endif
1109 #ifdef TIOCM_CTS
1110 {"TIOCM_CTS", TIOCM_CTS},
1111 #endif
1112 #ifdef TIOCM_DSR
1113 {"TIOCM_DSR", TIOCM_DSR},
1114 #endif
1115 #ifdef TIOCM_DTR
1116 {"TIOCM_DTR", TIOCM_DTR},
1117 #endif
1118 #ifdef TIOCM_LE
1119 {"TIOCM_LE", TIOCM_LE},
1120 #endif
1121 #ifdef TIOCM_RI
1122 {"TIOCM_RI", TIOCM_RI},
1123 #endif
1124 #ifdef TIOCM_RNG
1125 {"TIOCM_RNG", TIOCM_RNG},
1126 #endif
1127 #ifdef TIOCM_RTS
1128 {"TIOCM_RTS", TIOCM_RTS},
1129 #endif
1130 #ifdef TIOCM_SR
1131 {"TIOCM_SR", TIOCM_SR},
1132 #endif
1133 #ifdef TIOCM_ST
1134 {"TIOCM_ST", TIOCM_ST},
1135 #endif
1136 #ifdef TIOCNOTTY
1137 {"TIOCNOTTY", TIOCNOTTY},
1138 #endif
1139 #ifdef TIOCNXCL
1140 {"TIOCNXCL", TIOCNXCL},
1141 #endif
1142 #ifdef TIOCOUTQ
1143 {"TIOCOUTQ", TIOCOUTQ},
1144 #endif
1145 #ifdef TIOCPKT
1146 {"TIOCPKT", TIOCPKT},
1147 #endif
1148 #ifdef TIOCPKT_DATA
1149 {"TIOCPKT_DATA", TIOCPKT_DATA},
1150 #endif
1151 #ifdef TIOCPKT_DOSTOP
1152 {"TIOCPKT_DOSTOP", TIOCPKT_DOSTOP},
1153 #endif
1154 #ifdef TIOCPKT_FLUSHREAD
1155 {"TIOCPKT_FLUSHREAD", TIOCPKT_FLUSHREAD},
1156 #endif
1157 #ifdef TIOCPKT_FLUSHWRITE
1158 {"TIOCPKT_FLUSHWRITE", TIOCPKT_FLUSHWRITE},
1159 #endif
1160 #ifdef TIOCPKT_NOSTOP
1161 {"TIOCPKT_NOSTOP", TIOCPKT_NOSTOP},
1162 #endif
1163 #ifdef TIOCPKT_START
1164 {"TIOCPKT_START", TIOCPKT_START},
1165 #endif
1166 #ifdef TIOCPKT_STOP
1167 {"TIOCPKT_STOP", TIOCPKT_STOP},
1168 #endif
1169 #ifdef TIOCSCTTY
1170 {"TIOCSCTTY", TIOCSCTTY},
1171 #endif
1172 #ifdef TIOCSERCONFIG
1173 {"TIOCSERCONFIG", TIOCSERCONFIG},
1174 #endif
1175 #ifdef TIOCSERGETLSR
1176 {"TIOCSERGETLSR", TIOCSERGETLSR},
1177 #endif
1178 #ifdef TIOCSERGETMULTI
1179 {"TIOCSERGETMULTI", TIOCSERGETMULTI},
1180 #endif
1181 #ifdef TIOCSERGSTRUCT
1182 {"TIOCSERGSTRUCT", TIOCSERGSTRUCT},
1183 #endif
1184 #ifdef TIOCSERGWILD
1185 {"TIOCSERGWILD", TIOCSERGWILD},
1186 #endif
1187 #ifdef TIOCSERSETMULTI
1188 {"TIOCSERSETMULTI", TIOCSERSETMULTI},
1189 #endif
1190 #ifdef TIOCSERSWILD
1191 {"TIOCSERSWILD", TIOCSERSWILD},
1192 #endif
1193 #ifdef TIOCSER_TEMT
1194 {"TIOCSER_TEMT", TIOCSER_TEMT},
1195 #endif
1196 #ifdef TIOCSETD
1197 {"TIOCSETD", TIOCSETD},
1198 #endif
1199 #ifdef TIOCSLCKTRMIOS
1200 {"TIOCSLCKTRMIOS", TIOCSLCKTRMIOS},
1201 #endif
1202 #ifdef TIOCSPGRP
1203 {"TIOCSPGRP", TIOCSPGRP},
1204 #endif
1205 #ifdef TIOCSSERIAL
1206 {"TIOCSSERIAL", TIOCSSERIAL},
1207 #endif
1208 #ifdef TIOCSSIZE
1209 {"TIOCSSIZE", TIOCSSIZE},
1210 #endif
1211 #ifdef TIOCSSOFTCAR
1212 {"TIOCSSOFTCAR", TIOCSSOFTCAR},
1213 #endif
1214 #ifdef TIOCSTI
1215 {"TIOCSTI", TIOCSTI},
1216 #endif
1217 #ifdef TIOCSWINSZ
1218 {"TIOCSWINSZ", TIOCSWINSZ},
1219 #endif
1220 #ifdef TIOCTTYGSTRUCT
1221 {"TIOCTTYGSTRUCT", TIOCTTYGSTRUCT},
1222 #endif
1223
1224 /* sentinel */
1225 {NULL, 0}
1226 };
1227
1228 static int termiosmodule_traverse(PyObject *m, visitproc visit, void *arg) {
1229 Py_VISIT(get_termios_state(m)->TermiosError);
1230 return 0;
1231 }
1232
1233 static int termiosmodule_clear(PyObject *m) {
1234 Py_CLEAR(get_termios_state(m)->TermiosError);
1235 return 0;
1236 }
1237
1238 static void termiosmodule_free(void *m) {
1239 termiosmodule_clear((PyObject *)m);
1240 }
1241
1242 static int
1243 termios_exec(PyObject *mod)
1244 {
1245 struct constant *constant = termios_constants;
1246 termiosmodulestate *state = get_termios_state(mod);
1247 state->TermiosError = PyErr_NewException("termios.error", NULL, NULL);
1248 if (state->TermiosError == NULL) {
1249 return -1;
1250 }
1251 Py_INCREF(state->TermiosError);
1252 if (PyModule_AddObject(mod, "error", state->TermiosError) < 0) {
1253 Py_DECREF(state->TermiosError);
1254 return -1;
1255 }
1256
1257 while (constant->name != NULL) {
1258 if (PyModule_AddIntConstant(
1259 mod, constant->name, constant->value) < 0) {
1260 return -1;
1261 }
1262 ++constant;
1263 }
1264 return 0;
1265 }
1266
1267 static PyModuleDef_Slot termios_slots[] = {
1268 {Py_mod_exec, termios_exec},
1269 {0, NULL}
1270 };
1271
1272 static struct PyModuleDef termiosmodule = {
1273 PyModuleDef_HEAD_INIT,
1274 .m_name = "termios",
1275 .m_doc = termios__doc__,
1276 .m_size = sizeof(termiosmodulestate),
1277 .m_methods = termios_methods,
1278 .m_slots = termios_slots,
1279 .m_traverse = termiosmodule_traverse,
1280 .m_clear = termiosmodule_clear,
1281 .m_free = termiosmodule_free,
1282 };
1283
1284 PyMODINIT_FUNC PyInit_termios(void)
1285 {
1286 return PyModuleDef_Init(&termiosmodule);
1287 }