(root)/
Python-3.12.0/
Modules/
termios.c
       1  /* termios.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  /*[clinic input]
      33  module termios
      34  [clinic start generated code]*/
      35  /*[clinic end generated code: output=da39a3ee5e6b4b0d input=01105c85d0ca7252]*/
      36  
      37  #include "clinic/termios.c.h"
      38  
      39  PyDoc_STRVAR(termios__doc__,
      40  "This module provides an interface to the Posix calls for tty I/O control.\n\
      41  For a complete description of these calls, see the Posix or Unix manual\n\
      42  pages. It is only available for those Unix versions that support Posix\n\
      43  termios style tty I/O control.\n\
      44  \n\
      45  All functions in this module take a file descriptor fd as their first\n\
      46  argument. This can be an integer file descriptor, such as returned by\n\
      47  sys.stdin.fileno(), or a file object, such as sys.stdin itself.");
      48  
      49  typedef struct {
      50    PyObject *TermiosError;
      51  } termiosmodulestate;
      52  
      53  static inline termiosmodulestate*
      54  get_termios_state(PyObject *module)
      55  {
      56      void *state = PyModule_GetState(module);
      57      assert(state != NULL);
      58      return (termiosmodulestate *)state;
      59  }
      60  
      61  static struct PyModuleDef termiosmodule;
      62  
      63  /*[clinic input]
      64  termios.tcgetattr
      65  
      66      fd: fildes
      67      /
      68  
      69  Get the tty attributes for file descriptor fd.
      70  
      71  Returns a list [iflag, oflag, cflag, lflag, ispeed, ospeed, cc]
      72  where cc is a list of the tty special characters (each a string of
      73  length 1, except the items with indices VMIN and VTIME, which are
      74  integers when these fields are defined).  The interpretation of the
      75  flags and the speeds as well as the indexing in the cc array must be
      76  done using the symbolic constants defined in this module.
      77  [clinic start generated code]*/
      78  
      79  static PyObject *
      80  termios_tcgetattr_impl(PyObject *module, int fd)
      81  /*[clinic end generated code: output=2b3da39db870e629 input=54dad9779ebe74b1]*/
      82  {
      83      termiosmodulestate *state = PyModule_GetState(module);
      84      struct termios mode;
      85      int r;
      86  
      87      Py_BEGIN_ALLOW_THREADS
      88      r = tcgetattr(fd, &mode);
      89      Py_END_ALLOW_THREADS
      90      if (r == -1) {
      91          return PyErr_SetFromErrno(state->TermiosError);
      92      }
      93  
      94      speed_t ispeed = cfgetispeed(&mode);
      95      speed_t ospeed = cfgetospeed(&mode);
      96  
      97      PyObject *cc = PyList_New(NCCS);
      98      if (cc == NULL) {
      99          return NULL;
     100      }
     101  
     102      PyObject *v;
     103      int i;
     104      for (i = 0; i < NCCS; i++) {
     105          char ch = (char)mode.c_cc[i];
     106          v = PyBytes_FromStringAndSize(&ch, 1);
     107          if (v == NULL)
     108              goto err;
     109          PyList_SetItem(cc, i, v);
     110      }
     111  
     112      /* Convert the MIN and TIME slots to integer.  On some systems, the
     113         MIN and TIME slots are the same as the EOF and EOL slots.  So we
     114         only do this in noncanonical input mode.  */
     115      if ((mode.c_lflag & ICANON) == 0) {
     116          v = PyLong_FromLong((long)mode.c_cc[VMIN]);
     117          if (v == NULL)
     118              goto err;
     119          PyList_SetItem(cc, VMIN, v);
     120          v = PyLong_FromLong((long)mode.c_cc[VTIME]);
     121          if (v == NULL)
     122              goto err;
     123          PyList_SetItem(cc, VTIME, v);
     124      }
     125  
     126      if (!(v = PyList_New(7)))
     127          goto err;
     128  
     129      PyList_SetItem(v, 0, PyLong_FromLong((long)mode.c_iflag));
     130      PyList_SetItem(v, 1, PyLong_FromLong((long)mode.c_oflag));
     131      PyList_SetItem(v, 2, PyLong_FromLong((long)mode.c_cflag));
     132      PyList_SetItem(v, 3, PyLong_FromLong((long)mode.c_lflag));
     133      PyList_SetItem(v, 4, PyLong_FromLong((long)ispeed));
     134      PyList_SetItem(v, 5, PyLong_FromLong((long)ospeed));
     135      if (PyErr_Occurred()) {
     136          Py_DECREF(v);
     137          goto err;
     138      }
     139      PyList_SetItem(v, 6, cc);
     140      return v;
     141    err:
     142      Py_DECREF(cc);
     143      return NULL;
     144  }
     145  
     146  /*[clinic input]
     147  termios.tcsetattr
     148  
     149      fd: fildes
     150      when: int
     151      attributes as term: object
     152      /
     153  
     154  Set the tty attributes for file descriptor fd.
     155  
     156  The attributes to be set are taken from the attributes argument, which
     157  is a list like the one returned by tcgetattr(). The when argument
     158  determines when the attributes are changed: termios.TCSANOW to
     159  change immediately, termios.TCSADRAIN to change after transmitting all
     160  queued output, or termios.TCSAFLUSH to change after transmitting all
     161  queued output and discarding all queued input.
     162  [clinic start generated code]*/
     163  
     164  static PyObject *
     165  termios_tcsetattr_impl(PyObject *module, int fd, int when, PyObject *term)
     166  /*[clinic end generated code: output=bcd2b0a7b98a4bf5 input=5dafabdd5a08f018]*/
     167  {
     168      if (!PyList_Check(term) || PyList_Size(term) != 7) {
     169          PyErr_SetString(PyExc_TypeError,
     170                       "tcsetattr, arg 3: must be 7 element list");
     171          return NULL;
     172      }
     173  
     174      /* Get the old mode, in case there are any hidden fields... */
     175      termiosmodulestate *state = PyModule_GetState(module);
     176      struct termios mode;
     177      int r;
     178  
     179      Py_BEGIN_ALLOW_THREADS
     180      r = tcgetattr(fd, &mode);
     181      Py_END_ALLOW_THREADS
     182      if (r == -1) {
     183          return PyErr_SetFromErrno(state->TermiosError);
     184      }
     185  
     186      mode.c_iflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 0));
     187      mode.c_oflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 1));
     188      mode.c_cflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 2));
     189      mode.c_lflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 3));
     190      speed_t ispeed = (speed_t) PyLong_AsLong(PyList_GetItem(term, 4));
     191      speed_t ospeed = (speed_t) PyLong_AsLong(PyList_GetItem(term, 5));
     192      PyObject *cc = PyList_GetItem(term, 6);
     193      if (PyErr_Occurred()) {
     194          return NULL;
     195      }
     196  
     197      if (!PyList_Check(cc) || PyList_Size(cc) != NCCS) {
     198          PyErr_Format(PyExc_TypeError,
     199              "tcsetattr: attributes[6] must be %d element list",
     200                   NCCS);
     201          return NULL;
     202      }
     203  
     204      int i;
     205      PyObject *v;
     206      for (i = 0; i < NCCS; i++) {
     207          v = PyList_GetItem(cc, i);
     208  
     209          if (PyBytes_Check(v) && PyBytes_Size(v) == 1)
     210              mode.c_cc[i] = (cc_t) * PyBytes_AsString(v);
     211          else if (PyLong_Check(v))
     212              mode.c_cc[i] = (cc_t) PyLong_AsLong(v);
     213          else {
     214              PyErr_SetString(PyExc_TypeError,
     215       "tcsetattr: elements of attributes must be characters or integers");
     216                          return NULL;
     217                  }
     218      }
     219  
     220      if (cfsetispeed(&mode, (speed_t) ispeed) == -1)
     221          return PyErr_SetFromErrno(state->TermiosError);
     222      if (cfsetospeed(&mode, (speed_t) ospeed) == -1)
     223          return PyErr_SetFromErrno(state->TermiosError);
     224  
     225      Py_BEGIN_ALLOW_THREADS
     226      r = tcsetattr(fd, when, &mode);
     227      Py_END_ALLOW_THREADS
     228  
     229      if (r == -1)
     230          return PyErr_SetFromErrno(state->TermiosError);
     231  
     232      Py_RETURN_NONE;
     233  }
     234  
     235  /*[clinic input]
     236  termios.tcsendbreak
     237  
     238      fd: fildes
     239      duration: int
     240      /
     241  
     242  Send a break on file descriptor fd.
     243  
     244  A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration
     245  has a system dependent meaning.
     246  [clinic start generated code]*/
     247  
     248  static PyObject *
     249  termios_tcsendbreak_impl(PyObject *module, int fd, int duration)
     250  /*[clinic end generated code: output=5945f589b5d3ac66 input=dc2f32417691f8ed]*/
     251  {
     252      termiosmodulestate *state = PyModule_GetState(module);
     253      int r;
     254  
     255      Py_BEGIN_ALLOW_THREADS
     256      r = tcsendbreak(fd, duration);
     257      Py_END_ALLOW_THREADS
     258  
     259      if (r == -1) {
     260          return PyErr_SetFromErrno(state->TermiosError);
     261      }
     262  
     263      Py_RETURN_NONE;
     264  }
     265  
     266  /*[clinic input]
     267  termios.tcdrain
     268  
     269      fd: fildes
     270      /
     271  
     272  Wait until all output written to file descriptor fd has been transmitted.
     273  [clinic start generated code]*/
     274  
     275  static PyObject *
     276  termios_tcdrain_impl(PyObject *module, int fd)
     277  /*[clinic end generated code: output=5fd86944c6255955 input=c99241b140b32447]*/
     278  {
     279      termiosmodulestate *state = PyModule_GetState(module);
     280      int r;
     281  
     282      Py_BEGIN_ALLOW_THREADS
     283      r = tcdrain(fd);
     284      Py_END_ALLOW_THREADS
     285  
     286      if (r == -1) {
     287          return PyErr_SetFromErrno(state->TermiosError);
     288      }
     289  
     290      Py_RETURN_NONE;
     291  }
     292  
     293  /*[clinic input]
     294  termios.tcflush
     295  
     296      fd: fildes
     297      queue: int
     298      /
     299  
     300  Discard queued data on file descriptor fd.
     301  
     302  The queue selector specifies which queue: termios.TCIFLUSH for the input
     303  queue, termios.TCOFLUSH for the output queue, or termios.TCIOFLUSH for
     304  both queues.
     305  [clinic start generated code]*/
     306  
     307  static PyObject *
     308  termios_tcflush_impl(PyObject *module, int fd, int queue)
     309  /*[clinic end generated code: output=2424f80312ec2f21 input=0f7d08122ddc07b5]*/
     310  {
     311      termiosmodulestate *state = PyModule_GetState(module);
     312      int r;
     313  
     314      Py_BEGIN_ALLOW_THREADS
     315      r = tcflush(fd, queue);
     316      Py_END_ALLOW_THREADS
     317  
     318      if (r == -1) {
     319          return PyErr_SetFromErrno(state->TermiosError);
     320      }
     321  
     322      Py_RETURN_NONE;
     323  }
     324  
     325  /*[clinic input]
     326  termios.tcflow
     327  
     328      fd: fildes
     329      action: int
     330      /
     331  
     332  Suspend or resume input or output on file descriptor fd.
     333  
     334  The action argument can be termios.TCOOFF to suspend output,
     335  termios.TCOON to restart output, termios.TCIOFF to suspend input,
     336  or termios.TCION to restart input.
     337  [clinic start generated code]*/
     338  
     339  static PyObject *
     340  termios_tcflow_impl(PyObject *module, int fd, int action)
     341  /*[clinic end generated code: output=afd10928e6ea66eb input=c6aff0640b6efd9c]*/
     342  {
     343      termiosmodulestate *state = PyModule_GetState(module);
     344      int r;
     345  
     346      Py_BEGIN_ALLOW_THREADS
     347      r = tcflow(fd, action);
     348      Py_END_ALLOW_THREADS
     349  
     350      if (r == -1) {
     351          return PyErr_SetFromErrno(state->TermiosError);
     352      }
     353  
     354      Py_RETURN_NONE;
     355  }
     356  
     357  /*[clinic input]
     358  termios.tcgetwinsize
     359  
     360      fd: fildes
     361      /
     362  
     363  Get the tty winsize for file descriptor fd.
     364  
     365  Returns a tuple (ws_row, ws_col).
     366  [clinic start generated code]*/
     367  
     368  static PyObject *
     369  termios_tcgetwinsize_impl(PyObject *module, int fd)
     370  /*[clinic end generated code: output=31825977d5325fb6 input=5706c379d7fd984d]*/
     371  {
     372  #if defined(TIOCGWINSZ)
     373      termiosmodulestate *state = PyModule_GetState(module);
     374      struct winsize w;
     375      int r;
     376  
     377      Py_BEGIN_ALLOW_THREADS
     378      r = ioctl(fd, TIOCGWINSZ, &w);
     379      Py_END_ALLOW_THREADS
     380  
     381      if (r == -1) {
     382          return PyErr_SetFromErrno(state->TermiosError);
     383      }
     384  
     385      PyObject *v;
     386      if (!(v = PyTuple_New(2))) {
     387          return NULL;
     388      }
     389  
     390      PyTuple_SetItem(v, 0, PyLong_FromLong((long)w.ws_row));
     391      PyTuple_SetItem(v, 1, PyLong_FromLong((long)w.ws_col));
     392      if (PyErr_Occurred()) {
     393          Py_DECREF(v);
     394          return NULL;
     395      }
     396      return v;
     397  #elif defined(TIOCGSIZE)
     398      termiosmodulestate *state = PyModule_GetState(module);
     399      struct ttysize s;
     400      int r;
     401  
     402      Py_BEGIN_ALLOW_THREADS
     403      r = ioctl(fd, TIOCGSIZE, &s);
     404      Py_END_ALLOW_THREADS
     405      if (r == -1) {
     406          return PyErr_SetFromErrno(state->TermiosError);
     407      }
     408  
     409      PyObject *v;
     410      if (!(v = PyTuple_New(2))) {
     411          return NULL;
     412      }
     413  
     414      PyTuple_SetItem(v, 0, PyLong_FromLong((long)s.ts_lines));
     415      PyTuple_SetItem(v, 1, PyLong_FromLong((long)s.ts_cols));
     416      if (PyErr_Occurred()) {
     417          Py_DECREF(v);
     418          return NULL;
     419      }
     420      return v;
     421  #else
     422      PyErr_SetString(PyExc_NotImplementedError,
     423                      "requires termios.TIOCGWINSZ and/or termios.TIOCGSIZE");
     424      return NULL;
     425  #endif /* defined(TIOCGWINSZ) */
     426  }
     427  
     428  /*[clinic input]
     429  termios.tcsetwinsize
     430  
     431      fd: fildes
     432      winsize as winsz: object
     433      /
     434  
     435  Set the tty winsize for file descriptor fd.
     436  
     437  The winsize to be set is taken from the winsize argument, which
     438  is a two-item tuple (ws_row, ws_col) like the one returned by tcgetwinsize().
     439  [clinic start generated code]*/
     440  
     441  static PyObject *
     442  termios_tcsetwinsize_impl(PyObject *module, int fd, PyObject *winsz)
     443  /*[clinic end generated code: output=2ac3c9bb6eda83e1 input=4a06424465b24aee]*/
     444  {
     445      if (!PySequence_Check(winsz) || PySequence_Size(winsz) != 2) {
     446          PyErr_SetString(PyExc_TypeError,
     447                       "tcsetwinsize, arg 2: must be a two-item sequence");
     448          return NULL;
     449      }
     450  
     451      PyObject *tmp_item;
     452      long winsz_0, winsz_1;
     453      tmp_item = PySequence_GetItem(winsz, 0);
     454      winsz_0 = PyLong_AsLong(tmp_item);
     455      if (winsz_0 == -1 && PyErr_Occurred()) {
     456          Py_XDECREF(tmp_item);
     457          return NULL;
     458      }
     459      Py_XDECREF(tmp_item);
     460      tmp_item = PySequence_GetItem(winsz, 1);
     461      winsz_1 = PyLong_AsLong(tmp_item);
     462      if (winsz_1 == -1 && PyErr_Occurred()) {
     463          Py_XDECREF(tmp_item);
     464          return NULL;
     465      }
     466      Py_XDECREF(tmp_item);
     467  
     468      termiosmodulestate *state = PyModule_GetState(module);
     469  
     470  #if defined(TIOCGWINSZ) && defined(TIOCSWINSZ)
     471      struct winsize w;
     472      /* Get the old winsize because it might have
     473         more fields such as xpixel, ypixel. */
     474      if (ioctl(fd, TIOCGWINSZ, &w) == -1) {
     475          return PyErr_SetFromErrno(state->TermiosError);
     476      }
     477  
     478      w.ws_row = (unsigned short) winsz_0;
     479      w.ws_col = (unsigned short) winsz_1;
     480      if ((((long)w.ws_row) != winsz_0) || (((long)w.ws_col) != winsz_1)) {
     481          PyErr_SetString(PyExc_OverflowError,
     482                          "winsize value(s) out of range.");
     483          return NULL;
     484      }
     485  
     486      int r;
     487      Py_BEGIN_ALLOW_THREADS
     488      r = ioctl(fd, TIOCSWINSZ, &w);
     489      Py_END_ALLOW_THREADS
     490  
     491      if (r == -1) {
     492          return PyErr_SetFromErrno(state->TermiosError);
     493      }
     494  
     495      Py_RETURN_NONE;
     496  #elif defined(TIOCGSIZE) && defined(TIOCSSIZE)
     497      struct ttysize s;
     498      int r;
     499      /* Get the old ttysize because it might have more fields. */
     500      Py_BEGIN_ALLOW_THREADS
     501      r = ioctl(fd, TIOCGSIZE, &s);
     502      Py_END_ALLOW_THREADS
     503  
     504      if (r == -1) {
     505          return PyErr_SetFromErrno(state->TermiosError);
     506      }
     507  
     508      s.ts_lines = (int) winsz_0;
     509      s.ts_cols = (int) winsz_1;
     510      if ((((long)s.ts_lines) != winsz_0) || (((long)s.ts_cols) != winsz_1)) {
     511          PyErr_SetString(PyExc_OverflowError,
     512                          "winsize value(s) out of range.");
     513          return NULL;
     514      }
     515  
     516      Py_BEGIN_ALLOW_THREADS
     517      r = ioctl(fd, TIOCSSIZE, &s);
     518      Py_END_ALLOW_THREADS
     519  
     520      if (r == -1) {
     521          return PyErr_SetFromErrno(state->TermiosError);
     522      }
     523  
     524      Py_RETURN_NONE;
     525  #else
     526      PyErr_SetString(PyExc_NotImplementedError,
     527                      "requires termios.TIOCGWINSZ, termios.TIOCSWINSZ and/or termios.TIOCGSIZE, termios.TIOCSSIZE");
     528      return NULL;
     529  #endif /* defined(TIOCGWINSZ) && defined(TIOCSWINSZ) */
     530  }
     531  
     532  static PyMethodDef termios_methods[] =
     533  {
     534      TERMIOS_TCGETATTR_METHODDEF
     535      TERMIOS_TCSETATTR_METHODDEF
     536      TERMIOS_TCSENDBREAK_METHODDEF
     537      TERMIOS_TCDRAIN_METHODDEF
     538      TERMIOS_TCFLUSH_METHODDEF
     539      TERMIOS_TCFLOW_METHODDEF
     540      TERMIOS_TCGETWINSIZE_METHODDEF
     541      TERMIOS_TCSETWINSIZE_METHODDEF
     542      {NULL, NULL}
     543  };
     544  
     545  
     546  #if defined(VSWTCH) && !defined(VSWTC)
     547  #define VSWTC VSWTCH
     548  #endif
     549  
     550  #if defined(VSWTC) && !defined(VSWTCH)
     551  #define VSWTCH VSWTC
     552  #endif
     553  
     554  static struct constant {
     555      char *name;
     556      long value;
     557  } termios_constants[] = {
     558      /* cfgetospeed(), cfsetospeed() constants */
     559      {"B0", B0},
     560      {"B50", B50},
     561      {"B75", B75},
     562      {"B110", B110},
     563      {"B134", B134},
     564      {"B150", B150},
     565      {"B200", B200},
     566      {"B300", B300},
     567      {"B600", B600},
     568      {"B1200", B1200},
     569      {"B1800", B1800},
     570      {"B2400", B2400},
     571      {"B4800", B4800},
     572      {"B9600", B9600},
     573      {"B19200", B19200},
     574      {"B38400", B38400},
     575  #ifdef B57600
     576      {"B57600", B57600},
     577  #endif
     578  #ifdef B115200
     579      {"B115200", B115200},
     580  #endif
     581  #ifdef B230400
     582      {"B230400", B230400},
     583  #endif
     584  #ifdef B460800
     585      {"B460800", B460800},
     586  #endif
     587  #ifdef B500000
     588      {"B500000", B500000},
     589  #endif
     590  #ifdef B576000
     591      {"B576000", B576000},
     592  #endif
     593  #ifdef B921600
     594      {"B921600", B921600},
     595  #endif
     596  #ifdef B1000000
     597      {"B1000000", B1000000},
     598  #endif
     599  #ifdef B1152000
     600      {"B1152000", B1152000},
     601  #endif
     602  #ifdef B1500000
     603      {"B1500000", B1500000},
     604  #endif
     605  #ifdef B2000000
     606      {"B2000000", B2000000},
     607  #endif
     608  #ifdef B2500000
     609      {"B2500000", B2500000},
     610  #endif
     611  #ifdef B3000000
     612      {"B3000000", B3000000},
     613  #endif
     614  #ifdef B3500000
     615      {"B3500000", B3500000},
     616  #endif
     617  #ifdef B4000000
     618      {"B4000000", B4000000},
     619  #endif
     620  
     621  #ifdef CBAUDEX
     622      {"CBAUDEX", CBAUDEX},
     623  #endif
     624  
     625      /* tcsetattr() constants */
     626      {"TCSANOW", TCSANOW},
     627      {"TCSADRAIN", TCSADRAIN},
     628      {"TCSAFLUSH", TCSAFLUSH},
     629  #ifdef TCSASOFT
     630      {"TCSASOFT", TCSASOFT},
     631  #endif
     632  
     633      /* tcflush() constants */
     634      {"TCIFLUSH", TCIFLUSH},
     635      {"TCOFLUSH", TCOFLUSH},
     636      {"TCIOFLUSH", TCIOFLUSH},
     637  
     638      /* tcflow() constants */
     639      {"TCOOFF", TCOOFF},
     640      {"TCOON", TCOON},
     641      {"TCIOFF", TCIOFF},
     642      {"TCION", TCION},
     643  
     644      /* struct termios.c_iflag constants */
     645      {"IGNBRK", IGNBRK},
     646      {"BRKINT", BRKINT},
     647      {"IGNPAR", IGNPAR},
     648      {"PARMRK", PARMRK},
     649      {"INPCK", INPCK},
     650      {"ISTRIP", ISTRIP},
     651      {"INLCR", INLCR},
     652      {"IGNCR", IGNCR},
     653      {"ICRNL", ICRNL},
     654  #ifdef IUCLC
     655      {"IUCLC", IUCLC},
     656  #endif
     657      {"IXON", IXON},
     658      {"IXANY", IXANY},
     659      {"IXOFF", IXOFF},
     660  #ifdef IMAXBEL
     661      {"IMAXBEL", IMAXBEL},
     662  #endif
     663  
     664      /* struct termios.c_oflag constants */
     665      {"OPOST", OPOST},
     666  #ifdef OLCUC
     667      {"OLCUC", OLCUC},
     668  #endif
     669  #ifdef ONLCR
     670      {"ONLCR", ONLCR},
     671  #endif
     672  #ifdef OCRNL
     673      {"OCRNL", OCRNL},
     674  #endif
     675  #ifdef ONOCR
     676      {"ONOCR", ONOCR},
     677  #endif
     678  #ifdef ONLRET
     679      {"ONLRET", ONLRET},
     680  #endif
     681  #ifdef OFILL
     682      {"OFILL", OFILL},
     683  #endif
     684  #ifdef OFDEL
     685      {"OFDEL", OFDEL},
     686  #endif
     687  #ifdef NLDLY
     688      {"NLDLY", NLDLY},
     689  #endif
     690  #ifdef CRDLY
     691      {"CRDLY", CRDLY},
     692  #endif
     693  #ifdef TABDLY
     694      {"TABDLY", TABDLY},
     695  #endif
     696  #ifdef BSDLY
     697      {"BSDLY", BSDLY},
     698  #endif
     699  #ifdef VTDLY
     700      {"VTDLY", VTDLY},
     701  #endif
     702  #ifdef FFDLY
     703      {"FFDLY", FFDLY},
     704  #endif
     705  
     706      /* struct termios.c_oflag-related values (delay mask) */
     707  #ifdef NL0
     708      {"NL0", NL0},
     709  #endif
     710  #ifdef NL1
     711      {"NL1", NL1},
     712  #endif
     713  #ifdef CR0
     714      {"CR0", CR0},
     715  #endif
     716  #ifdef CR1
     717      {"CR1", CR1},
     718  #endif
     719  #ifdef CR2
     720      {"CR2", CR2},
     721  #endif
     722  #ifdef CR3
     723      {"CR3", CR3},
     724  #endif
     725  #ifdef TAB0
     726      {"TAB0", TAB0},
     727  #endif
     728  #ifdef TAB1
     729      {"TAB1", TAB1},
     730  #endif
     731  #ifdef TAB2
     732      {"TAB2", TAB2},
     733  #endif
     734  #ifdef TAB3
     735      {"TAB3", TAB3},
     736  #endif
     737  #ifdef XTABS
     738      {"XTABS", XTABS},
     739  #endif
     740  #ifdef BS0
     741      {"BS0", BS0},
     742  #endif
     743  #ifdef BS1
     744      {"BS1", BS1},
     745  #endif
     746  #ifdef VT0
     747      {"VT0", VT0},
     748  #endif
     749  #ifdef VT1
     750      {"VT1", VT1},
     751  #endif
     752  #ifdef FF0
     753      {"FF0", FF0},
     754  #endif
     755  #ifdef FF1
     756      {"FF1", FF1},
     757  #endif
     758  
     759      /* struct termios.c_cflag constants */
     760      {"CSIZE", CSIZE},
     761      {"CSTOPB", CSTOPB},
     762      {"CREAD", CREAD},
     763      {"PARENB", PARENB},
     764      {"PARODD", PARODD},
     765      {"HUPCL", HUPCL},
     766      {"CLOCAL", CLOCAL},
     767  #ifdef CIBAUD
     768      {"CIBAUD", CIBAUD},
     769  #endif
     770  #ifdef CRTSCTS
     771      {"CRTSCTS", (long)CRTSCTS},
     772  #endif
     773  
     774      /* struct termios.c_cflag-related values (character size) */
     775      {"CS5", CS5},
     776      {"CS6", CS6},
     777      {"CS7", CS7},
     778      {"CS8", CS8},
     779  
     780      /* struct termios.c_lflag constants */
     781      {"ISIG", ISIG},
     782      {"ICANON", ICANON},
     783  #ifdef XCASE
     784      {"XCASE", XCASE},
     785  #endif
     786      {"ECHO", ECHO},
     787      {"ECHOE", ECHOE},
     788      {"ECHOK", ECHOK},
     789      {"ECHONL", ECHONL},
     790  #ifdef ECHOCTL
     791      {"ECHOCTL", ECHOCTL},
     792  #endif
     793  #ifdef ECHOPRT
     794      {"ECHOPRT", ECHOPRT},
     795  #endif
     796  #ifdef ECHOKE
     797      {"ECHOKE", ECHOKE},
     798  #endif
     799  #ifdef FLUSHO
     800      {"FLUSHO", FLUSHO},
     801  #endif
     802      {"NOFLSH", NOFLSH},
     803      {"TOSTOP", TOSTOP},
     804  #ifdef PENDIN
     805      {"PENDIN", PENDIN},
     806  #endif
     807      {"IEXTEN", IEXTEN},
     808  
     809      /* indexes into the control chars array returned by tcgetattr() */
     810      {"VINTR", VINTR},
     811      {"VQUIT", VQUIT},
     812      {"VERASE", VERASE},
     813      {"VKILL", VKILL},
     814      {"VEOF", VEOF},
     815      {"VTIME", VTIME},
     816      {"VMIN", VMIN},
     817  #ifdef VSWTC
     818      /* The #defines above ensure that if either is defined, both are,
     819       * but both may be omitted by the system headers.  ;-(  */
     820      {"VSWTC", VSWTC},
     821      {"VSWTCH", VSWTCH},
     822  #endif
     823      {"VSTART", VSTART},
     824      {"VSTOP", VSTOP},
     825      {"VSUSP", VSUSP},
     826      {"VEOL", VEOL},
     827  #ifdef VREPRINT
     828      {"VREPRINT", VREPRINT},
     829  #endif
     830  #ifdef VDISCARD
     831      {"VDISCARD", VDISCARD},
     832  #endif
     833  #ifdef VWERASE
     834      {"VWERASE", VWERASE},
     835  #endif
     836  #ifdef VLNEXT
     837      {"VLNEXT", VLNEXT},
     838  #endif
     839  #ifdef VEOL2
     840      {"VEOL2", VEOL2},
     841  #endif
     842  
     843  
     844  #ifdef B460800
     845      {"B460800", B460800},
     846  #endif
     847  #ifdef B500000
     848      {"B500000", B500000},
     849  #endif
     850  #ifdef B576000
     851      { "B576000", B576000},
     852  #endif
     853  #ifdef B921600
     854      { "B921600", B921600},
     855  #endif
     856  #ifdef B1000000
     857      { "B1000000", B1000000},
     858  #endif
     859  #ifdef B1152000
     860      { "B1152000", B1152000},
     861  #endif
     862  #ifdef B1500000
     863      { "B1500000", B1500000},
     864  #endif
     865  #ifdef B2000000
     866      { "B2000000", B2000000},
     867  #endif
     868  #ifdef B2500000
     869      { "B2500000", B2500000},
     870  #endif
     871  #ifdef B3000000
     872      { "B3000000", B3000000},
     873  #endif
     874  #ifdef B3500000
     875      { "B3500000", B3500000},
     876  #endif
     877  #ifdef B4000000
     878      { "B4000000", B4000000},
     879  #endif
     880  #ifdef CBAUD
     881      {"CBAUD", CBAUD},
     882  #endif
     883  #ifdef CDEL
     884      {"CDEL", CDEL},
     885  #endif
     886  #ifdef CDSUSP
     887      {"CDSUSP", CDSUSP},
     888  #endif
     889  #ifdef CEOF
     890      {"CEOF", CEOF},
     891  #endif
     892  #ifdef CEOL
     893      {"CEOL", CEOL},
     894  #endif
     895  #ifdef CEOL2
     896      {"CEOL2", CEOL2},
     897  #endif
     898  #ifdef CEOT
     899      {"CEOT", CEOT},
     900  #endif
     901  #ifdef CERASE
     902      {"CERASE", CERASE},
     903  #endif
     904  #ifdef CESC
     905      {"CESC", CESC},
     906  #endif
     907  #ifdef CFLUSH
     908      {"CFLUSH", CFLUSH},
     909  #endif
     910  #ifdef CINTR
     911      {"CINTR", CINTR},
     912  #endif
     913  #ifdef CKILL
     914      {"CKILL", CKILL},
     915  #endif
     916  #ifdef CLNEXT
     917      {"CLNEXT", CLNEXT},
     918  #endif
     919  #ifdef CNUL
     920      {"CNUL", CNUL},
     921  #endif
     922  #ifdef COMMON
     923      {"COMMON", COMMON},
     924  #endif
     925  #ifdef CQUIT
     926      {"CQUIT", CQUIT},
     927  #endif
     928  #ifdef CRPRNT
     929      {"CRPRNT", CRPRNT},
     930  #endif
     931  #ifdef CSTART
     932      {"CSTART", CSTART},
     933  #endif
     934  #ifdef CSTOP
     935      {"CSTOP", CSTOP},
     936  #endif
     937  #ifdef CSUSP
     938      {"CSUSP", CSUSP},
     939  #endif
     940  #ifdef CSWTCH
     941      {"CSWTCH", CSWTCH},
     942  #endif
     943  #ifdef CWERASE
     944      {"CWERASE", CWERASE},
     945  #endif
     946  #ifdef EXTA
     947      {"EXTA", EXTA},
     948  #endif
     949  #ifdef EXTB
     950      {"EXTB", EXTB},
     951  #endif
     952  #ifdef FIOASYNC
     953      {"FIOASYNC", FIOASYNC},
     954  #endif
     955  #ifdef FIOCLEX
     956      {"FIOCLEX", FIOCLEX},
     957  #endif
     958  #ifdef FIONBIO
     959      {"FIONBIO", FIONBIO},
     960  #endif
     961  #ifdef FIONCLEX
     962      {"FIONCLEX", FIONCLEX},
     963  #endif
     964  #ifdef FIONREAD
     965      {"FIONREAD", FIONREAD},
     966  #endif
     967  #ifdef IBSHIFT
     968      {"IBSHIFT", IBSHIFT},
     969  #endif
     970  #ifdef INIT_C_CC
     971      {"INIT_C_CC", INIT_C_CC},
     972  #endif
     973  #ifdef IOCSIZE_MASK
     974      {"IOCSIZE_MASK", IOCSIZE_MASK},
     975  #endif
     976  #ifdef IOCSIZE_SHIFT
     977      {"IOCSIZE_SHIFT", IOCSIZE_SHIFT},
     978  #endif
     979  #ifdef NCC
     980      {"NCC", NCC},
     981  #endif
     982  #ifdef NCCS
     983      {"NCCS", NCCS},
     984  #endif
     985  #ifdef NSWTCH
     986      {"NSWTCH", NSWTCH},
     987  #endif
     988  #ifdef N_MOUSE
     989      {"N_MOUSE", N_MOUSE},
     990  #endif
     991  #ifdef N_PPP
     992      {"N_PPP", N_PPP},
     993  #endif
     994  #ifdef N_SLIP
     995      {"N_SLIP", N_SLIP},
     996  #endif
     997  #ifdef N_STRIP
     998      {"N_STRIP", N_STRIP},
     999  #endif
    1000  #ifdef N_TTY
    1001      {"N_TTY", N_TTY},
    1002  #endif
    1003  #ifdef TCFLSH
    1004      {"TCFLSH", TCFLSH},
    1005  #endif
    1006  #ifdef TCGETA
    1007      {"TCGETA", TCGETA},
    1008  #endif
    1009  #ifdef TCGETS
    1010      {"TCGETS", TCGETS},
    1011  #endif
    1012  #ifdef TCSBRK
    1013      {"TCSBRK", TCSBRK},
    1014  #endif
    1015  #ifdef TCSBRKP
    1016      {"TCSBRKP", TCSBRKP},
    1017  #endif
    1018  #ifdef TCSETA
    1019      {"TCSETA", TCSETA},
    1020  #endif
    1021  #ifdef TCSETAF
    1022      {"TCSETAF", TCSETAF},
    1023  #endif
    1024  #ifdef TCSETAW
    1025      {"TCSETAW", TCSETAW},
    1026  #endif
    1027  #ifdef TCSETS
    1028      {"TCSETS", TCSETS},
    1029  #endif
    1030  #ifdef TCSETSF
    1031      {"TCSETSF", TCSETSF},
    1032  #endif
    1033  #ifdef TCSETSW
    1034      {"TCSETSW", TCSETSW},
    1035  #endif
    1036  #ifdef TCXONC
    1037      {"TCXONC", TCXONC},
    1038  #endif
    1039  #ifdef TIOCCONS
    1040      {"TIOCCONS", TIOCCONS},
    1041  #endif
    1042  #ifdef TIOCEXCL
    1043      {"TIOCEXCL", TIOCEXCL},
    1044  #endif
    1045  #ifdef TIOCGETD
    1046      {"TIOCGETD", TIOCGETD},
    1047  #endif
    1048  #ifdef TIOCGICOUNT
    1049      {"TIOCGICOUNT", TIOCGICOUNT},
    1050  #endif
    1051  #ifdef TIOCGLCKTRMIOS
    1052      {"TIOCGLCKTRMIOS", TIOCGLCKTRMIOS},
    1053  #endif
    1054  #ifdef TIOCGPGRP
    1055      {"TIOCGPGRP", TIOCGPGRP},
    1056  #endif
    1057  #ifdef TIOCGSERIAL
    1058      {"TIOCGSERIAL", TIOCGSERIAL},
    1059  #endif
    1060  #ifdef TIOCGSIZE
    1061      {"TIOCGSIZE", TIOCGSIZE},
    1062  #endif
    1063  #ifdef TIOCGSOFTCAR
    1064      {"TIOCGSOFTCAR", TIOCGSOFTCAR},
    1065  #endif
    1066  #ifdef TIOCGWINSZ
    1067      {"TIOCGWINSZ", TIOCGWINSZ},
    1068  #endif
    1069  #ifdef TIOCINQ
    1070      {"TIOCINQ", TIOCINQ},
    1071  #endif
    1072  #ifdef TIOCLINUX
    1073      {"TIOCLINUX", TIOCLINUX},
    1074  #endif
    1075  #ifdef TIOCMBIC
    1076      {"TIOCMBIC", TIOCMBIC},
    1077  #endif
    1078  #ifdef TIOCMBIS
    1079      {"TIOCMBIS", TIOCMBIS},
    1080  #endif
    1081  #ifdef TIOCMGET
    1082      {"TIOCMGET", TIOCMGET},
    1083  #endif
    1084  #ifdef TIOCMIWAIT
    1085      {"TIOCMIWAIT", TIOCMIWAIT},
    1086  #endif
    1087  #ifdef TIOCMSET
    1088      {"TIOCMSET", TIOCMSET},
    1089  #endif
    1090  #ifdef TIOCM_CAR
    1091      {"TIOCM_CAR", TIOCM_CAR},
    1092  #endif
    1093  #ifdef TIOCM_CD
    1094      {"TIOCM_CD", TIOCM_CD},
    1095  #endif
    1096  #ifdef TIOCM_CTS
    1097      {"TIOCM_CTS", TIOCM_CTS},
    1098  #endif
    1099  #ifdef TIOCM_DSR
    1100      {"TIOCM_DSR", TIOCM_DSR},
    1101  #endif
    1102  #ifdef TIOCM_DTR
    1103      {"TIOCM_DTR", TIOCM_DTR},
    1104  #endif
    1105  #ifdef TIOCM_LE
    1106      {"TIOCM_LE", TIOCM_LE},
    1107  #endif
    1108  #ifdef TIOCM_RI
    1109      {"TIOCM_RI", TIOCM_RI},
    1110  #endif
    1111  #ifdef TIOCM_RNG
    1112      {"TIOCM_RNG", TIOCM_RNG},
    1113  #endif
    1114  #ifdef TIOCM_RTS
    1115      {"TIOCM_RTS", TIOCM_RTS},
    1116  #endif
    1117  #ifdef TIOCM_SR
    1118      {"TIOCM_SR", TIOCM_SR},
    1119  #endif
    1120  #ifdef TIOCM_ST
    1121      {"TIOCM_ST", TIOCM_ST},
    1122  #endif
    1123  #ifdef TIOCNOTTY
    1124      {"TIOCNOTTY", TIOCNOTTY},
    1125  #endif
    1126  #ifdef TIOCNXCL
    1127      {"TIOCNXCL", TIOCNXCL},
    1128  #endif
    1129  #ifdef TIOCOUTQ
    1130      {"TIOCOUTQ", TIOCOUTQ},
    1131  #endif
    1132  #ifdef TIOCPKT
    1133      {"TIOCPKT", TIOCPKT},
    1134  #endif
    1135  #ifdef TIOCPKT_DATA
    1136      {"TIOCPKT_DATA", TIOCPKT_DATA},
    1137  #endif
    1138  #ifdef TIOCPKT_DOSTOP
    1139      {"TIOCPKT_DOSTOP", TIOCPKT_DOSTOP},
    1140  #endif
    1141  #ifdef TIOCPKT_FLUSHREAD
    1142      {"TIOCPKT_FLUSHREAD", TIOCPKT_FLUSHREAD},
    1143  #endif
    1144  #ifdef TIOCPKT_FLUSHWRITE
    1145      {"TIOCPKT_FLUSHWRITE", TIOCPKT_FLUSHWRITE},
    1146  #endif
    1147  #ifdef TIOCPKT_NOSTOP
    1148      {"TIOCPKT_NOSTOP", TIOCPKT_NOSTOP},
    1149  #endif
    1150  #ifdef TIOCPKT_START
    1151      {"TIOCPKT_START", TIOCPKT_START},
    1152  #endif
    1153  #ifdef TIOCPKT_STOP
    1154      {"TIOCPKT_STOP", TIOCPKT_STOP},
    1155  #endif
    1156  #ifdef TIOCSCTTY
    1157      {"TIOCSCTTY", TIOCSCTTY},
    1158  #endif
    1159  #ifdef TIOCSERCONFIG
    1160      {"TIOCSERCONFIG", TIOCSERCONFIG},
    1161  #endif
    1162  #ifdef TIOCSERGETLSR
    1163      {"TIOCSERGETLSR", TIOCSERGETLSR},
    1164  #endif
    1165  #ifdef TIOCSERGETMULTI
    1166      {"TIOCSERGETMULTI", TIOCSERGETMULTI},
    1167  #endif
    1168  #ifdef TIOCSERGSTRUCT
    1169      {"TIOCSERGSTRUCT", TIOCSERGSTRUCT},
    1170  #endif
    1171  #ifdef TIOCSERGWILD
    1172      {"TIOCSERGWILD", TIOCSERGWILD},
    1173  #endif
    1174  #ifdef TIOCSERSETMULTI
    1175      {"TIOCSERSETMULTI", TIOCSERSETMULTI},
    1176  #endif
    1177  #ifdef TIOCSERSWILD
    1178      {"TIOCSERSWILD", TIOCSERSWILD},
    1179  #endif
    1180  #ifdef TIOCSER_TEMT
    1181      {"TIOCSER_TEMT", TIOCSER_TEMT},
    1182  #endif
    1183  #ifdef TIOCSETD
    1184      {"TIOCSETD", TIOCSETD},
    1185  #endif
    1186  #ifdef TIOCSLCKTRMIOS
    1187      {"TIOCSLCKTRMIOS", TIOCSLCKTRMIOS},
    1188  #endif
    1189  #ifdef TIOCSPGRP
    1190      {"TIOCSPGRP", TIOCSPGRP},
    1191  #endif
    1192  #ifdef TIOCSSERIAL
    1193      {"TIOCSSERIAL", TIOCSSERIAL},
    1194  #endif
    1195  #ifdef TIOCSSIZE
    1196      {"TIOCSSIZE", TIOCSSIZE},
    1197  #endif
    1198  #ifdef TIOCSSOFTCAR
    1199      {"TIOCSSOFTCAR", TIOCSSOFTCAR},
    1200  #endif
    1201  #ifdef TIOCSTI
    1202      {"TIOCSTI", TIOCSTI},
    1203  #endif
    1204  #ifdef TIOCSWINSZ
    1205      {"TIOCSWINSZ", TIOCSWINSZ},
    1206  #endif
    1207  #ifdef TIOCTTYGSTRUCT
    1208      {"TIOCTTYGSTRUCT", TIOCTTYGSTRUCT},
    1209  #endif
    1210  
    1211      /* sentinel */
    1212      {NULL, 0}
    1213  };
    1214  
    1215  static int termiosmodule_traverse(PyObject *m, visitproc visit, void *arg) {
    1216      Py_VISIT(get_termios_state(m)->TermiosError);
    1217      return 0;
    1218  }
    1219  
    1220  static int termiosmodule_clear(PyObject *m) {
    1221      Py_CLEAR(get_termios_state(m)->TermiosError);
    1222      return 0;
    1223  }
    1224  
    1225  static void termiosmodule_free(void *m) {
    1226      termiosmodule_clear((PyObject *)m);
    1227  }
    1228  
    1229  static int
    1230  termios_exec(PyObject *mod)
    1231  {
    1232      struct constant *constant = termios_constants;
    1233      termiosmodulestate *state = get_termios_state(mod);
    1234      state->TermiosError = PyErr_NewException("termios.error", NULL, NULL);
    1235      if (state->TermiosError == NULL) {
    1236          return -1;
    1237      }
    1238      Py_INCREF(state->TermiosError);
    1239      if (PyModule_AddObject(mod, "error", state->TermiosError) < 0) {
    1240          Py_DECREF(state->TermiosError);
    1241          return -1;
    1242      }
    1243  
    1244      while (constant->name != NULL) {
    1245          if (PyModule_AddIntConstant(
    1246              mod, constant->name, constant->value) < 0) {
    1247              return -1;
    1248          }
    1249          ++constant;
    1250      }
    1251      return 0;
    1252  }
    1253  
    1254  static PyModuleDef_Slot termios_slots[] = {
    1255      {Py_mod_exec, termios_exec},
    1256      {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
    1257      {0, NULL}
    1258  };
    1259  
    1260  static struct PyModuleDef termiosmodule = {
    1261      PyModuleDef_HEAD_INIT,
    1262      .m_name = "termios",
    1263      .m_doc = termios__doc__,
    1264      .m_size = sizeof(termiosmodulestate),
    1265      .m_methods = termios_methods,
    1266      .m_slots = termios_slots,
    1267      .m_traverse = termiosmodule_traverse,
    1268      .m_clear = termiosmodule_clear,
    1269      .m_free = termiosmodule_free,
    1270  };
    1271  
    1272  PyMODINIT_FUNC PyInit_termios(void)
    1273  {
    1274      return PyModuleDef_Init(&termiosmodule);
    1275  }