Home | History | Annotate | Download | only in Modules
      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 (appearantly 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 
     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 *
     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 *
    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 *
    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 *
    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 *
    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 *
    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
    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