Home | History | Annotate | Download | only in Modules
      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 }
    930