1 /* termiosmodule.c -- POSIX terminal I/O module implementation. */
5 #define PyInit_termios inittermios
9 /* On OSF, sys/ioctl.h requires that struct termio already be defined,
10 * so this needs to be included first on that platform. */
13 #include <sys/ioctl.h>
15 /* HP-UX requires that this be included to pick up MDCD, MCTS, MDSR,
16 * MDTR, MRI, and MRTS (appearantly used internally by some things
17 * defined as macros; these are not used here directly).
19 #ifdef HAVE_SYS_MODEM_H
20 #include <sys/modem.h>
23 PyDoc_STRVAR(termios__doc__
,
24 "This module provides an interface to the Posix calls for tty I/O control.\n\
25 For a complete description of these calls, see the Posix or Unix manual\n\
26 pages. It is only available for those Unix versions that support Posix\n\
27 termios style tty I/O control.\n\
29 All functions in this module take a file descriptor fd as their first\n\
30 argument. This can be an integer file descriptor, such as returned by\n\
31 sys.stdin.fileno(), or a file object, such as sys.stdin itself.");
33 static PyObject
*TermiosError
;
35 static int fdconv(PyObject
* obj
, void* p
)
39 fd
= PyObject_AsFileDescriptor(obj
);
47 PyDoc_STRVAR(termios_tcgetattr__doc__
,
48 "tcgetattr(fd) -> list_of_attrs\n\
50 Get the tty attributes for file descriptor fd, as follows:\n\
51 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] where cc is a list\n\
52 of the tty special characters (each a string of length 1, except the items\n\
53 with indices VMIN and VTIME, which are integers when these fields are\n\
54 defined). The interpretation of the flags and the speeds as well as the\n\
55 indexing in the cc array must be done using the symbolic constants defined\n\
59 termios_tcgetattr(PyObject
*self
, PyObject
*args
)
64 speed_t ispeed
, ospeed
;
69 if (!PyArg_ParseTuple(args
, "O&:tcgetattr",
73 if (tcgetattr(fd
, &mode
) == -1)
74 return PyErr_SetFromErrno(TermiosError
);
76 ispeed
= cfgetispeed(&mode
);
77 ospeed
= cfgetospeed(&mode
);
79 cc
= PyList_New(NCCS
);
82 for (i
= 0; i
< NCCS
; i
++) {
83 ch
= (char)mode
.c_cc
[i
];
84 v
= PyString_FromStringAndSize(&ch
, 1);
87 PyList_SetItem(cc
, i
, v
);
90 /* Convert the MIN and TIME slots to integer. On some systems, the
91 MIN and TIME slots are the same as the EOF and EOL slots. So we
92 only do this in noncanonical input mode. */
93 if ((mode
.c_lflag
& ICANON
) == 0) {
94 v
= PyInt_FromLong((long)mode
.c_cc
[VMIN
]);
97 PyList_SetItem(cc
, VMIN
, v
);
98 v
= PyInt_FromLong((long)mode
.c_cc
[VTIME
]);
101 PyList_SetItem(cc
, VTIME
, v
);
104 if (!(v
= PyList_New(7)))
107 PyList_SetItem(v
, 0, PyInt_FromLong((long)mode
.c_iflag
));
108 PyList_SetItem(v
, 1, PyInt_FromLong((long)mode
.c_oflag
));
109 PyList_SetItem(v
, 2, PyInt_FromLong((long)mode
.c_cflag
));
110 PyList_SetItem(v
, 3, PyInt_FromLong((long)mode
.c_lflag
));
111 PyList_SetItem(v
, 4, PyInt_FromLong((long)ispeed
));
112 PyList_SetItem(v
, 5, PyInt_FromLong((long)ospeed
));
113 PyList_SetItem(v
, 6, cc
);
114 if (PyErr_Occurred()){
124 PyDoc_STRVAR(termios_tcsetattr__doc__
,
125 "tcsetattr(fd, when, attributes) -> None\n\
127 Set the tty attributes for file descriptor fd.\n\
128 The attributes to be set are taken from the attributes argument, which\n\
129 is a list like the one returned by tcgetattr(). The when argument\n\
130 determines when the attributes are changed: termios.TCSANOW to\n\
131 change immediately, termios.TCSADRAIN to change after transmitting all\n\
132 queued output, or termios.TCSAFLUSH to change after transmitting all\n\
133 queued output and discarding all queued input. ");
136 termios_tcsetattr(PyObject
*self
, PyObject
*args
)
140 speed_t ispeed
, ospeed
;
141 PyObject
*term
, *cc
, *v
;
144 if (!PyArg_ParseTuple(args
, "O&iO:tcsetattr",
145 fdconv
, &fd
, &when
, &term
))
147 if (!PyList_Check(term
) || PyList_Size(term
) != 7) {
148 PyErr_SetString(PyExc_TypeError
,
149 "tcsetattr, arg 3: must be 7 element list");
153 /* Get the old mode, in case there are any hidden fields... */
154 if (tcgetattr(fd
, &mode
) == -1)
155 return PyErr_SetFromErrno(TermiosError
);
156 mode
.c_iflag
= (tcflag_t
) PyInt_AsLong(PyList_GetItem(term
, 0));
157 mode
.c_oflag
= (tcflag_t
) PyInt_AsLong(PyList_GetItem(term
, 1));
158 mode
.c_cflag
= (tcflag_t
) PyInt_AsLong(PyList_GetItem(term
, 2));
159 mode
.c_lflag
= (tcflag_t
) PyInt_AsLong(PyList_GetItem(term
, 3));
160 ispeed
= (speed_t
) PyInt_AsLong(PyList_GetItem(term
, 4));
161 ospeed
= (speed_t
) PyInt_AsLong(PyList_GetItem(term
, 5));
162 cc
= PyList_GetItem(term
, 6);
163 if (PyErr_Occurred())
166 if (!PyList_Check(cc
) || PyList_Size(cc
) != NCCS
) {
167 PyErr_Format(PyExc_TypeError
,
168 "tcsetattr: attributes[6] must be %d element list",
173 for (i
= 0; i
< NCCS
; i
++) {
174 v
= PyList_GetItem(cc
, i
);
176 if (PyString_Check(v
) && PyString_Size(v
) == 1)
177 mode
.c_cc
[i
] = (cc_t
) * PyString_AsString(v
);
178 else if (PyInt_Check(v
))
179 mode
.c_cc
[i
] = (cc_t
) PyInt_AsLong(v
);
181 PyErr_SetString(PyExc_TypeError
,
182 "tcsetattr: elements of attributes must be characters or integers");
187 if (cfsetispeed(&mode
, (speed_t
) ispeed
) == -1)
188 return PyErr_SetFromErrno(TermiosError
);
189 if (cfsetospeed(&mode
, (speed_t
) ospeed
) == -1)
190 return PyErr_SetFromErrno(TermiosError
);
191 if (tcsetattr(fd
, when
, &mode
) == -1)
192 return PyErr_SetFromErrno(TermiosError
);
198 PyDoc_STRVAR(termios_tcsendbreak__doc__
,
199 "tcsendbreak(fd, duration) -> None\n\
201 Send a break on file descriptor fd.\n\
202 A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration\n\
203 has a system dependent meaning.");
206 termios_tcsendbreak(PyObject
*self
, PyObject
*args
)
210 if (!PyArg_ParseTuple(args
, "O&i:tcsendbreak",
211 fdconv
, &fd
, &duration
))
213 if (tcsendbreak(fd
, duration
) == -1)
214 return PyErr_SetFromErrno(TermiosError
);
220 PyDoc_STRVAR(termios_tcdrain__doc__
,
221 "tcdrain(fd) -> None\n\
223 Wait until all output written to file descriptor fd has been transmitted.");
226 termios_tcdrain(PyObject
*self
, PyObject
*args
)
230 if (!PyArg_ParseTuple(args
, "O&:tcdrain",
233 if (tcdrain(fd
) == -1)
234 return PyErr_SetFromErrno(TermiosError
);
240 PyDoc_STRVAR(termios_tcflush__doc__
,
241 "tcflush(fd, queue) -> None\n\
243 Discard queued data on file descriptor fd.\n\
244 The queue selector specifies which queue: termios.TCIFLUSH for the input\n\
245 queue, termios.TCOFLUSH for the output queue, or termios.TCIOFLUSH for\n\
249 termios_tcflush(PyObject
*self
, PyObject
*args
)
253 if (!PyArg_ParseTuple(args
, "O&i:tcflush",
254 fdconv
, &fd
, &queue
))
256 if (tcflush(fd
, queue
) == -1)
257 return PyErr_SetFromErrno(TermiosError
);
263 PyDoc_STRVAR(termios_tcflow__doc__
,
264 "tcflow(fd, action) -> None\n\
266 Suspend or resume input or output on file descriptor fd.\n\
267 The action argument can be termios.TCOOFF to suspend output,\n\
268 termios.TCOON to restart output, termios.TCIOFF to suspend input,\n\
269 or termios.TCION to restart input.");
272 termios_tcflow(PyObject
*self
, PyObject
*args
)
276 if (!PyArg_ParseTuple(args
, "O&i:tcflow",
277 fdconv
, &fd
, &action
))
279 if (tcflow(fd
, action
) == -1)
280 return PyErr_SetFromErrno(TermiosError
);
286 static PyMethodDef termios_methods
[] =
288 {"tcgetattr", termios_tcgetattr
,
289 METH_VARARGS
, termios_tcgetattr__doc__
},
290 {"tcsetattr", termios_tcsetattr
,
291 METH_VARARGS
, termios_tcsetattr__doc__
},
292 {"tcsendbreak", termios_tcsendbreak
,
293 METH_VARARGS
, termios_tcsendbreak__doc__
},
294 {"tcdrain", termios_tcdrain
,
295 METH_VARARGS
, termios_tcdrain__doc__
},
296 {"tcflush", termios_tcflush
,
297 METH_VARARGS
, termios_tcflush__doc__
},
298 {"tcflow", termios_tcflow
,
299 METH_VARARGS
, termios_tcflow__doc__
},
304 #if defined(VSWTCH) && !defined(VSWTC)
308 #if defined(VSWTC) && !defined(VSWTCH)
312 static struct constant
{
315 } termios_constants
[] = {
316 /* cfgetospeed(), cfsetospeed() constants */
337 {"B115200", B115200
},
340 {"B230400", B230400
},
343 {"CBAUDEX", CBAUDEX
},
346 /* tcsetattr() constants */
347 {"TCSANOW", TCSANOW
},
348 {"TCSADRAIN", TCSADRAIN
},
349 {"TCSAFLUSH", TCSAFLUSH
},
351 /* tcflush() constants */
352 {"TCIFLUSH", TCIFLUSH
},
353 {"TCOFLUSH", TCOFLUSH
},
354 {"TCIOFLUSH", TCIOFLUSH
},
356 /* tcflow() constants */
362 /* struct termios.c_iflag constants */
379 {"IMAXBEL", IMAXBEL
},
382 /* struct termios.c_oflag constants */
424 /* struct termios.c_oflag-related values (delay mask) */
477 /* struct termios.c_cflag constants */
489 {"CRTSCTS", (long)CRTSCTS
},
492 /* struct termios.c_cflag-related values (character size) */
498 /* struct termios.c_lflag constants */
509 {"ECHOCTL", ECHOCTL
},
512 {"ECHOPRT", ECHOPRT
},
527 /* indexes into the control chars array returned by tcgetattr() */
536 /* The #defines above ensure that if either is defined, both are,
537 * but both may be omitted by the system headers. ;-( */
546 {"VREPRINT", VREPRINT
},
549 {"VDISCARD", VDISCARD
},
552 {"VWERASE", VWERASE
},
563 {"B460800", B460800
},
629 {"CWERASE", CWERASE
},
638 {"FIOASYNC", FIOASYNC
},
641 {"FIOCLEX", FIOCLEX
},
644 {"FIONBIO", FIONBIO
},
647 {"FIONCLEX", FIONCLEX
},
650 {"FIONREAD", FIONREAD
},
653 {"IBSHIFT", IBSHIFT
},
656 {"INIT_C_CC", INIT_C_CC
},
659 {"IOCSIZE_MASK", IOCSIZE_MASK
},
662 {"IOCSIZE_SHIFT", IOCSIZE_SHIFT
},
674 {"N_MOUSE", N_MOUSE
},
683 {"N_STRIP", N_STRIP
},
701 {"TCSBRKP", TCSBRKP
},
707 {"TCSETAF", TCSETAF
},
710 {"TCSETAW", TCSETAW
},
716 {"TCSETSF", TCSETSF
},
719 {"TCSETSW", TCSETSW
},
725 {"TIOCCONS", TIOCCONS
},
728 {"TIOCEXCL", TIOCEXCL
},
731 {"TIOCGETD", TIOCGETD
},
734 {"TIOCGICOUNT", TIOCGICOUNT
},
736 #ifdef TIOCGLCKTRMIOS
737 {"TIOCGLCKTRMIOS", TIOCGLCKTRMIOS
},
740 {"TIOCGPGRP", TIOCGPGRP
},
743 {"TIOCGSERIAL", TIOCGSERIAL
},
746 {"TIOCGSOFTCAR", TIOCGSOFTCAR
},
749 {"TIOCGWINSZ", TIOCGWINSZ
},
752 {"TIOCINQ", TIOCINQ
},
755 {"TIOCLINUX", TIOCLINUX
},
758 {"TIOCMBIC", TIOCMBIC
},
761 {"TIOCMBIS", TIOCMBIS
},
764 {"TIOCMGET", TIOCMGET
},
767 {"TIOCMIWAIT", TIOCMIWAIT
},
770 {"TIOCMSET", TIOCMSET
},
773 {"TIOCM_CAR", TIOCM_CAR
},
776 {"TIOCM_CD", TIOCM_CD
},
779 {"TIOCM_CTS", TIOCM_CTS
},
782 {"TIOCM_DSR", TIOCM_DSR
},
785 {"TIOCM_DTR", TIOCM_DTR
},
788 {"TIOCM_LE", TIOCM_LE
},
791 {"TIOCM_RI", TIOCM_RI
},
794 {"TIOCM_RNG", TIOCM_RNG
},
797 {"TIOCM_RTS", TIOCM_RTS
},
800 {"TIOCM_SR", TIOCM_SR
},
803 {"TIOCM_ST", TIOCM_ST
},
806 {"TIOCNOTTY", TIOCNOTTY
},
809 {"TIOCNXCL", TIOCNXCL
},
812 {"TIOCOUTQ", TIOCOUTQ
},
815 {"TIOCPKT", TIOCPKT
},
818 {"TIOCPKT_DATA", TIOCPKT_DATA
},
820 #ifdef TIOCPKT_DOSTOP
821 {"TIOCPKT_DOSTOP", TIOCPKT_DOSTOP
},
823 #ifdef TIOCPKT_FLUSHREAD
824 {"TIOCPKT_FLUSHREAD", TIOCPKT_FLUSHREAD
},
826 #ifdef TIOCPKT_FLUSHWRITE
827 {"TIOCPKT_FLUSHWRITE", TIOCPKT_FLUSHWRITE
},
829 #ifdef TIOCPKT_NOSTOP
830 {"TIOCPKT_NOSTOP", TIOCPKT_NOSTOP
},
833 {"TIOCPKT_START", TIOCPKT_START
},
836 {"TIOCPKT_STOP", TIOCPKT_STOP
},
839 {"TIOCSCTTY", TIOCSCTTY
},
842 {"TIOCSERCONFIG", TIOCSERCONFIG
},
845 {"TIOCSERGETLSR", TIOCSERGETLSR
},
847 #ifdef TIOCSERGETMULTI
848 {"TIOCSERGETMULTI", TIOCSERGETMULTI
},
850 #ifdef TIOCSERGSTRUCT
851 {"TIOCSERGSTRUCT", TIOCSERGSTRUCT
},
854 {"TIOCSERGWILD", TIOCSERGWILD
},
856 #ifdef TIOCSERSETMULTI
857 {"TIOCSERSETMULTI", TIOCSERSETMULTI
},
860 {"TIOCSERSWILD", TIOCSERSWILD
},
863 {"TIOCSER_TEMT", TIOCSER_TEMT
},
866 {"TIOCSETD", TIOCSETD
},
868 #ifdef TIOCSLCKTRMIOS
869 {"TIOCSLCKTRMIOS", TIOCSLCKTRMIOS
},
872 {"TIOCSPGRP", TIOCSPGRP
},
875 {"TIOCSSERIAL", TIOCSSERIAL
},
878 {"TIOCSSOFTCAR", TIOCSSOFTCAR
},
881 {"TIOCSTI", TIOCSTI
},
884 {"TIOCSWINSZ", TIOCSWINSZ
},
886 #ifdef TIOCTTYGSTRUCT
887 {"TIOCTTYGSTRUCT", TIOCTTYGSTRUCT
},
899 struct constant
*constant
= termios_constants
;
901 m
= Py_InitModule4("termios", termios_methods
, termios__doc__
,
902 (PyObject
*)NULL
, PYTHON_API_VERSION
);
904 if (TermiosError
== NULL
) {
905 TermiosError
= PyErr_NewException("termios.error", NULL
, NULL
);
907 Py_INCREF(TermiosError
);
908 PyModule_AddObject(m
, "error", TermiosError
);
910 while (constant
->name
!= NULL
) {
911 PyModule_AddIntConstant(m
, constant
->name
, constant
->value
);