21

How can I implement signal Handling for Ctrl-C and Ctrl-D in C....So If Ctrl-C is pressed then the program will ignore and try to get the input from the user again...If Ctrl-D is pressed then the program will terminate...

My program follows:

int main(){
 char msg[400];

 while(1){
   printf("Enter: ");
   fgets(msg,400,stdin);
   printf("%s\n",msg); 
 }
}

Thanks,

Dave

avakar
  • 32,009
  • 9
  • 68
  • 103
Dave
  • 211
  • 1
  • 2
  • 3
  • 3
    I would not recommend this. There are very few instances I can think of where it is a good idea for a program to override Ctrl-C's kill function - a remote connection tool such as SSH being one of them. – Daniel Bingham Mar 20 '10 at 22:37
  • This is just for an understanding of how to handle Signals – Dave Mar 20 '10 at 22:40
  • 2
    Any sort of interpreter program should catch ctrl-C to abort the hosted program, if it is running. – Potatoswatter Mar 20 '10 at 23:28

5 Answers5

33

When dealing with POSIX signals, you have two means at your disposal. First, the easy (but discouraged) way, signal(). Second, the more elegant, current but complex way, sigaction(). Please use sigaction() unless you find that it isn't available on some platform that you need to work on.

This chapter of the glibc manual explains differences between the two and gives good example code on how to use both. It also lists the signals that can be handled, recommends how they should be handled and goes more in depth on how to tell how any given signal is (or is not) currently being handled. That's way more code than I'd want to paste into an answer here, hence the links.

It really is worth the hour or two it would take you to read the links and work through the examples. Signal handling (especially in programs that daemonize) is extremely important. A good program should handle all fatal signals that can be handled (i.e. SIGHUP) and explicitly ignore signals that it might not be using (i.e. SIGUSR1 / SIGUSR2).

It also won't hurt to study the difference between normal and real time signals, at least up to the understanding of how the kernel merges the prior and not the latter.

Once you work through it, you'll probably feel inclined to write up an easy to modify set of functions to handle your signals and re-use that code over and over again.

Sorry for not giving a quick and dirty code snippet to show you how to solve your immediate need, but this isn't a quick and dirty topic :)

SO Stinks
  • 3,258
  • 4
  • 32
  • 37
Tim Post
  • 33,371
  • 15
  • 110
  • 174
15

Firstly, Ctrl+D is an EOF indicator which you cannot trap, when a program is waiting for input, hitting Ctrl+D signifies end of file and to expect no more input. On the other hand, using Ctrl+C to terminate a program - that is SIGINT, which can be trapped by doing this:

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <stdarg.h>

static void signal_handler(int);
static void cleanup(void);
void init_signals(void);
void panic(const char *, ...);

struct sigaction sigact;
char *progname;

int main(int argc, char **argv){
    char *s;
    progname = *(argv);
    atexit(cleanup);
    init_signals();
    // do the work
    exit(0);
}

void init_signals(void){
    sigact.sa_handler = signal_handler;
    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = 0;
    sigaction(SIGINT, &sigact, (struct sigaction *)NULL);
}

static void signal_handler(int sig){
    if (sig == SIGINT) panic("Caught signal for Ctrl+C\n");
}

void panic(const char *fmt, ...){
    char buf[50];
    va_list argptr;
    va_start(argptr, fmt);
    vsprintf(buf, fmt, argptr);
    va_end(argptr);
    fprintf(stderr, buf);
    exit(-1);
}

void cleanup(void){
    sigemptyset(&sigact.sa_mask);
    /* Do any cleaning up chores here */
}
iBug
  • 35,554
  • 7
  • 89
  • 134
t0mm13b
  • 34,087
  • 8
  • 78
  • 110
  • The SIG_IGN handler would fit the OP's needs nicely. – outis Mar 20 '10 at 22:56
  • 2
    Why is sigact a global variable? Why does cleanup fiddle with it; you'd have to call sigaction() again for changes to sigact to affect the way the program behaves. – Jonathan Leffler Mar 20 '10 at 23:11
  • @JonathanLeffler : Could u explain me better why is not a good idea declare sigact global, please? I'd like to understand this point. Thank you. – Kyrol Nov 03 '13 at 22:56
  • 2
    @Kyrol: There's no need for it to be a global variable; it can perfectly well be a local variable in the function, as it is only used inside the function. The kernel copies the information it needs from the structure when `sigaction()` is called; you don't need to preserve the value afterwards. – Jonathan Leffler Nov 03 '13 at 23:13
2

This is a program for handling signal when pressed Ctrl+c

The syntax for signal function is : signal(signal name, function name);

#include<stdio.h>
#include<signal.h>  // for handling signal 

void signal_handler() 
{
    printf("Signal Handled here\n");
}

main() 
{
    printf("In main function..\n");

    // SIGINT is signal name create  when Ctrl+c will pressed 
    signal(SIGINT,signal_handler);  

    sleep(15);

    printf("In main after called from signal_handle \n");

}
Federico Ponzi
  • 2,682
  • 4
  • 34
  • 60
RUSHIKESH KARDE
  • 281
  • 2
  • 6
  • `signal()` is deprecated and should be avoided where possible, almost all modern platforms (save for some embedded) offer `sigaction()`. – Tim Post May 29 '14 at 11:35
  • 1
    @TimPost `signal()` has never been deprecated. It offers less control than `sigaction()`. But that's not the same as deprecated. – P.P Apr 12 '20 at 10:37
  • @P.P `signal()` may not have been officially deprecated, but its use is **highly** discouraged. From `man 2 signal`: *WARNING: the behavior of signal() varies across UNIX versions, and has also varied historically across different versions of Linux. Avoid its use: use sigaction(2) instead. See Portability below.* It goes on as follows: *The only portable use of signal() is to set a signal's disposition to SIG_DFL or SIG_IGN. The semantics when using signal() to establish a signal handler vary across systems (and POSIX.1 explicitly permits this variation); do not use it for this purpose.* – Fonic Aug 02 '22 at 16:38
  • 1
    @Fonic Correct and `signal` hasn't been deprecated ;-) – P.P Aug 03 '22 at 17:27
2

In your example it seems you don't need CTRL-C handlind at all. A "signal(SIGINT,SIG_IGN)" seems enough for you, unless your application must handle a SIGINT coming from some other source. CTRL-D doesn't usually generates signals, it simply communicates the EOF condition. You can in general control the behavior of your terminal (we are talking about console input, it isn't?) by using the termios library (also here). You can enable, redefine or disable the "interrupt" character (CTRL-C), the EOF one and many other ones (XON, XOFF, modem control...)

Regards

Giuseppe Guerrini
  • 4,274
  • 17
  • 32
0
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
void signal_catch()
{
    printf("hi,Your signal catched Here");  
}
int main()
{
    signal(SIGINT,signal_catch);
//press ctrl+c
    sleep(10);
    return 0;
}//end main

//if you want to simply ignore ctrl+c interrupt use following code in main

int main()
{
    signal(SIGINT,SIG_IGN);
    sleep(100);
    return 0;
}//end main  
//this program  wont accept ctrl+c interrupt for 100 seconds. 
Sherlock
  • 1
  • 2