55#define PyInit_termios inittermios
66
77#include <termios.h>
8- /* XXX Some systems need this to get all the symbols, while
9- this breaks for others.
8+ #include <termio.h>
109#include <sys/ioctl.h>
11- */
10+
11+ #ifdef __BEOS__
12+ #include <unistd.h>
13+ #endif
1214
1315static char termios__doc__ [] = "\
1416This module provides an interface to the Posix calls for tty I/O control.\n\
1517For a complete description of these calls, see the Posix or Unix manual\n\
1618pages. It is only available for those Unix versions that support Posix\n\
17- termios style tty I/O control (and then only if configured at installation\n\
18- time).\n\
19+ termios style tty I/O control.\n\
1920\n\
2021All functions in this module take a file descriptor fd as their first\n\
21- argument. This must be an integer file descriptor, such as returned by\n\
22- sys.stdin.fileno()." ;
23-
22+ argument. This can be an integer file descriptor, such as returned by\n\
23+ sys.stdin.fileno(), or a file object, such as sys.stdin itself." ;
2424
25- #ifdef __BEOS__
26- #include <unistd.h>
27- #endif
25+ static PyObject * TermiosError ;
2826
29- #define BAD "bad termios argument"
27+ static char * fname ;
3028
31- static PyObject * TermiosError ;
29+ static int fdconv (PyObject * obj , void * p )
30+ {
31+ int fd ;
3232
33- /* termios = tcgetattr(fd)
34- termios is
35- [iflag, oflag, cflag, lflag, ispeed, ospeed, [cc[0], ..., cc[NCCS]]]
33+ fd = PyObject_AsFileDescriptor (obj );
34+ if (fd == -1 ) {
35+ if (PyInt_Check (obj )) {
36+ fd = PyInt_AS_LONG (obj );
37+ }
38+ else {
39+ char * tname ;
40+
41+ if (PyInstance_Check (obj )) {
42+ tname = PyString_AS_STRING (
43+ ((PyInstanceObject * )obj )-> in_class -> cl_name );
44+ }
45+ else {
46+ tname = obj -> ob_type -> tp_name ;
47+ }
48+
49+ PyErr_Format (PyExc_TypeError ,
50+ "%s, arg 1: can't extract file descriptor from \"%.500s\"" ,
51+ fname , tname );
52+ return 0 ;
53+ }
54+ }
3655
37- Return the attributes of the terminal device. */
56+ * (int * )p = fd ;
57+ return 1 ;
58+ }
3859
3960static char termios_tcgetattr__doc__ [] = "\
4061tcgetattr(fd) -> list_of_attrs\n\
62+ \n\
4163Get the tty attributes for file descriptor fd, as follows:\n\
4264[iflag, oflag, cflag, lflag, ispeed, ospeed, cc] where cc is a list\n\
4365of the tty special characters (each a string of length 1, except the items\n\
@@ -57,7 +79,10 @@ termios_tcgetattr(PyObject *self, PyObject *args)
5779 int i ;
5880 char ch ;
5981
60- if (!PyArg_Parse (args , "i" , & fd ))
82+ fname = "tcgetattr" ;
83+
84+ if (!PyArg_ParseTuple (args , "O&:tcgetattr" ,
85+ fdconv , (void * )& fd ))
6186 return NULL ;
6287
6388 if (tcgetattr (fd , & mode ) == -1 )
@@ -111,11 +136,9 @@ termios_tcgetattr(PyObject *self, PyObject *args)
111136 return NULL ;
112137}
113138
114- /* tcsetattr(fd, when, termios)
115- Set the attributes of the terminal device. */
116-
117139static char termios_tcsetattr__doc__ [] = "\
118140tcsetattr(fd, when, attributes) -> None\n\
141+ \n\
119142Set the tty attributes for file descriptor fd.\n\
120143The attributes to be set are taken from the attributes argument, which\n\
121144is a list like the one returned by tcgetattr(). The when argument\n\
@@ -133,10 +156,14 @@ termios_tcsetattr(PyObject *self, PyObject *args)
133156 PyObject * term , * cc , * v ;
134157 int i ;
135158
136- if (!PyArg_Parse (args , "(iiO)" , & fd , & when , & term ))
159+ fname = "tcsetattr" ;
160+
161+ if (!PyArg_ParseTuple (args , "O&iO:tcsetattr" ,
162+ fdconv , & fd , & when , & term ))
137163 return NULL ;
138164 if (!PyList_Check (term ) || PyList_Size (term ) != 7 ) {
139- PyErr_SetString (PyExc_TypeError , BAD );
165+ PyErr_SetString (PyExc_TypeError ,
166+ "tcsetattr, arg 3: must be 7 element list" );
140167 return NULL ;
141168 }
142169
@@ -154,7 +181,9 @@ termios_tcsetattr(PyObject *self, PyObject *args)
154181 return NULL ;
155182
156183 if (!PyList_Check (cc ) || PyList_Size (cc ) != NCCS ) {
157- PyErr_SetString (PyExc_TypeError , BAD );
184+ PyErr_Format (PyExc_TypeError ,
185+ "tcsetattr: attributes[6] must be %d element list" ,
186+ NCCS );
158187 return NULL ;
159188 }
160189
@@ -166,7 +195,8 @@ termios_tcsetattr(PyObject *self, PyObject *args)
166195 else if (PyInt_Check (v ))
167196 mode .c_cc [i ] = (cc_t ) PyInt_AsLong (v );
168197 else {
169- PyErr_SetString (PyExc_TypeError , BAD );
198+ PyErr_SetString (PyExc_TypeError ,
199+ "tcsetattr: elements of attributes must be characters or integers" );
170200 return NULL ;
171201 }
172202 }
@@ -182,21 +212,22 @@ termios_tcsetattr(PyObject *self, PyObject *args)
182212 return Py_None ;
183213}
184214
185- /* tcsendbreak(fd, duration)
186- Generate a break condition. */
187-
188215static char termios_tcsendbreak__doc__ [] = "\
189216tcsendbreak(fd, duration) -> None\n\
217+ \n\
190218Send a break on file descriptor fd.\n\
191- A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration \n\
192- has a system dependent meaning. " ;
219+ A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration\n\
220+ has a system dependent meaning." ;
193221
194222static PyObject *
195223termios_tcsendbreak (PyObject * self , PyObject * args )
196224{
197225 int fd , duration ;
198226
199- if (!PyArg_Parse (args , "(ii)" , & fd , & duration ))
227+ fname = "tcsendbreak" ;
228+
229+ if (!PyArg_ParseTuple (args , "O&i:tcsendbreak" ,
230+ fdconv , & fd , & duration ))
200231 return NULL ;
201232 if (tcsendbreak (fd , duration ) == -1 )
202233 return PyErr_SetFromErrno (TermiosError );
@@ -205,20 +236,20 @@ termios_tcsendbreak(PyObject *self, PyObject *args)
205236 return Py_None ;
206237}
207238
208- /* tcdrain(fd)
209- Wait until all queued output to the terminal has been
210- transmitted. */
211-
212239static char termios_tcdrain__doc__ [] = "\
213240tcdrain(fd) -> None\n\
214- Wait until all output written to file descriptor fd has been transmitted. " ;
241+ \n\
242+ Wait until all output written to file descriptor fd has been transmitted." ;
215243
216244static PyObject *
217245termios_tcdrain (PyObject * self , PyObject * args )
218246{
219247 int fd ;
220248
221- if (!PyArg_Parse (args , "i" , & fd ))
249+ fname = "tcdrain" ;
250+
251+ if (!PyArg_ParseTuple (args , "O&:tcdrain" ,
252+ fdconv , & fd ))
222253 return NULL ;
223254 if (tcdrain (fd ) == -1 )
224255 return PyErr_SetFromErrno (TermiosError );
@@ -227,12 +258,9 @@ termios_tcdrain(PyObject *self, PyObject *args)
227258 return Py_None ;
228259}
229260
230- /* tcflush(fd, queue)
231- Clear the input and/or output queues associated with
232- the terminal. */
233-
234261static char termios_tcflush__doc__ [] = "\
235262tcflush(fd, queue) -> None\n\
263+ \n\
236264Discard queued data on file descriptor fd.\n\
237265The queue selector specifies which queue: termios.TCIFLUSH for the input\n\
238266queue, termios.TCOFLUSH for the output queue, or termios.TCIOFLUSH for\n\
@@ -243,7 +271,10 @@ termios_tcflush(PyObject *self, PyObject *args)
243271{
244272 int fd , queue ;
245273
246- if (!PyArg_Parse (args , "(ii)" , & fd , & queue ))
274+ fname = "tcflush" ;
275+
276+ if (!PyArg_ParseTuple (args , "O&i:tcflush" ,
277+ fdconv , & fd , & queue ))
247278 return NULL ;
248279 if (tcflush (fd , queue ) == -1 )
249280 return PyErr_SetFromErrno (TermiosError );
@@ -252,12 +283,9 @@ termios_tcflush(PyObject *self, PyObject *args)
252283 return Py_None ;
253284}
254285
255- /* tcflow(fd, action)
256- Perform operations relating to XON/XOFF flow control on
257- the terminal. */
258-
259286static char termios_tcflow__doc__ [] = "\
260287tcflow(fd, action) -> None\n\
288+ \n\
261289Suspend or resume input or output on file descriptor fd.\n\
262290The action argument can be termios.TCOOFF to suspend output,\n\
263291termios.TCOON to restart output, termios.TCIOFF to suspend input,\n\
@@ -268,7 +296,10 @@ termios_tcflow(PyObject *self, PyObject *args)
268296{
269297 int fd , action ;
270298
271- if (!PyArg_Parse (args , "(ii)" , & fd , & action ))
299+ fname = "tcflow" ;
300+
301+ if (!PyArg_ParseTuple (args , "O&i:tcflow" ,
302+ fdconv , & fd , & action ))
272303 return NULL ;
273304 if (tcflow (fd , action ) == -1 )
274305 return PyErr_SetFromErrno (TermiosError );
@@ -280,17 +311,17 @@ termios_tcflow(PyObject *self, PyObject *args)
280311static PyMethodDef termios_methods [] =
281312{
282313 {"tcgetattr" , termios_tcgetattr ,
283- METH_OLDARGS , termios_tcgetattr__doc__ },
314+ METH_VARARGS , termios_tcgetattr__doc__ },
284315 {"tcsetattr" , termios_tcsetattr ,
285- METH_OLDARGS , termios_tcsetattr__doc__ },
316+ METH_VARARGS , termios_tcsetattr__doc__ },
286317 {"tcsendbreak" , termios_tcsendbreak ,
287- METH_OLDARGS , termios_tcsendbreak__doc__ },
318+ METH_VARARGS , termios_tcsendbreak__doc__ },
288319 {"tcdrain" , termios_tcdrain ,
289- METH_OLDARGS , termios_tcdrain__doc__ },
320+ METH_VARARGS , termios_tcdrain__doc__ },
290321 {"tcflush" , termios_tcflush ,
291- METH_OLDARGS , termios_tcflush__doc__ },
322+ METH_VARARGS , termios_tcflush__doc__ },
292323 {"tcflow" , termios_tcflow ,
293- METH_OLDARGS , termios_tcflow__doc__ },
324+ METH_VARARGS , termios_tcflow__doc__ },
294325 {NULL , NULL }
295326};
296327
0 commit comments