28

I just found out by accident that CTRL + 4 closes programs reading stdin input from the command-line.

This is how it looks when I type CTRL + 4 or CTRL + / into programs reading stdin

$ cat
wefwef
wefwef
^\Quit
$ bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
^\Quit
$

I get ^\Quit displayed and then the program closes. What is the difference of this compared to using ^C or ^D? What does ^\Quit do?

Edit: Found out that CTRL + \ does the very same thing.

wefwefa3
  • 1,385

2 Answers2

47

Ctrl+4 sends ^\

Terminals send characters (or more precisely bytes), not keys. When a key that represents a printable character is pressed, the terminal sends that character to the application. Most function keys are encoded as escape sequences: sequences of characters that start with the character number 27. Some keychords of the form Ctrl+character, and a few function keys, are sent as a control characters — in the ASCII character set, which all modern computers use as a basis (Unicode, ISO Latin-n, etc. are all supersets of ASCII), 33 characters are control characters: characters number 0 through 31 and 127. Control characters are not printable, but intended to have an effect in applications; for example character 10, which is Control-J (commonly written ^J), is a newline character, so when a terminal displays that character, it moves the cursor to the next line, rather than displaying a glyph. The escape character itself is a control character, ^[ (value 27).

There aren't enough control characters to cover all Ctrl+character keychords. Only letters and the characters @[\]^_? have a corresponding control character. When you press Ctrl+4 or Ctrl+$ (which I presume is Ctrl+Shift+4), the terminal has to pick something to send. Depending on the terminal and its configuration, there are several common possibilities:

  • The terminal ignores the Ctrl modifier and sends the character 4 or $.
  • The terminal sends an escape sequence that encodes the exact key and modifiers that were pressed.
  • The terminal sends some other control character.

Many terminal send control characters for some keys in the digit row:

  • Ctrl+2 → ^@
  • Ctrl+3 → ^[
  • Ctrl+4 → ^\
  • Ctrl+5 → ^]
  • Ctrl+6 → ^^
  • Ctrl+7 → ^_
  • Ctrl+8 → ^?

I don't know where this particular convention arose.

Ctrl+| sends the same character because it's Ctrl+Shift+\ and the terminal sends ^\ whether the shift key was pressed or not.

^\ quits

The terminal itself (more precisely, the generic terminal support in the kernel) interprets a few control characters specially. This interpretation can be configured to map different characters or turned off by applications that want to process the characters by themselves. One well-known such interpretation is that ^M, the character send by the Return key, sends the current line to the application, if the terminal is in cooked mode, in which applications receive input line by line.

A few characters send signals to the application in the foreground. ^C sends the interrupt signal (SIGINT), which conventionally tells the application to stop what it's doing and read the user's next command. Non-interactive applications usually exit. ^\ sends the quit signal (SIGQUIT), which conventionally tells the application to exit as soon as possible without saving anything; many applications don't override the default behavior, which is to kill the application immediately¹. So when you press Ctrl+4 (or anything that sends the ^\ character) in cat or bc, neither of which overrides the default behavior, the application is killed.

The terminal itself prints the ^\ part of the message: it's a visual depiction of the character that you typed, and the terminal is in cooked mode and with echo turned on (characters are displayed by the terminal as soon as you type them, as opposed to non-echo mode where the characters are only sent to the application, which may or may not choose to display them). The Quit part comes from bash: it notices that its child process died from a quit signal, and that's its way of letting you know.

Shells handle all common signals, so that if you type ^\ in a shell, you don't kill your session, you just get a new prompt, same as ^C.

You can play with terminal settings with the stty command.

¹ And traditionally generate a core dump, but many systems disable that by default nowadays.

  • SIGINT kills the foreground process group and SIGQUIT kills it with a core dump. Both signals can be handled. I'm not sure what you mean by reading the next command. Systems don't disable core dumps other than by setting the initial coredumpsize limit to 0 (not the hard one, you're generally free to raise it). – Stéphane Chazelas Aug 10 '16 at 20:08
  • @StéphaneChazelas In a program that performs user interactions, the usual semantics of SIGINT is to cancel the current user command and allow the user to interact with the program, i.e. to go back to the main command loop. On the other hand I don't remember seeing a program where SIGQUIT doesn't quit (barring bugs in the signal handler). Indeed the way many systems disable core dumps by default is to set the core dump size soft limit to 0, leaving users free to change this default setting if they wish. – Gilles 'SO- stop being evil' Aug 10 '16 at 20:14
  • That's the exception. SIGINT kills the currently running task. Only a few applications would extend that to kill their own "foreground" task. You must be thinking of less or vim. Note that in cmd | less, CTRL-C does generally kill cmd (while for less it's handled to cancel the current action (like a search)) (continued) – Stéphane Chazelas Aug 10 '16 at 20:24
  • I find the wording of your answer confusing in that regard. The fact that SIGQUIT is generally not handled is that it is not being used the same way. You press CTRL-C to abort what you're currently doing. You'd use CTRL-\\ only very occasionally for debugging to generate a core dump. There's generally no reason why an application would want to get in your way trying to do that. – Stéphane Chazelas Aug 10 '16 at 20:24
  • @StéphaneChazelas Not just less and vim, most terminal-based applications that read user commands to that. For example REPL (bash, dash, ksh, zsh, python, irb, fsharpi, Mathematica, …). It's hardly uncommon. Your first comment objects to painting SIGINT and SIGQUIT as too different and your latest comment objects to painting SIGINT and SIGQUIT as too similar, which leaves me puzzled as to what you're driving at. – Gilles 'SO- stop being evil' Aug 10 '16 at 20:41
  • From the system point of view, they are the same except one dumps a core, and the other one doesn't. The great majority of applications leave the signal disposition at that default. Those that handle them do it each in there own way (and most of them only bother with SIGINT). I honestly didn't know what you were meaning with your read the user's next command which got me really confused indeed and started this discussion. – Stéphane Chazelas Aug 10 '16 at 20:53
  • @Gilles Could you clarify which terminal (xterm, stty, kernel code) are you meaning when you say Many terminal send control characters for some keys in the digit row?. In particular: where should those conversions be removed/disabled/modified ? –  Dec 15 '18 at 22:47
  • @Isaac It's up to the terminal, e.g. xterm, rxvt, vte (a library that powers many terminals with a fancy GUI wrapping), konsole, Linux console, FreeBSD console, etc. – Gilles 'SO- stop being evil' Dec 16 '18 at 11:10
  • @Gilles I can not find any place in either xterm, konsole, etc. where to disable those keys (shortcuts?). Could you give an specific example of how those could be disabled in konsole (or xterm if you can not use konsole, or any other if xterm is also a problem). –  Dec 20 '18 at 02:48
  • @Isaac I don't know about konsole. For xterm, you need to change the XTerm.VT100.translations resource )example). – Gilles 'SO- stop being evil' Dec 20 '18 at 07:45
8

In addition to Gilles answer let me add, that you can always input non-printable characters in bash with Ctrl-v+key (Ctrl-v+Ctrl+4 in this case) and check the character code with

$ printf '^\' | od -An -tu    # input ^\ as C-v C-4
28

you get the decimal code of the character, which as you may check in man ascii corresponds to file separator (FS).

jimmij
  • 47,140
  • So what does ctrl+v do? I'm used to that being "paste clipboard". – JDługosz Aug 30 '15 at 04:21
  • 2
    @JDługosz: Ctrl-V tells the terminal to not interpret the following character. It is an unfortunate fact that GUI key combinations have taken over those control characters, causing unnecessary confusion. It used to be that Linux used Alt-[Key] for the GUI keys (e.g. Alt-C/Alt/V for copy/paste), but then people obviously thought doing the same as Windows was more important; meanwhile Mac users still have no problem to use the Command key instead of the Ctrl key for those operations. – celtschk Aug 30 '15 at 07:58
  • The (shorter) command is: printf '%d\n' '"^\' ? –  Dec 15 '18 at 22:49