improve treatment of multi-line replies, ignore empty lines
[python/dscho.git] / Modules / termios.c
blob4148d85dc159c6a06dbf8653c9f267b629cbb031
1 /* termiosmodule.c -- POSIX terminal I/O module implementation. */
3 #include <Python.h>
5 #define PyInit_termios inittermios
7 #include <termios.h>
9 #define BAD "bad termios argument"
11 static PyObject *TermiosError;
13 /* termios = tcgetattr(fd)
14 termios is
15 [iflag, oflag, cflag, lflag, ispeed, ospeed, [cc[0], ..., cc[NCCS]]]
17 Return the attributes of the terminal device. */
19 static PyObject *
20 termios_tcgetattr(self, args)
21 PyObject *self;
22 PyObject *args;
24 int fd;
25 struct termios mode;
26 PyObject *cc;
27 speed_t ispeed, ospeed;
28 PyObject *v;
29 int i;
30 char ch;
32 if (!PyArg_Parse(args, "i", &fd))
33 return NULL;
35 if (tcgetattr(fd, &mode) == -1)
36 PyErr_SetFromErrno(TermiosError);
38 ispeed = cfgetispeed(&mode);
39 ospeed = cfgetospeed(&mode);
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);
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);
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);
75 return v;
78 /* tcsetattr(fd, when, termios)
79 Set the attributes of the terminal device. */
81 static PyObject *
82 termios_tcsetattr(self, args)
83 PyObject *self;
84 PyObject *args;
86 int fd, when;
87 struct termios mode;
88 speed_t ispeed, ospeed;
89 PyObject *term, *cc, *v;
90 int i;
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;
98 for (i = 0; i < 6; i++)
99 if (!PyInt_Check(PyList_GetItem(term, i))) {
100 PyErr_SetString(PyExc_TypeError, BAD);
101 return NULL;
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);
112 if (!PyList_Check(cc) || PyList_Size(cc) != NCCS) {
113 PyErr_SetString(PyExc_TypeError, BAD);
114 return NULL;
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;
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);
136 Py_INCREF(Py_None);
137 return Py_None;
140 /* tcsendbreak(fd, duration)
141 Generate a break condition. */
143 static PyObject *
144 termios_tcsendbreak(self, args)
145 PyObject *self;
146 PyObject *args;
148 int fd, duration;
150 if (!PyArg_Parse(args, "(ii)", &fd, &duration))
151 return NULL;
152 if (tcsendbreak(fd, duration) == -1)
153 PyErr_SetFromErrno(TermiosError);
155 Py_INCREF(Py_None);
156 return Py_None;
159 /* tcdrain(fd)
160 Wait until all queued output to the terminal has been
161 transmitted. */
163 static PyObject *
164 termios_tcdrain(self, args)
165 PyObject *self;
166 PyObject *args;
168 int fd;
170 if (!PyArg_Parse(args, "i", &fd))
171 return NULL;
172 if (tcdrain(fd) == -1)
173 PyErr_SetFromErrno(TermiosError);
175 Py_INCREF(Py_None);
176 return Py_None;
179 /* tcflush(fd, queue)
180 Clear the input and/or output queues associated with
181 the terminal. */
183 static PyObject *
184 termios_tcflush(self, args)
185 PyObject *self;
186 PyObject *args;
188 int fd, queue;
190 if (!PyArg_Parse(args, "(ii)", &fd, &queue))
191 return NULL;
192 if (tcflush(fd, queue) == -1)
193 PyErr_SetFromErrno(TermiosError);
195 Py_INCREF(Py_None);
196 return Py_None;
199 /* tcflow(fd, action)
200 Perform operations relating to XON/XOFF flow control on
201 the terminal. */
203 static PyObject *
204 termios_tcflow(self, args)
205 PyObject *self;
206 PyObject *args;
208 int fd, action;
210 if (!PyArg_Parse(args, "(ii)", &fd, &action))
211 return NULL;
212 if (tcflow(fd, action) == -1)
213 PyErr_SetFromErrno(TermiosError);
215 Py_INCREF(Py_None);
216 return Py_None;
219 static PyMethodDef termios_methods[] =
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}
230 void
231 PyInit_termios()
233 PyObject *m, *d;
235 m = Py_InitModule("termios", termios_methods);
237 d = PyModule_GetDict(m);
238 TermiosError = Py_BuildValue("s", "termios.error");
239 PyDict_SetItemString(d, "error", TermiosError);
241 if (PyErr_Occurred())
242 Py_FatalError("can't initialize module termios");