I want to make a specific combination of keyboard keys in order to terminate a process e.x I want to terminate the process by pressin CTRL + C ^ 3 (pressing three times C: CTRL +CCC).
So basically I want to replace CTRL + C with CTRL + CCC
I want to make a specific combination of keyboard keys in order to terminate a process e.x I want to terminate the process by pressin CTRL + C ^ 3 (pressing three times C: CTRL +CCC).
So basically I want to replace CTRL + C with CTRL + CCC
The default behavior of Ctrl+C is a combination of two things. The terminal driver¹ does not transmit this key press, but instead sends a SIGINT signal to the foreground process². By default, a process dies when it receives a SIGINT, but the process can set a signal handler, and then it'll run the signal handler when it receives SIGINT.
There's no way to configure the terminal driver to only convert the third Ctrl+C in a row to kill the foreground process. To do that, you need to count to three in your program. There are two ways you can do that, which will behave differently if the user presses something else between the Ctrl+C's.
One way is to disable Ctrl+C's behavior of sending a signal and telling the terminal driver to instead pass it through. You can do that by calling stty intr \^-
from a shell script or tcsetattr(fd, &termios)
with termios.c_cc[VINTR]
set to _POSIX_VDISABLE
from C. Then, in your program's input processing loop, exit when you've seen three Ctrl+C's in a row.
The other way is to set a signal handler for SIGINT that counts how many times it's been invoked and terminates the program the third time. You may want to reset the counter if there's normal input in between.
¹ Not the terminal emulator, the generic part of the operating system that handles all terminals.
² I'm only explaining the simple case. This is not a treatise on how the terminal driver works.
IGNBRK
has nothing to do with Ctrl-C being translated to SIGINT
. It's ISIG
in c_lflag
who is controlling that (also c_cc[VINTR]
can be set to 0 to disable it, or to another char). stty -intr
is not a valid command. A VINTR
/Ctrl-C won't send a signal to the "foreground process", but to the foreground process group (job), ie. when running a|b|c
and pressing ^C, a signal will be sent to the a
, b
and c
processes.
–
Jun 01 '19 at 21:53
SIGINT
will be sent to all the processes in the group is essential, because it makes clear the dangerous futility of setting up a SIGINT
handler as a way of key-binding; if the program is run as part of a pipeline or through a wrapper, it will still be (indirectly) killed by the 1st ^C (it will get a SIGPIPE
when trying to write to the pipe, or have its children summarily killed while it's still counting up to 3). And changing tty attributes is no better, unless it's a full screen app (like vi
or emacs
) which has the tty all to itself.
–
Jun 01 '19 at 23:22
You can't change key binding in your code because a signal is a software generated interrupt that is sent to a process by the OS. when user press ctrl-c another process tell something to your process.
There are fix set of signals that can be sent to a process. signals are similar to interrupts, the difference being that interrupts are mediated by the processor and handled by the kernel while signals are mediated by the kernel (possibly via system calls) and handled by processes. The kernel may pass an interrupt as a signal to the process that caused it (typical examples are SIGSEGV, SIGBUS, SIGILL and SIGFPE).
you can remap signal key binding in your computer with stty
Enable Ctrl+C for copy and Ctrl+Shift+C for interrput
https://docstore.mik.ua/orelly/unix3/upt/ch05_08.htm
if you want exactly 3 times ctrl-c. you can count SIGINT and break the program when 3 times ctrl-c pressed. (pressing three times C: CTRL +CCC).
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
void sig_handler(int signo)
{
static int counter=0;
if (signo == SIGINT)
counter++;
printf("received SIGINT %d times\n", counter);
if (counter == 3)
exit(0);
}
int main()
{
if (signal(SIGINT, sig_handler) == SIG_ERR)
printf("\ncan't catch SIGINT\n");
while(1)
sleep(1);
return 0;
}
CTRL + AAA
instead of CTRL + CCC
?
– Abhik Bose
Jun 01 '19 at 19:22
printf
and exit
in signal handlers, ever. just think what happens if a SIGINT
is coming while the program is running another printf or flushing the stdio buffers, or within a handler registered with atexit(3).
–
Jun 01 '19 at 19:54
stty intr '^A'
(from C you do that with tcsetattr(), look up the termios(3) manpage).
–
Jun 01 '19 at 19:56
signal()
instead of sigaction()
is also highly dubious: on some systems, signal(3)
will set the handler as with SA_RESETHAND
ie the handler will be disabled after the first ^C.
–
Jun 01 '19 at 20:11