rpm/rpmio/rpmsq.c

115 lines
2.4 KiB
C

/** \ingroup rpmio
* \file rpmio/rpmsq.c
*/
#include "system.h"
#include <signal.h>
#include <sys/signal.h>
#include <errno.h>
#include <stdio.h>
#define ADD_REF(__tbl) (__tbl)->active++
#define SUB_REF(__tbl) --(__tbl)->active
#include <rpm/rpmsq.h>
#include "debug.h"
static sigset_t rpmsqCaught;
typedef struct rpmsig_s * rpmsig;
static struct rpmsig_s {
int signum;
rpmsqAction_t handler;
int active;
struct sigaction oact;
} rpmsigTbl[] = {
{ SIGINT, rpmsqAction },
#define rpmsigTbl_sigint (&rpmsigTbl[0])
{ SIGQUIT, rpmsqAction },
#define rpmsigTbl_sigquit (&rpmsigTbl[1])
{ SIGHUP, rpmsqAction },
#define rpmsigTbl_sighup (&rpmsigTbl[3])
{ SIGTERM, rpmsqAction },
#define rpmsigTbl_sigterm (&rpmsigTbl[4])
{ SIGPIPE, rpmsqAction },
#define rpmsigTbl_sigpipe (&rpmsigTbl[5])
{ -1, NULL },
};
int rpmsqIsCaught(int signum)
{
return sigismember(&rpmsqCaught, signum);
}
#ifdef SA_SIGINFO
void rpmsqAction(int signum, siginfo_t * info, void * context)
#else
void rpmsqAction(int signum)
#endif
{
int save = errno;
rpmsig tbl;
for (tbl = rpmsigTbl; tbl->signum >= 0; tbl++) {
if (tbl->signum != signum)
continue;
(void) sigaddset(&rpmsqCaught, signum);
break;
}
errno = save;
}
int rpmsqEnable(int signum, rpmsqAction_t handler)
{
int tblsignum = (signum >= 0 ? signum : -signum);
struct sigaction sa;
rpmsig tbl;
int ret = -1;
for (tbl = rpmsigTbl; tbl->signum >= 0; tbl++) {
if (tblsignum != tbl->signum)
continue;
if (signum >= 0) { /* Enable. */
if (ADD_REF(tbl) <= 0) {
(void) sigdelset(&rpmsqCaught, tbl->signum);
/* XXX Don't set a signal handler if already SIG_IGN */
(void) sigaction(tbl->signum, NULL, &tbl->oact);
if (tbl->oact.sa_handler == SIG_IGN)
continue;
(void) sigemptyset (&sa.sa_mask);
#ifdef SA_SIGINFO
sa.sa_flags = SA_SIGINFO;
#else
sa.sa_flags = 0;
#endif
sa.sa_sigaction = (handler != NULL ? handler : tbl->handler);
if (sigaction(tbl->signum, &sa, &tbl->oact) < 0) {
SUB_REF(tbl);
break;
}
tbl->active = 1; /* XXX just in case */
if (handler != NULL)
tbl->handler = handler;
}
} else { /* Disable. */
if (SUB_REF(tbl) <= 0) {
if (sigaction(tbl->signum, &tbl->oact, NULL) < 0)
break;
tbl->active = 0; /* XXX just in case */
tbl->handler = (handler != NULL ? handler : rpmsqAction);
}
}
ret = tbl->active;
break;
}
return ret;
}