1 /* termiosmodule.c -- POSIX terminal I/O module implementation. */
5 #define PyInit_termios inittermios
7 /* Apparently, on SGI, termios.h won't define CTRL if _XOPEN_SOURCE
8 is defined, so we define it here. */
10 #define CTRL(c) ((c)&037)
15 /* On OSF, sys/ioctl.h requires that struct termio already be defined,
16 * so this needs to be included first on that platform. */
19 #include <sys/ioctl.h>
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).
25 #ifdef HAVE_SYS_MODEM_H
26 #include <sys/modem.h>
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>
33 PyDoc_STRVAR(termios__doc__
,
34 "This module provides an interface to the Posix calls for tty I/O control.\n\
35 For a complete description of these calls, see the Posix or Unix manual\n\
36 pages. It is only available for those Unix versions that support Posix\n\
37 termios style tty I/O control.\n\
39 All functions in this module take a file descriptor fd as their first\n\
40 argument. This can be an integer file descriptor, such as returned by\n\
41 sys.stdin.fileno(), or a file object, such as sys.stdin itself.");
43 static PyObject
*TermiosError
;
45 static int fdconv(PyObject
* obj
, void* p
)
49 fd
= PyObject_AsFileDescriptor(obj
);
57 PyDoc_STRVAR(termios_tcgetattr__doc__
,
58 "tcgetattr(fd) -> list_of_attrs\n\
60 Get the tty attributes for file descriptor fd, as follows:\n\
61 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] where cc is a list\n\
62 of the tty special characters (each a string of length 1, except the items\n\
63 with indices VMIN and VTIME, which are integers when these fields are\n\
64 defined). The interpretation of the flags and the speeds as well as the\n\
65 indexing in the cc array must be done using the symbolic constants defined\n\
69 termios_tcgetattr(PyObject
*self
, PyObject
*args
)
74 speed_t ispeed
, ospeed
;
79 if (!PyArg_ParseTuple(args
, "O&:tcgetattr",
83 if (tcgetattr(fd
, &mode
) == -1)
84 return PyErr_SetFromErrno(TermiosError
);
86 ispeed
= cfgetispeed(&mode
);
87 ospeed
= cfgetospeed(&mode
);
89 cc
= PyList_New(NCCS
);
92 for (i
= 0; i
< NCCS
; i
++) {
93 ch
= (char)mode
.c_cc
[i
];
94 v
= PyString_FromStringAndSize(&ch
, 1);
97 PyList_SetItem(cc
, i
, v
);
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
]);
107 PyList_SetItem(cc
, VMIN
, v
);
108 v
= PyInt_FromLong((long)mode
.c_cc
[VTIME
]);
111 PyList_SetItem(cc
, VTIME
, v
);
114 if (!(v
= PyList_New(7)))
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()){
134 PyDoc_STRVAR(termios_tcsetattr__doc__
,
135 "tcsetattr(fd, when, attributes) -> None\n\
137 Set the tty attributes for file descriptor fd.\n\
138 The attributes to be set are taken from the attributes argument, which\n\
139 is a list like the one returned by tcgetattr(). The when argument\n\
140 determines when the attributes are changed: termios.TCSANOW to\n\
141 change immediately, termios.TCSADRAIN to change after transmitting all\n\
142 queued output, or termios.TCSAFLUSH to change after transmitting all\n\
143 queued output and discarding all queued input. ");
146 termios_tcsetattr(PyObject
*self
, PyObject
*args
)
150 speed_t ispeed
, ospeed
;
151 PyObject
*term
, *cc
, *v
;
154 if (!PyArg_ParseTuple(args
, "O&iO:tcsetattr",
155 fdconv
, &fd
, &when
, &term
))
157 if (!PyList_Check(term
) || PyList_Size(term
) != 7) {
158 PyErr_SetString(PyExc_TypeError
,
159 "tcsetattr, arg 3: must be 7 element list");
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())
176 if (!PyList_Check(cc
) || PyList_Size(cc
) != NCCS
) {
177 PyErr_Format(PyExc_TypeError
,
178 "tcsetattr: attributes[6] must be %d element list",
183 for (i
= 0; i
< NCCS
; i
++) {
184 v
= PyList_GetItem(cc
, i
);
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
);
191 PyErr_SetString(PyExc_TypeError
,
192 "tcsetattr: elements of attributes must be characters or integers");
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
);
208 PyDoc_STRVAR(termios_tcsendbreak__doc__
,
209 "tcsendbreak(fd, duration) -> None\n\
211 Send a break on file descriptor fd.\n\
212 A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration\n\
213 has a system dependent meaning.");
216 termios_tcsendbreak(PyObject
*self
, PyObject
*args
)
220 if (!PyArg_ParseTuple(args
, "O&i:tcsendbreak",
221 fdconv
, &fd
, &duration
))
223 if (tcsendbreak(fd
, duration
) == -1)
224 return PyErr_SetFromErrno(TermiosError
);
230 PyDoc_STRVAR(termios_tcdrain__doc__
,
231 "tcdrain(fd) -> None\n\
233 Wait until all output written to file descriptor fd has been transmitted.");
236 termios_tcdrain(PyObject
*self
, PyObject
*args
)
240 if (!PyArg_ParseTuple(args
, "O&:tcdrain",
243 if (tcdrain(fd
) == -1)
244 return PyErr_SetFromErrno(TermiosError
);
250 PyDoc_STRVAR(termios_tcflush__doc__
,
251 "tcflush(fd, queue) -> None\n\
253 Discard queued data on file descriptor fd.\n\
254 The queue selector specifies which queue: termios.TCIFLUSH for the input\n\
255 queue, termios.TCOFLUSH for the output queue, or termios.TCIOFLUSH for\n\
259 termios_tcflush(PyObject
*self
, PyObject
*args
)
263 if (!PyArg_ParseTuple(args
, "O&i:tcflush",
264 fdconv
, &fd
, &queue
))
266 if (tcflush(fd
, queue
) == -1)
267 return PyErr_SetFromErrno(TermiosError
);
273 PyDoc_STRVAR(termios_tcflow__doc__
,
274 "tcflow(fd, action) -> None\n\
276 Suspend or resume input or output on file descriptor fd.\n\
277 The action argument can be termios.TCOOFF to suspend output,\n\
278 termios.TCOON to restart output, termios.TCIOFF to suspend input,\n\
279 or termios.TCION to restart input.");
282 termios_tcflow(PyObject
*self
, PyObject
*args
)
286 if (!PyArg_ParseTuple(args
, "O&i:tcflow",
287 fdconv
, &fd
, &action
))
289 if (tcflow(fd
, action
) == -1)
290 return PyErr_SetFromErrno(TermiosError
);
296 static PyMethodDef termios_methods
[] =
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__
},
314 #if defined(VSWTCH) && !defined(VSWTC)
318 #if defined(VSWTC) && !defined(VSWTCH)
322 static struct constant
{
325 } termios_constants
[] = {
326 /* cfgetospeed(), cfsetospeed() constants */
347 {"B115200", B115200
},
350 {"B230400", B230400
},
353 {"CBAUDEX", CBAUDEX
},
356 /* tcsetattr() constants */
357 {"TCSANOW", TCSANOW
},
358 {"TCSADRAIN", TCSADRAIN
},
359 {"TCSAFLUSH", TCSAFLUSH
},
361 /* tcflush() constants */
362 {"TCIFLUSH", TCIFLUSH
},
363 {"TCOFLUSH", TCOFLUSH
},
364 {"TCIOFLUSH", TCIOFLUSH
},
366 /* tcflow() constants */
372 /* struct termios.c_iflag constants */
389 {"IMAXBEL", IMAXBEL
},
392 /* struct termios.c_oflag constants */
434 /* struct termios.c_oflag-related values (delay mask) */
487 /* struct termios.c_cflag constants */
499 {"CRTSCTS", (long)CRTSCTS
},
502 /* struct termios.c_cflag-related values (character size) */
508 /* struct termios.c_lflag constants */
519 {"ECHOCTL", ECHOCTL
},
522 {"ECHOPRT", ECHOPRT
},
537 /* indexes into the control chars array returned by tcgetattr() */
546 /* The #defines above ensure that if either is defined, both are,
547 * but both may be omitted by the system headers. ;-( */
556 {"VREPRINT", VREPRINT
},
559 {"VDISCARD", VDISCARD
},
562 {"VWERASE", VWERASE
},
573 {"B460800", B460800
},
639 {"CWERASE", CWERASE
},
648 {"FIOASYNC", FIOASYNC
},
651 {"FIOCLEX", FIOCLEX
},
654 {"FIONBIO", FIONBIO
},
657 {"FIONCLEX", FIONCLEX
},
660 {"FIONREAD", FIONREAD
},
663 {"IBSHIFT", IBSHIFT
},
666 {"INIT_C_CC", INIT_C_CC
},
669 {"IOCSIZE_MASK", IOCSIZE_MASK
},
672 {"IOCSIZE_SHIFT", IOCSIZE_SHIFT
},
684 {"N_MOUSE", N_MOUSE
},
693 {"N_STRIP", N_STRIP
},
711 {"TCSBRKP", TCSBRKP
},
717 {"TCSETAF", TCSETAF
},
720 {"TCSETAW", TCSETAW
},
726 {"TCSETSF", TCSETSF
},
729 {"TCSETSW", TCSETSW
},
735 {"TIOCCONS", TIOCCONS
},
738 {"TIOCEXCL", TIOCEXCL
},
741 {"TIOCGETD", TIOCGETD
},
744 {"TIOCGICOUNT", TIOCGICOUNT
},
746 #ifdef TIOCGLCKTRMIOS
747 {"TIOCGLCKTRMIOS", TIOCGLCKTRMIOS
},
750 {"TIOCGPGRP", TIOCGPGRP
},
753 {"TIOCGSERIAL", TIOCGSERIAL
},
756 {"TIOCGSOFTCAR", TIOCGSOFTCAR
},
759 {"TIOCGWINSZ", TIOCGWINSZ
},
762 {"TIOCINQ", TIOCINQ
},
765 {"TIOCLINUX", TIOCLINUX
},
768 {"TIOCMBIC", TIOCMBIC
},
771 {"TIOCMBIS", TIOCMBIS
},
774 {"TIOCMGET", TIOCMGET
},
777 {"TIOCMIWAIT", TIOCMIWAIT
},
780 {"TIOCMSET", TIOCMSET
},
783 {"TIOCM_CAR", TIOCM_CAR
},
786 {"TIOCM_CD", TIOCM_CD
},
789 {"TIOCM_CTS", TIOCM_CTS
},
792 {"TIOCM_DSR", TIOCM_DSR
},
795 {"TIOCM_DTR", TIOCM_DTR
},
798 {"TIOCM_LE", TIOCM_LE
},
801 {"TIOCM_RI", TIOCM_RI
},
804 {"TIOCM_RNG", TIOCM_RNG
},
807 {"TIOCM_RTS", TIOCM_RTS
},
810 {"TIOCM_SR", TIOCM_SR
},
813 {"TIOCM_ST", TIOCM_ST
},
816 {"TIOCNOTTY", TIOCNOTTY
},
819 {"TIOCNXCL", TIOCNXCL
},
822 {"TIOCOUTQ", TIOCOUTQ
},
825 {"TIOCPKT", TIOCPKT
},
828 {"TIOCPKT_DATA", TIOCPKT_DATA
},
830 #ifdef TIOCPKT_DOSTOP
831 {"TIOCPKT_DOSTOP", TIOCPKT_DOSTOP
},
833 #ifdef TIOCPKT_FLUSHREAD
834 {"TIOCPKT_FLUSHREAD", TIOCPKT_FLUSHREAD
},
836 #ifdef TIOCPKT_FLUSHWRITE
837 {"TIOCPKT_FLUSHWRITE", TIOCPKT_FLUSHWRITE
},
839 #ifdef TIOCPKT_NOSTOP
840 {"TIOCPKT_NOSTOP", TIOCPKT_NOSTOP
},
843 {"TIOCPKT_START", TIOCPKT_START
},
846 {"TIOCPKT_STOP", TIOCPKT_STOP
},
849 {"TIOCSCTTY", TIOCSCTTY
},
852 {"TIOCSERCONFIG", TIOCSERCONFIG
},
855 {"TIOCSERGETLSR", TIOCSERGETLSR
},
857 #ifdef TIOCSERGETMULTI
858 {"TIOCSERGETMULTI", TIOCSERGETMULTI
},
860 #ifdef TIOCSERGSTRUCT
861 {"TIOCSERGSTRUCT", TIOCSERGSTRUCT
},
864 {"TIOCSERGWILD", TIOCSERGWILD
},
866 #ifdef TIOCSERSETMULTI
867 {"TIOCSERSETMULTI", TIOCSERSETMULTI
},
870 {"TIOCSERSWILD", TIOCSERSWILD
},
873 {"TIOCSER_TEMT", TIOCSER_TEMT
},
876 {"TIOCSETD", TIOCSETD
},
878 #ifdef TIOCSLCKTRMIOS
879 {"TIOCSLCKTRMIOS", TIOCSLCKTRMIOS
},
882 {"TIOCSPGRP", TIOCSPGRP
},
885 {"TIOCSSERIAL", TIOCSSERIAL
},
888 {"TIOCSSOFTCAR", TIOCSSOFTCAR
},
891 {"TIOCSTI", TIOCSTI
},
894 {"TIOCSWINSZ", TIOCSWINSZ
},
896 #ifdef TIOCTTYGSTRUCT
897 {"TIOCTTYGSTRUCT", TIOCTTYGSTRUCT
},
909 struct constant
*constant
= termios_constants
;
911 m
= Py_InitModule4("termios", termios_methods
, termios__doc__
,
912 (PyObject
*)NULL
, PYTHON_API_VERSION
);
916 if (TermiosError
== NULL
) {
917 TermiosError
= PyErr_NewException("termios.error", NULL
, NULL
);
919 Py_INCREF(TermiosError
);
920 PyModule_AddObject(m
, "error", TermiosError
);
922 while (constant
->name
!= NULL
) {
923 PyModule_AddIntConstant(m
, constant
->name
, constant
->value
);