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] 33module termios 34[clinic start generated code]*/ 35/*[clinic end generated code: output=da39a3ee5e6b4b0d input=01105c85d0ca7252]*/ 36 37#include "clinic/termios.c.h" 38 39PyDoc_STRVAR(termios__doc__, 40"This module provides an interface to the Posix calls for tty I/O control.\n\ 41For a complete description of these calls, see the Posix or Unix manual\n\ 42pages. It is only available for those Unix versions that support Posix\n\ 43termios style tty I/O control.\n\ 44\n\ 45All functions in this module take a file descriptor fd as their first\n\ 46argument. This can be an integer file descriptor, such as returned by\n\ 47sys.stdin.fileno(), or a file object, such as sys.stdin itself."); 48 49typedef struct { 50 PyObject *TermiosError; 51} termiosmodulestate; 52 53static inline termiosmodulestate* 54get_termios_state(PyObject *module) 55{ 56 void *state = PyModule_GetState(module); 57 assert(state != NULL); 58 return (termiosmodulestate *)state; 59} 60 61static struct PyModuleDef termiosmodule; 62 63/*[clinic input] 64termios.tcgetattr 65 66 fd: fildes 67 / 68 69Get the tty attributes for file descriptor fd. 70 71Returns a list [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] 72where cc is a list of the tty special characters (each a string of 73length 1, except the items with indices VMIN and VTIME, which are 74integers when these fields are defined). The interpretation of the 75flags and the speeds as well as the indexing in the cc array must be 76done using the symbolic constants defined in this module. 77[clinic start generated code]*/ 78 79static PyObject * 80termios_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] 147termios.tcsetattr 148 149 fd: fildes 150 when: int 151 attributes as term: object 152 / 153 154Set the tty attributes for file descriptor fd. 155 156The attributes to be set are taken from the attributes argument, which 157is a list like the one returned by tcgetattr(). The when argument 158determines when the attributes are changed: termios.TCSANOW to 159change immediately, termios.TCSADRAIN to change after transmitting all 160queued output, or termios.TCSAFLUSH to change after transmitting all 161queued output and discarding all queued input. 162[clinic start generated code]*/ 163 164static PyObject * 165termios_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] 236termios.tcsendbreak 237 238 fd: fildes 239 duration: int 240 / 241 242Send a break on file descriptor fd. 243 244A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration 245has a system dependent meaning. 246[clinic start generated code]*/ 247 248static PyObject * 249termios_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] 267termios.tcdrain 268 269 fd: fildes 270 / 271 272Wait until all output written to file descriptor fd has been transmitted. 273[clinic start generated code]*/ 274 275static PyObject * 276termios_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] 294termios.tcflush 295 296 fd: fildes 297 queue: int 298 / 299 300Discard queued data on file descriptor fd. 301 302The queue selector specifies which queue: termios.TCIFLUSH for the input 303queue, termios.TCOFLUSH for the output queue, or termios.TCIOFLUSH for 304both queues. 305[clinic start generated code]*/ 306 307static PyObject * 308termios_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] 326termios.tcflow 327 328 fd: fildes 329 action: int 330 / 331 332Suspend or resume input or output on file descriptor fd. 333 334The action argument can be termios.TCOOFF to suspend output, 335termios.TCOON to restart output, termios.TCIOFF to suspend input, 336or termios.TCION to restart input. 337[clinic start generated code]*/ 338 339static PyObject * 340termios_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] 358termios.tcgetwinsize 359 360 fd: fildes 361 / 362 363Get the tty winsize for file descriptor fd. 364 365Returns a tuple (ws_row, ws_col). 366[clinic start generated code]*/ 367 368static PyObject * 369termios_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] 429termios.tcsetwinsize 430 431 fd: fildes 432 winsize as winsz: object 433 / 434 435Set the tty winsize for file descriptor fd. 436 437The winsize to be set is taken from the winsize argument, which 438is a two-item tuple (ws_row, ws_col) like the one returned by tcgetwinsize(). 439[clinic start generated code]*/ 440 441static PyObject * 442termios_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 532static 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 554static 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 1215static int termiosmodule_traverse(PyObject *m, visitproc visit, void *arg) { 1216 Py_VISIT(get_termios_state(m)->TermiosError); 1217 return 0; 1218} 1219 1220static int termiosmodule_clear(PyObject *m) { 1221 Py_CLEAR(get_termios_state(m)->TermiosError); 1222 return 0; 1223} 1224 1225static void termiosmodule_free(void *m) { 1226 termiosmodule_clear((PyObject *)m); 1227} 1228 1229static int 1230termios_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 1254static PyModuleDef_Slot termios_slots[] = { 1255 {Py_mod_exec, termios_exec}, 1256 {0, NULL} 1257}; 1258 1259static 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 1271PyMODINIT_FUNC PyInit_termios(void) 1272{ 1273 return PyModuleDef_Init(&termiosmodule); 1274} 1275