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