termios.c 18.4 KB
Newer Older
1 2
/* termiosmodule.c -- POSIX terminal I/O module implementation.  */

3
#include "Python.h"
4

5 6 7 8 9 10
/* Apparently, on SGI, termios.h won't define CTRL if _XOPEN_SOURCE
   is defined, so we define it here. */
#if defined(__sgi)
#define CTRL(c) ((c)&037)
#endif

11
#include <termios.h>
12 13 14
#ifdef __osf__
/* On OSF, sys/ioctl.h requires that struct termio already be defined,
 * so this needs to be included first on that platform. */
15
#include <termio.h>
16
#endif
17
#include <sys/ioctl.h>
18

19 20 21 22 23 24 25
/* HP-UX requires that this be included to pick up MDCD, MCTS, MDSR,
 * MDTR, MRI, and MRTS (appearantly used internally by some things
 * defined as macros; these are not used here directly).
 */
#ifdef HAVE_SYS_MODEM_H
#include <sys/modem.h>
#endif
26 27 28 29
/* HP-UX requires that this be included to pick up TIOCGPGRP and friends */
#ifdef HAVE_SYS_BSDTTY_H
#include <sys/bsdtty.h>
#endif
30

31 32
PyDoc_STRVAR(termios__doc__,
"This module provides an interface to the Posix calls for tty I/O control.\n\
33 34
For a complete description of these calls, see the Posix or Unix manual\n\
pages. It is only available for those Unix versions that support Posix\n\
35
termios style tty I/O control.\n\
36 37
\n\
All functions in this module take a file descriptor fd as their first\n\
38
argument. This can be an integer file descriptor, such as returned by\n\
39
sys.stdin.fileno(), or a file object, such as sys.stdin itself.");
40

41
static PyObject *TermiosError;
42

43 44 45
static int fdconv(PyObject* obj, void* p)
{
	int fd;
46

47
	fd = PyObject_AsFileDescriptor(obj);
48 49 50
	if (fd >= 0) {
		*(int*)p = fd;
		return 1;
51
	}
52
	return 0;
53
}
54

55 56
PyDoc_STRVAR(termios_tcgetattr__doc__,
"tcgetattr(fd) -> list_of_attrs\n\
57
\n\
58 59 60 61 62 63
Get the tty attributes for file descriptor fd, as follows:\n\
[iflag, oflag, cflag, lflag, ispeed, ospeed, cc] where cc is a list\n\
of the tty special characters (each a string of length 1, except the items\n\
with indices VMIN and VTIME, which are integers when these fields are\n\
defined).  The interpretation of the flags and the speeds as well as the\n\
indexing in the cc array must be done using the symbolic constants defined\n\
64
in this module.");
65

66
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
67
termios_tcgetattr(PyObject *self, PyObject *args)
68 69 70 71 72 73 74 75 76
{
	int fd;
	struct termios mode;
	PyObject *cc;
	speed_t ispeed, ospeed;
	PyObject *v;
	int i;
	char ch;

77 78
	if (!PyArg_ParseTuple(args, "O&:tcgetattr", 
			      fdconv, (void*)&fd))
79 80 81
		return NULL;

	if (tcgetattr(fd, &mode) == -1)
82
		return PyErr_SetFromErrno(TermiosError);
83 84 85 86 87 88 89 90 91

	ispeed = cfgetispeed(&mode);
	ospeed = cfgetospeed(&mode);

	cc = PyList_New(NCCS);
	if (cc == NULL)
		return NULL;
	for (i = 0; i < NCCS; i++) {
		ch = (char)mode.c_cc[i];
92
		v = PyBytes_FromStringAndSize(&ch, 1);
93
		if (v == NULL)
94
			goto err;
95 96 97 98 99 100
		PyList_SetItem(cc, i, v);
	}

	/* Convert the MIN and TIME slots to integer.  On some systems, the
	   MIN and TIME slots are the same as the EOF and EOL slots.  So we
	   only do this in noncanonical input mode.  */
101
	if ((mode.c_lflag & ICANON) == 0) {
102
		v = PyLong_FromLong((long)mode.c_cc[VMIN]);
103
		if (v == NULL)
104
			goto err;
105
		PyList_SetItem(cc, VMIN, v);
106
		v = PyLong_FromLong((long)mode.c_cc[VTIME]);
107
		if (v == NULL)
108
			goto err;
109 110 111
		PyList_SetItem(cc, VTIME, v);
	}

112 113 114
	if (!(v = PyList_New(7)))
		goto err;

115 116 117 118 119 120
	PyList_SetItem(v, 0, PyLong_FromLong((long)mode.c_iflag));
	PyList_SetItem(v, 1, PyLong_FromLong((long)mode.c_oflag));
	PyList_SetItem(v, 2, PyLong_FromLong((long)mode.c_cflag));
	PyList_SetItem(v, 3, PyLong_FromLong((long)mode.c_lflag));
	PyList_SetItem(v, 4, PyLong_FromLong((long)ispeed));
	PyList_SetItem(v, 5, PyLong_FromLong((long)ospeed));
121
	PyList_SetItem(v, 6, cc);
122 123 124 125
	if (PyErr_Occurred()){
		Py_DECREF(v);
		goto err;
	}
126
	return v;
127 128 129
  err:
	Py_DECREF(cc);
	return NULL;
130 131
}

132 133
PyDoc_STRVAR(termios_tcsetattr__doc__,
"tcsetattr(fd, when, attributes) -> None\n\
134
\n\
135 136 137
Set the tty attributes for file descriptor fd.\n\
The attributes to be set are taken from the attributes argument, which\n\
is a list like the one returned by tcgetattr(). The when argument\n\
138 139 140
determines when the attributes are changed: termios.TCSANOW to\n\
change immediately, termios.TCSADRAIN to change after transmitting all\n\
queued output, or termios.TCSAFLUSH to change after transmitting all\n\
141
queued output and discarding all queued input. ");
142

143
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
144
termios_tcsetattr(PyObject *self, PyObject *args)
145 146 147 148 149 150 151
{
	int fd, when;
	struct termios mode;
	speed_t ispeed, ospeed;
	PyObject *term, *cc, *v;
	int i;

152 153
	if (!PyArg_ParseTuple(args, "O&iO:tcsetattr", 
			      fdconv, &fd, &when, &term))
154 155
		return NULL;
	if (!PyList_Check(term) || PyList_Size(term) != 7) {
156 157
		PyErr_SetString(PyExc_TypeError, 
			     "tcsetattr, arg 3: must be 7 element list");
158 159 160
		return NULL;
	}

161 162 163
	/* Get the old mode, in case there are any hidden fields... */
	if (tcgetattr(fd, &mode) == -1)
		return PyErr_SetFromErrno(TermiosError);
164 165 166 167 168 169
	mode.c_iflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 0));
	mode.c_oflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 1));
	mode.c_cflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 2));
	mode.c_lflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 3));
	ispeed = (speed_t) PyLong_AsLong(PyList_GetItem(term, 4));
	ospeed = (speed_t) PyLong_AsLong(PyList_GetItem(term, 5));
170
	cc = PyList_GetItem(term, 6);
171 172
	if (PyErr_Occurred())
		return NULL;
173 174

	if (!PyList_Check(cc) || PyList_Size(cc) != NCCS) {
175 176 177
		PyErr_Format(PyExc_TypeError, 
			"tcsetattr: attributes[6] must be %d element list",
			     NCCS);
178 179 180 181 182
		return NULL;
	}

	for (i = 0; i < NCCS; i++) {
		v = PyList_GetItem(cc, i);
183

184 185
		if (PyBytes_Check(v) && PyBytes_Size(v) == 1)
			mode.c_cc[i] = (cc_t) * PyBytes_AsString(v);
186 187
		else if (PyLong_Check(v))
			mode.c_cc[i] = (cc_t) PyLong_AsLong(v);
188
		else {
189 190
			PyErr_SetString(PyExc_TypeError, 
     "tcsetattr: elements of attributes must be characters or integers");
191 192 193 194 195
			return NULL;
		}
	}

	if (cfsetispeed(&mode, (speed_t) ispeed) == -1)
196
		return PyErr_SetFromErrno(TermiosError);
197
	if (cfsetospeed(&mode, (speed_t) ospeed) == -1)
198
		return PyErr_SetFromErrno(TermiosError);
199
	if (tcsetattr(fd, when, &mode) == -1)
200
		return PyErr_SetFromErrno(TermiosError);
201 202 203 204 205

	Py_INCREF(Py_None);
	return Py_None;
}

206 207
PyDoc_STRVAR(termios_tcsendbreak__doc__,
"tcsendbreak(fd, duration) -> None\n\
208
\n\
209
Send a break on file descriptor fd.\n\
210
A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration\n\
211
has a system dependent meaning.");
212

213
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
214
termios_tcsendbreak(PyObject *self, PyObject *args)
215 216 217
{
	int fd, duration;

218 219
	if (!PyArg_ParseTuple(args, "O&i:tcsendbreak", 
			      fdconv, &fd, &duration))
220 221
		return NULL;
	if (tcsendbreak(fd, duration) == -1)
222
		return PyErr_SetFromErrno(TermiosError);
223 224 225 226 227

	Py_INCREF(Py_None);
	return Py_None;
}

228 229
PyDoc_STRVAR(termios_tcdrain__doc__,
"tcdrain(fd) -> None\n\
230
\n\
231
Wait until all output written to file descriptor fd has been transmitted.");
232

233
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
234
termios_tcdrain(PyObject *self, PyObject *args)
235 236 237
{
	int fd;

238 239
	if (!PyArg_ParseTuple(args, "O&:tcdrain", 
			      fdconv, &fd))
240 241
		return NULL;
	if (tcdrain(fd) == -1)
242
		return PyErr_SetFromErrno(TermiosError);
243 244 245 246 247

	Py_INCREF(Py_None);
	return Py_None;
}

248 249
PyDoc_STRVAR(termios_tcflush__doc__,
"tcflush(fd, queue) -> None\n\
250
\n\
251
Discard queued data on file descriptor fd.\n\
252 253
The queue selector specifies which queue: termios.TCIFLUSH for the input\n\
queue, termios.TCOFLUSH for the output queue, or termios.TCIOFLUSH for\n\
254
both queues. ");
255

256
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
257
termios_tcflush(PyObject *self, PyObject *args)
258 259 260
{
	int fd, queue;

261 262
	if (!PyArg_ParseTuple(args, "O&i:tcflush", 
			      fdconv, &fd, &queue))
263 264
		return NULL;
	if (tcflush(fd, queue) == -1)
265
		return PyErr_SetFromErrno(TermiosError);
266 267 268 269 270

	Py_INCREF(Py_None);
	return Py_None;
}

271 272
PyDoc_STRVAR(termios_tcflow__doc__,
"tcflow(fd, action) -> None\n\
273
\n\
274
Suspend or resume input or output on file descriptor fd.\n\
275 276
The action argument can be termios.TCOOFF to suspend output,\n\
termios.TCOON to restart output, termios.TCIOFF to suspend input,\n\
277
or termios.TCION to restart input.");
278

279
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
280
termios_tcflow(PyObject *self, PyObject *args)
281 282 283
{
	int fd, action;

284 285
	if (!PyArg_ParseTuple(args, "O&i:tcflow", 
			      fdconv, &fd, &action))
286 287
		return NULL;
	if (tcflow(fd, action) == -1)
288
		return PyErr_SetFromErrno(TermiosError);
289 290 291 292 293 294 295

	Py_INCREF(Py_None);
	return Py_None;
}

static PyMethodDef termios_methods[] =
{
296
	{"tcgetattr", termios_tcgetattr, 
297
	 METH_VARARGS, termios_tcgetattr__doc__},
298
	{"tcsetattr", termios_tcsetattr, 
299
	 METH_VARARGS, termios_tcsetattr__doc__},
300
	{"tcsendbreak", termios_tcsendbreak, 
301
	 METH_VARARGS, termios_tcsendbreak__doc__},
302
	{"tcdrain", termios_tcdrain, 
303
	 METH_VARARGS, termios_tcdrain__doc__},
304
	{"tcflush", termios_tcflush, 
305
	 METH_VARARGS, termios_tcflush__doc__},
306
	{"tcflow", termios_tcflow, 
307
	 METH_VARARGS, termios_tcflow__doc__},
308 309 310
	{NULL, NULL}
};

311

312 313 314 315 316 317 318 319
#if defined(VSWTCH) && !defined(VSWTC)
#define VSWTC VSWTCH
#endif

#if defined(VSWTC) && !defined(VSWTCH)
#define VSWTCH VSWTC
#endif

320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
static struct constant {
	char *name;
	long value;
} termios_constants[] = {
	/* cfgetospeed(), cfsetospeed() constants */
	{"B0", B0},
	{"B50", B50},
	{"B75", B75},
	{"B110", B110},
	{"B134", B134},
	{"B150", B150},
	{"B200", B200},
	{"B300", B300},
	{"B600", B600},
	{"B1200", B1200},
	{"B1800", B1800},
	{"B2400", B2400},
	{"B4800", B4800},
	{"B9600", B9600},
	{"B19200", B19200},
	{"B38400", B38400},
341
#ifdef B57600
342
	{"B57600", B57600},
343 344
#endif
#ifdef B115200
345
	{"B115200", B115200},
346
#endif
347
#ifdef B230400
348
	{"B230400", B230400},
349
#endif
350
#ifdef CBAUDEX
351
	{"CBAUDEX", CBAUDEX},
352
#endif
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379

	/* tcsetattr() constants */
	{"TCSANOW", TCSANOW},
	{"TCSADRAIN", TCSADRAIN},
	{"TCSAFLUSH", TCSAFLUSH},

	/* tcflush() constants */
	{"TCIFLUSH", TCIFLUSH},
	{"TCOFLUSH", TCOFLUSH},
	{"TCIOFLUSH", TCIOFLUSH},

	/* tcflow() constants */
	{"TCOOFF", TCOOFF},
	{"TCOON", TCOON},
	{"TCIOFF", TCIOFF},
	{"TCION", TCION},

	/* struct termios.c_iflag constants */
	{"IGNBRK", IGNBRK},
	{"BRKINT", BRKINT},
	{"IGNPAR", IGNPAR},
	{"PARMRK", PARMRK},
	{"INPCK", INPCK},
	{"ISTRIP", ISTRIP},
	{"INLCR", INLCR},
	{"IGNCR", IGNCR},
	{"ICRNL", ICRNL},
380
#ifdef IUCLC
381
	{"IUCLC", IUCLC},
382
#endif
383 384 385
	{"IXON", IXON},
	{"IXANY", IXANY},
	{"IXOFF", IXOFF},
386
#ifdef IMAXBEL
387
	{"IMAXBEL", IMAXBEL},
388
#endif
389 390 391

	/* struct termios.c_oflag constants */
	{"OPOST", OPOST},
392
#ifdef OLCUC
393
	{"OLCUC", OLCUC},
394
#endif
395
#ifdef ONLCR
396
	{"ONLCR", ONLCR},
397
#endif
398
#ifdef OCRNL
399
	{"OCRNL", OCRNL},
400 401
#endif
#ifdef ONOCR
402
	{"ONOCR", ONOCR},
403 404
#endif
#ifdef ONLRET
405
	{"ONLRET", ONLRET},
406 407
#endif
#ifdef OFILL
408
	{"OFILL", OFILL},
409 410
#endif
#ifdef OFDEL
411
	{"OFDEL", OFDEL},
412 413
#endif
#ifdef NLDLY
414
	{"NLDLY", NLDLY},
415 416
#endif
#ifdef CRDLY
417
	{"CRDLY", CRDLY},
418 419
#endif
#ifdef TABDLY
420
	{"TABDLY", TABDLY},
421 422
#endif
#ifdef BSDLY
423
	{"BSDLY", BSDLY},
424 425
#endif
#ifdef VTDLY
426
	{"VTDLY", VTDLY},
427 428
#endif
#ifdef FFDLY
429
	{"FFDLY", FFDLY},
430
#endif
431 432

	/* struct termios.c_oflag-related values (delay mask) */
433
#ifdef NL0
434
	{"NL0", NL0},
435 436
#endif
#ifdef NL1
437
	{"NL1", NL1},
438 439
#endif
#ifdef CR0
440
	{"CR0", CR0},
441 442
#endif
#ifdef CR1
443
	{"CR1", CR1},
444 445
#endif
#ifdef CR2
446
	{"CR2", CR2},
447 448
#endif
#ifdef CR3
449
	{"CR3", CR3},
450 451
#endif
#ifdef TAB0
452
	{"TAB0", TAB0},
453 454
#endif
#ifdef TAB1
455
	{"TAB1", TAB1},
456 457
#endif
#ifdef TAB2
458
	{"TAB2", TAB2},
459 460
#endif
#ifdef TAB3
461
	{"TAB3", TAB3},
462
#endif
463
#ifdef XTABS
464
	{"XTABS", XTABS},
465
#endif
466
#ifdef BS0
467
	{"BS0", BS0},
468 469
#endif
#ifdef BS1
470
	{"BS1", BS1},
471 472
#endif
#ifdef VT0
473
	{"VT0", VT0},
474 475
#endif
#ifdef VT1
476
	{"VT1", VT1},
477 478
#endif
#ifdef FF0
479
	{"FF0", FF0},
480 481
#endif
#ifdef FF1
482
	{"FF1", FF1},
483
#endif
484 485 486 487 488 489 490 491 492

	/* struct termios.c_cflag constants */
	{"CSIZE", CSIZE},
	{"CSTOPB", CSTOPB},
	{"CREAD", CREAD},
	{"PARENB", PARENB},
	{"PARODD", PARODD},
	{"HUPCL", HUPCL},
	{"CLOCAL", CLOCAL},
493
#ifdef CIBAUD
494
	{"CIBAUD", CIBAUD},
495
#endif
496 497 498
#ifdef CRTSCTS
	{"CRTSCTS", (long)CRTSCTS},
#endif
499 500 501 502 503 504 505 506 507 508

	/* struct termios.c_cflag-related values (character size) */
	{"CS5", CS5},
	{"CS6", CS6},
	{"CS7", CS7},
	{"CS8", CS8},

	/* struct termios.c_lflag constants */
	{"ISIG", ISIG},
	{"ICANON", ICANON},
509
#ifdef XCASE
510
	{"XCASE", XCASE},
511
#endif
512 513 514 515
	{"ECHO", ECHO},
	{"ECHOE", ECHOE},
	{"ECHOK", ECHOK},
	{"ECHONL", ECHONL},
516
#ifdef ECHOCTL
517
	{"ECHOCTL", ECHOCTL},
518
#endif
519
#ifdef ECHOPRT
520
	{"ECHOPRT", ECHOPRT},
521
#endif
522
#ifdef ECHOKE
523
	{"ECHOKE", ECHOKE},
524 525
#endif
#ifdef FLUSHO
526
	{"FLUSHO", FLUSHO},
527
#endif
528 529
	{"NOFLSH", NOFLSH},
	{"TOSTOP", TOSTOP},
530
#ifdef PENDIN
531
	{"PENDIN", PENDIN},
532
#endif
533 534 535 536 537 538 539 540 541 542
	{"IEXTEN", IEXTEN},

	/* indexes into the control chars array returned by tcgetattr() */
	{"VINTR", VINTR},
	{"VQUIT", VQUIT},
	{"VERASE", VERASE},
	{"VKILL", VKILL},
	{"VEOF", VEOF},
	{"VTIME", VTIME},
	{"VMIN", VMIN},
543 544 545
#ifdef VSWTC
	/* The #defines above ensure that if either is defined, both are,
         * but both may be omitted by the system headers.  ;-(  */
546
	{"VSWTC", VSWTC},
547
	{"VSWTCH", VSWTCH},
548
#endif
549 550 551 552
	{"VSTART", VSTART},
	{"VSTOP", VSTOP},
	{"VSUSP", VSUSP},
	{"VEOL", VEOL},
553
#ifdef VREPRINT
554
	{"VREPRINT", VREPRINT},
555
#endif
556
#ifdef VDISCARD
557
	{"VDISCARD", VDISCARD},
558
#endif
559
#ifdef VWERASE
560
	{"VWERASE", VWERASE},
561
#endif
562
#ifdef VLNEXT
563
	{"VLNEXT", VLNEXT},
564
#endif
565
#ifdef VEOL2
566
	{"VEOL2", VEOL2},
567
#endif
568

569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897

#ifdef B460800
	{"B460800", B460800},
#endif
#ifdef CBAUD
	{"CBAUD", CBAUD},
#endif
#ifdef CDEL
	{"CDEL", CDEL},
#endif
#ifdef CDSUSP
	{"CDSUSP", CDSUSP},
#endif
#ifdef CEOF
	{"CEOF", CEOF},
#endif
#ifdef CEOL
	{"CEOL", CEOL},
#endif
#ifdef CEOL2
	{"CEOL2", CEOL2},
#endif
#ifdef CEOT
	{"CEOT", CEOT},
#endif
#ifdef CERASE
	{"CERASE", CERASE},
#endif
#ifdef CESC
	{"CESC", CESC},
#endif
#ifdef CFLUSH
	{"CFLUSH", CFLUSH},
#endif
#ifdef CINTR
	{"CINTR", CINTR},
#endif
#ifdef CKILL
	{"CKILL", CKILL},
#endif
#ifdef CLNEXT
	{"CLNEXT", CLNEXT},
#endif
#ifdef CNUL
	{"CNUL", CNUL},
#endif
#ifdef COMMON
	{"COMMON", COMMON},
#endif
#ifdef CQUIT
	{"CQUIT", CQUIT},
#endif
#ifdef CRPRNT
	{"CRPRNT", CRPRNT},
#endif
#ifdef CSTART
	{"CSTART", CSTART},
#endif
#ifdef CSTOP
	{"CSTOP", CSTOP},
#endif
#ifdef CSUSP
	{"CSUSP", CSUSP},
#endif
#ifdef CSWTCH
	{"CSWTCH", CSWTCH},
#endif
#ifdef CWERASE
	{"CWERASE", CWERASE},
#endif
#ifdef EXTA
	{"EXTA", EXTA},
#endif
#ifdef EXTB
	{"EXTB", EXTB},
#endif
#ifdef FIOASYNC
	{"FIOASYNC", FIOASYNC},
#endif
#ifdef FIOCLEX
	{"FIOCLEX", FIOCLEX},
#endif
#ifdef FIONBIO
	{"FIONBIO", FIONBIO},
#endif
#ifdef FIONCLEX
	{"FIONCLEX", FIONCLEX},
#endif
#ifdef FIONREAD
	{"FIONREAD", FIONREAD},
#endif
#ifdef IBSHIFT
	{"IBSHIFT", IBSHIFT},
#endif
#ifdef INIT_C_CC
	{"INIT_C_CC", INIT_C_CC},
#endif
#ifdef IOCSIZE_MASK
	{"IOCSIZE_MASK", IOCSIZE_MASK},
#endif
#ifdef IOCSIZE_SHIFT
	{"IOCSIZE_SHIFT", IOCSIZE_SHIFT},
#endif
#ifdef NCC
	{"NCC", NCC},
#endif
#ifdef NCCS
	{"NCCS", NCCS},
#endif
#ifdef NSWTCH
	{"NSWTCH", NSWTCH},
#endif
#ifdef N_MOUSE
	{"N_MOUSE", N_MOUSE},
#endif
#ifdef N_PPP
	{"N_PPP", N_PPP},
#endif
#ifdef N_SLIP
	{"N_SLIP", N_SLIP},
#endif
#ifdef N_STRIP
	{"N_STRIP", N_STRIP},
#endif
#ifdef N_TTY
	{"N_TTY", N_TTY},
#endif
#ifdef TCFLSH
	{"TCFLSH", TCFLSH},
#endif
#ifdef TCGETA
	{"TCGETA", TCGETA},
#endif
#ifdef TCGETS
	{"TCGETS", TCGETS},
#endif
#ifdef TCSBRK
	{"TCSBRK", TCSBRK},
#endif
#ifdef TCSBRKP
	{"TCSBRKP", TCSBRKP},
#endif
#ifdef TCSETA
	{"TCSETA", TCSETA},
#endif
#ifdef TCSETAF
	{"TCSETAF", TCSETAF},
#endif
#ifdef TCSETAW
	{"TCSETAW", TCSETAW},
#endif
#ifdef TCSETS
	{"TCSETS", TCSETS},
#endif
#ifdef TCSETSF
	{"TCSETSF", TCSETSF},
#endif
#ifdef TCSETSW
	{"TCSETSW", TCSETSW},
#endif
#ifdef TCXONC
	{"TCXONC", TCXONC},
#endif
#ifdef TIOCCONS
	{"TIOCCONS", TIOCCONS},
#endif
#ifdef TIOCEXCL
	{"TIOCEXCL", TIOCEXCL},
#endif
#ifdef TIOCGETD
	{"TIOCGETD", TIOCGETD},
#endif
#ifdef TIOCGICOUNT
	{"TIOCGICOUNT", TIOCGICOUNT},
#endif
#ifdef TIOCGLCKTRMIOS
	{"TIOCGLCKTRMIOS", TIOCGLCKTRMIOS},
#endif
#ifdef TIOCGPGRP
	{"TIOCGPGRP", TIOCGPGRP},
#endif
#ifdef TIOCGSERIAL
	{"TIOCGSERIAL", TIOCGSERIAL},
#endif
#ifdef TIOCGSOFTCAR
	{"TIOCGSOFTCAR", TIOCGSOFTCAR},
#endif
#ifdef TIOCGWINSZ
	{"TIOCGWINSZ", TIOCGWINSZ},
#endif
#ifdef TIOCINQ
	{"TIOCINQ", TIOCINQ},
#endif
#ifdef TIOCLINUX
	{"TIOCLINUX", TIOCLINUX},
#endif
#ifdef TIOCMBIC
	{"TIOCMBIC", TIOCMBIC},
#endif
#ifdef TIOCMBIS
	{"TIOCMBIS", TIOCMBIS},
#endif
#ifdef TIOCMGET
	{"TIOCMGET", TIOCMGET},
#endif
#ifdef TIOCMIWAIT
	{"TIOCMIWAIT", TIOCMIWAIT},
#endif
#ifdef TIOCMSET
	{"TIOCMSET", TIOCMSET},
#endif
#ifdef TIOCM_CAR
	{"TIOCM_CAR", TIOCM_CAR},
#endif
#ifdef TIOCM_CD
	{"TIOCM_CD", TIOCM_CD},
#endif
#ifdef TIOCM_CTS
	{"TIOCM_CTS", TIOCM_CTS},
#endif
#ifdef TIOCM_DSR
	{"TIOCM_DSR", TIOCM_DSR},
#endif
#ifdef TIOCM_DTR
	{"TIOCM_DTR", TIOCM_DTR},
#endif
#ifdef TIOCM_LE
	{"TIOCM_LE", TIOCM_LE},
#endif
#ifdef TIOCM_RI
	{"TIOCM_RI", TIOCM_RI},
#endif
#ifdef TIOCM_RNG
	{"TIOCM_RNG", TIOCM_RNG},
#endif
#ifdef TIOCM_RTS
	{"TIOCM_RTS", TIOCM_RTS},
#endif
#ifdef TIOCM_SR
	{"TIOCM_SR", TIOCM_SR},
#endif
#ifdef TIOCM_ST
	{"TIOCM_ST", TIOCM_ST},
#endif
#ifdef TIOCNOTTY
	{"TIOCNOTTY", TIOCNOTTY},
#endif
#ifdef TIOCNXCL
	{"TIOCNXCL", TIOCNXCL},
#endif
#ifdef TIOCOUTQ
	{"TIOCOUTQ", TIOCOUTQ},
#endif
#ifdef TIOCPKT
	{"TIOCPKT", TIOCPKT},
#endif
#ifdef TIOCPKT_DATA
	{"TIOCPKT_DATA", TIOCPKT_DATA},
#endif
#ifdef TIOCPKT_DOSTOP
	{"TIOCPKT_DOSTOP", TIOCPKT_DOSTOP},
#endif
#ifdef TIOCPKT_FLUSHREAD
	{"TIOCPKT_FLUSHREAD", TIOCPKT_FLUSHREAD},
#endif
#ifdef TIOCPKT_FLUSHWRITE
	{"TIOCPKT_FLUSHWRITE", TIOCPKT_FLUSHWRITE},
#endif
#ifdef TIOCPKT_NOSTOP
	{"TIOCPKT_NOSTOP", TIOCPKT_NOSTOP},
#endif
#ifdef TIOCPKT_START
	{"TIOCPKT_START", TIOCPKT_START},
#endif
#ifdef TIOCPKT_STOP
	{"TIOCPKT_STOP", TIOCPKT_STOP},
#endif
#ifdef TIOCSCTTY
	{"TIOCSCTTY", TIOCSCTTY},
#endif
#ifdef TIOCSERCONFIG
	{"TIOCSERCONFIG", TIOCSERCONFIG},
#endif
#ifdef TIOCSERGETLSR
	{"TIOCSERGETLSR", TIOCSERGETLSR},
#endif
#ifdef TIOCSERGETMULTI
	{"TIOCSERGETMULTI", TIOCSERGETMULTI},
#endif
#ifdef TIOCSERGSTRUCT
	{"TIOCSERGSTRUCT", TIOCSERGSTRUCT},
#endif
#ifdef TIOCSERGWILD
	{"TIOCSERGWILD", TIOCSERGWILD},
#endif
#ifdef TIOCSERSETMULTI
	{"TIOCSERSETMULTI", TIOCSERSETMULTI},
#endif
#ifdef TIOCSERSWILD
	{"TIOCSERSWILD", TIOCSERSWILD},
#endif
#ifdef TIOCSER_TEMT
	{"TIOCSER_TEMT", TIOCSER_TEMT},
#endif
#ifdef TIOCSETD
	{"TIOCSETD", TIOCSETD},
#endif
#ifdef TIOCSLCKTRMIOS
	{"TIOCSLCKTRMIOS", TIOCSLCKTRMIOS},
#endif
#ifdef TIOCSPGRP
	{"TIOCSPGRP", TIOCSPGRP},
#endif
#ifdef TIOCSSERIAL
	{"TIOCSSERIAL", TIOCSSERIAL},
#endif
#ifdef TIOCSSOFTCAR
	{"TIOCSSOFTCAR", TIOCSSOFTCAR},
#endif
#ifdef TIOCSTI
	{"TIOCSTI", TIOCSTI},
#endif
#ifdef TIOCSWINSZ
	{"TIOCSWINSZ", TIOCSWINSZ},
#endif
#ifdef TIOCTTYGSTRUCT
	{"TIOCTTYGSTRUCT", TIOCTTYGSTRUCT},
#endif

898 899 900 901 902
	/* sentinel */
	{NULL, 0}
};


903 904 905 906 907 908 909 910 911 912 913 914
static struct PyModuleDef termiosmodule = {
	PyModuleDef_HEAD_INIT,
	"termios",
	termios__doc__,
	-1,
	termios_methods,
	NULL,
	NULL,
	NULL,
	NULL
};

915
PyMODINIT_FUNC
916
PyInit_termios(void)
917
{
918
	PyObject *m;
919
	struct constant *constant = termios_constants;
920

921
	m = PyModule_Create(&termiosmodule);
922
	if (m == NULL)
923
		return NULL;
924

925 926 927 928 929
	if (TermiosError == NULL) {
		TermiosError = PyErr_NewException("termios.error", NULL, NULL);
	}
	Py_INCREF(TermiosError);
	PyModule_AddObject(m, "error", TermiosError);
930 931 932 933 934

	while (constant->name != NULL) {
		PyModule_AddIntConstant(m, constant->name, constant->value);
		++constant;
	}
935
	return m;
936
}