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