The image is correct. The kernel (at least within the context of this question) does not act as a terminal emulator. It handles the line discipline, see the stty(1)
and termios(3)
manuals to have a feeling what the line discipline means. It's stuff like CR-LF conversion, ^C
(interrupt) handling, some minimal line editing capabilities (called the "cooked" mode, which implements the handling of backspace, ^W
and friends if you execute a command like cat
which does not have its own line editing capabilities, and only sends the entire line when you press Enter), control flow, serial port properties (pretty much obsolete), stuff like these. But it doesn't handle the \e
escape character.
Now, the Linux kernel does implement a terminal emulator, analogously to the "xterm" node of the image. It's the virtual console (typically on Ctrl+Alt+F1 and friends), the vt
component of the Linux kernel rather than the tty
component. For the purpose of this question, this is irrelevant; and I also see that your question is not speicific to Linux, I'm not familiar with other Unix variants in this regard.
Is it xterm
that processes escape sequences, or it just lets the kernel do the work?
It is xterm
. Overly simplified story: When xterm starts up, it sets up a tty line (master and slave side), fires up a command (typically a shell, "user process" in the picture, with TERM
being set properly) connected to this tty and also presents a graphical window with the cursor at the upper left corner. Then it does a two-way communication.
For keypresses it transfers their sequences as seen in the arrows of the picture. Depending on the line discipline, the kernel might handle it itself (e.g. if you're running cat
and press the letter 'x', it is not yet sent to cat
, it's the kernel handling the basic line editing), in this case the kernel will tell the terminal how to update the display (probably by printing an 'x'); or it may forward the keypress to the relevant user process(es).
In the other direction, the user process may or may not want to update its display (and it may want to do it regardless of a received keypress), which data traverses this path in the opposite direction.
Let's say an app outputs x\e[31my\n
. The line discipline converts \n
to \r\n
(otherwise you'd end up with the "staircase effect"), but it doesn't care about the \e
character, so the terminal emulator receives x\e[31my\r\n
.
xterm
receives this and says: I need to print an x
at the cursor, then \e[31m
means I need to switch to red, then print a y
(in red), then move the cursor back and down one line. It does so and updates its display accordingly.
In other words, the xterm
terminfo
database entry... does it correspond to the kernel, or to xterm
?
Terminfo describes the behavior of various terminal emulators towards user applications (because all terminal emulators handle the escape sequences somewhat differently). The kernel doesn't know anything about it.
There's a slight overlap though with the kernel and what the terminfo says, e.g. the terminfo might contain an entry for the backspace character (whether it's ^H
or ^?
), but this behavior is implemented in the line discipline rather than the terminal emulator. The terminal emulator should configure the line discipline accordingly, and in this sense it's valid to say that it describes the terminal emulator's behavior, even though it's not the terminal emulator itself but it delegates this task to the kernel's line discipline. Anyway, I digress, this is the exception and not the rule. The rule is that terminfo describes the terminal emulator's own behavior.
Do programs that create pseudoterminals emulate terminals?
No, not necessarily. I would categorize apps that create a terminal line like this:
- terminal emulators (
xterm
, urxvt
, screen
, tmux
, ...)
- not terminal emulators (
ssh
(when interactive or -t
is given), script
, luit
, ...)
I'm not familiar with docker
but I suspect it belongs to the second group.
The second group contains apps that by their very nature need to create a tty line, but only for the purpose of forwarding or logging or simple manipulation of the data that has nothing to do with escape sequences. These apps don't know what \e
means, don't know that \e[31m
means red, don't even know what "red" means, don't have a concept how the terminal's canvas should look like at a given moment.
The first group is apps that do have to care about such escape sequences. screen
and tmux
might be surprising at first, but these apps have absolutely no chance of implementing their behavior by just blindly forwarding the data - they wouldn't be able to restore the canvas when you reattach or switch between tabs, let alone handle a paned layout of multiple terminals at once. These tools have to parse and perfectly understand every escape sequence, and track in their memory how exactly the canvas needs to look like.
I prefer to think of screen
and tmux
as terminal emulators, with the main difference from xterm
and friends being that their backend, their canvas on which they present the contents to the user, is the character grid of another terminal emulator, rather than a window's pixels on the graphical user interface. (The other main difference is the ability to detach and reattach, which is irrelevant here.)
I hope this all makes sense.