blob: 4148d85dc159c6a06dbf8653c9f267b629cbb031 [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)
36 PyErr_SetFromErrno(TermiosError);
37
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)
48 return NULL;
49 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. */
55 if (mode.c_lflag & ICANON == 0) {
56 v = PyInt_FromLong((long)mode.c_cc[VMIN]);
57 if (v == NULL)
58 return NULL;
59 PyList_SetItem(cc, VMIN, v);
60 v = PyInt_FromLong((long)mode.c_cc[VTIME]);
61 if (v == NULL)
62 return NULL;
63 PyList_SetItem(cc, VTIME, v);
64 }
65
66 v = PyList_New(7);
67 PyList_SetItem(v, 0, PyInt_FromLong((long)mode.c_iflag));
68 PyList_SetItem(v, 1, PyInt_FromLong((long)mode.c_oflag));
69 PyList_SetItem(v, 2, PyInt_FromLong((long)mode.c_cflag));
70 PyList_SetItem(v, 3, PyInt_FromLong((long)mode.c_lflag));
71 PyList_SetItem(v, 4, PyInt_FromLong((long)ispeed));
72 PyList_SetItem(v, 5, PyInt_FromLong((long)ospeed));
73 PyList_SetItem(v, 6, cc);
74
75 return v;
76}
77
78/* tcsetattr(fd, when, termios)
79 Set the attributes of the terminal device. */
80
81static PyObject *
82termios_tcsetattr(self, args)
83 PyObject *self;
84 PyObject *args;
85{
86 int fd, when;
87 struct termios mode;
88 speed_t ispeed, ospeed;
89 PyObject *term, *cc, *v;
90 int i;
91
92 if (!PyArg_Parse(args, "(iiO)", &fd, &when, &term))
93 return NULL;
94 if (!PyList_Check(term) || PyList_Size(term) != 7) {
95 PyErr_SetString(PyExc_TypeError, BAD);
96 return NULL;
97 }
98 for (i = 0; i < 6; i++)
99 if (!PyInt_Check(PyList_GetItem(term, i))) {
100 PyErr_SetString(PyExc_TypeError, BAD);
101 return NULL;
102 }
103
104 mode.c_iflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 0));
105 mode.c_oflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 1));
106 mode.c_cflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 2));
107 mode.c_lflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 3));
108 ispeed = (speed_t) PyInt_AsLong(PyList_GetItem(term, 4));
109 ospeed = (speed_t) PyInt_AsLong(PyList_GetItem(term, 5));
110 cc = PyList_GetItem(term, 6);
111
112 if (!PyList_Check(cc) || PyList_Size(cc) != NCCS) {
113 PyErr_SetString(PyExc_TypeError, BAD);
114 return NULL;
115 }
116
117 for (i = 0; i < NCCS; i++) {
118 v = PyList_GetItem(cc, i);
119 if (PyString_Check(v) && PyString_Size(v) == 1)
120 mode.c_cc[i] = (cc_t) * PyString_AsString(v);
121 else if (PyInt_Check(v))
122 mode.c_cc[i] = (cc_t) PyInt_AsLong(v);
123 else {
124 PyErr_SetString(PyExc_TypeError, BAD);
125 return NULL;
126 }
127 }
128
129 if (cfsetispeed(&mode, (speed_t) ispeed) == -1)
130 PyErr_SetFromErrno(TermiosError);
131 if (cfsetospeed(&mode, (speed_t) ospeed) == -1)
132 PyErr_SetFromErrno(TermiosError);
133 if (tcsetattr(fd, when, &mode) == -1)
134 PyErr_SetFromErrno(TermiosError);
135
136 Py_INCREF(Py_None);
137 return Py_None;
138}
139
140/* tcsendbreak(fd, duration)
141 Generate a break condition. */
142
143static PyObject *
144termios_tcsendbreak(self, args)
145 PyObject *self;
146 PyObject *args;
147{
148 int fd, duration;
149
150 if (!PyArg_Parse(args, "(ii)", &fd, &duration))
151 return NULL;
152 if (tcsendbreak(fd, duration) == -1)
153 PyErr_SetFromErrno(TermiosError);
154
155 Py_INCREF(Py_None);
156 return Py_None;
157}
158
159/* tcdrain(fd)
160 Wait until all queued output to the terminal has been
161 transmitted. */
162
163static PyObject *
164termios_tcdrain(self, args)
165 PyObject *self;
166 PyObject *args;
167{
168 int fd;
169
170 if (!PyArg_Parse(args, "i", &fd))
171 return NULL;
172 if (tcdrain(fd) == -1)
173 PyErr_SetFromErrno(TermiosError);
174
175 Py_INCREF(Py_None);
176 return Py_None;
177}
178
179/* tcflush(fd, queue)
180 Clear the input and/or output queues associated with
181 the terminal. */
182
183static PyObject *
184termios_tcflush(self, args)
185 PyObject *self;
186 PyObject *args;
187{
188 int fd, queue;
189
190 if (!PyArg_Parse(args, "(ii)", &fd, &queue))
191 return NULL;
192 if (tcflush(fd, queue) == -1)
193 PyErr_SetFromErrno(TermiosError);
194
195 Py_INCREF(Py_None);
196 return Py_None;
197}
198
199/* tcflow(fd, action)
200 Perform operations relating to XON/XOFF flow control on
201 the terminal. */
202
203static PyObject *
204termios_tcflow(self, args)
205 PyObject *self;
206 PyObject *args;
207{
208 int fd, action;
209
210 if (!PyArg_Parse(args, "(ii)", &fd, &action))
211 return NULL;
212 if (tcflow(fd, action) == -1)
213 PyErr_SetFromErrno(TermiosError);
214
215 Py_INCREF(Py_None);
216 return Py_None;
217}
218
219static PyMethodDef termios_methods[] =
220{
221 {"tcgetattr", termios_tcgetattr},
222 {"tcsetattr", termios_tcsetattr},
223 {"tcsendbreak", termios_tcsendbreak},
224 {"tcdrain", termios_tcdrain},
225 {"tcflush", termios_tcflush},
226 {"tcflow", termios_tcflow},
227 {NULL, NULL}
228};
229
230void
231PyInit_termios()
232{
233 PyObject *m, *d;
234
235 m = Py_InitModule("termios", termios_methods);
236
237 d = PyModule_GetDict(m);
238 TermiosError = Py_BuildValue("s", "termios.error");
239 PyDict_SetItemString(d, "error", TermiosError);
240
241 if (PyErr_Occurred())
242 Py_FatalError("can't initialize module termios");
243}