mirror of
https://github.com/python/cpython.git
synced 2025-09-27 10:50:04 +00:00
bpo-41818: Add termios.tcgetwinsize(), termios.tcsetwinsize(). (GH-23686)
* Add termios.tcgetwinsize(), termios.tcsetwinsize(). Update docs. * Add TIOCGSIZE support to termios.tcgetwinsize() * Add TIOCSSIZE support to termios.tcsetwinsize() Authored-by: Soumendra Ganguly <soumendraganguly@gmail.com> * termios.tcgetwinsize() and termios.tcsetwinsize() should return/accept two-item tuples instead of lists. * Refactor tcsetwinsize to share common code and accept any two item sequence, with overflow checking. Co-authored-by: Gregory P. Smith <greg@krypto.org> [Google]
This commit is contained in:
parent
969ae7f735
commit
ae224bb566
4 changed files with 240 additions and 1 deletions
|
@ -74,6 +74,22 @@ The module defines the following functions:
|
||||||
output, :const:`TCIOFF` to suspend input, or :const:`TCION` to restart input.
|
output, :const:`TCIOFF` to suspend input, or :const:`TCION` to restart input.
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: tcgetwinsize(fd)
|
||||||
|
|
||||||
|
Return a tuple ``(ws_row, ws_col)`` containing the tty window size for file
|
||||||
|
descriptor *fd*. Requires :const:`termios.TIOCGWINSZ` or
|
||||||
|
:const:`termios.TIOCGSIZE`.
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: tcsetwinsize(fd, winsize)
|
||||||
|
|
||||||
|
Set the tty window size for file descriptor *fd* from *winsize*, which is
|
||||||
|
a two-item tuple ``(ws_row, ws_col)`` like the one returned by
|
||||||
|
:func:`tcgetwinsize`. Requires at least one of the pairs
|
||||||
|
(:const:`termios.TIOCGWINSZ`, :const:`termios.TIOCSWINSZ`);
|
||||||
|
(:const:`termios.TIOCGSIZE`, :const:`termios.TIOCSSIZE`) to be defined.
|
||||||
|
|
||||||
|
|
||||||
.. seealso::
|
.. seealso::
|
||||||
|
|
||||||
Module :mod:`tty`
|
Module :mod:`tty`
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Soumendra Ganguly: add termios.tcgetwinsize(), termios.tcsetwinsize().
|
66
Modules/clinic/termios.c.h
generated
66
Modules/clinic/termios.c.h
generated
|
@ -222,4 +222,68 @@ termios_tcflow(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
||||||
exit:
|
exit:
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
/*[clinic end generated code: output=a129179f1e2545cc input=a9049054013a1b77]*/
|
|
||||||
|
PyDoc_STRVAR(termios_tcgetwinsize__doc__,
|
||||||
|
"tcgetwinsize($module, fd, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"Get the tty winsize for file descriptor fd.\n"
|
||||||
|
"\n"
|
||||||
|
"Returns a tuple (ws_row, ws_col).");
|
||||||
|
|
||||||
|
#define TERMIOS_TCGETWINSIZE_METHODDEF \
|
||||||
|
{"tcgetwinsize", (PyCFunction)termios_tcgetwinsize, METH_O, termios_tcgetwinsize__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
termios_tcgetwinsize_impl(PyObject *module, int fd);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
termios_tcgetwinsize(PyObject *module, PyObject *arg)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (!_PyLong_FileDescriptor_Converter(arg, &fd)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
return_value = termios_tcgetwinsize_impl(module, fd);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(termios_tcsetwinsize__doc__,
|
||||||
|
"tcsetwinsize($module, fd, winsize, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"Set the tty winsize for file descriptor fd.\n"
|
||||||
|
"\n"
|
||||||
|
"The winsize to be set is taken from the winsize argument, which\n"
|
||||||
|
"is a two-item tuple (ws_row, ws_col) like the one returned by tcgetwinsize().");
|
||||||
|
|
||||||
|
#define TERMIOS_TCSETWINSIZE_METHODDEF \
|
||||||
|
{"tcsetwinsize", (PyCFunction)(void(*)(void))termios_tcsetwinsize, METH_FASTCALL, termios_tcsetwinsize__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
termios_tcsetwinsize_impl(PyObject *module, int fd, PyObject *winsz);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
termios_tcsetwinsize(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
int fd;
|
||||||
|
PyObject *winsz;
|
||||||
|
|
||||||
|
if (!_PyArg_CheckPositional("tcsetwinsize", nargs, 2, 2)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
winsz = args[1];
|
||||||
|
return_value = termios_tcsetwinsize_impl(module, fd, winsz);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
/*[clinic end generated code: output=db808d31296f6643 input=a9049054013a1b77]*/
|
||||||
|
|
|
@ -315,6 +315,156 @@ termios_tcflow_impl(PyObject *module, int fd, int action)
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
termios.tcgetwinsize
|
||||||
|
|
||||||
|
fd: fildes
|
||||||
|
/
|
||||||
|
|
||||||
|
Get the tty winsize for file descriptor fd.
|
||||||
|
|
||||||
|
Returns a tuple (ws_row, ws_col).
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
termios_tcgetwinsize_impl(PyObject *module, int fd)
|
||||||
|
/*[clinic end generated code: output=31825977d5325fb6 input=5706c379d7fd984d]*/
|
||||||
|
{
|
||||||
|
#if defined(TIOCGWINSZ)
|
||||||
|
termiosmodulestate *state = PyModule_GetState(module);
|
||||||
|
struct winsize w;
|
||||||
|
if (ioctl(fd, TIOCGWINSZ, &w) == -1) {
|
||||||
|
return PyErr_SetFromErrno(state->TermiosError);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *v;
|
||||||
|
if (!(v = PyTuple_New(2))) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyTuple_SetItem(v, 0, PyLong_FromLong((long)w.ws_row));
|
||||||
|
PyTuple_SetItem(v, 1, PyLong_FromLong((long)w.ws_col));
|
||||||
|
if (PyErr_Occurred()) {
|
||||||
|
Py_DECREF(v);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
#elif defined(TIOCGSIZE)
|
||||||
|
termiosmodulestate *state = PyModule_GetState(module);
|
||||||
|
struct ttysize s;
|
||||||
|
if (ioctl(fd, TIOCGSIZE, &s) == -1) {
|
||||||
|
return PyErr_SetFromErrno(state->TermiosError);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *v;
|
||||||
|
if (!(v = PyTuple_New(2))) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyTuple_SetItem(v, 0, PyLong_FromLong((long)s.ts_lines));
|
||||||
|
PyTuple_SetItem(v, 1, PyLong_FromLong((long)s.ts_cols));
|
||||||
|
if (PyErr_Occurred()) {
|
||||||
|
Py_DECREF(v);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
#else
|
||||||
|
PyErr_SetString(PyExc_NotImplementedError,
|
||||||
|
"requires termios.TIOCGWINSZ and/or termios.TIOCGSIZE");
|
||||||
|
return NULL;
|
||||||
|
#endif /* defined(TIOCGWINSZ) */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
termios.tcsetwinsize
|
||||||
|
|
||||||
|
fd: fildes
|
||||||
|
winsize as winsz: object
|
||||||
|
/
|
||||||
|
|
||||||
|
Set the tty winsize for file descriptor fd.
|
||||||
|
|
||||||
|
The winsize to be set is taken from the winsize argument, which
|
||||||
|
is a two-item tuple (ws_row, ws_col) like the one returned by tcgetwinsize().
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
termios_tcsetwinsize_impl(PyObject *module, int fd, PyObject *winsz)
|
||||||
|
/*[clinic end generated code: output=2ac3c9bb6eda83e1 input=4a06424465b24aee]*/
|
||||||
|
{
|
||||||
|
if (!PySequence_Check(winsz) || PySequence_Size(winsz) != 2) {
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"tcsetwinsize, arg 2: must be a two-item sequence");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *tmp_item;
|
||||||
|
long winsz_0, winsz_1;
|
||||||
|
tmp_item = PySequence_GetItem(winsz, 0);
|
||||||
|
winsz_0 = PyLong_AsLong(tmp_item);
|
||||||
|
if (winsz_0 == -1 && PyErr_Occurred()) {
|
||||||
|
Py_XDECREF(tmp_item);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Py_XDECREF(tmp_item);
|
||||||
|
tmp_item = PySequence_GetItem(winsz, 1);
|
||||||
|
winsz_1 = PyLong_AsLong(tmp_item);
|
||||||
|
if (winsz_1 == -1 && PyErr_Occurred()) {
|
||||||
|
Py_XDECREF(tmp_item);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Py_XDECREF(tmp_item);
|
||||||
|
|
||||||
|
termiosmodulestate *state = PyModule_GetState(module);
|
||||||
|
|
||||||
|
#if defined(TIOCGWINSZ) && defined(TIOCSWINSZ)
|
||||||
|
struct winsize w;
|
||||||
|
/* Get the old winsize because it might have
|
||||||
|
more fields such as xpixel, ypixel. */
|
||||||
|
if (ioctl(fd, TIOCGWINSZ, &w) == -1) {
|
||||||
|
return PyErr_SetFromErrno(state->TermiosError);
|
||||||
|
}
|
||||||
|
|
||||||
|
w.ws_row = (unsigned short) winsz_0;
|
||||||
|
w.ws_col = (unsigned short) winsz_1;
|
||||||
|
if ((((long)w.ws_row) != winsz_0) || (((long)w.ws_col) != winsz_1)) {
|
||||||
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
|
"winsize value(s) out of range.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctl(fd, TIOCSWINSZ, &w) == -1) {
|
||||||
|
return PyErr_SetFromErrno(state->TermiosError);
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
#elif defined(TIOCGSIZE) && defined(TIOCSSIZE)
|
||||||
|
struct ttysize s;
|
||||||
|
/* Get the old ttysize because it might have more fields. */
|
||||||
|
if (ioctl(fd, TIOCGSIZE, &s) == -1) {
|
||||||
|
return PyErr_SetFromErrno(state->TermiosError);
|
||||||
|
}
|
||||||
|
|
||||||
|
s.ts_lines = (int) winsz_0;
|
||||||
|
s.ts_cols = (int) winsz_1;
|
||||||
|
if ((((long)s.ts_lines) != winsz_0) || (((long)s.ts_cols) != winsz_1)) {
|
||||||
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
|
"winsize value(s) out of range.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctl(fd, TIOCSSIZE, &s) == -1) {
|
||||||
|
return PyErr_SetFromErrno(state->TermiosError);
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
#else
|
||||||
|
PyErr_SetString(PyExc_NotImplementedError,
|
||||||
|
"requires termios.TIOCGWINSZ, termios.TIOCSWINSZ and/or termios.TIOCGSIZE, termios.TIOCSSIZE");
|
||||||
|
return NULL;
|
||||||
|
#endif /* defined(TIOCGWINSZ) && defined(TIOCSWINSZ) */
|
||||||
|
}
|
||||||
|
|
||||||
static PyMethodDef termios_methods[] =
|
static PyMethodDef termios_methods[] =
|
||||||
{
|
{
|
||||||
TERMIOS_TCGETATTR_METHODDEF
|
TERMIOS_TCGETATTR_METHODDEF
|
||||||
|
@ -323,6 +473,8 @@ static PyMethodDef termios_methods[] =
|
||||||
TERMIOS_TCDRAIN_METHODDEF
|
TERMIOS_TCDRAIN_METHODDEF
|
||||||
TERMIOS_TCFLUSH_METHODDEF
|
TERMIOS_TCFLUSH_METHODDEF
|
||||||
TERMIOS_TCFLOW_METHODDEF
|
TERMIOS_TCFLOW_METHODDEF
|
||||||
|
TERMIOS_TCGETWINSIZE_METHODDEF
|
||||||
|
TERMIOS_TCSETWINSIZE_METHODDEF
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -841,6 +993,9 @@ static struct constant {
|
||||||
#ifdef TIOCGSERIAL
|
#ifdef TIOCGSERIAL
|
||||||
{"TIOCGSERIAL", TIOCGSERIAL},
|
{"TIOCGSERIAL", TIOCGSERIAL},
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef TIOCGSIZE
|
||||||
|
{"TIOCGSIZE", TIOCGSIZE},
|
||||||
|
#endif
|
||||||
#ifdef TIOCGSOFTCAR
|
#ifdef TIOCGSOFTCAR
|
||||||
{"TIOCGSOFTCAR", TIOCGSOFTCAR},
|
{"TIOCGSOFTCAR", TIOCGSOFTCAR},
|
||||||
#endif
|
#endif
|
||||||
|
@ -973,6 +1128,9 @@ static struct constant {
|
||||||
#ifdef TIOCSSERIAL
|
#ifdef TIOCSSERIAL
|
||||||
{"TIOCSSERIAL", TIOCSSERIAL},
|
{"TIOCSSERIAL", TIOCSSERIAL},
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef TIOCSSIZE
|
||||||
|
{"TIOCSSIZE", TIOCSSIZE},
|
||||||
|
#endif
|
||||||
#ifdef TIOCSSOFTCAR
|
#ifdef TIOCSSOFTCAR
|
||||||
{"TIOCSSOFTCAR", TIOCSSOFTCAR},
|
{"TIOCSSOFTCAR", TIOCSSOFTCAR},
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue