blob: 50661a2f2870b448257f14ff7ea25b23cdddc678 [file] [log] [blame]
Guido van Rossum9adae8e1994-09-12 10:41:22 +00001/* termiosmodule.c -- POSIX terminal I/O module implementation. */
2
3#if 0
4#include <Py/Python.h>
5#else
6
7#include "allobjects.h"
8#include "pythonrun.h"
9#include "intrcheck.h"
10#include "modsupport.h"
11#include "sysmodule.h"
12
13#ifndef PyObject
14#define PyObject object
15typedef struct methodlist PyMethodDef;
16#endif
17
18#define PyInit_termios inittermios
19
20#endif /* 0 */
21
22#include <termios.h>
23
24#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
34static PyObject *
35termios_tcgetattr(self, args)
36 PyObject *self;
37 PyObject *args;
38{
39 int fd;
40 struct termios mode;
41 PyObject *cc;
42 speed_t ispeed, ospeed;
43 PyObject *v;
44 int i;
45 char ch;
46
47 if (!PyArg_Parse(args, "i", &fd))
48 return NULL;
49
50 if (tcgetattr(fd, &mode) == -1)
51 PyErr_SetFromErrno(TermiosError);
52
53 ispeed = cfgetispeed(&mode);
54 ospeed = cfgetospeed(&mode);
55
56 cc = PyList_New(NCCS);
57 if (cc == NULL)
58 return NULL;
59 for (i = 0; i < NCCS; i++) {
60 ch = (char)mode.c_cc[i];
61 v = PyString_FromStringAndSize(&ch, 1);
62 if (v == NULL)
63 return NULL;
64 PyList_SetItem(cc, i, v);
65 }
66
67 /* Convert the MIN and TIME slots to integer. On some systems, the
68 MIN and TIME slots are the same as the EOF and EOL slots. So we
69 only do this in noncanonical input mode. */
70 if (mode.c_lflag & ICANON == 0) {
71 v = PyInt_FromLong((long)mode.c_cc[VMIN]);
72 if (v == NULL)
73 return NULL;
74 PyList_SetItem(cc, VMIN, v);
75 v = PyInt_FromLong((long)mode.c_cc[VTIME]);
76 if (v == NULL)
77 return NULL;
78 PyList_SetItem(cc, VTIME, v);
79 }
80
81 v = PyList_New(7);
82 PyList_SetItem(v, 0, PyInt_FromLong((long)mode.c_iflag));
83 PyList_SetItem(v, 1, PyInt_FromLong((long)mode.c_oflag));
84 PyList_SetItem(v, 2, PyInt_FromLong((long)mode.c_cflag));
85 PyList_SetItem(v, 3, PyInt_FromLong((long)mode.c_lflag));
86 PyList_SetItem(v, 4, PyInt_FromLong((long)ispeed));
87 PyList_SetItem(v, 5, PyInt_FromLong((long)ospeed));
88 PyList_SetItem(v, 6, cc);
89
90 return v;
91}
92
93/* tcsetattr(fd, when, termios)
94 Set the attributes of the terminal device. */
95
96static PyObject *
97termios_tcsetattr(self, args)
98 PyObject *self;
99 PyObject *args;
100{
101 int fd, when;
102 struct termios mode;
103 speed_t ispeed, ospeed;
104 PyObject *term, *cc, *v;
105 int i;
106
107 if (!PyArg_Parse(args, "(iiO)", &fd, &when, &term))
108 return NULL;
109 if (!PyList_Check(term) || PyList_Size(term) != 7) {
110 PyErr_SetString(PyExc_TypeError, BAD);
111 return NULL;
112 }
113 for (i = 0; i < 6; i++)
114 if (!PyInt_Check(PyList_GetItem(term, i))) {
115 PyErr_SetString(PyExc_TypeError, BAD);
116 return NULL;
117 }
118
119 mode.c_iflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 0));
120 mode.c_oflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 1));
121 mode.c_cflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 2));
122 mode.c_lflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 3));
123 ispeed = (speed_t) PyInt_AsLong(PyList_GetItem(term, 4));
124 ospeed = (speed_t) PyInt_AsLong(PyList_GetItem(term, 5));
125 cc = PyList_GetItem(term, 6);
126
127 if (!PyList_Check(cc) || PyList_Size(cc) != NCCS) {
128 PyErr_SetString(PyExc_TypeError, BAD);
129 return NULL;
130 }
131
132 for (i = 0; i < NCCS; i++) {
133 v = PyList_GetItem(cc, i);
134 if (PyString_Check(v) && PyString_Size(v) == 1)
135 mode.c_cc[i] = (cc_t) * PyString_AsString(v);
136 else if (PyInt_Check(v))
137 mode.c_cc[i] = (cc_t) PyInt_AsLong(v);
138 else {
139 PyErr_SetString(PyExc_TypeError, BAD);
140 return NULL;
141 }
142 }
143
144 if (cfsetispeed(&mode, (speed_t) ispeed) == -1)
145 PyErr_SetFromErrno(TermiosError);
146 if (cfsetospeed(&mode, (speed_t) ospeed) == -1)
147 PyErr_SetFromErrno(TermiosError);
148 if (tcsetattr(fd, when, &mode) == -1)
149 PyErr_SetFromErrno(TermiosError);
150
151 Py_INCREF(Py_None);
152 return Py_None;
153}
154
155/* tcsendbreak(fd, duration)
156 Generate a break condition. */
157
158static PyObject *
159termios_tcsendbreak(self, args)
160 PyObject *self;
161 PyObject *args;
162{
163 int fd, duration;
164
165 if (!PyArg_Parse(args, "(ii)", &fd, &duration))
166 return NULL;
167 if (tcsendbreak(fd, duration) == -1)
168 PyErr_SetFromErrno(TermiosError);
169
170 Py_INCREF(Py_None);
171 return Py_None;
172}
173
174/* tcdrain(fd)
175 Wait until all queued output to the terminal has been
176 transmitted. */
177
178static PyObject *
179termios_tcdrain(self, args)
180 PyObject *self;
181 PyObject *args;
182{
183 int fd;
184
185 if (!PyArg_Parse(args, "i", &fd))
186 return NULL;
187 if (tcdrain(fd) == -1)
188 PyErr_SetFromErrno(TermiosError);
189
190 Py_INCREF(Py_None);
191 return Py_None;
192}
193
194/* tcflush(fd, queue)
195 Clear the input and/or output queues associated with
196 the terminal. */
197
198static PyObject *
199termios_tcflush(self, args)
200 PyObject *self;
201 PyObject *args;
202{
203 int fd, queue;
204
205 if (!PyArg_Parse(args, "(ii)", &fd, &queue))
206 return NULL;
207 if (tcflush(fd, queue) == -1)
208 PyErr_SetFromErrno(TermiosError);
209
210 Py_INCREF(Py_None);
211 return Py_None;
212}
213
214/* tcflow(fd, action)
215 Perform operations relating to XON/XOFF flow control on
216 the terminal. */
217
218static PyObject *
219termios_tcflow(self, args)
220 PyObject *self;
221 PyObject *args;
222{
223 int fd, action;
224
225 if (!PyArg_Parse(args, "(ii)", &fd, &action))
226 return NULL;
227 if (tcflow(fd, action) == -1)
228 PyErr_SetFromErrno(TermiosError);
229
230 Py_INCREF(Py_None);
231 return Py_None;
232}
233
234static PyMethodDef termios_methods[] =
235{
236 {"tcgetattr", termios_tcgetattr},
237 {"tcsetattr", termios_tcsetattr},
238 {"tcsendbreak", termios_tcsendbreak},
239 {"tcdrain", termios_tcdrain},
240 {"tcflush", termios_tcflush},
241 {"tcflow", termios_tcflow},
242 {NULL, NULL}
243};
244
245void
246PyInit_termios()
247{
248 PyObject *m, *d;
249
250 m = Py_InitModule("termios", termios_methods);
251
252 d = PyModule_GetDict(m);
253 TermiosError = Py_BuildValue("s", "termios.error");
254 PyDict_SetItemString(d, "error", TermiosError);
255
256 if (PyErr_Occurred())
257 Py_FatalError("can't initialize module termios");
258}