1 /* termiosmodule.c -- POSIX terminal I/O module implementation. */
5 /* Apparently, on SGI, termios.h won't define CTRL if _XOPEN_SOURCE
6 is defined, so we define it here. */
8 #define CTRL(c) ((c)&037)
13 /* On OSF, sys/ioctl.h requires that struct termio already be defined,
14 * so this needs to be included first on that platform. */
17 #include <sys/ioctl.h>
19 /* HP-UX requires that this be included to pick up MDCD, MCTS, MDSR,
20 * MDTR, MRI, and MRTS (appearantly used internally by some things
21 * defined as macros; these are not used here directly).
23 #ifdef HAVE_SYS_MODEM_H
24 #include <sys/modem.h>
26 /* HP-UX requires that this be included to pick up TIOCGPGRP and friends */
27 #ifdef HAVE_SYS_BSDTTY_H
28 #include <sys/bsdtty.h>
31 PyDoc_STRVAR(termios__doc__
,
32 "This module provides an interface to the Posix calls for tty I/O control.\n\
33 For a complete description of these calls, see the Posix or Unix manual\n\
34 pages. It is only available for those Unix versions that support Posix\n\
35 termios style tty I/O control.\n\
37 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.");
41 static PyObject
*TermiosError
;
43 static int fdconv(PyObject
* obj
, void* p
)
47 fd
= PyObject_AsFileDescriptor(obj
);
55 PyDoc_STRVAR(termios_tcgetattr__doc__
,
56 "tcgetattr(fd) -> list_of_attrs\n\
58 Get the tty attributes for file descriptor fd, as follows:\n\
59 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] where cc is a list\n\
60 of the tty special characters (each a string of length 1, except the items\n\
61 with indices VMIN and VTIME, which are integers when these fields are\n\
62 defined). The interpretation of the flags and the speeds as well as the\n\
63 indexing in the cc array must be done using the symbolic constants defined\n\
67 termios_tcgetattr(PyObject
*self
, PyObject
*args
)
72 speed_t ispeed
, ospeed
;
77 if (!PyArg_ParseTuple(args
, "O&:tcgetattr",
81 if (tcgetattr(fd
, &mode
) == -1)
82 return PyErr_SetFromErrno(TermiosError
);
84 ispeed
= cfgetispeed(&mode
);
85 ospeed
= cfgetospeed(&mode
);
87 cc
= PyList_New(NCCS
);
90 for (i
= 0; i
< NCCS
; i
++) {
91 ch
= (char)mode
.c_cc
[i
];
92 v
= PyBytes_FromStringAndSize(&ch
, 1);
95 PyList_SetItem(cc
, i
, v
);
98 /* Convert the MIN and TIME slots to integer. On some systems, the
99 MIN and TIME slots are the same as the EOF and EOL slots. So we
100 only do this in noncanonical input mode. */
101 if ((mode
.c_lflag
& ICANON
) == 0) {
102 v
= PyLong_FromLong((long)mode
.c_cc
[VMIN
]);
105 PyList_SetItem(cc
, VMIN
, v
);
106 v
= PyLong_FromLong((long)mode
.c_cc
[VTIME
]);
109 PyList_SetItem(cc
, VTIME
, v
);
112 if (!(v
= PyList_New(7)))
115 PyList_SetItem(v
, 0, PyLong_FromLong((long)mode
.c_iflag
));
116 PyList_SetItem(v
, 1, PyLong_FromLong((long)mode
.c_oflag
));
117 PyList_SetItem(v
, 2, PyLong_FromLong((long)mode
.c_cflag
));
118 PyList_SetItem(v
, 3, PyLong_FromLong((long)mode
.c_lflag
));
119 PyList_SetItem(v
, 4, PyLong_FromLong((long)ispeed
));
120 PyList_SetItem(v
, 5, PyLong_FromLong((long)ospeed
));
121 PyList_SetItem(v
, 6, cc
);
122 if (PyErr_Occurred()){
132 PyDoc_STRVAR(termios_tcsetattr__doc__
,
133 "tcsetattr(fd, when, attributes) -> None\n\
135 Set the tty attributes for file descriptor fd.\n\
136 The attributes to be set are taken from the attributes argument, which\n\
137 is a list like the one returned by tcgetattr(). The when argument\n\
138 determines when the attributes are changed: termios.TCSANOW to\n\
139 change immediately, termios.TCSADRAIN to change after transmitting all\n\
140 queued output, or termios.TCSAFLUSH to change after transmitting all\n\
141 queued output and discarding all queued input. ");
144 termios_tcsetattr(PyObject
*self
, PyObject
*args
)
148 speed_t ispeed
, ospeed
;
149 PyObject
*term
, *cc
, *v
;
152 if (!PyArg_ParseTuple(args
, "O&iO:tcsetattr",
153 fdconv
, &fd
, &when
, &term
))
155 if (!PyList_Check(term
) || PyList_Size(term
) != 7) {
156 PyErr_SetString(PyExc_TypeError
,
157 "tcsetattr, arg 3: must be 7 element list");
161 /* Get the old mode, in case there are any hidden fields... */
162 if (tcgetattr(fd
, &mode
) == -1)
163 return PyErr_SetFromErrno(TermiosError
);
164 mode
.c_iflag
= (tcflag_t
) PyLong_AsLong(PyList_GetItem(term
, 0));
165 mode
.c_oflag
= (tcflag_t
) PyLong_AsLong(PyList_GetItem(term
, 1));
166 mode
.c_cflag
= (tcflag_t
) PyLong_AsLong(PyList_GetItem(term
, 2));
167 mode
.c_lflag
= (tcflag_t
) PyLong_AsLong(PyList_GetItem(term
, 3));
168 ispeed
= (speed_t
) PyLong_AsLong(PyList_GetItem(term
, 4));
169 ospeed
= (speed_t
) PyLong_AsLong(PyList_GetItem(term
, 5));
170 cc
= PyList_GetItem(term
, 6);
171 if (PyErr_Occurred())
174 if (!PyList_Check(cc
) || PyList_Size(cc
) != NCCS
) {
175 PyErr_Format(PyExc_TypeError
,
176 "tcsetattr: attributes[6] must be %d element list",
181 for (i
= 0; i
< NCCS
; i
++) {
182 v
= PyList_GetItem(cc
, i
);
184 if (PyBytes_Check(v
) && PyBytes_Size(v
) == 1)
185 mode
.c_cc
[i
] = (cc_t
) * PyBytes_AsString(v
);
186 else if (PyLong_Check(v
))
187 mode
.c_cc
[i
] = (cc_t
) PyLong_AsLong(v
);
189 PyErr_SetString(PyExc_TypeError
,
190 "tcsetattr: elements of attributes must be characters or integers");
195 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
);
206 PyDoc_STRVAR(termios_tcsendbreak__doc__
,
207 "tcsendbreak(fd, duration) -> None\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.");
214 termios_tcsendbreak(PyObject
*self
, PyObject
*args
)
218 if (!PyArg_ParseTuple(args
, "O&i:tcsendbreak",
219 fdconv
, &fd
, &duration
))
221 if (tcsendbreak(fd
, duration
) == -1)
222 return PyErr_SetFromErrno(TermiosError
);
228 PyDoc_STRVAR(termios_tcdrain__doc__
,
229 "tcdrain(fd) -> None\n\
231 Wait until all output written to file descriptor fd has been transmitted.");
234 termios_tcdrain(PyObject
*self
, PyObject
*args
)
238 if (!PyArg_ParseTuple(args
, "O&:tcdrain",
241 if (tcdrain(fd
) == -1)
242 return PyErr_SetFromErrno(TermiosError
);
248 PyDoc_STRVAR(termios_tcflush__doc__
,
249 "tcflush(fd, queue) -> None\n\
251 Discard queued data on file descriptor fd.\n\
252 The queue selector specifies which queue: termios.TCIFLUSH for the input\n\
253 queue, termios.TCOFLUSH for the output queue, or termios.TCIOFLUSH for\n\
257 termios_tcflush(PyObject
*self
, PyObject
*args
)
261 if (!PyArg_ParseTuple(args
, "O&i:tcflush",
262 fdconv
, &fd
, &queue
))
264 if (tcflush(fd
, queue
) == -1)
265 return PyErr_SetFromErrno(TermiosError
);
271 PyDoc_STRVAR(termios_tcflow__doc__
,
272 "tcflow(fd, action) -> None\n\
274 Suspend or resume input or output on file descriptor fd.\n\
275 The action argument can be termios.TCOOFF to suspend output,\n\
276 termios.TCOON to restart output, termios.TCIOFF to suspend input,\n\
277 or termios.TCION to restart input.");
280 termios_tcflow(PyObject
*self
, PyObject
*args
)
284 if (!PyArg_ParseTuple(args
, "O&i:tcflow",
285 fdconv
, &fd
, &action
))
287 if (tcflow(fd
, action
) == -1)
288 return PyErr_SetFromErrno(TermiosError
);
294 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__
},
312 #if defined(VSWTCH) && !defined(VSWTC)
316 #if defined(VSWTC) && !defined(VSWTCH)
320 static struct constant
{
323 } termios_constants
[] = {
324 /* cfgetospeed(), cfsetospeed() constants */
345 {"B115200", B115200
},
348 {"B230400", B230400
},
351 {"CBAUDEX", CBAUDEX
},
354 /* tcsetattr() constants */
355 {"TCSANOW", TCSANOW
},
356 {"TCSADRAIN", TCSADRAIN
},
357 {"TCSAFLUSH", TCSAFLUSH
},
359 /* tcflush() constants */
360 {"TCIFLUSH", TCIFLUSH
},
361 {"TCOFLUSH", TCOFLUSH
},
362 {"TCIOFLUSH", TCIOFLUSH
},
364 /* tcflow() constants */
370 /* struct termios.c_iflag constants */
387 {"IMAXBEL", IMAXBEL
},
390 /* struct termios.c_oflag constants */
432 /* struct termios.c_oflag-related values (delay mask) */
485 /* struct termios.c_cflag constants */
497 {"CRTSCTS", (long)CRTSCTS
},
500 /* struct termios.c_cflag-related values (character size) */
506 /* struct termios.c_lflag constants */
517 {"ECHOCTL", ECHOCTL
},
520 {"ECHOPRT", ECHOPRT
},
535 /* indexes into the control chars array returned by tcgetattr() */
544 /* The #defines above ensure that if either is defined, both are,
545 * but both may be omitted by the system headers. ;-( */
554 {"VREPRINT", VREPRINT
},
557 {"VDISCARD", VDISCARD
},
560 {"VWERASE", VWERASE
},
571 {"B460800", B460800
},
637 {"CWERASE", CWERASE
},
646 {"FIOASYNC", FIOASYNC
},
649 {"FIOCLEX", FIOCLEX
},
652 {"FIONBIO", FIONBIO
},
655 {"FIONCLEX", FIONCLEX
},
658 {"FIONREAD", FIONREAD
},
661 {"IBSHIFT", IBSHIFT
},
664 {"INIT_C_CC", INIT_C_CC
},
667 {"IOCSIZE_MASK", IOCSIZE_MASK
},
670 {"IOCSIZE_SHIFT", IOCSIZE_SHIFT
},
682 {"N_MOUSE", N_MOUSE
},
691 {"N_STRIP", N_STRIP
},
709 {"TCSBRKP", TCSBRKP
},
715 {"TCSETAF", TCSETAF
},
718 {"TCSETAW", TCSETAW
},
724 {"TCSETSF", TCSETSF
},
727 {"TCSETSW", TCSETSW
},
733 {"TIOCCONS", TIOCCONS
},
736 {"TIOCEXCL", TIOCEXCL
},
739 {"TIOCGETD", TIOCGETD
},
742 {"TIOCGICOUNT", TIOCGICOUNT
},
744 #ifdef TIOCGLCKTRMIOS
745 {"TIOCGLCKTRMIOS", TIOCGLCKTRMIOS
},
748 {"TIOCGPGRP", TIOCGPGRP
},
751 {"TIOCGSERIAL", TIOCGSERIAL
},
754 {"TIOCGSOFTCAR", TIOCGSOFTCAR
},
757 {"TIOCGWINSZ", TIOCGWINSZ
},
760 {"TIOCINQ", TIOCINQ
},
763 {"TIOCLINUX", TIOCLINUX
},
766 {"TIOCMBIC", TIOCMBIC
},
769 {"TIOCMBIS", TIOCMBIS
},
772 {"TIOCMGET", TIOCMGET
},
775 {"TIOCMIWAIT", TIOCMIWAIT
},
778 {"TIOCMSET", TIOCMSET
},
781 {"TIOCM_CAR", TIOCM_CAR
},
784 {"TIOCM_CD", TIOCM_CD
},
787 {"TIOCM_CTS", TIOCM_CTS
},
790 {"TIOCM_DSR", TIOCM_DSR
},
793 {"TIOCM_DTR", TIOCM_DTR
},
796 {"TIOCM_LE", TIOCM_LE
},
799 {"TIOCM_RI", TIOCM_RI
},
802 {"TIOCM_RNG", TIOCM_RNG
},
805 {"TIOCM_RTS", TIOCM_RTS
},
808 {"TIOCM_SR", TIOCM_SR
},
811 {"TIOCM_ST", TIOCM_ST
},
814 {"TIOCNOTTY", TIOCNOTTY
},
817 {"TIOCNXCL", TIOCNXCL
},
820 {"TIOCOUTQ", TIOCOUTQ
},
823 {"TIOCPKT", TIOCPKT
},
826 {"TIOCPKT_DATA", TIOCPKT_DATA
},
828 #ifdef TIOCPKT_DOSTOP
829 {"TIOCPKT_DOSTOP", TIOCPKT_DOSTOP
},
831 #ifdef TIOCPKT_FLUSHREAD
832 {"TIOCPKT_FLUSHREAD", TIOCPKT_FLUSHREAD
},
834 #ifdef TIOCPKT_FLUSHWRITE
835 {"TIOCPKT_FLUSHWRITE", TIOCPKT_FLUSHWRITE
},
837 #ifdef TIOCPKT_NOSTOP
838 {"TIOCPKT_NOSTOP", TIOCPKT_NOSTOP
},
841 {"TIOCPKT_START", TIOCPKT_START
},
844 {"TIOCPKT_STOP", TIOCPKT_STOP
},
847 {"TIOCSCTTY", TIOCSCTTY
},
850 {"TIOCSERCONFIG", TIOCSERCONFIG
},
853 {"TIOCSERGETLSR", TIOCSERGETLSR
},
855 #ifdef TIOCSERGETMULTI
856 {"TIOCSERGETMULTI", TIOCSERGETMULTI
},
858 #ifdef TIOCSERGSTRUCT
859 {"TIOCSERGSTRUCT", TIOCSERGSTRUCT
},
862 {"TIOCSERGWILD", TIOCSERGWILD
},
864 #ifdef TIOCSERSETMULTI
865 {"TIOCSERSETMULTI", TIOCSERSETMULTI
},
868 {"TIOCSERSWILD", TIOCSERSWILD
},
871 {"TIOCSER_TEMT", TIOCSER_TEMT
},
874 {"TIOCSETD", TIOCSETD
},
876 #ifdef TIOCSLCKTRMIOS
877 {"TIOCSLCKTRMIOS", TIOCSLCKTRMIOS
},
880 {"TIOCSPGRP", TIOCSPGRP
},
883 {"TIOCSSERIAL", TIOCSSERIAL
},
886 {"TIOCSSOFTCAR", TIOCSSOFTCAR
},
889 {"TIOCSTI", TIOCSTI
},
892 {"TIOCSWINSZ", TIOCSWINSZ
},
894 #ifdef TIOCTTYGSTRUCT
895 {"TIOCTTYGSTRUCT", TIOCTTYGSTRUCT
},
903 static struct PyModuleDef termiosmodule
= {
904 PyModuleDef_HEAD_INIT
,
919 struct constant
*constant
= termios_constants
;
921 m
= PyModule_Create(&termiosmodule
);
925 if (TermiosError
== NULL
) {
926 TermiosError
= PyErr_NewException("termios.error", NULL
, NULL
);
928 Py_INCREF(TermiosError
);
929 PyModule_AddObject(m
, "error", TermiosError
);
931 while (constant
->name
!= NULL
) {
932 PyModule_AddIntConstant(m
, constant
->name
, constant
->value
);