blob: 12418b5736bc3d54e5c438b0894b3b5c92ab9ec0 [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
9#define BAD "bad termios argument"
10
11static PyObject *TermiosError;
12
13/* termios = tcgetattr(fd)
14 termios is
15 [iflag, oflag, cflag, lflag, ispeed, ospeed, [cc[0], ..., cc[NCCS]]]
16
17 Return the attributes of the terminal device. */
18
19static PyObject *
20termios_tcgetattr(self, args)
21 PyObject *self;
22 PyObject *args;
23{
24 int fd;
25 struct termios mode;
26 PyObject *cc;
27 speed_t ispeed, ospeed;
28 PyObject *v;
29 int i;
30 char ch;
31
32 if (!PyArg_Parse(args, "i", &fd))
33 return NULL;
34
35 if (tcgetattr(fd, &mode) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +000036 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +000037
38 ispeed = cfgetispeed(&mode);
39 ospeed = cfgetospeed(&mode);
40
41 cc = PyList_New(NCCS);
42 if (cc == NULL)
43 return NULL;
44 for (i = 0; i < NCCS; i++) {
45 ch = (char)mode.c_cc[i];
46 v = PyString_FromStringAndSize(&ch, 1);
47 if (v == NULL)
Barry Warsaw5709dcf1997-01-10 18:42:18 +000048 goto err;
Guido van Rossum9adae8e1994-09-12 10:41:22 +000049 PyList_SetItem(cc, i, v);
50 }
51
52 /* Convert the MIN and TIME slots to integer. On some systems, the
53 MIN and TIME slots are the same as the EOF and EOL slots. So we
54 only do this in noncanonical input mode. */
Guido van Rossum36dd0d21996-12-10 15:23:00 +000055 if ((mode.c_lflag & ICANON) == 0) {
Guido van Rossum9adae8e1994-09-12 10:41:22 +000056 v = PyInt_FromLong((long)mode.c_cc[VMIN]);
57 if (v == NULL)
Barry Warsaw5709dcf1997-01-10 18:42:18 +000058 goto err;
Guido van Rossum9adae8e1994-09-12 10:41:22 +000059 PyList_SetItem(cc, VMIN, v);
60 v = PyInt_FromLong((long)mode.c_cc[VTIME]);
61 if (v == NULL)
Barry Warsaw5709dcf1997-01-10 18:42:18 +000062 goto err;
Guido van Rossum9adae8e1994-09-12 10:41:22 +000063 PyList_SetItem(cc, VTIME, v);
64 }
65
Barry Warsaw5709dcf1997-01-10 18:42:18 +000066 if (!(v = PyList_New(7)))
67 goto err;
68
Guido van Rossum9adae8e1994-09-12 10:41:22 +000069 PyList_SetItem(v, 0, PyInt_FromLong((long)mode.c_iflag));
70 PyList_SetItem(v, 1, PyInt_FromLong((long)mode.c_oflag));
71 PyList_SetItem(v, 2, PyInt_FromLong((long)mode.c_cflag));
72 PyList_SetItem(v, 3, PyInt_FromLong((long)mode.c_lflag));
73 PyList_SetItem(v, 4, PyInt_FromLong((long)ispeed));
74 PyList_SetItem(v, 5, PyInt_FromLong((long)ospeed));
75 PyList_SetItem(v, 6, cc);
Barry Warsaw5709dcf1997-01-10 18:42:18 +000076 if (PyErr_Occurred()){
77 Py_DECREF(v);
78 goto err;
79 }
Guido van Rossum9adae8e1994-09-12 10:41:22 +000080 return v;
Barry Warsaw5709dcf1997-01-10 18:42:18 +000081 err:
82 Py_DECREF(cc);
83 return NULL;
Guido van Rossum9adae8e1994-09-12 10:41:22 +000084}
85
86/* tcsetattr(fd, when, termios)
87 Set the attributes of the terminal device. */
88
89static PyObject *
90termios_tcsetattr(self, args)
91 PyObject *self;
92 PyObject *args;
93{
94 int fd, when;
95 struct termios mode;
96 speed_t ispeed, ospeed;
97 PyObject *term, *cc, *v;
98 int i;
99
100 if (!PyArg_Parse(args, "(iiO)", &fd, &when, &term))
101 return NULL;
102 if (!PyList_Check(term) || PyList_Size(term) != 7) {
103 PyErr_SetString(PyExc_TypeError, BAD);
104 return NULL;
105 }
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000106
107 mode.c_iflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 0));
108 mode.c_oflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 1));
109 mode.c_cflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 2));
110 mode.c_lflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 3));
111 ispeed = (speed_t) PyInt_AsLong(PyList_GetItem(term, 4));
112 ospeed = (speed_t) PyInt_AsLong(PyList_GetItem(term, 5));
113 cc = PyList_GetItem(term, 6);
Barry Warsaw5709dcf1997-01-10 18:42:18 +0000114 if (PyErr_Occurred())
115 return NULL;
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000116
117 if (!PyList_Check(cc) || PyList_Size(cc) != NCCS) {
118 PyErr_SetString(PyExc_TypeError, BAD);
119 return NULL;
120 }
121
122 for (i = 0; i < NCCS; i++) {
123 v = PyList_GetItem(cc, i);
Barry Warsaw5709dcf1997-01-10 18:42:18 +0000124
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000125 if (PyString_Check(v) && PyString_Size(v) == 1)
126 mode.c_cc[i] = (cc_t) * PyString_AsString(v);
127 else if (PyInt_Check(v))
128 mode.c_cc[i] = (cc_t) PyInt_AsLong(v);
129 else {
130 PyErr_SetString(PyExc_TypeError, BAD);
131 return NULL;
132 }
133 }
134
135 if (cfsetispeed(&mode, (speed_t) ispeed) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +0000136 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000137 if (cfsetospeed(&mode, (speed_t) ospeed) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +0000138 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000139 if (tcsetattr(fd, when, &mode) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +0000140 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000141
142 Py_INCREF(Py_None);
143 return Py_None;
144}
145
146/* tcsendbreak(fd, duration)
147 Generate a break condition. */
148
149static PyObject *
150termios_tcsendbreak(self, args)
151 PyObject *self;
152 PyObject *args;
153{
154 int fd, duration;
155
156 if (!PyArg_Parse(args, "(ii)", &fd, &duration))
157 return NULL;
158 if (tcsendbreak(fd, duration) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +0000159 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000160
161 Py_INCREF(Py_None);
162 return Py_None;
163}
164
165/* tcdrain(fd)
166 Wait until all queued output to the terminal has been
167 transmitted. */
168
169static PyObject *
170termios_tcdrain(self, args)
171 PyObject *self;
172 PyObject *args;
173{
174 int fd;
175
176 if (!PyArg_Parse(args, "i", &fd))
177 return NULL;
178 if (tcdrain(fd) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +0000179 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000180
181 Py_INCREF(Py_None);
182 return Py_None;
183}
184
185/* tcflush(fd, queue)
186 Clear the input and/or output queues associated with
187 the terminal. */
188
189static PyObject *
190termios_tcflush(self, args)
191 PyObject *self;
192 PyObject *args;
193{
194 int fd, queue;
195
196 if (!PyArg_Parse(args, "(ii)", &fd, &queue))
197 return NULL;
198 if (tcflush(fd, queue) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +0000199 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000200
201 Py_INCREF(Py_None);
202 return Py_None;
203}
204
205/* tcflow(fd, action)
206 Perform operations relating to XON/XOFF flow control on
207 the terminal. */
208
209static PyObject *
210termios_tcflow(self, args)
211 PyObject *self;
212 PyObject *args;
213{
214 int fd, action;
215
216 if (!PyArg_Parse(args, "(ii)", &fd, &action))
217 return NULL;
218 if (tcflow(fd, action) == -1)
Guido van Rossumb8ad0241997-07-17 22:55:06 +0000219 return PyErr_SetFromErrno(TermiosError);
Guido van Rossum9adae8e1994-09-12 10:41:22 +0000220
221 Py_INCREF(Py_None);
222 return Py_None;
223}
224
225static PyMethodDef termios_methods[] =
226{
227 {"tcgetattr", termios_tcgetattr},
228 {"tcsetattr", termios_tcsetattr},
229 {"tcsendbreak", termios_tcsendbreak},
230 {"tcdrain", termios_tcdrain},
231 {"tcflush", termios_tcflush},
232 {"tcflow", termios_tcflow},
233 {NULL, NULL}
234};
235
236void
237PyInit_termios()
238{
239 PyObject *m, *d;
240
241 m = Py_InitModule("termios", termios_methods);
242
243 d = PyModule_GetDict(m);
244 TermiosError = Py_BuildValue("s", "termios.error");
245 PyDict_SetItemString(d, "error", TermiosError);
246
247 if (PyErr_Occurred())
248 Py_FatalError("can't initialize module termios");
249}