PageRenderTime 79ms CodeModel.GetById 14ms app.highlight 48ms RepoModel.GetById 1ms app.codeStats 0ms

/Modules/termios.c

http://unladen-swallow.googlecode.com/
C | 926 lines | 832 code | 66 blank | 28 comment | 60 complexity | cbbb236c6a516b379d34a4d12b9cfd30 MD5 | raw file
  1/* termiosmodule.c -- POSIX terminal I/O module implementation.  */
  2
  3#include "Python.h"
  4
  5#define PyInit_termios inittermios
  6
  7/* Apparently, on SGI, termios.h won't define CTRL if _XOPEN_SOURCE
  8   is defined, so we define it here. */
  9#if defined(__sgi)
 10#define CTRL(c) ((c)&037)
 11#endif
 12
 13#include <termios.h>
 14#ifdef __osf__
 15/* On OSF, sys/ioctl.h requires that struct termio already be defined,
 16 * so this needs to be included first on that platform. */
 17#include <termio.h>
 18#endif
 19#include <sys/ioctl.h>
 20
 21/* HP-UX requires that this be included to pick up MDCD, MCTS, MDSR,
 22 * MDTR, MRI, and MRTS (appearantly used internally by some things
 23 * defined as macros; these are not used here directly).
 24 */
 25#ifdef HAVE_SYS_MODEM_H
 26#include <sys/modem.h>
 27#endif
 28/* HP-UX requires that this be included to pick up TIOCGPGRP and friends */
 29#ifdef HAVE_SYS_BSDTTY_H
 30#include <sys/bsdtty.h>
 31#endif
 32
 33PyDoc_STRVAR(termios__doc__,
 34"This module provides an interface to the Posix calls for tty I/O control.\n\
 35For a complete description of these calls, see the Posix or Unix manual\n\
 36pages. It is only available for those Unix versions that support Posix\n\
 37termios style tty I/O control.\n\
 38\n\
 39All functions in this module take a file descriptor fd as their first\n\
 40argument. This can be an integer file descriptor, such as returned by\n\
 41sys.stdin.fileno(), or a file object, such as sys.stdin itself.");
 42
 43static PyObject *TermiosError;
 44
 45static int fdconv(PyObject* obj, void* p)
 46{
 47	int fd;
 48
 49	fd = PyObject_AsFileDescriptor(obj);
 50	if (fd >= 0) {
 51		*(int*)p = fd;
 52		return 1;
 53	}
 54	return 0;
 55}
 56
 57PyDoc_STRVAR(termios_tcgetattr__doc__,
 58"tcgetattr(fd) -> list_of_attrs\n\
 59\n\
 60Get the tty attributes for file descriptor fd, as follows:\n\
 61[iflag, oflag, cflag, lflag, ispeed, ospeed, cc] where cc is a list\n\
 62of the tty special characters (each a string of length 1, except the items\n\
 63with indices VMIN and VTIME, which are integers when these fields are\n\
 64defined).  The interpretation of the flags and the speeds as well as the\n\
 65indexing in the cc array must be done using the symbolic constants defined\n\
 66in this module.");
 67
 68static PyObject *
 69termios_tcgetattr(PyObject *self, PyObject *args)
 70{
 71	int fd;
 72	struct termios mode;
 73	PyObject *cc;
 74	speed_t ispeed, ospeed;
 75	PyObject *v;
 76	int i;
 77	char ch;
 78
 79	if (!PyArg_ParseTuple(args, "O&:tcgetattr", 
 80			      fdconv, (void*)&fd))
 81		return NULL;
 82
 83	if (tcgetattr(fd, &mode) == -1)
 84		return PyErr_SetFromErrno(TermiosError);
 85
 86	ispeed = cfgetispeed(&mode);
 87	ospeed = cfgetospeed(&mode);
 88
 89	cc = PyList_New(NCCS);
 90	if (cc == NULL)
 91		return NULL;
 92	for (i = 0; i < NCCS; i++) {
 93		ch = (char)mode.c_cc[i];
 94		v = PyString_FromStringAndSize(&ch, 1);
 95		if (v == NULL)
 96			goto err;
 97		PyList_SetItem(cc, i, v);
 98	}
 99
100	/* Convert the MIN and TIME slots to integer.  On some systems, the
101	   MIN and TIME slots are the same as the EOF and EOL slots.  So we
102	   only do this in noncanonical input mode.  */
103	if ((mode.c_lflag & ICANON) == 0) {
104		v = PyInt_FromLong((long)mode.c_cc[VMIN]);
105		if (v == NULL)
106			goto err;
107		PyList_SetItem(cc, VMIN, v);
108		v = PyInt_FromLong((long)mode.c_cc[VTIME]);
109		if (v == NULL)
110			goto err;
111		PyList_SetItem(cc, VTIME, v);
112	}
113
114	if (!(v = PyList_New(7)))
115		goto err;
116
117	PyList_SetItem(v, 0, PyInt_FromLong((long)mode.c_iflag));
118	PyList_SetItem(v, 1, PyInt_FromLong((long)mode.c_oflag));
119	PyList_SetItem(v, 2, PyInt_FromLong((long)mode.c_cflag));
120	PyList_SetItem(v, 3, PyInt_FromLong((long)mode.c_lflag));
121	PyList_SetItem(v, 4, PyInt_FromLong((long)ispeed));
122	PyList_SetItem(v, 5, PyInt_FromLong((long)ospeed));
123	PyList_SetItem(v, 6, cc);
124	if (PyErr_Occurred()){
125		Py_DECREF(v);
126		goto err;
127	}
128	return v;
129  err:
130	Py_DECREF(cc);
131	return NULL;
132}
133
134PyDoc_STRVAR(termios_tcsetattr__doc__,
135"tcsetattr(fd, when, attributes) -> None\n\
136\n\
137Set the tty attributes for file descriptor fd.\n\
138The attributes to be set are taken from the attributes argument, which\n\
139is a list like the one returned by tcgetattr(). The when argument\n\
140determines when the attributes are changed: termios.TCSANOW to\n\
141change immediately, termios.TCSADRAIN to change after transmitting all\n\
142queued output, or termios.TCSAFLUSH to change after transmitting all\n\
143queued output and discarding all queued input. ");
144
145static PyObject *
146termios_tcsetattr(PyObject *self, PyObject *args)
147{
148	int fd, when;
149	struct termios mode;
150	speed_t ispeed, ospeed;
151	PyObject *term, *cc, *v;
152	int i;
153
154	if (!PyArg_ParseTuple(args, "O&iO:tcsetattr", 
155			      fdconv, &fd, &when, &term))
156		return NULL;
157	if (!PyList_Check(term) || PyList_Size(term) != 7) {
158		PyErr_SetString(PyExc_TypeError, 
159			     "tcsetattr, arg 3: must be 7 element list");
160		return NULL;
161	}
162
163	/* Get the old mode, in case there are any hidden fields... */
164	if (tcgetattr(fd, &mode) == -1)
165		return PyErr_SetFromErrno(TermiosError);
166	mode.c_iflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 0));
167	mode.c_oflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 1));
168	mode.c_cflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 2));
169	mode.c_lflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 3));
170	ispeed = (speed_t) PyInt_AsLong(PyList_GetItem(term, 4));
171	ospeed = (speed_t) PyInt_AsLong(PyList_GetItem(term, 5));
172	cc = PyList_GetItem(term, 6);
173	if (PyErr_Occurred())
174		return NULL;
175
176	if (!PyList_Check(cc) || PyList_Size(cc) != NCCS) {
177		PyErr_Format(PyExc_TypeError, 
178			"tcsetattr: attributes[6] must be %d element list",
179			     NCCS);
180		return NULL;
181	}
182
183	for (i = 0; i < NCCS; i++) {
184		v = PyList_GetItem(cc, i);
185
186		if (PyString_Check(v) && PyString_Size(v) == 1)
187			mode.c_cc[i] = (cc_t) * PyString_AsString(v);
188		else if (PyInt_Check(v))
189			mode.c_cc[i] = (cc_t) PyInt_AsLong(v);
190		else {
191			PyErr_SetString(PyExc_TypeError, 
192     "tcsetattr: elements of attributes must be characters or integers");
193			return NULL;
194		}
195	}
196
197	if (cfsetispeed(&mode, (speed_t) ispeed) == -1)
198		return PyErr_SetFromErrno(TermiosError);
199	if (cfsetospeed(&mode, (speed_t) ospeed) == -1)
200		return PyErr_SetFromErrno(TermiosError);
201	if (tcsetattr(fd, when, &mode) == -1)
202		return PyErr_SetFromErrno(TermiosError);
203
204	Py_INCREF(Py_None);
205	return Py_None;
206}
207
208PyDoc_STRVAR(termios_tcsendbreak__doc__,
209"tcsendbreak(fd, duration) -> None\n\
210\n\
211Send a break on file descriptor fd.\n\
212A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration\n\
213has a system dependent meaning.");
214
215static PyObject *
216termios_tcsendbreak(PyObject *self, PyObject *args)
217{
218	int fd, duration;
219
220	if (!PyArg_ParseTuple(args, "O&i:tcsendbreak", 
221			      fdconv, &fd, &duration))
222		return NULL;
223	if (tcsendbreak(fd, duration) == -1)
224		return PyErr_SetFromErrno(TermiosError);
225
226	Py_INCREF(Py_None);
227	return Py_None;
228}
229
230PyDoc_STRVAR(termios_tcdrain__doc__,
231"tcdrain(fd) -> None\n\
232\n\
233Wait until all output written to file descriptor fd has been transmitted.");
234
235static PyObject *
236termios_tcdrain(PyObject *self, PyObject *args)
237{
238	int fd;
239
240	if (!PyArg_ParseTuple(args, "O&:tcdrain", 
241			      fdconv, &fd))
242		return NULL;
243	if (tcdrain(fd) == -1)
244		return PyErr_SetFromErrno(TermiosError);
245
246	Py_INCREF(Py_None);
247	return Py_None;
248}
249
250PyDoc_STRVAR(termios_tcflush__doc__,
251"tcflush(fd, queue) -> None\n\
252\n\
253Discard queued data on file descriptor fd.\n\
254The queue selector specifies which queue: termios.TCIFLUSH for the input\n\
255queue, termios.TCOFLUSH for the output queue, or termios.TCIOFLUSH for\n\
256both queues. ");
257
258static PyObject *
259termios_tcflush(PyObject *self, PyObject *args)
260{
261	int fd, queue;
262
263	if (!PyArg_ParseTuple(args, "O&i:tcflush", 
264			      fdconv, &fd, &queue))
265		return NULL;
266	if (tcflush(fd, queue) == -1)
267		return PyErr_SetFromErrno(TermiosError);
268
269	Py_INCREF(Py_None);
270	return Py_None;
271}
272
273PyDoc_STRVAR(termios_tcflow__doc__,
274"tcflow(fd, action) -> None\n\
275\n\
276Suspend or resume input or output on file descriptor fd.\n\
277The action argument can be termios.TCOOFF to suspend output,\n\
278termios.TCOON to restart output, termios.TCIOFF to suspend input,\n\
279or termios.TCION to restart input.");
280
281static PyObject *
282termios_tcflow(PyObject *self, PyObject *args)
283{
284	int fd, action;
285
286	if (!PyArg_ParseTuple(args, "O&i:tcflow", 
287			      fdconv, &fd, &action))
288		return NULL;
289	if (tcflow(fd, action) == -1)
290		return PyErr_SetFromErrno(TermiosError);
291
292	Py_INCREF(Py_None);
293	return Py_None;
294}
295
296static PyMethodDef termios_methods[] =
297{
298	{"tcgetattr", termios_tcgetattr, 
299	 METH_VARARGS, termios_tcgetattr__doc__},
300	{"tcsetattr", termios_tcsetattr, 
301	 METH_VARARGS, termios_tcsetattr__doc__},
302	{"tcsendbreak", termios_tcsendbreak, 
303	 METH_VARARGS, termios_tcsendbreak__doc__},
304	{"tcdrain", termios_tcdrain, 
305	 METH_VARARGS, termios_tcdrain__doc__},
306	{"tcflush", termios_tcflush, 
307	 METH_VARARGS, termios_tcflush__doc__},
308	{"tcflow", termios_tcflow, 
309	 METH_VARARGS, termios_tcflow__doc__},
310	{NULL, NULL}
311};
312
313
314#if defined(VSWTCH) && !defined(VSWTC)
315#define VSWTC VSWTCH
316#endif
317
318#if defined(VSWTC) && !defined(VSWTCH)
319#define VSWTCH VSWTC
320#endif
321
322static struct constant {
323	char *name;
324	long value;
325} termios_constants[] = {
326	/* cfgetospeed(), cfsetospeed() constants */
327	{"B0", B0},
328	{"B50", B50},
329	{"B75", B75},
330	{"B110", B110},
331	{"B134", B134},
332	{"B150", B150},
333	{"B200", B200},
334	{"B300", B300},
335	{"B600", B600},
336	{"B1200", B1200},
337	{"B1800", B1800},
338	{"B2400", B2400},
339	{"B4800", B4800},
340	{"B9600", B9600},
341	{"B19200", B19200},
342	{"B38400", B38400},
343#ifdef B57600
344	{"B57600", B57600},
345#endif
346#ifdef B115200
347	{"B115200", B115200},
348#endif
349#ifdef B230400
350	{"B230400", B230400},
351#endif
352#ifdef CBAUDEX
353	{"CBAUDEX", CBAUDEX},
354#endif
355
356	/* tcsetattr() constants */
357	{"TCSANOW", TCSANOW},
358	{"TCSADRAIN", TCSADRAIN},
359	{"TCSAFLUSH", TCSAFLUSH},
360
361	/* tcflush() constants */
362	{"TCIFLUSH", TCIFLUSH},
363	{"TCOFLUSH", TCOFLUSH},
364	{"TCIOFLUSH", TCIOFLUSH},
365
366	/* tcflow() constants */
367	{"TCOOFF", TCOOFF},
368	{"TCOON", TCOON},
369	{"TCIOFF", TCIOFF},
370	{"TCION", TCION},
371
372	/* struct termios.c_iflag constants */
373	{"IGNBRK", IGNBRK},
374	{"BRKINT", BRKINT},
375	{"IGNPAR", IGNPAR},
376	{"PARMRK", PARMRK},
377	{"INPCK", INPCK},
378	{"ISTRIP", ISTRIP},
379	{"INLCR", INLCR},
380	{"IGNCR", IGNCR},
381	{"ICRNL", ICRNL},
382#ifdef IUCLC
383	{"IUCLC", IUCLC},
384#endif
385	{"IXON", IXON},
386	{"IXANY", IXANY},
387	{"IXOFF", IXOFF},
388#ifdef IMAXBEL
389	{"IMAXBEL", IMAXBEL},
390#endif
391
392	/* struct termios.c_oflag constants */
393	{"OPOST", OPOST},
394#ifdef OLCUC
395	{"OLCUC", OLCUC},
396#endif
397#ifdef ONLCR
398	{"ONLCR", ONLCR},
399#endif
400#ifdef OCRNL
401	{"OCRNL", OCRNL},
402#endif
403#ifdef ONOCR
404	{"ONOCR", ONOCR},
405#endif
406#ifdef ONLRET
407	{"ONLRET", ONLRET},
408#endif
409#ifdef OFILL
410	{"OFILL", OFILL},
411#endif
412#ifdef OFDEL
413	{"OFDEL", OFDEL},
414#endif
415#ifdef NLDLY
416	{"NLDLY", NLDLY},
417#endif
418#ifdef CRDLY
419	{"CRDLY", CRDLY},
420#endif
421#ifdef TABDLY
422	{"TABDLY", TABDLY},
423#endif
424#ifdef BSDLY
425	{"BSDLY", BSDLY},
426#endif
427#ifdef VTDLY
428	{"VTDLY", VTDLY},
429#endif
430#ifdef FFDLY
431	{"FFDLY", FFDLY},
432#endif
433
434	/* struct termios.c_oflag-related values (delay mask) */
435#ifdef NL0
436	{"NL0", NL0},
437#endif
438#ifdef NL1
439	{"NL1", NL1},
440#endif
441#ifdef CR0
442	{"CR0", CR0},
443#endif
444#ifdef CR1
445	{"CR1", CR1},
446#endif
447#ifdef CR2
448	{"CR2", CR2},
449#endif
450#ifdef CR3
451	{"CR3", CR3},
452#endif
453#ifdef TAB0
454	{"TAB0", TAB0},
455#endif
456#ifdef TAB1
457	{"TAB1", TAB1},
458#endif
459#ifdef TAB2
460	{"TAB2", TAB2},
461#endif
462#ifdef TAB3
463	{"TAB3", TAB3},
464#endif
465#ifdef XTABS
466	{"XTABS", XTABS},
467#endif
468#ifdef BS0
469	{"BS0", BS0},
470#endif
471#ifdef BS1
472	{"BS1", BS1},
473#endif
474#ifdef VT0
475	{"VT0", VT0},
476#endif
477#ifdef VT1
478	{"VT1", VT1},
479#endif
480#ifdef FF0
481	{"FF0", FF0},
482#endif
483#ifdef FF1
484	{"FF1", FF1},
485#endif
486
487	/* struct termios.c_cflag constants */
488	{"CSIZE", CSIZE},
489	{"CSTOPB", CSTOPB},
490	{"CREAD", CREAD},
491	{"PARENB", PARENB},
492	{"PARODD", PARODD},
493	{"HUPCL", HUPCL},
494	{"CLOCAL", CLOCAL},
495#ifdef CIBAUD
496	{"CIBAUD", CIBAUD},
497#endif
498#ifdef CRTSCTS
499	{"CRTSCTS", (long)CRTSCTS},
500#endif
501
502	/* struct termios.c_cflag-related values (character size) */
503	{"CS5", CS5},
504	{"CS6", CS6},
505	{"CS7", CS7},
506	{"CS8", CS8},
507
508	/* struct termios.c_lflag constants */
509	{"ISIG", ISIG},
510	{"ICANON", ICANON},
511#ifdef XCASE
512	{"XCASE", XCASE},
513#endif
514	{"ECHO", ECHO},
515	{"ECHOE", ECHOE},
516	{"ECHOK", ECHOK},
517	{"ECHONL", ECHONL},
518#ifdef ECHOCTL
519	{"ECHOCTL", ECHOCTL},
520#endif
521#ifdef ECHOPRT
522	{"ECHOPRT", ECHOPRT},
523#endif
524#ifdef ECHOKE
525	{"ECHOKE", ECHOKE},
526#endif
527#ifdef FLUSHO
528	{"FLUSHO", FLUSHO},
529#endif
530	{"NOFLSH", NOFLSH},
531	{"TOSTOP", TOSTOP},
532#ifdef PENDIN
533	{"PENDIN", PENDIN},
534#endif
535	{"IEXTEN", IEXTEN},
536
537	/* indexes into the control chars array returned by tcgetattr() */
538	{"VINTR", VINTR},
539	{"VQUIT", VQUIT},
540	{"VERASE", VERASE},
541	{"VKILL", VKILL},
542	{"VEOF", VEOF},
543	{"VTIME", VTIME},
544	{"VMIN", VMIN},
545#ifdef VSWTC
546	/* The #defines above ensure that if either is defined, both are,
547         * but both may be omitted by the system headers.  ;-(  */
548	{"VSWTC", VSWTC},
549	{"VSWTCH", VSWTCH},
550#endif
551	{"VSTART", VSTART},
552	{"VSTOP", VSTOP},
553	{"VSUSP", VSUSP},
554	{"VEOL", VEOL},
555#ifdef VREPRINT
556	{"VREPRINT", VREPRINT},
557#endif
558#ifdef VDISCARD
559	{"VDISCARD", VDISCARD},
560#endif
561#ifdef VWERASE
562	{"VWERASE", VWERASE},
563#endif
564#ifdef VLNEXT
565	{"VLNEXT", VLNEXT},
566#endif
567#ifdef VEOL2
568	{"VEOL2", VEOL2},
569#endif
570
571
572#ifdef B460800
573	{"B460800", B460800},
574#endif
575#ifdef CBAUD
576	{"CBAUD", CBAUD},
577#endif
578#ifdef CDEL
579	{"CDEL", CDEL},
580#endif
581#ifdef CDSUSP
582	{"CDSUSP", CDSUSP},
583#endif
584#ifdef CEOF
585	{"CEOF", CEOF},
586#endif
587#ifdef CEOL
588	{"CEOL", CEOL},
589#endif
590#ifdef CEOL2
591	{"CEOL2", CEOL2},
592#endif
593#ifdef CEOT
594	{"CEOT", CEOT},
595#endif
596#ifdef CERASE
597	{"CERASE", CERASE},
598#endif
599#ifdef CESC
600	{"CESC", CESC},
601#endif
602#ifdef CFLUSH
603	{"CFLUSH", CFLUSH},
604#endif
605#ifdef CINTR
606	{"CINTR", CINTR},
607#endif
608#ifdef CKILL
609	{"CKILL", CKILL},
610#endif
611#ifdef CLNEXT
612	{"CLNEXT", CLNEXT},
613#endif
614#ifdef CNUL
615	{"CNUL", CNUL},
616#endif
617#ifdef COMMON
618	{"COMMON", COMMON},
619#endif
620#ifdef CQUIT
621	{"CQUIT", CQUIT},
622#endif
623#ifdef CRPRNT
624	{"CRPRNT", CRPRNT},
625#endif
626#ifdef CSTART
627	{"CSTART", CSTART},
628#endif
629#ifdef CSTOP
630	{"CSTOP", CSTOP},
631#endif
632#ifdef CSUSP
633	{"CSUSP", CSUSP},
634#endif
635#ifdef CSWTCH
636	{"CSWTCH", CSWTCH},
637#endif
638#ifdef CWERASE
639	{"CWERASE", CWERASE},
640#endif
641#ifdef EXTA
642	{"EXTA", EXTA},
643#endif
644#ifdef EXTB
645	{"EXTB", EXTB},
646#endif
647#ifdef FIOASYNC
648	{"FIOASYNC", FIOASYNC},
649#endif
650#ifdef FIOCLEX
651	{"FIOCLEX", FIOCLEX},
652#endif
653#ifdef FIONBIO
654	{"FIONBIO", FIONBIO},
655#endif
656#ifdef FIONCLEX
657	{"FIONCLEX", FIONCLEX},
658#endif
659#ifdef FIONREAD
660	{"FIONREAD", FIONREAD},
661#endif
662#ifdef IBSHIFT
663	{"IBSHIFT", IBSHIFT},
664#endif
665#ifdef INIT_C_CC
666	{"INIT_C_CC", INIT_C_CC},
667#endif
668#ifdef IOCSIZE_MASK
669	{"IOCSIZE_MASK", IOCSIZE_MASK},
670#endif
671#ifdef IOCSIZE_SHIFT
672	{"IOCSIZE_SHIFT", IOCSIZE_SHIFT},
673#endif
674#ifdef NCC
675	{"NCC", NCC},
676#endif
677#ifdef NCCS
678	{"NCCS", NCCS},
679#endif
680#ifdef NSWTCH
681	{"NSWTCH", NSWTCH},
682#endif
683#ifdef N_MOUSE
684	{"N_MOUSE", N_MOUSE},
685#endif
686#ifdef N_PPP
687	{"N_PPP", N_PPP},
688#endif
689#ifdef N_SLIP
690	{"N_SLIP", N_SLIP},
691#endif
692#ifdef N_STRIP
693	{"N_STRIP", N_STRIP},
694#endif
695#ifdef N_TTY
696	{"N_TTY", N_TTY},
697#endif
698#ifdef TCFLSH
699	{"TCFLSH", TCFLSH},
700#endif
701#ifdef TCGETA
702	{"TCGETA", TCGETA},
703#endif
704#ifdef TCGETS
705	{"TCGETS", TCGETS},
706#endif
707#ifdef TCSBRK
708	{"TCSBRK", TCSBRK},
709#endif
710#ifdef TCSBRKP
711	{"TCSBRKP", TCSBRKP},
712#endif
713#ifdef TCSETA
714	{"TCSETA", TCSETA},
715#endif
716#ifdef TCSETAF
717	{"TCSETAF", TCSETAF},
718#endif
719#ifdef TCSETAW
720	{"TCSETAW", TCSETAW},
721#endif
722#ifdef TCSETS
723	{"TCSETS", TCSETS},
724#endif
725#ifdef TCSETSF
726	{"TCSETSF", TCSETSF},
727#endif
728#ifdef TCSETSW
729	{"TCSETSW", TCSETSW},
730#endif
731#ifdef TCXONC
732	{"TCXONC", TCXONC},
733#endif
734#ifdef TIOCCONS
735	{"TIOCCONS", TIOCCONS},
736#endif
737#ifdef TIOCEXCL
738	{"TIOCEXCL", TIOCEXCL},
739#endif
740#ifdef TIOCGETD
741	{"TIOCGETD", TIOCGETD},
742#endif
743#ifdef TIOCGICOUNT
744	{"TIOCGICOUNT", TIOCGICOUNT},
745#endif
746#ifdef TIOCGLCKTRMIOS
747	{"TIOCGLCKTRMIOS", TIOCGLCKTRMIOS},
748#endif
749#ifdef TIOCGPGRP
750	{"TIOCGPGRP", TIOCGPGRP},
751#endif
752#ifdef TIOCGSERIAL
753	{"TIOCGSERIAL", TIOCGSERIAL},
754#endif
755#ifdef TIOCGSOFTCAR
756	{"TIOCGSOFTCAR", TIOCGSOFTCAR},
757#endif
758#ifdef TIOCGWINSZ
759	{"TIOCGWINSZ", TIOCGWINSZ},
760#endif
761#ifdef TIOCINQ
762	{"TIOCINQ", TIOCINQ},
763#endif
764#ifdef TIOCLINUX
765	{"TIOCLINUX", TIOCLINUX},
766#endif
767#ifdef TIOCMBIC
768	{"TIOCMBIC", TIOCMBIC},
769#endif
770#ifdef TIOCMBIS
771	{"TIOCMBIS", TIOCMBIS},
772#endif
773#ifdef TIOCMGET
774	{"TIOCMGET", TIOCMGET},
775#endif
776#ifdef TIOCMIWAIT
777	{"TIOCMIWAIT", TIOCMIWAIT},
778#endif
779#ifdef TIOCMSET
780	{"TIOCMSET", TIOCMSET},
781#endif
782#ifdef TIOCM_CAR
783	{"TIOCM_CAR", TIOCM_CAR},
784#endif
785#ifdef TIOCM_CD
786	{"TIOCM_CD", TIOCM_CD},
787#endif
788#ifdef TIOCM_CTS
789	{"TIOCM_CTS", TIOCM_CTS},
790#endif
791#ifdef TIOCM_DSR
792	{"TIOCM_DSR", TIOCM_DSR},
793#endif
794#ifdef TIOCM_DTR
795	{"TIOCM_DTR", TIOCM_DTR},
796#endif
797#ifdef TIOCM_LE
798	{"TIOCM_LE", TIOCM_LE},
799#endif
800#ifdef TIOCM_RI
801	{"TIOCM_RI", TIOCM_RI},
802#endif
803#ifdef TIOCM_RNG
804	{"TIOCM_RNG", TIOCM_RNG},
805#endif
806#ifdef TIOCM_RTS
807	{"TIOCM_RTS", TIOCM_RTS},
808#endif
809#ifdef TIOCM_SR
810	{"TIOCM_SR", TIOCM_SR},
811#endif
812#ifdef TIOCM_ST
813	{"TIOCM_ST", TIOCM_ST},
814#endif
815#ifdef TIOCNOTTY
816	{"TIOCNOTTY", TIOCNOTTY},
817#endif
818#ifdef TIOCNXCL
819	{"TIOCNXCL", TIOCNXCL},
820#endif
821#ifdef TIOCOUTQ
822	{"TIOCOUTQ", TIOCOUTQ},
823#endif
824#ifdef TIOCPKT
825	{"TIOCPKT", TIOCPKT},
826#endif
827#ifdef TIOCPKT_DATA
828	{"TIOCPKT_DATA", TIOCPKT_DATA},
829#endif
830#ifdef TIOCPKT_DOSTOP
831	{"TIOCPKT_DOSTOP", TIOCPKT_DOSTOP},
832#endif
833#ifdef TIOCPKT_FLUSHREAD
834	{"TIOCPKT_FLUSHREAD", TIOCPKT_FLUSHREAD},
835#endif
836#ifdef TIOCPKT_FLUSHWRITE
837	{"TIOCPKT_FLUSHWRITE", TIOCPKT_FLUSHWRITE},
838#endif
839#ifdef TIOCPKT_NOSTOP
840	{"TIOCPKT_NOSTOP", TIOCPKT_NOSTOP},
841#endif
842#ifdef TIOCPKT_START
843	{"TIOCPKT_START", TIOCPKT_START},
844#endif
845#ifdef TIOCPKT_STOP
846	{"TIOCPKT_STOP", TIOCPKT_STOP},
847#endif
848#ifdef TIOCSCTTY
849	{"TIOCSCTTY", TIOCSCTTY},
850#endif
851#ifdef TIOCSERCONFIG
852	{"TIOCSERCONFIG", TIOCSERCONFIG},
853#endif
854#ifdef TIOCSERGETLSR
855	{"TIOCSERGETLSR", TIOCSERGETLSR},
856#endif
857#ifdef TIOCSERGETMULTI
858	{"TIOCSERGETMULTI", TIOCSERGETMULTI},
859#endif
860#ifdef TIOCSERGSTRUCT
861	{"TIOCSERGSTRUCT", TIOCSERGSTRUCT},
862#endif
863#ifdef TIOCSERGWILD
864	{"TIOCSERGWILD", TIOCSERGWILD},
865#endif
866#ifdef TIOCSERSETMULTI
867	{"TIOCSERSETMULTI", TIOCSERSETMULTI},
868#endif
869#ifdef TIOCSERSWILD
870	{"TIOCSERSWILD", TIOCSERSWILD},
871#endif
872#ifdef TIOCSER_TEMT
873	{"TIOCSER_TEMT", TIOCSER_TEMT},
874#endif
875#ifdef TIOCSETD
876	{"TIOCSETD", TIOCSETD},
877#endif
878#ifdef TIOCSLCKTRMIOS
879	{"TIOCSLCKTRMIOS", TIOCSLCKTRMIOS},
880#endif
881#ifdef TIOCSPGRP
882	{"TIOCSPGRP", TIOCSPGRP},
883#endif
884#ifdef TIOCSSERIAL
885	{"TIOCSSERIAL", TIOCSSERIAL},
886#endif
887#ifdef TIOCSSOFTCAR
888	{"TIOCSSOFTCAR", TIOCSSOFTCAR},
889#endif
890#ifdef TIOCSTI
891	{"TIOCSTI", TIOCSTI},
892#endif
893#ifdef TIOCSWINSZ
894	{"TIOCSWINSZ", TIOCSWINSZ},
895#endif
896#ifdef TIOCTTYGSTRUCT
897	{"TIOCTTYGSTRUCT", TIOCTTYGSTRUCT},
898#endif
899
900	/* sentinel */
901	{NULL, 0}
902};
903
904
905PyMODINIT_FUNC
906PyInit_termios(void)
907{
908	PyObject *m;
909	struct constant *constant = termios_constants;
910
911	m = Py_InitModule4("termios", termios_methods, termios__doc__,
912                           (PyObject *)NULL, PYTHON_API_VERSION);
913	if (m == NULL)
914		return;
915
916	if (TermiosError == NULL) {
917		TermiosError = PyErr_NewException("termios.error", NULL, NULL);
918	}
919	Py_INCREF(TermiosError);
920	PyModule_AddObject(m, "error", TermiosError);
921
922	while (constant->name != NULL) {
923		PyModule_AddIntConstant(m, constant->name, constant->value);
924		++constant;
925	}
926}