4

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

3
  • 4
    Trap that signal and do counting by yourself Commented Jun 1, 2019 at 13:53
  • How to trap it, i can't figure it out ? Commented Jun 1, 2019 at 14:28
  • check man pages for signal(7) and sigaction, set a handler for SIGINT and count inside the handler. Commented Jun 1, 2019 at 18:11

2 Answers 2

9

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.

6
  • Can you briefly give me an example for second way ? Commented Jun 1, 2019 at 21:06
  • @AlbionShala You never said what programming language you're using. And anyway programming is off-topic here when it goes beyond simple scripting. But a web search with the name of your programming language and "signal handler" and "tutorial" should give you examples. Commented Jun 1, 2019 at 21:14
  • Actually yes i mentioned that i am using C in Linux but it was editted, anyhow thanks a lot, i really appreciate it Commented Jun 1, 2019 at 21:17
  • 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. Commented Jun 1, 2019 at 21:53
  • @mosvy Thanks, I hadn't done that in a while and I should have spent more than 5s re-reading the man page. Regarding process groups, see footnote 2. Commented Jun 1, 2019 at 22:04
5

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;
}
7
  • What happens if I want to terminate with CTRL + AAA instead of CTRL + CCC? Commented Jun 1, 2019 at 19:22
  • 1
    Changing key binding in your code is not possible as far as i know. but like i said you can change signal key binding in stty and in your terminal emulator. Commented Jun 1, 2019 at 19:29
  • 1
    you do not use 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). Commented Jun 1, 2019 at 19:54
  • 1
    Thanks @mosvy but this is a proof of concept code not a real one. why you don't add an answer and explain us more about what you know. because i didn't get what you said in your last comment. Commented Jun 1, 2019 at 20:05
  • 2
    @RasoolZiafaty just because it's a proof of concept it should be correct. Besides, doing it correctly will make it shorter and simpler, not the reverse. Notice that the use of 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. Commented Jun 1, 2019 at 20:11

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.