Using a Linux OS, I need to transparently pass all keystrokes from remote connections to local hardware connections. This is fairly straight forward for everything but signals. I know I can register handlers for each signal that capture and pass the keystroke, but this seems like a hack that might not work for edge cases (what if someone changes the interrupt key combo mapping, would I be double passing the keystrokes, etc.).
In order to come up with a better solution, I really need to know more about how the key combos, IE: CTRL-C, become signals, IE: SIGINT.
- How does the keycombo become a Signal (in the kernel, client application, runtime)?
- Is the keystroke still passed? If CTRL-C has a null handler, does STDIN still get CTRL-C?
- What is the best way to not interpret any keystroke as a signal combination? Can this be done in TTY or Environment settings?
Advertisement
Answer
- The key combo is turned into a signal by the terminal’s line discipline, a layer in the TTY subsystem. Here’s the description from Wikipedia:
For example, the standard line discipline processes the data it receives from the hardware driver and from applications writing to the device according to the requirements of a terminal on a Unix-like system. On input, it handles special characters such as the interrupt character (typically Control-C) and the erase and kill characters (typically backspace or delete, and Control-U, respectively) and, on output, it replaces all the LF characters with a CR/LF sequence.
The keypress is not passed, it’s suppressed when the signal is raised. If the process has no SIGINT handler, the kernel will terminate it.
You can obviously override this: that’s how tools like
ssh
work. You can easily do this by setting the terminal to “raw” mode, e.g. with the shell commandstty raw
. If you then runcat -vE
you can hit any keys you want and see them printed in caret notation. Make sure to plan on a way to close the terminal because you can obviously not Ctrl-C/Z/D out of it anymore.