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