• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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*
get_termios_state(PyObject * module)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 *
termios_tcgetattr_impl(PyObject * module,int fd)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     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]
142 termios.tcsetattr
143 
144     fd: fildes
145     when: int
146     attributes as term: object
147     /
148 
149 Set the tty attributes for file descriptor fd.
150 
151 The attributes to be set are taken from the attributes argument, which
152 is a list like the one returned by tcgetattr(). The when argument
153 determines when the attributes are changed: termios.TCSANOW to
154 change immediately, termios.TCSADRAIN to change after transmitting all
155 queued output, or termios.TCSAFLUSH to change after transmitting all
156 queued output and discarding all queued input.
157 [clinic start generated code]*/
158 
159 static PyObject *
termios_tcsetattr_impl(PyObject * module,int fd,int when,PyObject * term)160 termios_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]
221 termios.tcsendbreak
222 
223     fd: fildes
224     duration: int
225     /
226 
227 Send a break on file descriptor fd.
228 
229 A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration
230 has a system dependent meaning.
231 [clinic start generated code]*/
232 
233 static PyObject *
termios_tcsendbreak_impl(PyObject * module,int fd,int duration)234 termios_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]
246 termios.tcdrain
247 
248     fd: fildes
249     /
250 
251 Wait until all output written to file descriptor fd has been transmitted.
252 [clinic start generated code]*/
253 
254 static PyObject *
termios_tcdrain_impl(PyObject * module,int fd)255 termios_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]
267 termios.tcflush
268 
269     fd: fildes
270     queue: int
271     /
272 
273 Discard queued data on file descriptor fd.
274 
275 The queue selector specifies which queue: termios.TCIFLUSH for the input
276 queue, termios.TCOFLUSH for the output queue, or termios.TCIOFLUSH for
277 both queues.
278 [clinic start generated code]*/
279 
280 static PyObject *
termios_tcflush_impl(PyObject * module,int fd,int queue)281 termios_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]
293 termios.tcflow
294 
295     fd: fildes
296     action: int
297     /
298 
299 Suspend or resume input or output on file descriptor fd.
300 
301 The action argument can be termios.TCOOFF to suspend output,
302 termios.TCOON to restart output, termios.TCIOFF to suspend input,
303 or termios.TCION to restart input.
304 [clinic start generated code]*/
305 
306 static PyObject *
termios_tcflow_impl(PyObject * module,int fd,int action)307 termios_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 
318 static 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 
338 static 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 
termiosmodule_traverse(PyObject * m,visitproc visit,void * arg)993 static int termiosmodule_traverse(PyObject *m, visitproc visit, void *arg) {
994     Py_VISIT(get_termios_state(m)->TermiosError);
995     return 0;
996 }
997 
termiosmodule_clear(PyObject * m)998 static int termiosmodule_clear(PyObject *m) {
999     Py_CLEAR(get_termios_state(m)->TermiosError);
1000     return 0;
1001 }
1002 
termiosmodule_free(void * m)1003 static void termiosmodule_free(void *m) {
1004     termiosmodule_clear((PyObject *)m);
1005 }
1006 
1007 static int
termios_exec(PyObject * mod)1008 termios_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 
1032 static PyModuleDef_Slot termios_slots[] = {
1033     {Py_mod_exec, termios_exec},
1034     {0, NULL}
1035 };
1036 
1037 static 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 
PyInit_termios(void)1049 PyMODINIT_FUNC PyInit_termios(void)
1050 {
1051     return PyModuleDef_Init(&termiosmodule);
1052 }
1053