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>
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>
27 static char termios__doc__
[] = "\
28 This module provides an interface to the Posix calls for tty I/O control.\n\
29 For a complete description of these calls, see the Posix or Unix manual\n\
30 pages. It is only available for those Unix versions that support Posix\n\
31 termios style tty I/O control.\n\
33 All functions in this module take a file descriptor fd as their first\n\
34 argument. This can be an integer file descriptor, such as returned by\n\
35 sys.stdin.fileno(), or a file object, such as sys.stdin itself.";
37 static PyObject
*TermiosError
;
39 static int fdconv(PyObject
* obj
, void* p
)
43 fd
= PyObject_AsFileDescriptor(obj
);
51 static char termios_tcgetattr__doc__
[] = "\
52 tcgetattr(fd) -> list_of_attrs\n\
54 Get the tty attributes for file descriptor fd, as follows:\n\
55 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] where cc is a list\n\
56 of the tty special characters (each a string of length 1, except the items\n\
57 with indices VMIN and VTIME, which are integers when these fields are\n\
58 defined). The interpretation of the flags and the speeds as well as the\n\
59 indexing in the cc array must be done using the symbolic constants defined\n\
63 termios_tcgetattr(PyObject
*self
, PyObject
*args
)
68 speed_t ispeed
, ospeed
;
73 if (!PyArg_ParseTuple(args
, "O&:tcgetattr",
77 if (tcgetattr(fd
, &mode
) == -1)
78 return PyErr_SetFromErrno(TermiosError
);
80 ispeed
= cfgetispeed(&mode
);
81 ospeed
= cfgetospeed(&mode
);
83 cc
= PyList_New(NCCS
);
86 for (i
= 0; i
< NCCS
; i
++) {
87 ch
= (char)mode
.c_cc
[i
];
88 v
= PyString_FromStringAndSize(&ch
, 1);
91 PyList_SetItem(cc
, i
, v
);
94 /* Convert the MIN and TIME slots to integer. On some systems, the
95 MIN and TIME slots are the same as the EOF and EOL slots. So we
96 only do this in noncanonical input mode. */
97 if ((mode
.c_lflag
& ICANON
) == 0) {
98 v
= PyInt_FromLong((long)mode
.c_cc
[VMIN
]);
101 PyList_SetItem(cc
, VMIN
, v
);
102 v
= PyInt_FromLong((long)mode
.c_cc
[VTIME
]);
105 PyList_SetItem(cc
, VTIME
, v
);
108 if (!(v
= PyList_New(7)))
111 PyList_SetItem(v
, 0, PyInt_FromLong((long)mode
.c_iflag
));
112 PyList_SetItem(v
, 1, PyInt_FromLong((long)mode
.c_oflag
));
113 PyList_SetItem(v
, 2, PyInt_FromLong((long)mode
.c_cflag
));
114 PyList_SetItem(v
, 3, PyInt_FromLong((long)mode
.c_lflag
));
115 PyList_SetItem(v
, 4, PyInt_FromLong((long)ispeed
));
116 PyList_SetItem(v
, 5, PyInt_FromLong((long)ospeed
));
117 PyList_SetItem(v
, 6, cc
);
118 if (PyErr_Occurred()){
128 static char termios_tcsetattr__doc__
[] = "\
129 tcsetattr(fd, when, attributes) -> None\n\
131 Set the tty attributes for file descriptor fd.\n\
132 The attributes to be set are taken from the attributes argument, which\n\
133 is a list like the one returned by tcgetattr(). The when argument\n\
134 determines when the attributes are changed: termios.TCSANOW to\n\
135 change immediately, termios.TCSADRAIN to change after transmitting all\n\
136 queued output, or termios.TCSAFLUSH to change after transmitting all\n\
137 queued output and discarding all queued input. ";
140 termios_tcsetattr(PyObject
*self
, PyObject
*args
)
144 speed_t ispeed
, ospeed
;
145 PyObject
*term
, *cc
, *v
;
148 if (!PyArg_ParseTuple(args
, "O&iO:tcsetattr",
149 fdconv
, &fd
, &when
, &term
))
151 if (!PyList_Check(term
) || PyList_Size(term
) != 7) {
152 PyErr_SetString(PyExc_TypeError
,
153 "tcsetattr, arg 3: must be 7 element list");
157 /* Get the old mode, in case there are any hidden fields... */
158 if (tcgetattr(fd
, &mode
) == -1)
159 return PyErr_SetFromErrno(TermiosError
);
160 mode
.c_iflag
= (tcflag_t
) PyInt_AsLong(PyList_GetItem(term
, 0));
161 mode
.c_oflag
= (tcflag_t
) PyInt_AsLong(PyList_GetItem(term
, 1));
162 mode
.c_cflag
= (tcflag_t
) PyInt_AsLong(PyList_GetItem(term
, 2));
163 mode
.c_lflag
= (tcflag_t
) PyInt_AsLong(PyList_GetItem(term
, 3));
164 ispeed
= (speed_t
) PyInt_AsLong(PyList_GetItem(term
, 4));
165 ospeed
= (speed_t
) PyInt_AsLong(PyList_GetItem(term
, 5));
166 cc
= PyList_GetItem(term
, 6);
167 if (PyErr_Occurred())
170 if (!PyList_Check(cc
) || PyList_Size(cc
) != NCCS
) {
171 PyErr_Format(PyExc_TypeError
,
172 "tcsetattr: attributes[6] must be %d element list",
177 for (i
= 0; i
< NCCS
; i
++) {
178 v
= PyList_GetItem(cc
, i
);
180 if (PyString_Check(v
) && PyString_Size(v
) == 1)
181 mode
.c_cc
[i
] = (cc_t
) * PyString_AsString(v
);
182 else if (PyInt_Check(v
))
183 mode
.c_cc
[i
] = (cc_t
) PyInt_AsLong(v
);
185 PyErr_SetString(PyExc_TypeError
,
186 "tcsetattr: elements of attributes must be characters or integers");
191 if (cfsetispeed(&mode
, (speed_t
) ispeed
) == -1)
192 return PyErr_SetFromErrno(TermiosError
);
193 if (cfsetospeed(&mode
, (speed_t
) ospeed
) == -1)
194 return PyErr_SetFromErrno(TermiosError
);
195 if (tcsetattr(fd
, when
, &mode
) == -1)
196 return PyErr_SetFromErrno(TermiosError
);
202 static char termios_tcsendbreak__doc__
[] = "\
203 tcsendbreak(fd, duration) -> None\n\
205 Send a break on file descriptor fd.\n\
206 A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration\n\
207 has a system dependent meaning.";
210 termios_tcsendbreak(PyObject
*self
, PyObject
*args
)
214 if (!PyArg_ParseTuple(args
, "O&i:tcsendbreak",
215 fdconv
, &fd
, &duration
))
217 if (tcsendbreak(fd
, duration
) == -1)
218 return PyErr_SetFromErrno(TermiosError
);
224 static char termios_tcdrain__doc__
[] = "\
225 tcdrain(fd) -> None\n\
227 Wait until all output written to file descriptor fd has been transmitted.";
230 termios_tcdrain(PyObject
*self
, PyObject
*args
)
234 if (!PyArg_ParseTuple(args
, "O&:tcdrain",
237 if (tcdrain(fd
) == -1)
238 return PyErr_SetFromErrno(TermiosError
);
244 static char termios_tcflush__doc__
[] = "\
245 tcflush(fd, queue) -> None\n\
247 Discard queued data on file descriptor fd.\n\
248 The queue selector specifies which queue: termios.TCIFLUSH for the input\n\
249 queue, termios.TCOFLUSH for the output queue, or termios.TCIOFLUSH for\n\
253 termios_tcflush(PyObject
*self
, PyObject
*args
)
257 if (!PyArg_ParseTuple(args
, "O&i:tcflush",
258 fdconv
, &fd
, &queue
))
260 if (tcflush(fd
, queue
) == -1)
261 return PyErr_SetFromErrno(TermiosError
);
267 static char termios_tcflow__doc__
[] = "\
268 tcflow(fd, action) -> None\n\
270 Suspend or resume input or output on file descriptor fd.\n\
271 The action argument can be termios.TCOOFF to suspend output,\n\
272 termios.TCOON to restart output, termios.TCIOFF to suspend input,\n\
273 or termios.TCION to restart input.";
276 termios_tcflow(PyObject
*self
, PyObject
*args
)
280 if (!PyArg_ParseTuple(args
, "O&i:tcflow",
281 fdconv
, &fd
, &action
))
283 if (tcflow(fd
, action
) == -1)
284 return PyErr_SetFromErrno(TermiosError
);
290 static PyMethodDef termios_methods
[] =
292 {"tcgetattr", termios_tcgetattr
,
293 METH_VARARGS
, termios_tcgetattr__doc__
},
294 {"tcsetattr", termios_tcsetattr
,
295 METH_VARARGS
, termios_tcsetattr__doc__
},
296 {"tcsendbreak", termios_tcsendbreak
,
297 METH_VARARGS
, termios_tcsendbreak__doc__
},
298 {"tcdrain", termios_tcdrain
,
299 METH_VARARGS
, termios_tcdrain__doc__
},
300 {"tcflush", termios_tcflush
,
301 METH_VARARGS
, termios_tcflush__doc__
},
302 {"tcflow", termios_tcflow
,
303 METH_VARARGS
, termios_tcflow__doc__
},
308 #if defined(VSWTCH) && !defined(VSWTC)
312 #if defined(VSWTC) && !defined(VSWTCH)
316 static struct constant
{
319 } termios_constants
[] = {
320 /* cfgetospeed(), cfsetospeed() constants */
341 {"B115200", B115200
},
344 {"B230400", B230400
},
347 {"CBAUDEX", CBAUDEX
},
350 /* tcsetattr() constants */
351 {"TCSANOW", TCSANOW
},
352 {"TCSADRAIN", TCSADRAIN
},
353 {"TCSAFLUSH", TCSAFLUSH
},
355 /* tcflush() constants */
356 {"TCIFLUSH", TCIFLUSH
},
357 {"TCOFLUSH", TCOFLUSH
},
358 {"TCIOFLUSH", TCIOFLUSH
},
360 /* tcflow() constants */
366 /* struct termios.c_iflag constants */
383 {"IMAXBEL", IMAXBEL
},
386 /* struct termios.c_oflag constants */
426 /* struct termios.c_oflag-related values (delay mask) */
479 /* struct termios.c_cflag constants */
491 {"CRTSCTS", (long)CRTSCTS
},
494 /* struct termios.c_cflag-related values (character size) */
500 /* struct termios.c_lflag constants */
511 {"ECHOCTL", ECHOCTL
},
514 {"ECHOPRT", ECHOPRT
},
529 /* indexes into the control chars array returned by tcgetattr() */
538 /* The #defines above ensure that if either is defined, both are,
539 * but both may be omitted by the system headers. ;-( */
548 {"VREPRINT", VREPRINT
},
551 {"VDISCARD", VDISCARD
},
554 {"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 d
= PyModule_GetDict(m
);
905 TermiosError
= PyErr_NewException("termios.error", NULL
, NULL
);
906 PyDict_SetItemString(d
, "error", TermiosError
);
908 while (constant
->name
!= NULL
) {
909 PyModule_AddIntConstant(m
, constant
->name
, constant
->value
);