If Ctrl+c is sent over SSH, it's one byte: ^C
i.e. hex 0x03
i.e. octal 003
i.e. ASCII ETX.
If Ctrl+z is sent over SSH, it's one byte: ^Z
i.e. hex 0x1a
i.e. octal 032
i.e. ASCII SUB.
I wrote "if" because Ctrl+c on the client side may or may not generate a byte that gets to the server side. And on the server side this byte may or may not get to whatever program was started by the SSH server.
I don't know how exactly PuTTY in Windows handles this, but I know the mechanics in Linux (i.e. Linux client + Linux server). My answer puts together information from several other answers:
Let's suppose you run ssh
using a terminal emulator, then you press Ctrl+c. This is what happens:
The terminal emulator generates ^C
.
There's a tty line discipline that may or may not intercept this byte and "convert" it to a signal.
If the line discipline is configured to trigger SIGINT upon ^C
then it will send SIGINT to the current foreground process group. ssh
, being in the foreground process group, will receive the signal and exit.
If the line discipline is configured not to treat ^C
specially then it will send ^C
like any "normal" byte (e.g. like a
or 5
), ssh
will read it and send it to the remote side. And then…
On the remote side there may or may not be a tty allocated.
If there is no tty then a program started by the SSH server will receive ^C
on its stdin.
If there is a tty then there is a line discipline that in turn may or may not be configured to treat ^C
specially. Similarly to what can happen locally, the remote line discipline will send SIGINT to the (remote) foreground process group xor pass ^C
like any "normal" byte.
ssh
started as ssh … some_command
or ssh -T …
does not allocate a tty on the remote side and does not make the local terminal stop treating ^C
specially. In effect local Ctrl+c will terminate the local program (i.e. the ssh
itself). But if you bypass the local line discipline by piping to ssh
then you will be able to pass arbitrary data (including ^C
byte) to some_command
; on the remote side there will be no line discipline that could mangle the data.
ssh
started without a command or with -t
(-tt
is needed in some circumstances) does allocate a tty on the remote side and does make the local terminal stop treating ^C
specially. In effect local Ctrl+c won't terminate the local program (i.e. the ssh
itself) but it will get as ^C
to the remote side where the remote line discipline will handle it; so local Ctrl+c will possibly terminate the remote program. The remote line discipline won't be able to tell if ^C
it gets comes from local Ctrl+c or (e.g.) from piping printf "\003"
to ssh
; it's the same byte. When a tty is allocated on the remote side, you cannot reliably send/receive arbitrary data by piping to/from ssh
; the line discipline on the remote side will mangle the data. You can get some additional insight from this question of mine: ssh
with separate stdin, stdout, stderr AND tty.
So far every time I send ^C
or \cc
or \003
it just prints it out.
Possibilities:
There is no tty on the remote side, so there is no line discipline that would "convert" ^C
to SIGINT there; and the program "prints it out" in a form you can actually see (like cat -A
).
Or there is a tty on the remote side, but the line discipline is configured not to treat ^C
specially; and the terminal driver xor the program "prints it out" (it's easy to configure the terminal driver to echo (in caret notation) what it gets as input: stty ctlecho
).
Or there is a tty on the remote side and the line discipline is configured to treat ^C
specially; but the program traps SIGINT and instead of terminating itself "prints it out".
'\x03'
. OpenSSH is a suite of utilities and libraries, not an SSH client, so it's meaningless to ask what happens when you "press CTL-C in OpenSSH". – AlexP Oct 20 '19 at 03:04