1: /*
   2:  * $Id: catch.c,v 1.20 2006/05/31 10:35:38 yamamoto Exp yamamoto $
   3:  */
   4: 
   5: #include <signal.h>             /* For sigaction(). */
   6: #include <stdarg.h>             /* For variable argument lists. */
   7: #include <stdio.h>
   8: #include <stdlib.h>             /* For EXIT_SUCCESS. */
   9: 
  10: #define MAX_LINE_LEN    81
  11: 
  12: #ifndef FALSE
  13: #define FALSE           0
  14: #define TRUE            1
  15: #endif
  16: 
  17: static int          debug_mode = FALSE;
  18: 
  19: static void set_signal_handler(void);
  20: 
  21: static void debug(const char *format, ...);
  22: static void handler(int x);
  23: 
  24: int main(int argc, char *argv[])
  25: {
  26:     char        input[MAX_LINE_LEN];
  27:     int         status;
  28:     pid_t       pid;
  29: 
  30:     if (2 <= argc && !strcmp(argv[1], "-d")) {
  31:         debug_mode = TRUE;
  32:     }
  33:     set_signal_handler();               /* シグナルハンドラの登録. */
  34: 
  35:     /* 意図的にSIGSEGVを起こす. */
  36:     /* { char *cp = NULL; *cp = '\0'; } */
  37: 
  38:     debug("catch: getpid() %d.\n", getpid());
  39:     while (1) {
  40:         fprintf(stderr, "catch: Zzz.\n");
  41:         sleep(1);
  42:     }
  43: 
  44:     exit (EXIT_SUCCESS);
  45: }
  46: 
  47: /*
  48:  * シグナルハンドラを設定する.
  49:  */
  50: 
  51: static void set_signal_handler(void)
  52: {
  53:     static struct sigaction    action;
  54: 
  55:     action.sa_handler = handler;                /* シグナルハンドラ. */
  56: 
  57:     /* ハンドラ内でSIGINTをブロックする. */
  58:     sigemptyset(&action.sa_mask);               /* マスクのクリア. */  
  59:     sigaddset(&action.sa_mask, SIGINT);
  60: 
  61:     action.sa_flags = SA_RESTART;               /* BSDとの互換性(おまじない). */
  62: 
  63:     /* 実験: シグナルハンドラが一度呼ばれると設定をクリアする. */
  64:     /* action.sa_flags = action.sa_flags | SA_ONESHOT; */
  65: 
  66:     sigaction(SIGINT, &action, NULL);           /* SIGINTにハンドラを設定.*/
  67:     sigaction(SIGSEGV, &action, NULL);          /* SIGSEGVにも設定.*/
  68:     sigaction(SIGUSR1, &action, NULL);          /* SIGUSR1にも設定. */
  69:     sigaction(SIGCONT, &action, NULL);          /* SIGCONTにも設定. */
  70: }
  71: 
  72: /*
  73:  * シグナルハンドラ.
  74:  */
  75: 
  76: static void handler(int x)
  77: {
  78:     char    *sig_name;
  79: 
  80:     fflush(stdout);
  81:     fflush(stderr);
  82: 
  83:     /* !! Not so good. */
  84:     if (x == SIGINT) {
  85:         sig_name = "SIGINT";
  86:     } else if (x == SIGSEGV) {
  87:         sig_name = "SIGSEGV";
  88:     } else if (x == SIGUSR1) {
  89:         sig_name = "SIGUSR1";
  90:     } else if (x == SIGCONT) {
  91:         sig_name = "SIGCONT";
  92:     } else {
  93:         sig_name = "UNKNOWN";
  94:     }
  95:     fprintf(stderr, "catch: Signal (%s, %d).\n", sig_name, x);
  96: 
  97:     if (x == SIGSEGV) {
  98:         exit (EXIT_FAILURE);
  99:     }
 100: }
 101: 
 102: static void debug(const char *format, ...)
 103: {
 104:     va_list     args;
 105:     
 106:     if (!debug_mode) {
 107:         return;
 108:     }
 109: 
 110:     fflush(stdout);
 111:     fflush(stderr);
 112: 
 113:     fputs("Debug: ", stderr);
 114:     va_start(args, format);
 115:     vfprintf(stderr, format, args);
 116:     va_end(args);
 117: 
 118:     fflush(stderr);
 119: }