Python-2.7.3/Modules/termios.c

No issues found

  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 
 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 *
 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 *
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 (PyInt_Check(v))
189             mode.c_cc[i] = (cc_t) PyInt_AsLong(v);
190         else {
191             PyErr_SetString(PyExc_TypeError,
192      "tcsetattr: elements of attributes must be characters or integers");
193                         return NULL;
194                 }
195     }
196 
197     if (cfsetispeed(&mode, (speed_t) ispeed) == -1)
198         return PyErr_SetFromErrno(TermiosError);
199     if (cfsetospeed(&mode, (speed_t) ospeed) == -1)
200         return PyErr_SetFromErrno(TermiosError);
201     if (tcsetattr(fd, when, &mode) == -1)
202         return PyErr_SetFromErrno(TermiosError);
203 
204     Py_INCREF(Py_None);
205     return Py_None;
206 }
207 
208 PyDoc_STRVAR(termios_tcsendbreak__doc__,
209 "tcsendbreak(fd, duration) -> None\n\
210 \n\
211 Send a break on file descriptor fd.\n\
212 A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration\n\
213 has a system dependent meaning.");
214 
215 static PyObject *
216 termios_tcsendbreak(PyObject *self, PyObject *args)
217 {
218     int fd, duration;
219 
220     if (!PyArg_ParseTuple(args, "O&i:tcsendbreak",
221                           fdconv, &fd, &duration))
222         return NULL;
223     if (tcsendbreak(fd, duration) == -1)
224         return PyErr_SetFromErrno(TermiosError);
225 
226     Py_INCREF(Py_None);
227     return Py_None;
228 }
229 
230 PyDoc_STRVAR(termios_tcdrain__doc__,
231 "tcdrain(fd) -> None\n\
232 \n\
233 Wait until all output written to file descriptor fd has been transmitted.");
234 
235 static PyObject *
236 termios_tcdrain(PyObject *self, PyObject *args)
237 {
238     int fd;
239 
240     if (!PyArg_ParseTuple(args, "O&:tcdrain",
241                           fdconv, &fd))
242         return NULL;
243     if (tcdrain(fd) == -1)
244         return PyErr_SetFromErrno(TermiosError);
245 
246     Py_INCREF(Py_None);
247     return Py_None;
248 }
249 
250 PyDoc_STRVAR(termios_tcflush__doc__,
251 "tcflush(fd, queue) -> None\n\
252 \n\
253 Discard queued data on file descriptor fd.\n\
254 The queue selector specifies which queue: termios.TCIFLUSH for the input\n\
255 queue, termios.TCOFLUSH for the output queue, or termios.TCIOFLUSH for\n\
256 both queues. ");
257 
258 static PyObject *
259 termios_tcflush(PyObject *self, PyObject *args)
260 {
261     int fd, queue;
262 
263     if (!PyArg_ParseTuple(args, "O&i:tcflush",
264                           fdconv, &fd, &queue))
265         return NULL;
266     if (tcflush(fd, queue) == -1)
267         return PyErr_SetFromErrno(TermiosError);
268 
269     Py_INCREF(Py_None);
270     return Py_None;
271 }
272 
273 PyDoc_STRVAR(termios_tcflow__doc__,
274 "tcflow(fd, action) -> None\n\
275 \n\
276 Suspend or resume input or output on file descriptor fd.\n\
277 The action argument can be termios.TCOOFF to suspend output,\n\
278 termios.TCOON to restart output, termios.TCIOFF to suspend input,\n\
279 or termios.TCION to restart input.");
280 
281 static PyObject *
282 termios_tcflow(PyObject *self, PyObject *args)
283 {
284     int fd, action;
285 
286     if (!PyArg_ParseTuple(args, "O&i:tcflow",
287                           fdconv, &fd, &action))
288         return NULL;
289     if (tcflow(fd, action) == -1)
290         return PyErr_SetFromErrno(TermiosError);
291 
292     Py_INCREF(Py_None);
293     return Py_None;
294 }
295 
296 static PyMethodDef termios_methods[] =
297 {
298     {"tcgetattr", termios_tcgetattr,
299      METH_VARARGS, termios_tcgetattr__doc__},
300     {"tcsetattr", termios_tcsetattr,
301      METH_VARARGS, termios_tcsetattr__doc__},
302     {"tcsendbreak", termios_tcsendbreak,
303      METH_VARARGS, termios_tcsendbreak__doc__},
304     {"tcdrain", termios_tcdrain,
305      METH_VARARGS, termios_tcdrain__doc__},
306     {"tcflush", termios_tcflush,
307      METH_VARARGS, termios_tcflush__doc__},
308     {"tcflow", termios_tcflow,
309      METH_VARARGS, termios_tcflow__doc__},
310     {NULL, NULL}
311 };
312 
313 
314 #if defined(VSWTCH) && !defined(VSWTC)
315 #define VSWTC VSWTCH
316 #endif
317 
318 #if defined(VSWTC) && !defined(VSWTCH)
319 #define VSWTCH VSWTC
320 #endif
321 
322 static struct constant {
323     char *name;
324     long value;
325 } termios_constants[] = {
326     /* cfgetospeed(), cfsetospeed() constants */
327     {"B0", B0},
328     {"B50", B50},
329     {"B75", B75},
330     {"B110", B110},
331     {"B134", B134},
332     {"B150", B150},
333     {"B200", B200},
334     {"B300", B300},
335     {"B600", B600},
336     {"B1200", B1200},
337     {"B1800", B1800},
338     {"B2400", B2400},
339     {"B4800", B4800},
340     {"B9600", B9600},
341     {"B19200", B19200},
342     {"B38400", B38400},
343 #ifdef B57600
344     {"B57600", B57600},
345 #endif
346 #ifdef B115200
347     {"B115200", B115200},
348 #endif
349 #ifdef B230400
350     {"B230400", B230400},
351 #endif
352 #ifdef CBAUDEX
353     {"CBAUDEX", CBAUDEX},
354 #endif
355 
356     /* tcsetattr() constants */
357     {"TCSANOW", TCSANOW},
358     {"TCSADRAIN", TCSADRAIN},
359     {"TCSAFLUSH", TCSAFLUSH},
360 #ifdef TCSASOFT
361     {"TCSASOFT", TCSASOFT},
362 #endif
363 
364     /* tcflush() constants */
365     {"TCIFLUSH", TCIFLUSH},
366     {"TCOFLUSH", TCOFLUSH},
367     {"TCIOFLUSH", TCIOFLUSH},
368 
369     /* tcflow() constants */
370     {"TCOOFF", TCOOFF},
371     {"TCOON", TCOON},
372     {"TCIOFF", TCIOFF},
373     {"TCION", TCION},
374 
375     /* struct termios.c_iflag constants */
376     {"IGNBRK", IGNBRK},
377     {"BRKINT", BRKINT},
378     {"IGNPAR", IGNPAR},
379     {"PARMRK", PARMRK},
380     {"INPCK", INPCK},
381     {"ISTRIP", ISTRIP},
382     {"INLCR", INLCR},
383     {"IGNCR", IGNCR},
384     {"ICRNL", ICRNL},
385 #ifdef IUCLC
386     {"IUCLC", IUCLC},
387 #endif
388     {"IXON", IXON},
389     {"IXANY", IXANY},
390     {"IXOFF", IXOFF},
391 #ifdef IMAXBEL
392     {"IMAXBEL", IMAXBEL},
393 #endif
394 
395     /* struct termios.c_oflag constants */
396     {"OPOST", OPOST},
397 #ifdef OLCUC
398     {"OLCUC", OLCUC},
399 #endif
400 #ifdef ONLCR
401     {"ONLCR", ONLCR},
402 #endif
403 #ifdef OCRNL
404     {"OCRNL", OCRNL},
405 #endif
406 #ifdef ONOCR
407     {"ONOCR", ONOCR},
408 #endif
409 #ifdef ONLRET
410     {"ONLRET", ONLRET},
411 #endif
412 #ifdef OFILL
413     {"OFILL", OFILL},
414 #endif
415 #ifdef OFDEL
416     {"OFDEL", OFDEL},
417 #endif
418 #ifdef NLDLY
419     {"NLDLY", NLDLY},
420 #endif
421 #ifdef CRDLY
422     {"CRDLY", CRDLY},
423 #endif
424 #ifdef TABDLY
425     {"TABDLY", TABDLY},
426 #endif
427 #ifdef BSDLY
428     {"BSDLY", BSDLY},
429 #endif
430 #ifdef VTDLY
431     {"VTDLY", VTDLY},
432 #endif
433 #ifdef FFDLY
434     {"FFDLY", FFDLY},
435 #endif
436 
437     /* struct termios.c_oflag-related values (delay mask) */
438 #ifdef NL0
439     {"NL0", NL0},
440 #endif
441 #ifdef NL1
442     {"NL1", NL1},
443 #endif
444 #ifdef CR0
445     {"CR0", CR0},
446 #endif
447 #ifdef CR1
448     {"CR1", CR1},
449 #endif
450 #ifdef CR2
451     {"CR2", CR2},
452 #endif
453 #ifdef CR3
454     {"CR3", CR3},
455 #endif
456 #ifdef TAB0
457     {"TAB0", TAB0},
458 #endif
459 #ifdef TAB1
460     {"TAB1", TAB1},
461 #endif
462 #ifdef TAB2
463     {"TAB2", TAB2},
464 #endif
465 #ifdef TAB3
466     {"TAB3", TAB3},
467 #endif
468 #ifdef XTABS
469     {"XTABS", XTABS},
470 #endif
471 #ifdef BS0
472     {"BS0", BS0},
473 #endif
474 #ifdef BS1
475     {"BS1", BS1},
476 #endif
477 #ifdef VT0
478     {"VT0", VT0},
479 #endif
480 #ifdef VT1
481     {"VT1", VT1},
482 #endif
483 #ifdef FF0
484     {"FF0", FF0},
485 #endif
486 #ifdef FF1
487     {"FF1", FF1},
488 #endif
489 
490     /* struct termios.c_cflag constants */
491     {"CSIZE", CSIZE},
492     {"CSTOPB", CSTOPB},
493     {"CREAD", CREAD},
494     {"PARENB", PARENB},
495     {"PARODD", PARODD},
496     {"HUPCL", HUPCL},
497     {"CLOCAL", CLOCAL},
498 #ifdef CIBAUD
499     {"CIBAUD", CIBAUD},
500 #endif
501 #ifdef CRTSCTS
502     {"CRTSCTS", (long)CRTSCTS},
503 #endif
504 
505     /* struct termios.c_cflag-related values (character size) */
506     {"CS5", CS5},
507     {"CS6", CS6},
508     {"CS7", CS7},
509     {"CS8", CS8},
510 
511     /* struct termios.c_lflag constants */
512     {"ISIG", ISIG},
513     {"ICANON", ICANON},
514 #ifdef XCASE
515     {"XCASE", XCASE},
516 #endif
517     {"ECHO", ECHO},
518     {"ECHOE", ECHOE},
519     {"ECHOK", ECHOK},
520     {"ECHONL", ECHONL},
521 #ifdef ECHOCTL
522     {"ECHOCTL", ECHOCTL},
523 #endif
524 #ifdef ECHOPRT
525     {"ECHOPRT", ECHOPRT},
526 #endif
527 #ifdef ECHOKE
528     {"ECHOKE", ECHOKE},
529 #endif
530 #ifdef FLUSHO
531     {"FLUSHO", FLUSHO},
532 #endif
533     {"NOFLSH", NOFLSH},
534     {"TOSTOP", TOSTOP},
535 #ifdef PENDIN
536     {"PENDIN", PENDIN},
537 #endif
538     {"IEXTEN", IEXTEN},
539 
540     /* indexes into the control chars array returned by tcgetattr() */
541     {"VINTR", VINTR},
542     {"VQUIT", VQUIT},
543     {"VERASE", VERASE},
544     {"VKILL", VKILL},
545     {"VEOF", VEOF},
546     {"VTIME", VTIME},
547     {"VMIN", VMIN},
548 #ifdef VSWTC
549     /* The #defines above ensure that if either is defined, both are,
550      * but both may be omitted by the system headers.  ;-(  */
551     {"VSWTC", VSWTC},
552     {"VSWTCH", VSWTCH},
553 #endif
554     {"VSTART", VSTART},
555     {"VSTOP", VSTOP},
556     {"VSUSP", VSUSP},
557     {"VEOL", VEOL},
558 #ifdef VREPRINT
559     {"VREPRINT", VREPRINT},
560 #endif
561 #ifdef VDISCARD
562     {"VDISCARD", VDISCARD},
563 #endif
564 #ifdef VWERASE
565     {"VWERASE", VWERASE},
566 #endif
567 #ifdef VLNEXT
568     {"VLNEXT", VLNEXT},
569 #endif
570 #ifdef VEOL2
571     {"VEOL2", VEOL2},
572 #endif
573 
574 
575 #ifdef B460800
576     {"B460800", B460800},
577 #endif
578 #ifdef CBAUD
579     {"CBAUD", CBAUD},
580 #endif
581 #ifdef CDEL
582     {"CDEL", CDEL},
583 #endif
584 #ifdef CDSUSP
585     {"CDSUSP", CDSUSP},
586 #endif
587 #ifdef CEOF
588     {"CEOF", CEOF},
589 #endif
590 #ifdef CEOL
591     {"CEOL", CEOL},
592 #endif
593 #ifdef CEOL2
594     {"CEOL2", CEOL2},
595 #endif
596 #ifdef CEOT
597     {"CEOT", CEOT},
598 #endif
599 #ifdef CERASE
600     {"CERASE", CERASE},
601 #endif
602 #ifdef CESC
603     {"CESC", CESC},
604 #endif
605 #ifdef CFLUSH
606     {"CFLUSH", CFLUSH},
607 #endif
608 #ifdef CINTR
609     {"CINTR", CINTR},
610 #endif
611 #ifdef CKILL
612     {"CKILL", CKILL},
613 #endif
614 #ifdef CLNEXT
615     {"CLNEXT", CLNEXT},
616 #endif
617 #ifdef CNUL
618     {"CNUL", CNUL},
619 #endif
620 #ifdef COMMON
621     {"COMMON", COMMON},
622 #endif
623 #ifdef CQUIT
624     {"CQUIT", CQUIT},
625 #endif
626 #ifdef CRPRNT
627     {"CRPRNT", CRPRNT},
628 #endif
629 #ifdef CSTART
630     {"CSTART", CSTART},
631 #endif
632 #ifdef CSTOP
633     {"CSTOP", CSTOP},
634 #endif
635 #ifdef CSUSP
636     {"CSUSP", CSUSP},
637 #endif
638 #ifdef CSWTCH
639     {"CSWTCH", CSWTCH},
640 #endif
641 #ifdef CWERASE
642     {"CWERASE", CWERASE},
643 #endif
644 #ifdef EXTA
645     {"EXTA", EXTA},
646 #endif
647 #ifdef EXTB
648     {"EXTB", EXTB},
649 #endif
650 #ifdef FIOASYNC
651     {"FIOASYNC", FIOASYNC},
652 #endif
653 #ifdef FIOCLEX
654     {"FIOCLEX", FIOCLEX},
655 #endif
656 #ifdef FIONBIO
657     {"FIONBIO", FIONBIO},
658 #endif
659 #ifdef FIONCLEX
660     {"FIONCLEX", FIONCLEX},
661 #endif
662 #ifdef FIONREAD
663     {"FIONREAD", FIONREAD},
664 #endif
665 #ifdef IBSHIFT
666     {"IBSHIFT", IBSHIFT},
667 #endif
668 #ifdef INIT_C_CC
669     {"INIT_C_CC", INIT_C_CC},
670 #endif
671 #ifdef IOCSIZE_MASK
672     {"IOCSIZE_MASK", IOCSIZE_MASK},
673 #endif
674 #ifdef IOCSIZE_SHIFT
675     {"IOCSIZE_SHIFT", IOCSIZE_SHIFT},
676 #endif
677 #ifdef NCC
678     {"NCC", NCC},
679 #endif
680 #ifdef NCCS
681     {"NCCS", NCCS},
682 #endif
683 #ifdef NSWTCH
684     {"NSWTCH", NSWTCH},
685 #endif
686 #ifdef N_MOUSE
687     {"N_MOUSE", N_MOUSE},
688 #endif
689 #ifdef N_PPP
690     {"N_PPP", N_PPP},
691 #endif
692 #ifdef N_SLIP
693     {"N_SLIP", N_SLIP},
694 #endif
695 #ifdef N_STRIP
696     {"N_STRIP", N_STRIP},
697 #endif
698 #ifdef N_TTY
699     {"N_TTY", N_TTY},
700 #endif
701 #ifdef TCFLSH
702     {"TCFLSH", TCFLSH},
703 #endif
704 #ifdef TCGETA
705     {"TCGETA", TCGETA},
706 #endif
707 #ifdef TCGETS
708     {"TCGETS", TCGETS},
709 #endif
710 #ifdef TCSBRK
711     {"TCSBRK", TCSBRK},
712 #endif
713 #ifdef TCSBRKP
714     {"TCSBRKP", TCSBRKP},
715 #endif
716 #ifdef TCSETA
717     {"TCSETA", TCSETA},
718 #endif
719 #ifdef TCSETAF
720     {"TCSETAF", TCSETAF},
721 #endif
722 #ifdef TCSETAW
723     {"TCSETAW", TCSETAW},
724 #endif
725 #ifdef TCSETS
726     {"TCSETS", TCSETS},
727 #endif
728 #ifdef TCSETSF
729     {"TCSETSF", TCSETSF},
730 #endif
731 #ifdef TCSETSW
732     {"TCSETSW", TCSETSW},
733 #endif
734 #ifdef TCXONC
735     {"TCXONC", TCXONC},
736 #endif
737 #ifdef TIOCCONS
738     {"TIOCCONS", TIOCCONS},
739 #endif
740 #ifdef TIOCEXCL
741     {"TIOCEXCL", TIOCEXCL},
742 #endif
743 #ifdef TIOCGETD
744     {"TIOCGETD", TIOCGETD},
745 #endif
746 #ifdef TIOCGICOUNT
747     {"TIOCGICOUNT", TIOCGICOUNT},
748 #endif
749 #ifdef TIOCGLCKTRMIOS
750     {"TIOCGLCKTRMIOS", TIOCGLCKTRMIOS},
751 #endif
752 #ifdef TIOCGPGRP
753     {"TIOCGPGRP", TIOCGPGRP},
754 #endif
755 #ifdef TIOCGSERIAL
756     {"TIOCGSERIAL", TIOCGSERIAL},
757 #endif
758 #ifdef TIOCGSOFTCAR
759     {"TIOCGSOFTCAR", TIOCGSOFTCAR},
760 #endif
761 #ifdef TIOCGWINSZ
762     {"TIOCGWINSZ", TIOCGWINSZ},
763 #endif
764 #ifdef TIOCINQ
765     {"TIOCINQ", TIOCINQ},
766 #endif
767 #ifdef TIOCLINUX
768     {"TIOCLINUX", TIOCLINUX},
769 #endif
770 #ifdef TIOCMBIC
771     {"TIOCMBIC", TIOCMBIC},
772 #endif
773 #ifdef TIOCMBIS
774     {"TIOCMBIS", TIOCMBIS},
775 #endif
776 #ifdef TIOCMGET
777     {"TIOCMGET", TIOCMGET},
778 #endif
779 #ifdef TIOCMIWAIT
780     {"TIOCMIWAIT", TIOCMIWAIT},
781 #endif
782 #ifdef TIOCMSET
783     {"TIOCMSET", TIOCMSET},
784 #endif
785 #ifdef TIOCM_CAR
786     {"TIOCM_CAR", TIOCM_CAR},
787 #endif
788 #ifdef TIOCM_CD
789     {"TIOCM_CD", TIOCM_CD},
790 #endif
791 #ifdef TIOCM_CTS
792     {"TIOCM_CTS", TIOCM_CTS},
793 #endif
794 #ifdef TIOCM_DSR
795     {"TIOCM_DSR", TIOCM_DSR},
796 #endif
797 #ifdef TIOCM_DTR
798     {"TIOCM_DTR", TIOCM_DTR},
799 #endif
800 #ifdef TIOCM_LE
801     {"TIOCM_LE", TIOCM_LE},
802 #endif
803 #ifdef TIOCM_RI
804     {"TIOCM_RI", TIOCM_RI},
805 #endif
806 #ifdef TIOCM_RNG
807     {"TIOCM_RNG", TIOCM_RNG},
808 #endif
809 #ifdef TIOCM_RTS
810     {"TIOCM_RTS", TIOCM_RTS},
811 #endif
812 #ifdef TIOCM_SR
813     {"TIOCM_SR", TIOCM_SR},
814 #endif
815 #ifdef TIOCM_ST
816     {"TIOCM_ST", TIOCM_ST},
817 #endif
818 #ifdef TIOCNOTTY
819     {"TIOCNOTTY", TIOCNOTTY},
820 #endif
821 #ifdef TIOCNXCL
822     {"TIOCNXCL", TIOCNXCL},
823 #endif
824 #ifdef TIOCOUTQ
825     {"TIOCOUTQ", TIOCOUTQ},
826 #endif
827 #ifdef TIOCPKT
828     {"TIOCPKT", TIOCPKT},
829 #endif
830 #ifdef TIOCPKT_DATA
831     {"TIOCPKT_DATA", TIOCPKT_DATA},
832 #endif
833 #ifdef TIOCPKT_DOSTOP
834     {"TIOCPKT_DOSTOP", TIOCPKT_DOSTOP},
835 #endif
836 #ifdef TIOCPKT_FLUSHREAD
837     {"TIOCPKT_FLUSHREAD", TIOCPKT_FLUSHREAD},
838 #endif
839 #ifdef TIOCPKT_FLUSHWRITE
840     {"TIOCPKT_FLUSHWRITE", TIOCPKT_FLUSHWRITE},
841 #endif
842 #ifdef TIOCPKT_NOSTOP
843     {"TIOCPKT_NOSTOP", TIOCPKT_NOSTOP},
844 #endif
845 #ifdef TIOCPKT_START
846     {"TIOCPKT_START", TIOCPKT_START},
847 #endif
848 #ifdef TIOCPKT_STOP
849     {"TIOCPKT_STOP", TIOCPKT_STOP},
850 #endif
851 #ifdef TIOCSCTTY
852     {"TIOCSCTTY", TIOCSCTTY},
853 #endif
854 #ifdef TIOCSERCONFIG
855     {"TIOCSERCONFIG", TIOCSERCONFIG},
856 #endif
857 #ifdef TIOCSERGETLSR
858     {"TIOCSERGETLSR", TIOCSERGETLSR},
859 #endif
860 #ifdef TIOCSERGETMULTI
861     {"TIOCSERGETMULTI", TIOCSERGETMULTI},
862 #endif
863 #ifdef TIOCSERGSTRUCT
864     {"TIOCSERGSTRUCT", TIOCSERGSTRUCT},
865 #endif
866 #ifdef TIOCSERGWILD
867     {"TIOCSERGWILD", TIOCSERGWILD},
868 #endif
869 #ifdef TIOCSERSETMULTI
870     {"TIOCSERSETMULTI", TIOCSERSETMULTI},
871 #endif
872 #ifdef TIOCSERSWILD
873     {"TIOCSERSWILD", TIOCSERSWILD},
874 #endif
875 #ifdef TIOCSER_TEMT
876     {"TIOCSER_TEMT", TIOCSER_TEMT},
877 #endif
878 #ifdef TIOCSETD
879     {"TIOCSETD", TIOCSETD},
880 #endif
881 #ifdef TIOCSLCKTRMIOS
882     {"TIOCSLCKTRMIOS", TIOCSLCKTRMIOS},
883 #endif
884 #ifdef TIOCSPGRP
885     {"TIOCSPGRP", TIOCSPGRP},
886 #endif
887 #ifdef TIOCSSERIAL
888     {"TIOCSSERIAL", TIOCSSERIAL},
889 #endif
890 #ifdef TIOCSSOFTCAR
891     {"TIOCSSOFTCAR", TIOCSSOFTCAR},
892 #endif
893 #ifdef TIOCSTI
894     {"TIOCSTI", TIOCSTI},
895 #endif
896 #ifdef TIOCSWINSZ
897     {"TIOCSWINSZ", TIOCSWINSZ},
898 #endif
899 #ifdef TIOCTTYGSTRUCT
900     {"TIOCTTYGSTRUCT", TIOCTTYGSTRUCT},
901 #endif
902 
903     /* sentinel */
904     {NULL, 0}
905 };
906 
907 
908 PyMODINIT_FUNC
909 PyInit_termios(void)
910 {
911     PyObject *m;
912     struct constant *constant = termios_constants;
913 
914     m = Py_InitModule4("termios", termios_methods, termios__doc__,
915                        (PyObject *)NULL, PYTHON_API_VERSION);
916     if (m == NULL)
917         return;
918 
919     if (TermiosError == NULL) {
920         TermiosError = PyErr_NewException("termios.error", NULL, NULL);
921     }
922     Py_INCREF(TermiosError);
923     PyModule_AddObject(m, "error", TermiosError);
924 
925     while (constant->name != NULL) {
926         PyModule_AddIntConstant(m, constant->name, constant->value);
927         ++constant;
928     }
929 }