Bump version to 0.9.1.
[python/dscho.git] / Modules / termios.c
blob91ab4840e8f90a07761ba34c9542967540e4b77f
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(PyObject *self, PyObject *args)
51 int fd;
52 struct termios mode;
53 PyObject *cc;
54 speed_t ispeed, ospeed;
55 PyObject *v;
56 int i;
57 char ch;
59 if (!PyArg_Parse(args, "i", &fd))
60 return NULL;
62 if (tcgetattr(fd, &mode) == -1)
63 return PyErr_SetFromErrno(TermiosError);
65 ispeed = cfgetispeed(&mode);
66 ospeed = cfgetospeed(&mode);
68 cc = PyList_New(NCCS);
69 if (cc == NULL)
70 return NULL;
71 for (i = 0; i < NCCS; i++) {
72 ch = (char)mode.c_cc[i];
73 v = PyString_FromStringAndSize(&ch, 1);
74 if (v == NULL)
75 goto err;
76 PyList_SetItem(cc, i, v);
79 /* Convert the MIN and TIME slots to integer. On some systems, the
80 MIN and TIME slots are the same as the EOF and EOL slots. So we
81 only do this in noncanonical input mode. */
82 if ((mode.c_lflag & ICANON) == 0) {
83 v = PyInt_FromLong((long)mode.c_cc[VMIN]);
84 if (v == NULL)
85 goto err;
86 PyList_SetItem(cc, VMIN, v);
87 v = PyInt_FromLong((long)mode.c_cc[VTIME]);
88 if (v == NULL)
89 goto err;
90 PyList_SetItem(cc, VTIME, v);
93 if (!(v = PyList_New(7)))
94 goto err;
96 PyList_SetItem(v, 0, PyInt_FromLong((long)mode.c_iflag));
97 PyList_SetItem(v, 1, PyInt_FromLong((long)mode.c_oflag));
98 PyList_SetItem(v, 2, PyInt_FromLong((long)mode.c_cflag));
99 PyList_SetItem(v, 3, PyInt_FromLong((long)mode.c_lflag));
100 PyList_SetItem(v, 4, PyInt_FromLong((long)ispeed));
101 PyList_SetItem(v, 5, PyInt_FromLong((long)ospeed));
102 PyList_SetItem(v, 6, cc);
103 if (PyErr_Occurred()){
104 Py_DECREF(v);
105 goto err;
107 return v;
108 err:
109 Py_DECREF(cc);
110 return NULL;
113 /* tcsetattr(fd, when, termios)
114 Set the attributes of the terminal device. */
116 static char termios_tcsetattr__doc__[] = "\
117 tcsetattr(fd, when, attributes) -> None\n\
118 Set the tty attributes for file descriptor fd.\n\
119 The attributes to be set are taken from the attributes argument, which\n\
120 is a list like the one returned by tcgetattr(). The when argument\n\
121 determines when the attributes are changed: TERMIOS.TCSANOW to\n\
122 change immediately, TERMIOS.TCSADRAIN to change after transmitting all\n\
123 queued output, or TERMIOS.TCSAFLUSH to change after transmitting all\n\
124 queued output and discarding all queued input. ";
126 static PyObject *
127 termios_tcsetattr(PyObject *self, PyObject *args)
129 int fd, when;
130 struct termios mode;
131 speed_t ispeed, ospeed;
132 PyObject *term, *cc, *v;
133 int i;
135 if (!PyArg_Parse(args, "(iiO)", &fd, &when, &term))
136 return NULL;
137 if (!PyList_Check(term) || PyList_Size(term) != 7) {
138 PyErr_SetString(PyExc_TypeError, BAD);
139 return NULL;
142 /* Get the old mode, in case there are any hidden fields... */
143 if (tcgetattr(fd, &mode) == -1)
144 return PyErr_SetFromErrno(TermiosError);
145 mode.c_iflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 0));
146 mode.c_oflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 1));
147 mode.c_cflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 2));
148 mode.c_lflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 3));
149 ispeed = (speed_t) PyInt_AsLong(PyList_GetItem(term, 4));
150 ospeed = (speed_t) PyInt_AsLong(PyList_GetItem(term, 5));
151 cc = PyList_GetItem(term, 6);
152 if (PyErr_Occurred())
153 return NULL;
155 if (!PyList_Check(cc) || PyList_Size(cc) != NCCS) {
156 PyErr_SetString(PyExc_TypeError, BAD);
157 return NULL;
160 for (i = 0; i < NCCS; i++) {
161 v = PyList_GetItem(cc, i);
163 if (PyString_Check(v) && PyString_Size(v) == 1)
164 mode.c_cc[i] = (cc_t) * PyString_AsString(v);
165 else if (PyInt_Check(v))
166 mode.c_cc[i] = (cc_t) PyInt_AsLong(v);
167 else {
168 PyErr_SetString(PyExc_TypeError, BAD);
169 return NULL;
173 if (cfsetispeed(&mode, (speed_t) ispeed) == -1)
174 return PyErr_SetFromErrno(TermiosError);
175 if (cfsetospeed(&mode, (speed_t) ospeed) == -1)
176 return PyErr_SetFromErrno(TermiosError);
177 if (tcsetattr(fd, when, &mode) == -1)
178 return PyErr_SetFromErrno(TermiosError);
180 Py_INCREF(Py_None);
181 return Py_None;
184 /* tcsendbreak(fd, duration)
185 Generate a break condition. */
187 static char termios_tcsendbreak__doc__[] = "\
188 tcsendbreak(fd, duration) -> None\n\
189 Send a break on file descriptor fd.\n\
190 A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration \n\
191 has a system dependent meaning. ";
193 static PyObject *
194 termios_tcsendbreak(PyObject *self, PyObject *args)
196 int fd, duration;
198 if (!PyArg_Parse(args, "(ii)", &fd, &duration))
199 return NULL;
200 if (tcsendbreak(fd, duration) == -1)
201 return PyErr_SetFromErrno(TermiosError);
203 Py_INCREF(Py_None);
204 return Py_None;
207 /* tcdrain(fd)
208 Wait until all queued output to the terminal has been
209 transmitted. */
211 static char termios_tcdrain__doc__[] = "\
212 tcdrain(fd) -> None\n\
213 Wait until all output written to file descriptor fd has been transmitted. ";
215 static PyObject *
216 termios_tcdrain(PyObject *self, PyObject *args)
218 int fd;
220 if (!PyArg_Parse(args, "i", &fd))
221 return NULL;
222 if (tcdrain(fd) == -1)
223 return PyErr_SetFromErrno(TermiosError);
225 Py_INCREF(Py_None);
226 return Py_None;
229 /* tcflush(fd, queue)
230 Clear the input and/or output queues associated with
231 the terminal. */
233 static char termios_tcflush__doc__[] = "\
234 tcflush(fd, queue) -> None\n\
235 Discard queued data on file descriptor fd.\n\
236 The queue selector specifies which queue: TERMIOS.TCIFLUSH for the input\n\
237 queue, TERMIOS.TCOFLUSH for the output queue, or TERMIOS.TCIOFLUSH for\n\
238 both queues. ";
240 static PyObject *
241 termios_tcflush(PyObject *self, PyObject *args)
243 int fd, queue;
245 if (!PyArg_Parse(args, "(ii)", &fd, &queue))
246 return NULL;
247 if (tcflush(fd, queue) == -1)
248 return PyErr_SetFromErrno(TermiosError);
250 Py_INCREF(Py_None);
251 return Py_None;
254 /* tcflow(fd, action)
255 Perform operations relating to XON/XOFF flow control on
256 the terminal. */
258 static char termios_tcflow__doc__[] = "\
259 tcflow(fd, action) -> None\n\
260 Suspend or resume input or output on file descriptor fd.\n\
261 The action argument can be TERMIOS.TCOOFF to suspend output,\n\
262 TERMIOS.TCOON to restart output, TERMIOS.TCIOFF to suspend input,\n\
263 or TERMIOS.TCION to restart input. ";
265 static PyObject *
266 termios_tcflow(PyObject *self, PyObject *args)
268 int fd, action;
270 if (!PyArg_Parse(args, "(ii)", &fd, &action))
271 return NULL;
272 if (tcflow(fd, action) == -1)
273 return PyErr_SetFromErrno(TermiosError);
275 Py_INCREF(Py_None);
276 return Py_None;
279 static PyMethodDef termios_methods[] =
281 {"tcgetattr", termios_tcgetattr,
282 METH_OLDARGS, termios_tcgetattr__doc__},
283 {"tcsetattr", termios_tcsetattr,
284 METH_OLDARGS, termios_tcsetattr__doc__},
285 {"tcsendbreak", termios_tcsendbreak,
286 METH_OLDARGS, termios_tcsendbreak__doc__},
287 {"tcdrain", termios_tcdrain,
288 METH_OLDARGS, termios_tcdrain__doc__},
289 {"tcflush", termios_tcflush,
290 METH_OLDARGS, termios_tcflush__doc__},
291 {"tcflow", termios_tcflow,
292 METH_OLDARGS, termios_tcflow__doc__},
293 {NULL, NULL}
296 DL_EXPORT(void)
297 PyInit_termios(void)
299 PyObject *m, *d;
301 m = Py_InitModule4("termios", termios_methods, termios__doc__,
302 (PyObject *)NULL, PYTHON_API_VERSION);
304 d = PyModule_GetDict(m);
305 TermiosError = PyErr_NewException("termios.error", NULL, NULL);
306 PyDict_SetItemString(d, "error", TermiosError);