/* syssignal.h - System-dependent definitions for signals.
   Copyright (C) 1992, 1993 Free Software Foundation, Inc.

This file is part of XEmacs.

XEmacs is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.

XEmacs is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with XEmacs; see the file COPYING.  If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */

/* Synched up with: FSF 19.28. */

#ifndef _XEMACS_SYSSIGNAL_H_
#define _XEMACS_SYSSIGNAL_H_

/* In the old world, one could not #include <signal.h> here.  The party line
   was that that header should always be #included before <config.h>, because
   some configuration files (like s/hpux.h) indicate that SIGIO doesn't work
   by #undef-ing SIGIO, and if this file #includes <signal.h>, then that will
   re-#define SIGIO and confuse things.

   This was, however, a completely fucked up state of affairs, because on some
   systems it's necessary for the s/m files to #define things in order to get
   <signal.h> to provide the right typedefs, etc.  And it's generally a broken
   concept for <config.h> to not be the very very first file included.

   So instead of #undef'ing SIGIO in the various s/m files, I've changed them
   to define BROKEN_SIGIO instead, then we (syssignal.h) do an #undef SIGIO
   at the end, after including signal.h.  Therefore, it's important that
   <signal.h> not be included after "syssignal.h", but that's the normal state:
   nothing should be directly including <signal.h> these days.
							-- jwz, 29-nov-93
 */

#include <signal.h>
#include <errno.h>

/* Interrupt input is not used if there is no FIONREAD.  */
#if defined (BROKEN_SIGIO) || defined (BROKEN_FIONREAD) || !defined (FIONREAD)
# undef SIGIO
#endif
#ifdef BSD4_1
# define SIGIO SIGTINT
#endif

/* Define SIGCHLD as an alias for SIGCLD.  There are many conditionals
   testing SIGCHLD.  */
#if !defined (VMS) && defined (SIGCLD) && !defined (SIGCHLD)
# define SIGCHLD SIGCLD
#endif /* SIGCHLD */


#ifdef POSIX_SIGNALS

#define EMACS_BLOCK_SIGNAL(sig) do		\
{						\
  sigset_t _mask;				\
  sigemptyset (&_mask);				\
  sigaddset (&_mask, sig);			\
  sigprocmask (SIG_BLOCK, &_mask, NULL);	\
} while (0)
#define EMACS_UNBLOCK_SIGNAL(sig) do		\
{						\
  sigset_t _mask;				\
  sigemptyset (&_mask);				\
  sigaddset (&_mask, sig);			\
  sigprocmask (SIG_UNBLOCK, &_mask, NULL);	\
} while (0)
#define EMACS_UNBLOCK_ALL_SIGNALS() do		\
{						\
  sigset_t _mask;				\
  sigemptyset (&_mask);				\
  sigprocmask (SIG_SETMASK, &_mask, NULL);	\
} while (0)
#define EMACS_WAIT_FOR_SIGNAL(sig) do		\
{						\
  sigset_t _mask;				\
  sigprocmask (0, NULL, &_mask);		\
  sigdelset (&_mask, sig);			\
  sigsuspend (&_mask);				\
} while (0)
  
#elif defined (BSD4_1)

#define EMACS_BLOCK_SIGNAL(sig) sighold (sig)
#define EMACS_UNBLOCK_SIGNAL(sig) sigrelse (sig)
#define EMACS_UNBLOCK_ALL_SIGNALS() ####
#define EMACS_WAIT_FOR_SIGNAL(sig) ####

#elif defined (BSD)

/* Is it necessary to define sigmask like this? */
#ifndef sigmask
# define sigmask(no) (1L << ((no) - 1))
#endif
#define EMACS_BLOCK_SIGNAL(sig) sigblock (sigmask (sig))
/* SunOS (i.e. BSD) provides a sigblock() but no sigunblock().  The Solaris
   BSD compatibility functions provide both.

   As Jamie says: You're in a twisty maze of OS features, all alike ... */
#define EMACS_UNBLOCK_SIGNAL(sig) sigsetmask (sigblock (0) & ~sigmask (sig))
#define EMACS_UNBLOCK_ALL_SIGNALS() sigsetmask (0)
#define EMACS_WAIT_FOR_SIGNAL(sig) do		\
{						\
  int _mask = sigblock (0);			\
  sigpause (_mask & ~sigmask (sig));		\
} while (0)

#elif defined (USG)

/* Older USG systems don't really have signal blocking.
   We indicate this by not defining EMACS_BLOCK_SIGNAL. */
#define EMACS_UNBLOCK_SIGNAL(sig) 0
#define EMACS_UNBLOCK_ALL_SIGNALS() 0

#endif

/* USG systems forget handlers when they are used;
   must reestablish each time */
#if !defined (POSIX_SIGNALS) && (defined (USG) || defined (VMS))
# define EMACS_REESTABLISH_SIGNAL(sig, handler) do	\
{							\
  int old_errno = errno;				\
  signal (sig, handler);				\
  errno = old_errno;					\
} while (0)
#else
# define EMACS_REESTABLISH_SIGNAL(sig, handler)
#endif

#ifdef POSIX_SIGNALS
typedef SIGTYPE (*signal_handler_t) (int);
extern signal_handler_t sys_do_signal (int signal_number,
				       signal_handler_t action);
/* Not sys_signal() because a function of that name exists in
   libenergize.a */
#define signal sys_do_signal
#endif

/* On bsd, [man says] kill does not accept a negative number to kill a pgrp.
   Must do that using the killpg call.  */
#ifdef BSD
#define EMACS_KILLPG(gid, signo) (killpg ( (gid), (signo)))
#else
#define EMACS_KILLPG(gid, signo) (kill   (-(gid), (signo)))
#endif

#ifdef VMS
# define sys_siglist sys_errlist
# define NSIG sys_nerr
#endif /* VMS */

#ifndef NSIG
# define NSIG (SIGUSR2+1) /* guess how many elements are in sys_siglist... */
#endif

/* SYS_SIGLIST_DECLARED is determined by configure.  On Linux, it seems,
   configure incorrectly fails to find it, so s/linux.h defines
   HAVE_SYS_SIGLIST. */
#if !defined (SYS_SIGLIST_DECLARED) && !defined (HAVE_SYS_SIGLIST)
extern CONST char *sys_siglist[];
#endif

#ifdef SIGDANGER
extern SIGTYPE memory_warning_signal (int sig);
#endif

#endif /* _XEMACS_SYSSIGNAL_H_ */
