Ditched '_find_SET()', since it was a no-value-added wrapper around
[python/dscho.git] / Modules / termios.c
blobaab6b8a71c4e1020ef6512f1880c761e45acac34
1 /* termiosmodule.c -- POSIX terminal I/O module implementation. */
3 #include "Python.h"
5 #define PyInit_termios inittermios
7 #include <termios.h>
9 static char termios__doc__[] = "\
10 This module provides an interface to the Posix calls for tty I/O control.\n\
11 For a complete description of these calls, see the Posix or Unix manual\n\
12 pages. It is only available for those Unix versions that support Posix\n\
13 termios style tty I/O control (and then only if configured at installation\n\
14 time).\n\
15 \n\
16 All functions in this module take a file descriptor fd as their first\n\
17 argument. This must be an integer file descriptor, such as returned by\n\
18 sys.stdin.fileno().\n\
19 \n\
20 This module should be used in conjunction with the TERMIOS module,\n\
21 which defines the relevant symbolic constants.";
24 #ifdef __BEOS__
25 #include <unistd.h>
26 #endif
28 #define BAD "bad termios argument"
30 static PyObject *TermiosError;
32 /* termios = tcgetattr(fd)
33 termios is
34 [iflag, oflag, cflag, lflag, ispeed, ospeed, [cc[0], ..., cc[NCCS]]]
36 Return the attributes of the terminal device. */
38 static char termios_tcgetattr__doc__[] = "\
39 tcgetattr(fd) -> list_of_attrs\n\
40 Get the tty attributes for file descriptor fd, as follows:\n\
41 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] where cc is a list\n\
42 of the tty special characters (each a string of length 1, except the items\n\
43 with indices VMIN and VTIME, which are integers when these fields are\n\
44 defined). The interpretation of the flags and the speeds as well as the\n\
45 indexing in the cc array must be done using the symbolic constants defined\n\
46 in the TERMIOS module.";
48 static PyObject *
49 termios_tcgetattr(self, args)
50 PyObject *self;
51 PyObject *args;
53 int fd;
54 struct termios mode;
55 PyObject *cc;
56 speed_t ispeed, ospeed;
57 PyObject *v;
58 int i;
59 char ch;
61 if (!PyArg_Parse(args, "i", &fd))
62 return NULL;
64 if (tcgetattr(fd, &mode) == -1)
65 return PyErr_SetFromErrno(TermiosError);
67 ispeed = cfgetispeed(&mode);
68 ospeed = cfgetospeed(&mode);
70 cc = PyList_New(NCCS);
71 if (cc == NULL)
72 return NULL;
73 for (i = 0; i < NCCS; i++) {
74 ch = (char)mode.c_cc[i];
75 v = PyString_FromStringAndSize(&ch, 1);
76 if (v == NULL)
77 goto err;
78 PyList_SetItem(cc, i, v);
81 /* Convert the MIN and TIME slots to integer. On some systems, the
82 MIN and TIME slots are the same as the EOF and EOL slots. So we
83 only do this in noncanonical input mode. */
84 if ((mode.c_lflag & ICANON) == 0) {
85 v = PyInt_FromLong((long)mode.c_cc[VMIN]);
86 if (v == NULL)
87 goto err;
88 PyList_SetItem(cc, VMIN, v);
89 v = PyInt_FromLong((long)mode.c_cc[VTIME]);
90 if (v == NULL)
91 goto err;
92 PyList_SetItem(cc, VTIME, v);
95 if (!(v = PyList_New(7)))
96 goto err;
98 PyList_SetItem(v, 0, PyInt_FromLong((long)mode.c_iflag));
99 PyList_SetItem(v, 1, PyInt_FromLong((long)mode.c_oflag));
100 PyList_SetItem(v, 2, PyInt_FromLong((long)mode.c_cflag));
101 PyList_SetItem(v, 3, PyInt_FromLong((long)mode.c_lflag));
102 PyList_SetItem(v, 4, PyInt_FromLong((long)ispeed));
103 PyList_SetItem(v, 5, PyInt_FromLong((long)ospeed));
104 PyList_SetItem(v, 6, cc);
105 if (PyErr_Occurred()){
106 Py_DECREF(v);
107 goto err;
109 return v;
110 err:
111 Py_DECREF(cc);
112 return NULL;
115 /* tcsetattr(fd, when, termios)
116 Set the attributes of the terminal device. */
118 static char termios_tcsetattr__doc__[] = "\
119 tcsetattr(fd, when, attributes) -> None\n\
120 Set the tty attributes for file descriptor fd.\n\
121 The attributes to be set are taken from the attributes argument, which\n\
122 is a list like the one returned by tcgetattr(). The when argument\n\
123 determines when the attributes are changed: TERMIOS.TCSANOW to\n\
124 change immediately, TERMIOS.TCSADRAIN to change after transmitting all\n\
125 queued output, or TERMIOS.TCSAFLUSH to change after transmitting all\n\
126 queued output and discarding all queued input. ";
128 static PyObject *
129 termios_tcsetattr(self, args)
130 PyObject *self;
131 PyObject *args;
133 int fd, when;
134 struct termios mode;
135 speed_t ispeed, ospeed;
136 PyObject *term, *cc, *v;
137 int i;
139 if (!PyArg_Parse(args, "(iiO)", &fd, &when, &term))
140 return NULL;
141 if (!PyList_Check(term) || PyList_Size(term) != 7) {
142 PyErr_SetString(PyExc_TypeError, BAD);
143 return NULL;
146 /* Get the old mode, in case there are any hidden fields... */
147 if (tcgetattr(fd, &mode) == -1)
148 return PyErr_SetFromErrno(TermiosError);
149 mode.c_iflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 0));
150 mode.c_oflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 1));
151 mode.c_cflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 2));
152 mode.c_lflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 3));
153 ispeed = (speed_t) PyInt_AsLong(PyList_GetItem(term, 4));
154 ospeed = (speed_t) PyInt_AsLong(PyList_GetItem(term, 5));
155 cc = PyList_GetItem(term, 6);
156 if (PyErr_Occurred())
157 return NULL;
159 if (!PyList_Check(cc) || PyList_Size(cc) != NCCS) {
160 PyErr_SetString(PyExc_TypeError, BAD);
161 return NULL;
164 for (i = 0; i < NCCS; i++) {
165 v = PyList_GetItem(cc, i);
167 if (PyString_Check(v) && PyString_Size(v) == 1)
168 mode.c_cc[i] = (cc_t) * PyString_AsString(v);
169 else if (PyInt_Check(v))
170 mode.c_cc[i] = (cc_t) PyInt_AsLong(v);
171 else {
172 PyErr_SetString(PyExc_TypeError, BAD);
173 return NULL;
177 if (cfsetispeed(&mode, (speed_t) ispeed) == -1)
178 return PyErr_SetFromErrno(TermiosError);
179 if (cfsetospeed(&mode, (speed_t) ospeed) == -1)
180 return PyErr_SetFromErrno(TermiosError);
181 if (tcsetattr(fd, when, &mode) == -1)
182 return PyErr_SetFromErrno(TermiosError);
184 Py_INCREF(Py_None);
185 return Py_None;
188 /* tcsendbreak(fd, duration)
189 Generate a break condition. */
191 static char termios_tcsendbreak__doc__[] = "\
192 tcsendbreak(fd, duration) -> None\n\
193 Send a break on file descriptor fd.\n\
194 A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration \n\
195 has a system dependent meaning. ";
197 static PyObject *
198 termios_tcsendbreak(self, args)
199 PyObject *self;
200 PyObject *args;
202 int fd, duration;
204 if (!PyArg_Parse(args, "(ii)", &fd, &duration))
205 return NULL;
206 if (tcsendbreak(fd, duration) == -1)
207 return PyErr_SetFromErrno(TermiosError);
209 Py_INCREF(Py_None);
210 return Py_None;
213 /* tcdrain(fd)
214 Wait until all queued output to the terminal has been
215 transmitted. */
217 static char termios_tcdrain__doc__[] = "\
218 tcdrain(fd) -> None\n\
219 Wait until all output written to file descriptor fd has been transmitted. ";
221 static PyObject *
222 termios_tcdrain(self, args)
223 PyObject *self;
224 PyObject *args;
226 int fd;
228 if (!PyArg_Parse(args, "i", &fd))
229 return NULL;
230 if (tcdrain(fd) == -1)
231 return PyErr_SetFromErrno(TermiosError);
233 Py_INCREF(Py_None);
234 return Py_None;
237 /* tcflush(fd, queue)
238 Clear the input and/or output queues associated with
239 the terminal. */
241 static char termios_tcflush__doc__[] = "\
242 tcflush(fd, queue) -> None\n\
243 Discard queued data on file descriptor fd.\n\
244 The queue selector specifies which queue: TERMIOS.TCIFLUSH for the input\n\
245 queue, TERMIOS.TCOFLUSH for the output queue, or TERMIOS.TCIOFLUSH for\n\
246 both queues. ";
248 static PyObject *
249 termios_tcflush(self, args)
250 PyObject *self;
251 PyObject *args;
253 int fd, queue;
255 if (!PyArg_Parse(args, "(ii)", &fd, &queue))
256 return NULL;
257 if (tcflush(fd, queue) == -1)
258 return PyErr_SetFromErrno(TermiosError);
260 Py_INCREF(Py_None);
261 return Py_None;
264 /* tcflow(fd, action)
265 Perform operations relating to XON/XOFF flow control on
266 the terminal. */
268 static char termios_tcflow__doc__[] = "\
269 tcflow(fd, action) -> None\n\
270 Suspend or resume input or output on file descriptor fd.\n\
271 The action argument can be TERMIOS.TCOOFF to suspend output,\n\
272 TERMIOS.TCOON to restart output, TERMIOS.TCIOFF to suspend input,\n\
273 or TERMIOS.TCION to restart input. ";
275 static PyObject *
276 termios_tcflow(self, args)
277 PyObject *self;
278 PyObject *args;
280 int fd, action;
282 if (!PyArg_Parse(args, "(ii)", &fd, &action))
283 return NULL;
284 if (tcflow(fd, action) == -1)
285 return PyErr_SetFromErrno(TermiosError);
287 Py_INCREF(Py_None);
288 return Py_None;
291 static PyMethodDef termios_methods[] =
293 {"tcgetattr", termios_tcgetattr, 0, termios_tcgetattr__doc__},
294 {"tcsetattr", termios_tcsetattr, 0, termios_tcsetattr__doc__},
295 {"tcsendbreak", termios_tcsendbreak, 0, termios_tcsendbreak__doc__},
296 {"tcdrain", termios_tcdrain, 0, termios_tcdrain__doc__},
297 {"tcflush", termios_tcflush, 0, termios_tcflush__doc__},
298 {"tcflow", termios_tcflow, 0, termios_tcflow__doc__},
299 {NULL, NULL}
302 DL_EXPORT(void)
303 PyInit_termios()
305 PyObject *m, *d;
307 m = Py_InitModule4("termios", termios_methods, termios__doc__,
308 (PyObject *)NULL, PYTHON_API_VERSION);
310 d = PyModule_GetDict(m);
311 TermiosError = PyErr_NewException("termios.error", NULL, NULL);
312 PyDict_SetItemString(d, "error", TermiosError);