/*****************************************************************************
POPular -- A POP3 server and proxy for large mail systems
$Id: sig.c,v 1.6 2002/09/15 12:27:16 sqrt Exp $
http://www.remote.org/jochen/mail/popular/
******************************************************************************
Copyright (C) 1999-2002 Jochen Topf <jochen@remote.org>
This program 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 of the License, or
(at your option) any later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*****************************************************************************/
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include "popular.h"
#include "sig.h"
static volatile int signal_remember[SIGNAL_MAX];
/*****************************************************************************
signal_handler()
The signal handler just saves the information which signal occurred into
an array.
*****************************************************************************/
void
signal_handler(int signum)
{
if (signum < SIGNAL_MAX) signal_remember[signum] = 1;
}
/*****************************************************************************
signal_set()
*****************************************************************************/
void
signal_set(signal_handler_t what, int signum, int flags)
{
struct sigaction sigAction;
memset(&sigAction, 0, sizeof(sigAction));
sigemptyset(&sigAction.sa_mask);
switch (what) {
case sigIgnore:
sigAction.sa_handler = SIG_IGN;
sigAction.sa_flags = 0;
break;
case sigDefault:
sigAction.sa_handler = SIG_DFL;
sigAction.sa_flags = 0;
break;
case sigHandler:
sigAction.sa_handler = signal_handler;
sigAction.sa_flags = SA_RESTART | flags;
break;
}
if (sigaction(signum, &sigAction, (struct sigaction *)0) != 0) {
/* XLOG-DOC:BUG:014a:sigaction_failed
* A sigaction () system call failed. This should never happen. */
xlog_printf(xlog_bug, 0x014a, "sigaction_failed signal=%d", signum);
}
}
/*****************************************************************************
signal_init(int c)
Setup standard signal handling for servers.
c=1: Call signal handler if child dies
*****************************************************************************/
void
signal_init(int c)
{
int i;
for (i=0; i < SIGNAL_MAX; i++) signal_remember[i] = 0;
signal_set(sigIgnore, SIGPIPE, 0);
if (c) {
signal_set(sigHandler, SIGCHLD, SA_NOCLDSTOP);
} else {
signal_set(sigDefault, SIGCHLD, 0);
}
signal_set(sigHandler, SIGHUP, 0);
signal_set(sigHandler, SIGTERM, 0);
signal_set(sigHandler, SIGINT, 0);
signal_set(sigHandler, SIGQUIT, 0);
signal_set(sigHandler, SIGUSR1, 0);
signal_set(sigHandler, SIGUSR2, 0);
}
/*****************************************************************************
signal_init_child()
Setup standard signal handling for children of servers.
*****************************************************************************/
void
signal_init_child()
{
int i;
signal_set(sigIgnore, SIGPIPE, 0);
signal_set(sigDefault, SIGCHLD, 0);
signal_set(sigDefault, SIGHUP, 0);
signal_set(sigDefault, SIGTERM, 0);
signal_set(sigDefault, SIGINT, 0);
signal_set(sigDefault, SIGQUIT, 0);
signal_set(sigDefault, SIGUSR1, 0);
signal_set(sigDefault, SIGUSR2, 0);
if (signal_remember[SIGTERM] || signal_remember[SIGINT]) {
/* XLOG-DOC:INF:0133:got_term_signal
* The child got a TERM or INT signal and will shut down. This signal
* was either delivered to the parent between the last check for signals
* and the fork, or it was delivered to the child before the child
* could change its signal handling to the default behaviour. In any
* case, calling exit immediately is the right thing to do here. */
xlog_printf(xlog_inf, 0x0133, "got_term_signal");
exit(0);
}
for (i=0; i < SIGNAL_MAX; i++) signal_remember[i] = 0;
}
/*****************************************************************************
signal_came()
Return 1 if the specified signal arrived, 0 otherwise.
*****************************************************************************/
int
signal_came(int signum)
{
if (signum < SIGNAL_MAX) {
int ret = signal_remember[signum];
signal_remember[signum] = 0;
return ret;
}
return 0;
}
/*****************************************************************************
signal_next()
Return the next signal, that was caught. If there was no signal, return 0.
*****************************************************************************/
int
signal_next()
{
int n;
for (n=1; n < SIGNAL_MAX; n++) {
if (signal_remember[n]) {
signal_remember[n] = 0;
return n;
}
}
return 0;
}
/** THE END *****************************************************************/
syntax highlighted by Code2HTML, v. 0.9.1