Skip to content
16 changes: 16 additions & 0 deletions Doc/library/termios.rst
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,22 @@ The module defines the following functions:
output, :const:`TCIOFF` to suspend input, or :const:`TCION` to restart input.


.. function:: tcgetwinsize(fd)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one follow up PR as I forgot to fix it up here, these need versionadded tags. I'll take care of it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gpshead Thank you for making the improvements!


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::

Module :mod:`tty`
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Soumendra Ganguly: add termios.tcgetwinsize(), termios.tcsetwinsize().
66 changes: 65 additions & 1 deletion Modules/clinic/termios.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

158 changes: 158 additions & 0 deletions Modules/termios.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,156 @@ termios_tcflow_impl(PyObject *module, int fd, int action)
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[] =
{
TERMIOS_TCGETATTR_METHODDEF
Expand All @@ -323,6 +473,8 @@ static PyMethodDef termios_methods[] =
TERMIOS_TCDRAIN_METHODDEF
TERMIOS_TCFLUSH_METHODDEF
TERMIOS_TCFLOW_METHODDEF
TERMIOS_TCGETWINSIZE_METHODDEF
TERMIOS_TCSETWINSIZE_METHODDEF
{NULL, NULL}
};

Expand Down Expand Up @@ -841,6 +993,9 @@ static struct constant {
#ifdef TIOCGSERIAL
{"TIOCGSERIAL", TIOCGSERIAL},
#endif
#ifdef TIOCGSIZE
{"TIOCGSIZE", TIOCGSIZE},
#endif
#ifdef TIOCGSOFTCAR
{"TIOCGSOFTCAR", TIOCGSOFTCAR},
#endif
Expand Down Expand Up @@ -973,6 +1128,9 @@ static struct constant {
#ifdef TIOCSSERIAL
{"TIOCSSERIAL", TIOCSSERIAL},
#endif
#ifdef TIOCSSIZE
{"TIOCSSIZE", TIOCSSIZE},
#endif
#ifdef TIOCSSOFTCAR
{"TIOCSSOFTCAR", TIOCSSOFTCAR},
#endif
Expand Down