1 /* termiosmodule.c -- POSIX terminal I/O module implementation. */
5 #define PyInit_termios inittermios
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\
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\
20 This module should be used in conjunction with the TERMIOS module,\n\
21 which defines the relevant symbolic constants.";
28 #define BAD "bad termios argument"
30 static PyObject
*TermiosError
;
32 /* termios = tcgetattr(fd)
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.";
49 termios_tcgetattr(PyObject
*self
, PyObject
*args
)
54 speed_t ispeed
, ospeed
;
59 if (!PyArg_Parse(args
, "i", &fd
))
62 if (tcgetattr(fd
, &mode
) == -1)
63 return PyErr_SetFromErrno(TermiosError
);
65 ispeed
= cfgetispeed(&mode
);
66 ospeed
= cfgetospeed(&mode
);
68 cc
= PyList_New(NCCS
);
71 for (i
= 0; i
< NCCS
; i
++) {
72 ch
= (char)mode
.c_cc
[i
];
73 v
= PyString_FromStringAndSize(&ch
, 1);
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
]);
86 PyList_SetItem(cc
, VMIN
, v
);
87 v
= PyInt_FromLong((long)mode
.c_cc
[VTIME
]);
90 PyList_SetItem(cc
, VTIME
, v
);
93 if (!(v
= PyList_New(7)))
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()){
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. ";
127 termios_tcsetattr(PyObject
*self
, PyObject
*args
)
131 speed_t ispeed
, ospeed
;
132 PyObject
*term
, *cc
, *v
;
135 if (!PyArg_Parse(args
, "(iiO)", &fd
, &when
, &term
))
137 if (!PyList_Check(term
) || PyList_Size(term
) != 7) {
138 PyErr_SetString(PyExc_TypeError
, BAD
);
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())
155 if (!PyList_Check(cc
) || PyList_Size(cc
) != NCCS
) {
156 PyErr_SetString(PyExc_TypeError
, BAD
);
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
);
168 PyErr_SetString(PyExc_TypeError
, BAD
);
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
);
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. ";
194 termios_tcsendbreak(PyObject
*self
, PyObject
*args
)
198 if (!PyArg_Parse(args
, "(ii)", &fd
, &duration
))
200 if (tcsendbreak(fd
, duration
) == -1)
201 return PyErr_SetFromErrno(TermiosError
);
208 Wait until all queued output to the terminal has been
211 static char termios_tcdrain__doc__
[] = "\
212 tcdrain(fd) -> None\n\
213 Wait until all output written to file descriptor fd has been transmitted. ";
216 termios_tcdrain(PyObject
*self
, PyObject
*args
)
220 if (!PyArg_Parse(args
, "i", &fd
))
222 if (tcdrain(fd
) == -1)
223 return PyErr_SetFromErrno(TermiosError
);
229 /* tcflush(fd, queue)
230 Clear the input and/or output queues associated with
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\
241 termios_tcflush(PyObject
*self
, PyObject
*args
)
245 if (!PyArg_Parse(args
, "(ii)", &fd
, &queue
))
247 if (tcflush(fd
, queue
) == -1)
248 return PyErr_SetFromErrno(TermiosError
);
254 /* tcflow(fd, action)
255 Perform operations relating to XON/XOFF flow control on
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. ";
266 termios_tcflow(PyObject
*self
, PyObject
*args
)
270 if (!PyArg_Parse(args
, "(ii)", &fd
, &action
))
272 if (tcflow(fd
, action
) == -1)
273 return PyErr_SetFromErrno(TermiosError
);
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__
},
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
);