diff src/msdos.c @ 16872:1efa81ac7e5a

* (sigprocmask, sig_suspender): New functions, implement signal blocking on MSDOS.
author Eli Zaretskii <eliz@gnu.org>
date Thu, 16 Jan 1997 12:50:00 +0000
parents 45a12f628d3f
children 8d28d96f6031
line wrap: on
line diff
--- a/src/msdos.c	Thu Jan 16 12:20:49 1997 +0000
+++ b/src/msdos.c	Thu Jan 16 12:50:00 1997 +0000
@@ -69,6 +69,7 @@
 #if __DJGPP__ > 1
 
 #include <signal.h>
+#include "syssignal.h"
 
 #ifndef SYSTEM_MALLOC
 
@@ -3144,13 +3145,122 @@
 nice (p) int p; {}
 void volatile pause () {}
 sigsetmask (x) int x; { return 0; }
+sigblock (mask) int mask; { return 0; } 
 #endif
 
 request_sigio () {}
 setpgrp () {return 0; }
 setpriority (x,y,z) int x,y,z; { return 0; }
+unrequest_sigio () {}
+
+#if __DJGPP__ > 1
+
+#ifdef POSIX_SIGNALS
+
+/* Augment DJGPP library POSIX signal functions.  This is needed
+   as of DJGPP v2.01, but might be in the library in later releases. */
+
+#include <libc/bss.h>
+
+/* A counter to know when to re-initialize the static sets.  */
+static int sigprocmask_count = -1;
+
+/* Which signals are currently blocked (initially none).  */
+static sigset_t current_mask;
+
+/* Which signals are pending (initially none).  */
+static sigset_t pending_signals;
+
+/* Previous handlers to restore when the blocked signals are unblocked.  */
+typedef void (*sighandler_t)(int);
+static sighandler_t prev_handlers[320];
+
+/* A signal handler which just records that a signal occured
+   (it will be raised later, if and when the signal is unblocked).  */
+static void
+sig_suspender (signo)
+     int signo;
+{
+  sigaddset (&pending_signals, signo);
+}
+
+int
+sigprocmask (how, new_set, old_set)
+     int how;
+     const sigset_t *new_set;
+     sigset_t *old_set;
+{
+  int signo;
+  sigset_t new_mask;
+
+  /* If called for the first time, initialize.  */
+  if (sigprocmask_count != __bss_count)
+    {
+      sigprocmask_count = __bss_count;
+      sigemptyset (&pending_signals);
+      sigemptyset (&current_mask);
+      for (signo = 0; signo < 320; signo++)
+	prev_handlers[signo] = SIG_ERR;
+    }
+
+  if (old_set)
+    *old_set = current_mask;
+
+  if (new_set == 0)
+    return 0;
+
+  if (how != SIG_BLOCK && how != SIG_UNBLOCK && how != SIG_SETMASK)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  sigemptyset (&new_mask);
+
+  /* DJGPP supports upto 320 signals.  */
+  for (signo = 0; signo < 320; signo++)
+    {
+      if (sigismember (&current_mask, signo))
+	sigaddset (&new_mask, signo);
+      else if (sigismember (new_set, signo) && how != SIG_UNBLOCK)
+	{
+	  sigaddset (&new_mask, signo);
+
+	  /* SIGKILL is silently ignored, as on other platforms.  */
+	  if (signo != SIGKILL && prev_handlers[signo] == SIG_ERR)
+	    prev_handlers[signo] = signal (signo, sig_suspender);
+	}
+      if ((   how == SIG_UNBLOCK
+	      && sigismember (&new_mask, signo)
+	      && sigismember (new_set, signo))
+	  || (how == SIG_SETMASK
+	      && sigismember (&new_mask, signo)
+	      && !sigismember (new_set, signo)))
+	{
+	  sigdelset (&new_mask, signo);
+	  if (prev_handlers[signo] != SIG_ERR)
+	    {
+	      signal (signo, prev_handlers[signo]);
+	      prev_handlers[signo] = SIG_ERR;
+	    }
+	  if (sigismember (&pending_signals, signo))
+	    {
+	      sigdelset (&pending_signals, signo);
+	      raise (signo);
+	    }
+	}
+    }
+  current_mask = new_mask;
+  return 0;
+}
+
+#else /* not POSIX_SIGNALS */
+
+sigsetmask (x) int x; { return 0; }
 sigblock (mask) int mask; { return 0; } 
-unrequest_sigio () {}
+
+#endif /* not POSIX_SIGNALS */
+#endif /* __DJGPP__ > 1 */
 
 #ifndef HAVE_SELECT
 #include "sysselect.h"