#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "system.h"
#include <sys/types.h>
#include <stdio.h>
#include <signal.h>
#ifdef STDC_HEADERS
#include <stdlib.h>
#else
#if __STDC__
char *calloc(unsigned nelem, unsigned size);
char *malloc(unsigned size);
#else
char *calloc();
char *malloc();
#endif
#endif
#ifndef SIGMAX
#define SIGMAX 64
#endif
struct SIG_hlist {
RETSIGTYPE (*handler)();
struct SIG_hlist *next;
};
static struct SIG_hlist **SIG_handlers;
#ifdef POSIX_SIGNALS
static struct sigaction *SIG_defaults;
#else
#ifdef BSD_SIGNALS
static struct sigvec *SIG_defaults;
#else
static RETSIGTYPE (**SIG_defaults) (int);
#endif
#endif
static int SIG_crSectNest = 0;
#ifdef POSIX_SIGNALS
static sigset_t SIG_crSectMask;
#else
static int SIG_crSectMask;
#endif
static int SIG_init()
{
int i;
#ifdef POSIX_SIGNALS
sigset_t sigset_test;
#endif
if (SIG_defaults && SIG_handlers)
return (0);
#ifdef POSIX_SIGNALS
(void) sigfillset(&sigset_test);
for (i = 1; i < SIGMAX && sigismember(&sigset_test, i) == 1; i++)
;
if (i < SIGMAX)
i = SIGMAX;
i++;
if (!SIG_defaults)
SIG_defaults = (struct sigaction *)
calloc(i, sizeof(struct sigaction));
(void) sigemptyset(&SIG_crSectMask);
#else
i = SIGMAX+1;
#ifdef BSD_SIGNALS
if (!SIG_defaults)
SIG_defaults = (struct sigvec *)
calloc(i, sizeof(struct sigvec));
#else
if (!SIG_defaults)
SIG_defaults = ( RETSIGTYPE (**) (int) )
calloc( i, sizeof( RETSIGTYPE (**) (int) ) );
#endif
SIG_crSectMask = 0;
#endif
if (!SIG_handlers)
SIG_handlers = (struct SIG_hlist **)
calloc(i, sizeof(struct SIG_hlist *));
return (!SIG_defaults || !SIG_handlers);
}
void SIG_beginCrSect (void)
{
if (SIG_init() == 0)
{
if (SIG_crSectNest == 0)
{
#ifdef POSIX_SIGNALS
sigset_t sigset_mask;
(void) sigfillset(&sigset_mask);
(void) sigprocmask(SIG_SETMASK,
&sigset_mask, &SIG_crSectMask);
#else
#ifdef BSD_SIGNALS
SIG_crSectMask = sigblock(~0);
#else
#endif
#endif
}
SIG_crSectNest++;
}
}
void SIG_endCrSect (void)
{
if (SIG_init() == 0)
{
SIG_crSectNest--;
if (SIG_crSectNest == 0)
{
#ifdef POSIX_SIGNALS
(void) sigprocmask(SIG_SETMASK, &SIG_crSectMask, NULL);
#else
#ifdef BSD_SIGNALS
(void) sigsetmask(SIG_crSectMask);
#else
#endif
#endif
}
}
}
static RETSIGTYPE SIG_handle (int sig)
{
struct SIG_hlist *this;
SIG_beginCrSect();
this = SIG_handlers[sig];
while (this != (struct SIG_hlist *) NULL)
{
(*this->handler)(sig);
this = this->next;
}
SIG_endCrSect();
return;
}
int SIG_register(int sig, RETSIGTYPE (*fn)())
{
int val;
struct SIG_hlist *this;
#ifdef POSIX_SIGNALS
struct sigaction act;
sigset_t sigset_mask, sigset_omask;
#else
#ifdef BSD_SIGNALS
struct sigvec vec;
int mask;
#endif
#endif
if (SIG_init() != 0)
return (-1);
val = 0;
#ifdef POSIX_SIGNALS
(void) sigemptyset(&sigset_mask);
(void) sigaddset(&sigset_mask, sig);
(void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask);
#else
#ifdef BSD_SIGNALS
mask = sigblock(sigmask(sig));
#endif
#endif
this = SIG_handlers[sig];
while (this != (struct SIG_hlist *) NULL)
{
if (this->handler == fn) break;
this = this->next;
}
if (this == (struct SIG_hlist *) NULL)
{
if (SIG_handlers[sig] == (struct SIG_hlist *) NULL)
{
#ifdef POSIX_SIGNALS
act.sa_handler = SIG_handle;
(void) sigemptyset(&act.sa_mask);
act.sa_flags = 0;
val = sigaction(sig, &act, &SIG_defaults[sig]);
#else
#ifdef BSD_SIGNALS
memset (&vec, 0, sizeof (vec));
vec.sv_handler = SIG_handle;
val = sigvec(sig, &vec, &SIG_defaults[sig]);
#else
if ((SIG_defaults[sig] = signal(sig, SIG_handle)) == SIG_ERR)
val = -1;
#endif
#endif
}
if ((val == 0) && (this == (struct SIG_hlist *) NULL))
{
this = (struct SIG_hlist *)
malloc(sizeof(struct SIG_hlist));
if (this == NULL)
{
val = -1;
}
else
{
this->handler = fn;
this->next = SIG_handlers[sig];
SIG_handlers[sig] = this;
}
}
}
#ifdef POSIX_SIGNALS
(void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL);
#else
#ifdef BSD_SIGNALS
(void) sigsetmask(mask);
#endif
#endif
return val;
}
int SIG_deregister(int sig, RETSIGTYPE (*fn)())
{
int val;
struct SIG_hlist *this;
struct SIG_hlist *last;
#ifdef POSIX_SIGNALS
sigset_t sigset_mask, sigset_omask;
#else
#ifdef BSD_SIGNALS
int mask;
#endif
#endif
if (SIG_init() != 0)
return (-1);
val = 0;
last = (struct SIG_hlist *) NULL;
#ifdef POSIX_SIGNALS
(void) sigemptyset(&sigset_mask);
(void) sigaddset(&sigset_mask, sig);
(void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask);
#else
#ifdef BSD_SIGNALS
mask = sigblock(sigmask(sig));
#endif
#endif
this = SIG_handlers[sig];
while ((this != (struct SIG_hlist *) NULL) && (this->handler != fn))
{
last = this;
this = this->next;
}
if (this != (struct SIG_hlist *) NULL)
{
if (last == (struct SIG_hlist *) NULL)
{
SIG_handlers[sig] = this->next;
}
else
{
last->next = this->next;
}
free((char *) this);
}
if (SIG_handlers[sig] == (struct SIG_hlist *) NULL)
{
#ifdef POSIX_SIGNALS
val = sigaction(sig, &SIG_defaults[sig],
(struct sigaction *) NULL);
#else
#ifdef BSD_SIGNALS
val = sigvec(sig, &SIG_defaults[sig], (struct sigvec *) NULL);
#else
if (signal(sig, SIG_defaults[sig]) == SIG_ERR)
val = -1;
#endif
#endif
}
#ifdef POSIX_SIGNALS
(void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL);
#else
#ifdef BSD_SIGNALS
(void) sigsetmask(mask);
#endif
#endif
return val;
}
int SIG_inCrSect (void)
{
return SIG_crSectNest > 0;
}