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