blob: 55295a8e45e113dd001d19ac3494249234f3b4b2 [file] [log] [blame]
Guido van Rossum9adae8e1994-09-12 10:41:22 +00001/* termiosmodule.c -- POSIX terminal I/O module implementation. */
2
Guido van Rossum602099a1994-09-14 13:32:22 +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 Rossum9adae8e1994-09-12 10:41:22 +000024#define BAD "bad termios argument"
25
26static PyObject *TermiosError;
27
28/* termios = tcgetattr(fd)
29 termios is
30 [iflag, oflag, cflag, lflag, ispeed, ospeed, [cc[0], ..., cc[NCCS]]]
31
32 Return the attributes of the terminal device. */
33
Guido van Rossum1aca4d81998-03-03 22:10:18 +000034static char termios_tcgetattr__doc__[] = "\
35tcgetattr(fd) -> list_of_attrs\n\
36Get the tty attributes for file descriptor fd, as follows:\n\
37[iflag, oflag, cflag, lflag, ispeed, ospeed, cc] where cc is a list\n\
38of the tty special characters (each a string of length 1, except the items\n\
39with indices VMIN and VTIME, which are integers when these fields are\n\
40defined). The interpretation of the flags and the speeds as well as the\n\
41indexing in the cc array must be done using the symbolic constants defined\n\
42in the TERMIOS module.";
43
Guido van Rossum9adae8e1994-09-12 10:41:22 +000044static PyObject *
45termios_tcgetattr(self, args)
46 PyObject *self;
47 PyObject *args;
48{
49 int fd;
50 struct termios mode;
51 PyObject *cc;
52 speed_t ispeed, ospeed;
53 PyObject *v;
54 int i;
55 char ch;
56
57 if (!PyArg_Parse(args, "i", &fd))
58 return NULL;
59
60 if (tcgetattr(fd, &mode) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +000061 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +000062
63 ispeed = cfgetispeed(&mode);
64 ospeed = cfgetospeed(&mode);
65
66 cc = PyList_New(NCCS);
67 if (cc == NULL)
68 return NULL;
69 for (i = 0; i < NCCS; i++) {
70 ch = (char)mode.c_cc[i];
71 v = PyString_FromStringAndSize(&ch, 1);
72 if (v == NULL)
Barry Warsaw5709dcf1997-01-10 18:42:18 +000073 goto err;
Guido van Rossum9adae8e1994-09-12 10:41:22 +000074 PyList_SetItem(cc, i, v);
75 }
76
77 /* Convert the MIN and TIME slots to integer. On some systems, the
78 MIN and TIME slots are the same as the EOF and EOL slots. So we
79 only do this in noncanonical input mode. */
Guido van Rossum36dd0d21996-12-10 15:23:00 +000080 if ((mode.c_lflag & ICANON) == 0) {
Guido van Rossum9adae8e1994-09-12 10:41:22 +000081 v = PyInt_FromLong((long)mode.c_cc[VMIN]);
82 if (v == NULL)
Barry Warsaw5709dcf1997-01-10 18:42:18 +000083 goto err;
Guido van Rossum9adae8e1994-09-12 10:41:22 +000084 PyList_SetItem(cc, VMIN, v);
85 v = PyInt_FromLong((long)mode.c_cc[VTIME]);
86 if (v == NULL)
Barry Warsaw5709dcf1997-01-10 18:42:18 +000087 goto err;
Guido van Rossum9adae8e1994-09-12 10:41:22 +000088 PyList_SetItem(cc, VTIME, v);
89 }
90
Barry Warsaw5709dcf1997-01-10 18:42:18 +000091 if (!(v = PyList_New(7)))
92 goto err;
93
Guido van Rossum9adae8e1994-09-12 10:41:22 +000094 PyList_SetItem(v, 0, PyInt_FromLong((long)mode.c_iflag));
95 PyList_SetItem(v, 1, PyInt_FromLong((long)mode.c_oflag));
96 PyList_SetItem(v, 2, PyInt_FromLong((long)mode.c_cflag));
97 PyList_SetItem(v, 3, PyInt_FromLong((long)mode.c_lflag));
98 PyList_SetItem(v, 4, PyInt_FromLong((long)ispeed));
99 PyList_SetItem(v, 5, PyInt_FromLong((long)ospeed));
100 PyList_SetItem(v, 6, cc);
Barry Warsaw5709dcf1997-01-10 18:42:18 +0000101 if (PyErr_Occurred()){
102 Py_DECREF(v);
103 goto err;
104 }
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000105 return v;
Barry Warsaw5709dcf1997-01-10 18:42:18 +0000106 err:
107 Py_DECREF(cc);
108 return NULL;
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000109}
110
111/* tcsetattr(fd, when, termios)
112 Set the attributes of the terminal device. */
113
Guido van Rossum1aca4d81998-03-03 22:10:18 +0000114static char termios_tcsetattr__doc__[] = "\
115tcsetattr(fd, when, attributes) -> None\n\
116Set the tty attributes for file descriptor fd.\n\
117The attributes to be set are taken from the attributes argument, which\n\
118is a list like the one returned by tcgetattr(). The when argument\n\
119determines when the attributes are changed: TERMIOS.TCSANOW to\n\
120change immediately, TERMIOS.TCSADRAIN to change after transmitting all\n\
121queued output, or TERMIOS.TCSAFLUSH to change after transmitting all\n\
122queued output and discarding all queued input. ";
123
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000124static PyObject *
125termios_tcsetattr(self, args)
126 PyObject *self;
127 PyObject *args;
128{
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
142 mode.c_iflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 0));
143 mode.c_oflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 1));
144 mode.c_cflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 2));
145 mode.c_lflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 3));
146 ispeed = (speed_t) PyInt_AsLong(PyList_GetItem(term, 4));
147 ospeed = (speed_t) PyInt_AsLong(PyList_GetItem(term, 5));
148 cc = PyList_GetItem(term, 6);
Barry Warsaw5709dcf1997-01-10 18:42:18 +0000149 if (PyErr_Occurred())
150 return NULL;
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000151
152 if (!PyList_Check(cc) || PyList_Size(cc) != NCCS) {
153 PyErr_SetString(PyExc_TypeError, BAD);
154 return NULL;
155 }
156
157 for (i = 0; i < NCCS; i++) {
158 v = PyList_GetItem(cc, i);
Barry Warsaw5709dcf1997-01-10 18:42:18 +0000159
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000160 if (PyString_Check(v) && PyString_Size(v) == 1)
161 mode.c_cc[i] = (cc_t) * PyString_AsString(v);
162 else if (PyInt_Check(v))
163 mode.c_cc[i] = (cc_t) PyInt_AsLong(v);
164 else {
165 PyErr_SetString(PyExc_TypeError, BAD);
166 return NULL;
167 }
168 }
169
170 if (cfsetispeed(&mode, (speed_t) ispeed) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +0000171 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000172 if (cfsetospeed(&mode, (speed_t) ospeed) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +0000173 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000174 if (tcsetattr(fd, when, &mode) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +0000175 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000176
177 Py_INCREF(Py_None);
178 return Py_None;
179}
180
181/* tcsendbreak(fd, duration)
182 Generate a break condition. */
183
Guido van Rossum1aca4d81998-03-03 22:10:18 +0000184static char termios_tcsendbreak__doc__[] = "\
185tcsendbreak(fd, duration) -> None\n\
186Send a break on file descriptor fd.\n\
187A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration \n\
188has a system dependent meaning. ";
189
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000190static PyObject *
191termios_tcsendbreak(self, args)
192 PyObject *self;
193 PyObject *args;
194{
195 int fd, duration;
196
197 if (!PyArg_Parse(args, "(ii)", &fd, &duration))
198 return NULL;
199 if (tcsendbreak(fd, duration) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +0000200 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000201
202 Py_INCREF(Py_None);
203 return Py_None;
204}
205
206/* tcdrain(fd)
207 Wait until all queued output to the terminal has been
208 transmitted. */
209
Guido van Rossum1aca4d81998-03-03 22:10:18 +0000210static char termios_tcdrain__doc__[] = "\
211tcdrain(fd) -> None\n\
212Wait until all output written to file descriptor fd has been transmitted. ";
213
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000214static PyObject *
215termios_tcdrain(self, args)
216 PyObject *self;
217 PyObject *args;
218{
219 int fd;
220
221 if (!PyArg_Parse(args, "i", &fd))
222 return NULL;
223 if (tcdrain(fd) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +0000224 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000225
226 Py_INCREF(Py_None);
227 return Py_None;
228}
229
230/* tcflush(fd, queue)
231 Clear the input and/or output queues associated with
232 the terminal. */
233
Guido van Rossum1aca4d81998-03-03 22:10:18 +0000234static char termios_tcflush__doc__[] = "\
235tcflush(fd, queue) -> None\n\
236Discard queued data on file descriptor fd.\n\
237The queue selector specifies which queue: TERMIOS.TCIFLUSH for the input\n\
238queue, TERMIOS.TCOFLUSH for the output queue, or TERMIOS.TCIOFLUSH for\n\
239both queues. ";
240
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000241static PyObject *
242termios_tcflush(self, args)
243 PyObject *self;
244 PyObject *args;
245{
246 int fd, queue;
247
248 if (!PyArg_Parse(args, "(ii)", &fd, &queue))
249 return NULL;
250 if (tcflush(fd, queue) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +0000251 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000252
253 Py_INCREF(Py_None);
254 return Py_None;
255}
256
257/* tcflow(fd, action)
258 Perform operations relating to XON/XOFF flow control on
259 the terminal. */
260
Guido van Rossum1aca4d81998-03-03 22:10:18 +0000261static char termios_tcflow__doc__[] = "\
262tcflow(fd, action) -> None\n\
263Suspend or resume input or output on file descriptor fd.\n\
264The action argument can be TERMIOS.TCOOFF to suspend output,\n\
265TERMIOS.TCOON to restart output, TERMIOS.TCIOFF to suspend input,\n\
266or TERMIOS.TCION to restart input. ";
267
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000268static PyObject *
269termios_tcflow(self, args)
270 PyObject *self;
271 PyObject *args;
272{
273 int fd, action;
274
275 if (!PyArg_Parse(args, "(ii)", &fd, &action))
276 return NULL;
277 if (tcflow(fd, action) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +0000278 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000279
280 Py_INCREF(Py_None);
281 return Py_None;
282}
283
284static PyMethodDef termios_methods[] =
285{
Guido van Rossum1aca4d81998-03-03 22:10:18 +0000286 {"tcgetattr", termios_tcgetattr, 0, termios_tcgetattr__doc__},
287 {"tcsetattr", termios_tcsetattr, 0, termios_tcsetattr__doc__},
288 {"tcsendbreak", termios_tcsendbreak, 0, termios_tcsendbreak__doc__},
289 {"tcdrain", termios_tcdrain, 0, termios_tcdrain__doc__},
290 {"tcflush", termios_tcflush, 0, termios_tcflush__doc__},
291 {"tcflow", termios_tcflow, 0, termios_tcflow__doc__},
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000292 {NULL, NULL}
293};
294
295void
296PyInit_termios()
297{
298 PyObject *m, *d;
299
Guido van Rossum1aca4d81998-03-03 22:10:18 +0000300 m = Py_InitModule4("termios", termios_methods, termios__doc__,
301 (PyObject *)NULL, PYTHON_API_VERSION);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000302
303 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000304 TermiosError = PyErr_NewException("termios.error", NULL, NULL);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000305 PyDict_SetItemString(d, "error", TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000306}