hash: allow C89 compilation
[gnulib.git] / lib / sigprocmask.c
index a8f2eb4..7b486a2 100644 (file)
@@ -24,8 +24,6 @@
 #include <stdint.h>
 #include <stdlib.h>
 
-#include "sig-handler.h"
-
 /* We assume that a platform without POSIX signal blocking functions
    also does not have the POSIX sigaction() function, only the
    signal() function.  We also assume signal() has SysV semantics,
 # define SIGSTOP (-1)
 #endif
 
+/* On native Windows, as of 2008, the signal SIGABRT_COMPAT is an alias
+   for the signal SIGABRT.  Only one signal handler is stored for both
+   SIGABRT and SIGABRT_COMPAT.  SIGABRT_COMPAT is not a signal of its own.  */
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# undef SIGABRT_COMPAT
+# define SIGABRT_COMPAT 6
+#endif
+#ifdef SIGABRT_COMPAT
+# define SIGABRT_COMPAT_MASK (1U << SIGABRT_COMPAT)
+#else
+# define SIGABRT_COMPAT_MASK 0
+#endif
+
+typedef void (*handler_t) (int);
+
+/* Handling of gnulib defined signals.  */
+
+#if GNULIB_defined_SIGPIPE
+static handler_t SIGPIPE_handler = SIG_DFL;
+#endif
+
+#if GNULIB_defined_SIGPIPE
+static handler_t
+ext_signal (int sig, handler_t handler)
+{
+  switch (sig)
+    {
+    case SIGPIPE:
+      {
+       handler_t old_handler = SIGPIPE_handler;
+       SIGPIPE_handler = handler;
+       return old_handler;
+      }
+    default: /* System defined signal */
+      return signal (sig, handler);
+    }
+}
+# define signal ext_signal
+#endif
+
 int
 sigismember (const sigset_t *set, int sig)
 {
   if (sig >= 0 && sig < NSIG)
-    return (*set >> sig) & 1;
+    {
+      #ifdef SIGABRT_COMPAT
+      if (sig == SIGABRT_COMPAT)
+       sig = SIGABRT;
+      #endif
+
+      return (*set >> sig) & 1;
+    }
   else
     return 0;
 }
@@ -66,6 +111,11 @@ sigaddset (sigset_t *set, int sig)
 {
   if (sig >= 0 && sig < NSIG)
     {
+      #ifdef SIGABRT_COMPAT
+      if (sig == SIGABRT_COMPAT)
+       sig = SIGABRT;
+      #endif
+
       *set |= 1U << sig;
       return 0;
     }
@@ -81,6 +131,11 @@ sigdelset (sigset_t *set, int sig)
 {
   if (sig >= 0 && sig < NSIG)
     {
+      #ifdef SIGABRT_COMPAT
+      if (sig == SIGABRT_COMPAT)
+       sig = SIGABRT;
+      #endif
+
       *set &= ~(1U << sig);
       return 0;
     }
@@ -91,10 +146,11 @@ sigdelset (sigset_t *set, int sig)
     }
 }
 
+
 int
 sigfillset (sigset_t *set)
 {
-  *set = (2U << (NSIG - 1)) - 1;
+  *set = ((2U << (NSIG - 1)) - 1) & ~ SIGABRT_COMPAT_MASK;
   return 0;
 }
 
@@ -133,7 +189,7 @@ sigpending (sigset_t *set)
 
 /* The previous signal handlers.
    Only the array elements corresponding to blocked signals are relevant.  */
-static volatile sa_handler_t old_handlers[NSIG];
+static volatile handler_t old_handlers[NSIG];
 
 int
 sigprocmask (int operation, const sigset_t *set, sigset_t *old_set)
@@ -188,7 +244,8 @@ sigprocmask (int operation, const sigset_t *set, sigset_t *old_set)
              {
                if (signal (sig, old_handlers[sig]) != blocked_handler)
                  /* The application changed a signal handler while the signal
-                    was blocked.  We don't support this.  */
+                    was blocked, bypassing our rpl_signal replacement.
+                    We don't support this.  */
                  abort ();
                received[sig] = pending_array[sig];
                blocked_set &= ~(1U << sig);
@@ -207,14 +264,19 @@ sigprocmask (int operation, const sigset_t *set, sigset_t *old_set)
 
 /* Install the handler FUNC for signal SIG, and return the previous
    handler.  */
-sa_handler_t
-rpl_signal (int sig, sa_handler_t handler)
+handler_t
+rpl_signal (int sig, handler_t handler)
 {
   /* We must provide a wrapper, so that a user can query what handler
      they installed even if that signal is currently blocked.  */
   if (sig >= 0 && sig < NSIG && sig != SIGKILL && sig != SIGSTOP
       && handler != SIG_ERR)
     {
+      #ifdef SIGABRT_COMPAT
+      if (sig == SIGABRT_COMPAT)
+       sig = SIGABRT;
+      #endif
+
       if (blocked_set & (1U << sig))
        {
          /* POSIX states that sigprocmask and signal are both
@@ -226,11 +288,12 @@ rpl_signal (int sig, sa_handler_t handler)
             stale information if it calls signal(B).  Oh well -
             signal handlers really shouldn't try to manipulate the
             installed handlers of unrelated signals.  */
-         sa_handler_t result = old_handlers[sig];
+         handler_t result = old_handlers[sig];
          old_handlers[sig] = handler;
          return result;
        }
-      return signal (sig, handler);
+      else
+       return signal (sig, handler);
     }
   else
     {
@@ -238,3 +301,29 @@ rpl_signal (int sig, sa_handler_t handler)
       return SIG_ERR;
     }
 }
+
+#if GNULIB_defined_SIGPIPE
+/* Raise the signal SIG.  */
+int
+rpl_raise (int sig)
+# undef raise
+{
+  switch (sig)
+    {
+    case SIGPIPE:
+      if (blocked_set & (1U << sig))
+       pending_array[sig] = 1;
+      else
+       {
+         handler_t handler = SIGPIPE_handler;
+         if (handler == SIG_DFL)
+           exit (128 + SIGPIPE);
+         else if (handler != SIG_IGN)
+           (*handler) (sig);
+       }
+      return 0;
+    default: /* System defined signal */
+      return raise (sig);
+    }
+}
+#endif