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