Skip to content
Advertisement

How to get fully interactive bash terminal in C with shift + ctrl keys?

I want to know how to create a fully interactive terminal. I am creating an interactive bash terminal like this:

JavaScript

I can then go on to use read()/write() to send commands and receive output. My problem is how do I automate CTRL & SHIFT keys? Python’s subprocess does this so it’s definitely possible.

  1. How to send ctrl-c to kill foreground process? In python it would be the follow and I want to know what it looks like in C:
JavaScript
  1. How to send shift, ctrl, esc keys? For example, how to open nano, then send ctrl-a-esc? In python it would be the following & I want to know what it looks like in C:
JavaScript

Advertisement

Answer

There are four separate issues here:

1. How to trigger a Ctrl-C on the PTY

The sigint is triggered by the terminal’s line discipline upon receiving Ctrl-C as input (in cooked mode). You can do this by sending 0x03, which is equivalent to uppercase ASCII ‘C’ with the 7th bit cleared:

JavaScript

2. The C equivalent of process.send_signal

JavaScript

This simply does a fork+kill, so it’s unrelated to anything you’d do to accomplish #1. You can see this in strace:

JavaScript

3. How to send Shift, Ctrl and Esc

Esc is simple: you just send its ASCII value. Here’s man ascii:

JavaScript

Shift and Control are modifiers, so you don’t actually send them. You just modify the character you send. #1 already covered how to do this for Ctrl on simple ascii characters.

For shift, you should simply uppercase the character you’re interested in using appropriate string functions. The traditional hardware logic of clearing/setting bit 6 doesn’t work well for unicode characters, but 'c' == 'C'+0x20 if you feel like it.

Note that this does not apply to things like arrow keys, where you need to send a different ANSI escape code corresponding to the terminal you’re trying to emulate.

For completeness, Alt/Meta has two forms: Traditionally setting bit 8 (mostly deprecated for Unicode reasons), or Meta-As-Escape where you simply send the two bytes ESC x for Alt+x.


4. The C equivalent of the piping to xte

JavaScript

This opens an X11 utility that simulates an X11 key sequence. If you are running the program in an XTerm and don’t switch focus, this will hopefully end up in the terminal where you started, but this is not at all a guarantee. It is definitely nothing like #3.

If you wanted to do this though, you can use popen from C in much the same way, but it won’t help you do anything of what you describe textually.


You can find a complete example for sending Ctrl+C adapted from your code here:

JavaScript

Execution shows that sleep is interrupted, the shell continues, and is finally exited:

JavaScript
Advertisement