-  Signals Overview
        
        -  signal table
        
 -  signals sent
        
 -  signals received
        
 -  catching, masking, blocking
        
 
 -  /usr/include/signal.h
 -  Signal Table
 -  Processing with signals
        
        -  signal(SIGnum, myfunc) to set up entry in table, return value is ...
        
 -  When a SIGnum signal is received, consult table to get myfunc
        
 -  call myfunc as an interrupt service routine 
        
 -  after myfunc return to next instruction
        
 
 -  Signal Table Values
	
	-  SIGINT  2  ^C typed usually sends SIGINT
	
 -  SIGQUIT 3  ^\ typed usually sends SIGQUIT
	
 -  SUREKILL 9 // can't be caught
	
 -  ps /kill combination
	
 -  SIG_DFL
	
 -  SIG_IGN
	
 
 -  Signal system call
  #include 
  void (*signal(
          int sig,
          void (*function) (int))) (int);
 When to catch signals?
 -  Example: graceful.c
#include 
#include 
main(){
   int onint();  /* SIGINT handler */
   int i;
   signal(SIGINT, (void *) onint);
   signal(SIGQUIT, (void *) onint);
   for(i=0; ;i++)
     fprintf(stdout,"%d\n",i);
 }
int
onint(int sig){
   fprintf(stderr,"STDERR:Recieved SIGNAL NUMBER =%d\n", sig);
   fprintf(stdout,"STDOUT:Recieved SIGNAL NUMBER =%d\n", sig);
   /*
    * Graceful exit type things removing temporary files etc.
    */
   exit(1);
}
 -  The kill system Call - kill(pid_t pid, int sig)
 -  abort
 -  alarm(int n) - sends SIGALRM to self
 -  Setjmp, Longjmp
 -  Restarting on a signal (like vi, shell)
 -  Setjmp, Longjmp
 -  Example: shell0.c
#include 
#include 
#include 
static jmp_buf  restoreBuf;      /* buffer for saving PC, SP etc. */
void fatal();
main(){
   void onint(), onquit();       /* Signal handlers */
   char buffer[1024];
   int pid;
   int jmpFlag;
   signal(SIGINT, onint);
   signal(SIGQUIT, onquit);
   if((jmpFlag=setjmp(restoreBuf)) < 0) fatal(" setjmp error");
   else if(jmpFlag != 0) 
       fprintf(stderr,"SIGINT received restoring registers\n");
   printf("\nprompt: ");
   while(gets(buffer) != NULL){	 /* command loop */
     if((pid = fork()) < 0) fatal("Fork error - too many processes");
     else if (pid == 0){
         signal(SIGINT, SIG_DFL);
         signal(SIGQUIT, SIG_DFL);
         execlp(buffer, buffer, NULL);
         fprintf(stderr,"Command not Found\n");
         exit(1);
     } else (wait(0));
     printf("\nprompt: ");
     fflush(stdout);
   }
   
}
void
onint(int sig){
   fprintf(stderr,"STDERR:Recieved SIGNAL NUMBER =%d\n", sig);
   longjmp(restoreBuf,1);
   fatal("longjmp returned\n");
}
void
onquit(int sig){
   fprintf(stderr,"STDERR:Recieved SIGNAL NUMBER =%d\n", sig);
   exit(1);
}
void
fatal(char *s)
{
    if(s) fprintf(stderr, "Fatal error: %s\n", s);
    else fprintf(stderr, "\nStop.\n");
    exit(1);
}
 -  Interrupting System Calls
 -  Slow system Calls
 -  Reentrant functions
	
	-  do not use heap or global data, everything on the stack
	
 -  cannot use stdio
	
 
 -  New Improved Signals
	
	-  sigactions replacing functions in table
	
 -  int sigaction(int sig, const struct sigaction  *act,  struct
     sigaction *oact);
	
 -  man  signal
	
 -  man 2 sigaction
	
 
 -  Review Signal Terminology
        
        -  generated
        
 -  delivered
        
 -  received
        
 -  blocked
        
 -  pending
        
 
 -  Signal sets
        
        -  int sigemptyset(sigset_t *set)
        
 -  int sigfillset(sigset_t *set)
        
 -  int sigaddset(sigset_t *set)
        
 -  int sigdelset(sigset_t *set)
        
 -  int sigismember(sigset_t *set)
        
 
 -  Possible macro definitions
#define sigemptyset(ptr) (*(ptr) = 0)
#define sigfillset(ptr)  (*(ptr) = ~(sigset_t)0, 0)  
/* Note comma operator above */
 -  int sigpending(sigset_t *set)
 -  sigaction(int sig, struct sigaction *act,  struct sigaction *oldact)
 -  sigsetjmp and siglongjmp save and restore sigmask
 -  sigsetjmp and siglongjmp
 -  int str2sig(const char *str, int *signum); sig2str
 -  int sigsend(idtype_t idtype, id_t id, int sig);
 -  int sigprocmask(int cmd, const sigset_t *set, sigset_t *oset)
SIG_SETMASK
SIG_BLOCK
SIG_UNBLOCK
 -  Example: sigmask0.c
#include 
#include 
main() {
   sigset_t sigset, oldset;
   sigemptyset(&sigset);
   sigaddset(&sigset, SIGINT);
   if(sigprocmask(SIG_SETMASK, &sigset, &oldset) < 0) {
       fprintf(stderr, "sigprocmask ERROR\n");
       exit(1);
   }
   if(sigismember(&sigset, SIGINT)) printf("SIGINT MASKED\n");
   else printf("SIGINT NOT MASKED\n");
}
 -  sigmask1.c
#include 
#include 
main() {
   sigset_t sigset, oldset, newset;
   int pid;
   sigemptyset(&sigset);
   sigaddset(&sigset, SIGINT);
   if(sigprocmask(SIG_SETMASK, &sigset, &oldset) < 0) fatal("sigprocmask");
   if((pid = fork()) < 0) fatal("Fork failed");
   else if (pid == 0) {
      sleep(3);    
      if(sigpending(&newset)< 0) fatal("SIGpending");
      if(sigismember(&newset,SIGINT))
          printf("SIGINT signal is pending\n");
   }else{
     if(kill(pid, SIGINT)< 0) fatal("Fork failed"); /* sigsend on SUNs */
   }
}
fatal(char *s) {
   fprintf(stderr,"ERROR %s\n", s);
   exit(1);
}