blob: 91ab4840e8f90a07761ba34c9542967540e4b77f [file] [log] [blame]
Guido van Rossum9adae8e1994-09-12 10:41:22 +00001/* termiosmodule.c -- POSIX terminal I/O module implementation. */
2
Guido van Rossumca6954a1999-01-14 19:31:42 +00003#include "Python.h"
Guido van Rossum9adae8e1994-09-12 10:41:22 +00004
5#define PyInit_termios inittermios
6
Guido van Rossum9adae8e1994-09-12 10:41:22 +00007#include <termios.h>
8
Guido van Rossum1aca4d81998-03-03 22:10:18 +00009static char termios__doc__[] = "\
10This module provides an interface to the Posix calls for tty I/O control.\n\
11For a complete description of these calls, see the Posix or Unix manual\n\
12pages. It is only available for those Unix versions that support Posix\n\
13termios style tty I/O control (and then only if configured at installation\n\
14time).\n\
15\n\
16All functions in this module take a file descriptor fd as their first\n\
17argument. This must be an integer file descriptor, such as returned by\n\
18sys.stdin.fileno().\n\
19\n\
20This module should be used in conjunction with the TERMIOS module,\n\
21which defines the relevant symbolic constants.";
22
23
Guido van Rossumbcc20741998-08-04 22:53:56 +000024#ifdef __BEOS__
25#include <unistd.h>
26#endif
27
Guido van Rossum9adae8e1994-09-12 10:41:22 +000028#define BAD "bad termios argument"
29
30static PyObject *TermiosError;
31
32/* termios = tcgetattr(fd)
33 termios is
34 [iflag, oflag, cflag, lflag, ispeed, ospeed, [cc[0], ..., cc[NCCS]]]
35
36 Return the attributes of the terminal device. */
37
Guido van Rossum1aca4d81998-03-03 22:10:18 +000038static char termios_tcgetattr__doc__[] = "\
39tcgetattr(fd) -> list_of_attrs\n\
40Get the tty attributes for file descriptor fd, as follows:\n\
41[iflag, oflag, cflag, lflag, ispeed, ospeed, cc] where cc is a list\n\
42of the tty special characters (each a string of length 1, except the items\n\
43with indices VMIN and VTIME, which are integers when these fields are\n\
44defined). The interpretation of the flags and the speeds as well as the\n\
45indexing in the cc array must be done using the symbolic constants defined\n\
46in the TERMIOS module.";
47
Guido van Rossum9adae8e1994-09-12 10:41:22 +000048static PyObject *
Peter Schneider-Kamp416d4132000-07-10 12:15:54 +000049termios_tcgetattr(PyObject *self, PyObject *args)
Guido van Rossum9adae8e1994-09-12 10:41:22 +000050{
51 int fd;
52 struct termios mode;
53 PyObject *cc;
54 speed_t ispeed, ospeed;
55 PyObject *v;
56 int i;
57 char ch;
58
59 if (!PyArg_Parse(args, "i", &fd))
60 return NULL;
61
62 if (tcgetattr(fd, &mode) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +000063 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +000064
65 ispeed = cfgetispeed(&mode);
66 ospeed = cfgetospeed(&mode);
67
68 cc = PyList_New(NCCS);
69 if (cc == NULL)
70 return NULL;
71 for (i = 0; i < NCCS; i++) {
72 ch = (char)mode.c_cc[i];
73 v = PyString_FromStringAndSize(&ch, 1);
74 if (v == NULL)
Barry Warsaw5709dcf1997-01-10 18:42:18 +000075 goto err;
Guido van Rossum9adae8e1994-09-12 10:41:22 +000076 PyList_SetItem(cc, i, v);
77 }
78
79 /* Convert the MIN and TIME slots to integer. On some systems, the
80 MIN and TIME slots are the same as the EOF and EOL slots. So we
81 only do this in noncanonical input mode. */
Guido van Rossum36dd0d21996-12-10 15:23:00 +000082 if ((mode.c_lflag & ICANON) == 0) {
Guido van Rossum9adae8e1994-09-12 10:41:22 +000083 v = PyInt_FromLong((long)mode.c_cc[VMIN]);
84 if (v == NULL)
Barry Warsaw5709dcf1997-01-10 18:42:18 +000085 goto err;
Guido van Rossum9adae8e1994-09-12 10:41:22 +000086 PyList_SetItem(cc, VMIN, v);
87 v = PyInt_FromLong((long)mode.c_cc[VTIME]);
88 if (v == NULL)
Barry Warsaw5709dcf1997-01-10 18:42:18 +000089 goto err;
Guido van Rossum9adae8e1994-09-12 10:41:22 +000090 PyList_SetItem(cc, VTIME, v);
91 }
92
Barry Warsaw5709dcf1997-01-10 18:42:18 +000093 if (!(v = PyList_New(7)))
94 goto err;
95
Guido van Rossum9adae8e1994-09-12 10:41:22 +000096 PyList_SetItem(v, 0, PyInt_FromLong((long)mode.c_iflag));
97 PyList_SetItem(v, 1, PyInt_FromLong((long)mode.c_oflag));
98 PyList_SetItem(v, 2, PyInt_FromLong((long)mode.c_cflag));
99 PyList_SetItem(v, 3, PyInt_FromLong((long)mode.c_lflag));
100 PyList_SetItem(v, 4, PyInt_FromLong((long)ispeed));
101 PyList_SetItem(v, 5, PyInt_FromLong((long)ospeed));
102 PyList_SetItem(v, 6, cc);
Barry Warsaw5709dcf1997-01-10 18:42:18 +0000103 if (PyErr_Occurred()){
104 Py_DECREF(v);
105 goto err;
106 }
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000107 return v;
Barry Warsaw5709dcf1997-01-10 18:42:18 +0000108 err:
109 Py_DECREF(cc);
110 return NULL;
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000111}
112
113/* tcsetattr(fd, when, termios)
114 Set the attributes of the terminal device. */
115
Guido van Rossum1aca4d81998-03-03 22:10:18 +0000116static char termios_tcsetattr__doc__[] = "\
117tcsetattr(fd, when, attributes) -> None\n\
118Set the tty attributes for file descriptor fd.\n\
119The attributes to be set are taken from the attributes argument, which\n\
120is a list like the one returned by tcgetattr(). The when argument\n\
121determines when the attributes are changed: TERMIOS.TCSANOW to\n\
122change immediately, TERMIOS.TCSADRAIN to change after transmitting all\n\
123queued output, or TERMIOS.TCSAFLUSH to change after transmitting all\n\
124queued output and discarding all queued input. ";
125
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000126static PyObject *
Peter Schneider-Kamp416d4132000-07-10 12:15:54 +0000127termios_tcsetattr(PyObject *self, PyObject *args)
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000128{
129 int fd, when;
130 struct termios mode;
131 speed_t ispeed, ospeed;
132 PyObject *term, *cc, *v;
133 int i;
134
135 if (!PyArg_Parse(args, "(iiO)", &fd, &when, &term))
136 return NULL;
137 if (!PyList_Check(term) || PyList_Size(term) != 7) {
138 PyErr_SetString(PyExc_TypeError, BAD);
139 return NULL;
140 }
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000141
Guido van Rossume7c41931998-06-12 14:26:18 +0000142 /* Get the old mode, in case there are any hidden fields... */
143 if (tcgetattr(fd, &mode) == -1)
144 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000145 mode.c_iflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 0));
146 mode.c_oflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 1));
147 mode.c_cflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 2));
148 mode.c_lflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 3));
149 ispeed = (speed_t) PyInt_AsLong(PyList_GetItem(term, 4));
150 ospeed = (speed_t) PyInt_AsLong(PyList_GetItem(term, 5));
151 cc = PyList_GetItem(term, 6);
Barry Warsaw5709dcf1997-01-10 18:42:18 +0000152 if (PyErr_Occurred())
153 return NULL;
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000154
155 if (!PyList_Check(cc) || PyList_Size(cc) != NCCS) {
156 PyErr_SetString(PyExc_TypeError, BAD);
157 return NULL;
158 }
159
160 for (i = 0; i < NCCS; i++) {
161 v = PyList_GetItem(cc, i);
Barry Warsaw5709dcf1997-01-10 18:42:18 +0000162
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000163 if (PyString_Check(v) && PyString_Size(v) == 1)
164 mode.c_cc[i] = (cc_t) * PyString_AsString(v);
165 else if (PyInt_Check(v))
166 mode.c_cc[i] = (cc_t) PyInt_AsLong(v);
167 else {
168 PyErr_SetString(PyExc_TypeError, BAD);
169 return NULL;
170 }
171 }
172
173 if (cfsetispeed(&mode, (speed_t) ispeed) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +0000174 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000175 if (cfsetospeed(&mode, (speed_t) ospeed) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +0000176 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000177 if (tcsetattr(fd, when, &mode) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +0000178 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000179
180 Py_INCREF(Py_None);
181 return Py_None;
182}
183
184/* tcsendbreak(fd, duration)
185 Generate a break condition. */
186
Guido van Rossum1aca4d81998-03-03 22:10:18 +0000187static char termios_tcsendbreak__doc__[] = "\
188tcsendbreak(fd, duration) -> None\n\
189Send a break on file descriptor fd.\n\
190A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration \n\
191has a system dependent meaning. ";
192
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000193static PyObject *
Peter Schneider-Kamp416d4132000-07-10 12:15:54 +0000194termios_tcsendbreak(PyObject *self, PyObject *args)
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000195{
196 int fd, duration;
197
198 if (!PyArg_Parse(args, "(ii)", &fd, &duration))
199 return NULL;
200 if (tcsendbreak(fd, duration) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +0000201 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000202
203 Py_INCREF(Py_None);
204 return Py_None;
205}
206
207/* tcdrain(fd)
208 Wait until all queued output to the terminal has been
209 transmitted. */
210
Guido van Rossum1aca4d81998-03-03 22:10:18 +0000211static char termios_tcdrain__doc__[] = "\
212tcdrain(fd) -> None\n\
213Wait until all output written to file descriptor fd has been transmitted. ";
214
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000215static PyObject *
Peter Schneider-Kamp416d4132000-07-10 12:15:54 +0000216termios_tcdrain(PyObject *self, PyObject *args)
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000217{
218 int fd;
219
220 if (!PyArg_Parse(args, "i", &fd))
221 return NULL;
222 if (tcdrain(fd) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +0000223 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000224
225 Py_INCREF(Py_None);
226 return Py_None;
227}
228
229/* tcflush(fd, queue)
230 Clear the input and/or output queues associated with
231 the terminal. */
232
Guido van Rossum1aca4d81998-03-03 22:10:18 +0000233static char termios_tcflush__doc__[] = "\
234tcflush(fd, queue) -> None\n\
235Discard queued data on file descriptor fd.\n\
236The queue selector specifies which queue: TERMIOS.TCIFLUSH for the input\n\
237queue, TERMIOS.TCOFLUSH for the output queue, or TERMIOS.TCIOFLUSH for\n\
238both queues. ";
239
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000240static PyObject *
Peter Schneider-Kamp416d4132000-07-10 12:15:54 +0000241termios_tcflush(PyObject *self, PyObject *args)
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000242{
243 int fd, queue;
244
245 if (!PyArg_Parse(args, "(ii)", &fd, &queue))
246 return NULL;
247 if (tcflush(fd, queue) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +0000248 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000249
250 Py_INCREF(Py_None);
251 return Py_None;
252}
253
254/* tcflow(fd, action)
255 Perform operations relating to XON/XOFF flow control on
256 the terminal. */
257
Guido van Rossum1aca4d81998-03-03 22:10:18 +0000258static char termios_tcflow__doc__[] = "\
259tcflow(fd, action) -> None\n\
260Suspend or resume input or output on file descriptor fd.\n\
261The action argument can be TERMIOS.TCOOFF to suspend output,\n\
262TERMIOS.TCOON to restart output, TERMIOS.TCIOFF to suspend input,\n\
263or TERMIOS.TCION to restart input. ";
264
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000265static PyObject *
Peter Schneider-Kamp416d4132000-07-10 12:15:54 +0000266termios_tcflow(PyObject *self, PyObject *args)
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000267{
268 int fd, action;
269
270 if (!PyArg_Parse(args, "(ii)", &fd, &action))
271 return NULL;
272 if (tcflow(fd, action) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +0000273 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000274
275 Py_INCREF(Py_None);
276 return Py_None;
277}
278
279static PyMethodDef termios_methods[] =
280{
Andrew M. Kuchlinga1abb722000-08-03 02:34:44 +0000281 {"tcgetattr", termios_tcgetattr,
282 METH_OLDARGS, termios_tcgetattr__doc__},
283 {"tcsetattr", termios_tcsetattr,
284 METH_OLDARGS, termios_tcsetattr__doc__},
285 {"tcsendbreak", termios_tcsendbreak,
286 METH_OLDARGS, termios_tcsendbreak__doc__},
287 {"tcdrain", termios_tcdrain,
288 METH_OLDARGS, termios_tcdrain__doc__},
289 {"tcflush", termios_tcflush,
290 METH_OLDARGS, termios_tcflush__doc__},
291 {"tcflow", termios_tcflow,
292 METH_OLDARGS, termios_tcflow__doc__},
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000293 {NULL, NULL}
294};
295
Guido van Rossum3886bb61998-12-04 18:50:17 +0000296DL_EXPORT(void)
Thomas Woutersf3f33dc2000-07-21 06:00:07 +0000297PyInit_termios(void)
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000298{
299 PyObject *m, *d;
300
Guido van Rossum1aca4d81998-03-03 22:10:18 +0000301 m = Py_InitModule4("termios", termios_methods, termios__doc__,
302 (PyObject *)NULL, PYTHON_API_VERSION);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000303
304 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000305 TermiosError = PyErr_NewException("termios.error", NULL, NULL);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000306 PyDict_SetItemString(d, "error", TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000307}