/* sys/signal.h */

#ifndef _SYS_SIGNAL_H
#define _SYS_SIGNAL_H

#include "_ansi.h"
#include <sys/cdefs.h>
#include <sys/features.h>
#include <sys/types.h>
#include <sys/_sigset.h>
#include <sys/_timespec.h>

__BEGIN_DECLS

#if !defined(_SIGSET_T_DECLARED)
#define _SIGSET_T_DECLARED
typedef __sigset_t sigset_t;
#endif

#if defined(_POSIX_REALTIME_SIGNALS) || __POSIX_VISIBLE >= 199309

/* sigev_notify values
   NOTE: P1003.1c/D10, p. 34 adds SIGEV_THREAD.  */

#define SIGEV_NONE 1 /* No asynchronous notification shall be delivered */
/*   when the event of interest occurs. */
#define SIGEV_SIGNAL 2 /* A queued signal, with an application defined */
/*  value, shall be delivered when the event of */
/*  interest occurs. */
#define SIGEV_THREAD 3 /* A notification function shall be called to */
/*   perform notification. */

/*  Signal Generation and Delivery, P1003.1b-1993, p. 63
    NOTE: P1003.1c/D10, p. 34 adds sigev_notify_function and
          sigev_notify_attributes to the sigevent structure.  */

union sigval {
    int sival_int;   /* Integer signal value */
    void* sival_ptr; /* Pointer signal value */
};

struct sigevent {
    int sigev_notify;         /* Notification type */
    int sigev_signo;          /* Signal number */
    union sigval sigev_value; /* Signal value */

#if 0
    void (*sigev_notify_function)(union sigval);
    /* Notification function */
    pthread_attr_t* sigev_notify_attributes; /* Notification Attributes */
#endif
};

/* Signal Actions, P1003.1b-1993, p. 64 */
/* si_code values, p. 66 */

#define SI_USER    1 /* Sent by a user. kill(), abort(), etc */
#define SI_QUEUE   2 /* Sent by sigqueue() */
#define SI_TIMER   3 /* Sent by expiration of a timer_settime() timer */
#define SI_ASYNCIO 4 /* Indicates completion of asycnhronous IO */
#define SI_MESGQ   5 /* Indicates arrival of a message at an empty queue */

typedef struct {
    int si_signo;
    int si_code;
    int si_errno;
    pid_t si_pid;
    uid_t si_uid;
    void* si_addr;
    int si_status;
    union sigval si_value;
} siginfo_t;

#define CLD_EXITED    1
#define CLD_KILLED    2
#define CLD_DUMPED    3
#define CLD_TRAPPED   4
#define CLD_STOPPED   5
#define CLD_CONTINUED 6

#endif /* defined(_POSIX_REALTIME_SIGNALS) || __POSIX_VISIBLE >= 199309 */

/* Bits in `sa_flags'.  */
#define SA_NOCLDSTOP 1 /* Don't send SIGCHLD when children stop.  */
#define SA_NOCLDWAIT 2 /* Don't create zombie on child death.  */
#define SA_SIGINFO                            \
    4 /* Invoke signal-catching function with \
three arguments instead of one.  */
#if defined __USE_XOPEN_EXTENDED || defined __USE_MISC
#define SA_ONSTACK 0x08000000 /* Use signal stack by using `sa_restorer'. */
#endif

#define SA_RESTART 0x10000000 /* Restart syscall on signal return.  */
#define SA_NODEFER                                          \
    0x40000000 /* Don't automatically block the signal when \
  its handler is being executed.  */
#define SA_RESETHAND 0x80000000 /* Reset to SIG_DFL on entry to handler.  */

#ifdef __USE_MISC
#define SA_INTERRUPT 0x20000000 /* Historical no-op.  */

/* Some aliases for the SA_ constants.  */
#define SA_NOMASK  SA_NODEFER
#define SA_ONESHOT SA_RESETHAND
#define SA_STACK   SA_ONSTACK
#endif

typedef void (*_sig_func_ptr)(int);

struct sigaction {
    /* Signal handler.  */
#if __POSIX_VISIBLE >= 199309
    union {
        /* Used if SA_SIGINFO is not set.  */
        _sig_func_ptr sa_handler;
        /* Used if SA_SIGINFO is set.  */
        void (*sa_sigaction)(int, siginfo_t*, void*);
    } __sigaction_handler;
#define sa_handler   __sigaction_handler.sa_handler
#define sa_sigaction __sigaction_handler.sa_sigaction
#else
    _sig_func_ptr sa_handler;
#endif

    /* Additional set of signals to be blocked.  */
    __sigset_t sa_mask;

    /* Special flags.  */
    int sa_flags;

    /* Restore handler.  */
    void (*sa_restorer)(void);
};

#if __BSD_VISIBLE || __XSI_VISIBLE >= 4 || __POSIX_VISIBLE >= 200809
/*
 * Minimum and default signal stack constants. Allow for target overrides
 * from <sys/features.h>.
 */
#ifndef MINSIGSTKSZ
#define MINSIGSTKSZ 2048
#endif
#ifndef SIGSTKSZ
#define SIGSTKSZ 8192
#endif

/*
 * Possible values for ss_flags in stack_t below.
 */
#define SS_ONSTACK 0x1
#define SS_DISABLE 0x2

#endif

/*
 * Structure used in sigaltstack call.
 */
typedef struct sigaltstack {
    void* ss_sp;    /* Stack base or pointer.  */
    int ss_flags;   /* Flags.  */
    size_t ss_size; /* Stack size.  */
} stack_t;

#if __POSIX_VISIBLE
#define SIG_SETMASK 0 /* set mask with sigprocmask() */
#define SIG_BLOCK   1 /* set of signals to block */
#define SIG_UNBLOCK 2 /* set of signals to, well, unblock */

int sigprocmask(int how, const sigset_t* set, sigset_t* oset);
#endif

#if __POSIX_VISIBLE >= 199506
int pthread_sigmask(int how, const sigset_t* set, sigset_t* oset);
#endif

#ifdef _COMPILING_NEWLIB
int _kill(pid_t, int);
#endif /* _COMPILING_NEWLIB */

#if __POSIX_VISIBLE
int kill(pid_t, int);
#endif

#if __BSD_VISIBLE || __XSI_VISIBLE >= 4
int killpg(pid_t, int);
#endif
#if __POSIX_VISIBLE
int sigaction(int, const struct sigaction*, struct sigaction*);
int sigaddset(sigset_t*, const int);
int sigdelset(sigset_t*, const int);
int sigismember(const sigset_t*, int);
int sigfillset(sigset_t*);
int sigemptyset(sigset_t*);
int sigpending(sigset_t*);
int sigsuspend(const sigset_t*);
int sigwait(const sigset_t* set, int* sig);

#if !defined(__CYGWIN__) && !defined(__rtems__)
/* These depend upon the type of sigset_t, which right now
   is always a long.. They're in the POSIX namespace, but
   are not ANSI. */
#define sigaddset(what, sig)   (*(what) |= (1 << (sig)), 0)
#define sigdelset(what, sig)   (*(what) &= ~(1 << (sig)), 0)
#define sigemptyset(what)      (*(what) = 0, 0)
#define sigfillset(what)       (*(what) = ~(0), 0)
#define sigismember(what, sig) (((*(what)) & (1 << (sig))) != 0)
#endif /* !__CYGWIN__ && !__rtems__ */
#endif /* __POSIX_VISIBLE */

/* There are two common sigpause variants, both of which take an int argument.
   If you request _XOPEN_SOURCE or _GNU_SOURCE, you get the System V version,
   which removes the given signal from the process's signal mask; otherwise
   you get the BSD version, which sets the process's signal mask to the given
   value. */
#if __XSI_VISIBLE && !defined(__INSIDE_CYGWIN__)
#ifdef __GNUC__
int sigpause(int) __asm__(__ASMNAME("__xpg_sigpause"));
#else
int __xpg_sigpause(int);
#define sigpause __xpg_sigpause
#endif
#elif __BSD_VISIBLE
int sigpause(int);
#endif

#if __BSD_VISIBLE || __XSI_VISIBLE >= 4 || __POSIX_VISIBLE >= 200809
int sigaltstack(const stack_t* __restrict, stack_t* __restrict);
#endif

#if __POSIX_VISIBLE >= 199506
int pthread_kill(pthread_t thread, int sig);
#endif

#if __POSIX_VISIBLE >= 199309

/*  3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
    NOTE: P1003.1c/D10, p. 39 adds sigwait().  */

int sigwaitinfo(const sigset_t* set, siginfo_t* info);
int sigtimedwait(const sigset_t* set, siginfo_t* info,
                 const struct timespec* timeout);
/*  3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 78 */
int sigqueue(pid_t pid, int signo, const union sigval value);

#endif /* __POSIX_VISIBLE >= 199309 */

#if defined(___AM29K__)
/* These all need to be defined for ANSI C, but I don't think they are
   meaningful.  */
#define SIGABRT 1
#define SIGFPE  1
#define SIGILL  1
#define SIGINT  1
#define SIGSEGV 1
#define SIGTERM 1
/* These need to be defined for POSIX, and some others do too.  */
#define SIGHUP  1
#define SIGQUIT 1
#define NSIG    2
#elif defined(__GO32__)
#define SIGINT  1
#define SIGKILL 2
#define SIGPIPE 3
#define SIGFPE  4
#define SIGHUP  5
#define SIGTERM 6
#define SIGSEGV 7
#define SIGTSTP 8
#define SIGQUIT 9
#define SIGTRAP 10
#define SIGILL  11
#define SIGEMT  12
#define SIGALRM 13
#define SIGBUS  14
#define SIGLOST 15
#define SIGSTOP 16
#define SIGABRT 17
#define SIGUSR1 18
#define SIGUSR2 19
#define NSIG    20
#elif !defined(SIGTRAP)
#define SIGHUP  1 /* hangup */
#define SIGINT  2 /* interrupt */
#define SIGQUIT 3 /* quit */
#define SIGILL  4 /* illegal instruction (not reset when caught) */
#define SIGTRAP 5 /* trace trap (not reset when caught) */
#define SIGIOT  6 /* IOT instruction */
#define SIGABRT 6 /* used by abort, replace SIGIOT in the future */
#define SIGEMT  7 /* EMT instruction */
#define SIGFPE  8 /* floating point exception */
#define SIGKILL 9 /* kill (cannot be caught or ignored) */
#define SIGBUS  10 /* bus error */
#define SIGSEGV 11 /* segmentation violation */
#define SIGSYS  12 /* bad argument to system call */
#define SIGPIPE 13 /* write on a pipe with no one to read it */
#define SIGALRM 14 /* alarm clock */
#define SIGTERM 15 /* software termination signal from kill */

#if defined(__rtems__)
#define SIGURG          16 /* urgent condition on IO channel */
#define SIGSTOP         17 /* sendable stop signal not from tty */
#define SIGTSTP         18 /* stop signal from tty */
#define SIGCONT         19 /* continue a stopped process */
#define SIGCHLD         20 /* to parent on child stop or exit */
#define SIGCLD          20 /* System V name for SIGCHLD */
#define SIGTTIN         21 /* to readers pgrp upon background tty read */
#define SIGTTOU         22 /* like TTIN for output if (tp->t_local&LTOSTOP) */
#define SIGIO           23 /* input/output possible signal */
#define SIGPOLL         SIGIO /* System V name for SIGIO */
#define SIGWINCH        24 /* window changed */
#define SIGUSR1         25 /* user defined signal 1 */
#define SIGUSR2         26 /* user defined signal 2 */

/* Real-Time Signals Range, P1003.1b-1993, p. 61
   NOTE: By P1003.1b-1993, this should be at least RTSIG_MAX
         (which is a minimum of 8) signals.
 */
#define SIGRTMIN        27
#define SIGRTMAX        31
#define __SIGFIRSTNOTRT SIGHUP
#define __SIGLASTNOTRT  SIGUSR2

#define NSIG 32 /* signal 0 implied */

#elif defined(__svr4__)
/* svr4 specifics. different signals above 15, and sigaction. */
#define SIGUSR1  16
#define SIGUSR2  17
#define SIGCLD   18
#define SIGPWR   19
#define SIGWINCH 20
#define SIGPOLL  22 /* 20 for x.out binaries!!!! */
#define SIGSTOP  23 /* sendable stop signal not from tty */
#define SIGTSTP  24 /* stop signal from tty */
#define SIGCONT  25 /* continue a stopped process */
#define SIGTTIN  26 /* to readers pgrp upon background tty read */
#define SIGTTOU  27 /* like TTIN for output if (tp->t_local&LTOSTOP) */
#define NSIG     28
#else
#define SIGURG    16 /* urgent condition on IO channel */
#define SIGSTOP   17 /* sendable stop signal not from tty */
#define SIGTSTP   18 /* stop signal from tty */
#define SIGCONT   19 /* continue a stopped process */
#define SIGCHLD   20 /* to parent on child stop or exit */
#define SIGCLD    20 /* System V name for SIGCHLD */
#define SIGTTIN   21 /* to readers pgrp upon background tty read */
#define SIGTTOU   22 /* like TTIN for output if (tp->t_local&LTOSTOP) */
#define SIGIO     23 /* input/output possible signal */
#define SIGPOLL   SIGIO /* System V name for SIGIO */
#define SIGXCPU   24 /* exceeded CPU time limit */
#define SIGXFSZ   25 /* exceeded file size limit */
#define SIGVTALRM 26 /* virtual time alarm */
#define SIGPROF   27 /* profiling time alarm */
#define SIGWINCH  28 /* window changed */
#define SIGPWR    29
#define SIGUSR1   30 /* user defined signal 1 */
#define SIGUSR2   31 /* user defined signal 2 */
#define NSIG      32 /* signal 0 implied */

#define SIGUNUSED SIGUSR2

#define SIGRTMIN 32
#define SIGRTMAX 33

#endif
#endif

__END_DECLS

#if defined(__CYGWIN__)
#if __XSI_VISIBLE >= 4 || __POSIX_VISIBLE >= 200809
#include <sys/ucontext.h>
#endif
#endif

#ifndef _SIGNAL_H_
/* Some applications take advantage of the fact that <sys/signal.h>
 * and <signal.h> are equivalent in glibc.  Allow for that here.  */
#include <signal.h>
#endif
#endif /* _SYS_SIGNAL_H */
