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*
get_termios_state(PyObject * module)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 *
termios_tcgetattr_impl(PyObject * module,int fd)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 *
termios_tcsetattr_impl(PyObject * module,int fd,int when,PyObject * term)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 *
termios_tcsendbreak_impl(PyObject * module,int fd,int duration)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 *
termios_tcdrain_impl(PyObject * module,int fd)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 *
termios_tcflush_impl(PyObject * module,int fd,int queue)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 *
termios_tcflow_impl(PyObject * module,int fd,int action)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 *
termios_tcgetwinsize_impl(PyObject * module,int fd)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 *
termios_tcsetwinsize_impl(PyObject * module,int fd,PyObject * winsz)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
termiosmodule_traverse(PyObject * m,visitproc visit,void * arg)1215 static int termiosmodule_traverse(PyObject *m, visitproc visit, void *arg) {
1216 Py_VISIT(get_termios_state(m)->TermiosError);
1217 return 0;
1218 }
1219
termiosmodule_clear(PyObject * m)1220 static int termiosmodule_clear(PyObject *m) {
1221 Py_CLEAR(get_termios_state(m)->TermiosError);
1222 return 0;
1223 }
1224
termiosmodule_free(void * m)1225 static void termiosmodule_free(void *m) {
1226 termiosmodule_clear((PyObject *)m);
1227 }
1228
1229 static int
termios_exec(PyObject * mod)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 {0, NULL}
1257 };
1258
1259 static struct PyModuleDef termiosmodule = {
1260 PyModuleDef_HEAD_INIT,
1261 .m_name = "termios",
1262 .m_doc = termios__doc__,
1263 .m_size = sizeof(termiosmodulestate),
1264 .m_methods = termios_methods,
1265 .m_slots = termios_slots,
1266 .m_traverse = termiosmodule_traverse,
1267 .m_clear = termiosmodule_clear,
1268 .m_free = termiosmodule_free,
1269 };
1270
PyInit_termios(void)1271 PyMODINIT_FUNC PyInit_termios(void)
1272 {
1273 return PyModuleDef_Init(&termiosmodule);
1274 }
1275