Why do terminals sometimes echo special characters like ^C?
Run this, it's just a terminal setting, by default, everything you type is echoed :
stty -ctlecho
Now, your terminal is set to not display these characters.
man stty | less +/ctlecho
[-]ctlecho
echo control characters in hat notation ('^c')
To keep this configuration permanently, add it to your *rc file. (~/.bashrc
or such).
To list stty
settings, just type the command alone.
The character is echoed back because you have the ECHO
flag on in the terminal settings, and is echoed in the ^C form because you also have the ECHOCTL
flag on. Both flags are on by default on most systems. You can turn them on and off by using their lowercase form with the stty(1)
utility:
stty -echoctl # turn echoctl off
stty echoctl # turn echoctl on
You can refer to the termios(3)
manpage on Linux for a description [1]:
ECHOCTL
(not in POSIX)If
ECHO
is also set, terminal special characters other thanTAB
,NL
,START
, andSTOP
are echoed as^X
, whereX
is the character with ASCII code0x40
greater than the special character. For example, character0x08
(BS
) is echoed as^H
. [requires_BSD_SOURCE
or_SVID_SOURCE
]
Notice that turning just the ECHOCTL
flag off will not prevent control characters from being echoed back, but will cause them to be echoed back in their raw form, rather than in the ^X
caret form. The fact that a character is special and will generate a signal (eg. ^C
-> VINTR
-> SIGINT
) does not affect in any way whether it will be echoed back or not.
Most terminal emulators will not display the control characters in any way (unfortunately), but they may interpret them in funny ways: for an illustrative example, start a command like
sleep 3600
or cat > /dev/null
, then on the next line press the <Escape>[41m foo<Enter>
keys. With echoctl
on, you'll have ^[[41m foo
printed on your screen, and nothing special will happen. But with echoctl
off, the terminal will interpret the echoed back <Raw_esc>[41m
as an ANSI color escape (without displaying any of the [41m
, etc) and will turn the background red.
Depending on the terminal emulator and its settings, an emacs user pressing ^N
by reflex may end up switching to the alternate character set, and turn all the letters into line-drawing squiggles.
You usually don't want these to happen, thence ECHOCTL
can be considered a reasonable default.
[1] That description is not very accurate:
It's not the "terminal special characters" which are echoed in that caret form, but the control characters (ASCII
0x0 - 0x1f
and0x7f
), no matter if they're special or not. If you defineQ
as theVINTR
"terminal special character" (replacing the default^C
, eg. withstty intr Q
), it will still be echoed back as simplyQ
, not as^Q
orchr(0x91)
.On Linux,
VEOF
will not be echoed back (as^D
or in any other form) when theICANON
flag is also set. But it will be echoed back in that case too on *BSD and MacOS.ASCII
0x7f
(DEL
) will not be displayed aschar + 0x40
(as described), but aschar ^ 0x40
(^?
). Just like all the others, btw ;-)