Skip to main content

Modules/termios.c

Source:

cpython 3.14 @ ab2d84fe1023/Modules/termios.c

termios provides low-level control over terminal I/O. It is used by readline, tty, and interactive prompts.

Map

LinesSymbolRole
1-80termios_tcgetattrRead terminal attributes into a 7-element list
81-180termios_tcsetattrWrite terminal attributes from a 7-element list
181-220termios_tcsendbreakSend a break condition
221-260termios_tcdrainWait until all output has been transmitted
261-300termios_tcflushDiscard pending input or output
301-350ConstantsTCSANOW, TCSADRAIN, TCSAFLUSH, ICANON, ECHO, etc.

Reading

tcgetattr

// CPython: Modules/termios.c:62 termios_tcgetattr
static PyObject *
termios_tcgetattr(PyObject *self, PyObject *args)
{
int fd;
PyArg_ParseTuple(args, "O&:tcgetattr", conv_descriptor, &fd);
struct termios mode;
tcgetattr(fd, &mode);
/* Return a list of 7 elements:
* [iflag, oflag, cflag, lflag, ispeed, ospeed, cc]
* cc is a list of control characters (c_cc array as bytes) */
PyObject *v = PyList_New(7);
PyList_SetItem(v, 0, PyLong_FromLong((long)mode.c_iflag));
PyList_SetItem(v, 1, PyLong_FromLong((long)mode.c_oflag));
PyList_SetItem(v, 2, PyLong_FromLong((long)mode.c_cflag));
PyList_SetItem(v, 3, PyLong_FromLong((long)mode.c_lflag));
PyList_SetItem(v, 4, PyLong_FromLong((long)cfgetispeed(&mode)));
PyList_SetItem(v, 5, PyLong_FromLong((long)cfgetospeed(&mode)));
/* cc: NCCS bytes */
PyObject *cc = PyList_New(NCCS);
for (int i = 0; i < NCCS; i++)
PyList_SetItem(cc, i, PyBytes_FromStringAndSize((char *)&mode.c_cc[i], 1));
PyList_SetItem(v, 6, cc);
return v;
}

tcsetattr

// CPython: Modules/termios.c:128 termios_tcsetattr
static PyObject *
termios_tcsetattr(PyObject *self, PyObject *args)
{
int fd, when;
PyObject *term;
PyArg_ParseTuple(args, "O&iO:tcsetattr", conv_descriptor, &fd, &when, &term);
struct termios mode;
tcgetattr(fd, &mode); /* read current to fill unspecified fields */
mode.c_iflag = (tcflag_t)PyLong_AsLong(PyList_GetItem(term, 0));
mode.c_oflag = (tcflag_t)PyLong_AsLong(PyList_GetItem(term, 1));
mode.c_cflag = (tcflag_t)PyLong_AsLong(PyList_GetItem(term, 2));
mode.c_lflag = (tcflag_t)PyLong_AsLong(PyList_GetItem(term, 3));
cfsetispeed(&mode, (speed_t)PyLong_AsLong(PyList_GetItem(term, 4)));
cfsetospeed(&mode, (speed_t)PyLong_AsLong(PyList_GetItem(term, 5)));
/* Fill cc array */
...
tcsetattr(fd, when, &mode);
Py_RETURN_NONE;
}

when=TCSANOW applies immediately; TCSADRAIN waits for output to drain; TCSAFLUSH also discards pending input.

Common use: raw mode

# CPython: Lib/tty.py:12 setraw
def setraw(fd, when=termios.TCSAFLUSH):
"""Put terminal into a raw mode."""
mode = termios.tcgetattr(fd)
mode[3] = mode[3] & ~(termios.ECHO | termios.ICANON)
termios.tcsetattr(fd, when, mode)

Disabling ICANON turns off line buffering (reads return immediately). Disabling ECHO hides typed characters.

gopy notes

termios is in module/termios/. tcgetattr calls syscall.IoctlTermios (macOS) or unix.IoctlTermios (Linux). The 7-element list is constructed from the syscall.Termios struct fields. tcsetattr reconstructs the struct from the Python list and calls the corresponding ioctl.