commit - c135d0dded909e2e5780697c4066ad44a3f488c8
commit + 1fe17e246cba4ee2f4349196c544296790ab5d55
blob - 7c5d0b614294a98180e29fb388190e9e93bdb6d8
blob + b7e0ea1382f17fdf96956b8d32702f27b0bae326
--- configure.in
+++ configure.in
bind gethostbyaddr gethostbyname gethostname inet_ntoa \
setsid setsockopt socket strcasecmp waitpid],,AC_MSG_ERROR([required function missing!]))
-AC_CHECK_FUNCS(getaddrinfo getnameinfo inet_aton isdigit sigaction snprintf \
+AC_CHECK_FUNCS(getaddrinfo getnameinfo inet_aton isdigit sigaction sigprocmask snprintf \
vsnprintf strdup strlcpy strlcat strtok_r)
# -- Configuration options --
blob - 4c9d9fa09c1ce5401b720b57dbee3f6d1e8349ad
blob + 8987c852a4d87588da9582b5e93e5e71929276cf
--- src/ngircd/Makefile.am
+++ src/ngircd/Makefile.am
ngircd_SOURCES = ngircd.c array.c channel.c client.c conf.c conn.c conn-func.c \
conn-ssl.c conn-zip.c hash.c io.c irc.c irc-channel.c irc-info.c irc-login.c \
irc-mode.c irc-op.c irc-oper.c irc-server.c irc-write.c lists.c log.c \
- match.c op.c numeric.c pam.c parse.c proc.c rendezvous.c resolve.c
+ match.c op.c numeric.c pam.c parse.c proc.c rendezvous.c resolve.c sighandlers.c
ngircd_LDFLAGS = -L../portab -L../tool -L../ipaddr
blob - 78a20b055ea523a1692998a45e08c9d49bc1bd42
blob + 03e2905cc5af0e1afa70f4299627d0cfbe43a373
--- src/ngircd/conn.c
+++ src/ngircd/conn.c
unsigned int created = 0;
char *copy, *listen_addr;
- if (!io_library_init(CONNECTION_POOL)) {
- Log(LOG_EMERG, "Cannot initialize IO routines: %s", strerror(errno));
- return -1;
- }
-
assert(Conf_ListenAddress);
/* can't use Conf_ListenAddress directly, see below */
blob - 4d329d2ade1c89724bf975c98cb758f12fa310b0
blob + de0b490dab81a5aa025a859ac3801c17ffb602c8
--- src/ngircd/ngircd.c
+++ src/ngircd/ngircd.c
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/wait.h>
#include <fcntl.h>
#include <pwd.h>
#include <grp.h>
#include "lists.h"
#include "log.h"
#include "parse.h"
+#include "sighandlers.h"
+#include "io.h"
#include "irc.h"
#ifdef ZEROCONF
#include "ngircd.h"
-static void Initialize_Signal_Handler PARAMS(( void ));
-static void Signal_Handler PARAMS(( int Signal ));
-
static void Show_Version PARAMS(( void ));
static void Show_Help PARAMS(( void ));
* when not running in "no daemon" mode: */
if( ! NGIRCd_NoDaemon ) Log_InitErrorfile( );
#endif
+ if (!io_library_init(CONNECTION_POOL)) {
+ Log(LOG_ALERT, "Fatal: Cannot initialize IO routines: %s", strerror(errno));
+ exit(1);
+ }
- Initialize_Signal_Handler( );
+ if (!Signals_Init()) {
+ Log(LOG_ALERT, "Fatal: Could not set up signal handlers: %s", strerror(errno));
+ exit(1);
+ }
/*
* create protocol and server identification.
/**
- * Initialize the signal handler.
- */
-static void
-Initialize_Signal_Handler( void )
-{
-#ifdef HAVE_SIGACTION
- struct sigaction saction;
-
- memset( &saction, 0, sizeof( saction ));
- saction.sa_handler = Signal_Handler;
-#ifdef SA_RESTART
- saction.sa_flags |= SA_RESTART;
-#endif
-#ifdef SA_NOCLDWAIT
- saction.sa_flags |= SA_NOCLDWAIT;
-#endif
-
- sigaction(SIGINT, &saction, NULL);
- sigaction(SIGQUIT, &saction, NULL);
- sigaction(SIGTERM, &saction, NULL);
- sigaction(SIGHUP, &saction, NULL);
- sigaction(SIGCHLD, &saction, NULL);
-
- /* we handle write errors properly; ignore SIGPIPE */
- saction.sa_handler = SIG_IGN;
- sigaction(SIGPIPE, &saction, NULL);
-#else
- signal(SIGINT, Signal_Handler);
- signal(SIGQUIT, Signal_Handler);
- signal(SIGTERM, Signal_Handler);
- signal(SIGHUP, Signal_Handler);
- signal(SIGCHLD, Signal_Handler);
-
- signal(SIGPIPE, SIG_IGN);
-#endif
-} /* Initialize_Signal_Handler */
-
-
-/**
- * Signal handler of ngIRCd.
- * This function is called whenever ngIRCd catches a signal sent by the
- * user and/or the system to it. For example SIGTERM and SIGHUP.
- * @param Signal Number of the signal to handle.
- */
-static void
-Signal_Handler( int Signal )
-{
- switch( Signal )
- {
- case SIGTERM:
- case SIGINT:
- case SIGQUIT:
- /* shut down sever */
- NGIRCd_SignalQuit = true;
- break;
- case SIGHUP:
- /* re-read configuration */
- NGIRCd_SignalRehash = true;
- break;
- case SIGCHLD:
- /* child-process exited, avoid zombies */
- while (waitpid( -1, NULL, WNOHANG) > 0)
- ;
- break;
-#ifdef DEBUG
- default:
- /* unbekanntes bzw. unbehandeltes Signal */
- Log( LOG_DEBUG, "Got signal %d! Ignored.", Signal );
-#endif
- }
-} /* Signal_Handler */
-
-
-/**
* Display copyright and version information of ngIRCd on the console.
*/
static void
blob - b615f2631e649ba85ae796c0fe2f681f291c72fc
blob + bd0aed0a7b5509337a1c3c460d00c43ed4d7f9ca
--- src/ngircd/ngircd.h
+++ src/ngircd/ngircd.h
#include "defines.h"
+#define C_ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
+
GLOBAL time_t NGIRCd_Start; /* Startzeitpunkt des Daemon */
GLOBAL char NGIRCd_StartStr[64];
GLOBAL char NGIRCd_Version[126];
blob - 95c49a513db779063e79429bccec40d8363b5191
blob + 479b300450e4dcfd4f601b703bc4a573fc3f8a77
--- src/ngircd/parse.c
+++ src/ngircd/parse.c
static bool Validate_Args PARAMS(( CONN_ID Idx, REQUEST *Req, bool *Closed ));
static bool Handle_Request PARAMS(( CONN_ID Idx, REQUEST *Req ));
-
-#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
/**
* Return the pointer to the global "IRC command structure".
/* This server is the target of the numeric */
num = atoi(Req->command);
- for (i = 0; i < (int) ARRAY_SIZE(Numerics); i++) {
+ for (i = 0; i < (int) C_ARRAY_SIZE(Numerics); i++) {
if (num == Numerics[i].numeric) {
if (!Numerics[i].function)
return CONNECTED;
blob - dbcff6f1aa5cfe0edf16ac4b90aace58a681698f
blob + 614aef4c39a741044c745ac4c5e7232f1a54d2bf
--- src/ngircd/proc.c
+++ src/ngircd/proc.c
#include "conn.h"
#include "exp.h"
+#include "sighandlers.h"
#include "proc.h"
/**
return -1;
case 0:
/* New child process: */
+ Signals_Exit();
signal(SIGTERM, Proc_GenericSignalHandler);
signal(SIGALRM, Proc_GenericSignalHandler);
close(pipefds[0]);
blob - /dev/null
blob + f3ce24feb4935b77d13577ab66e526a7bedb9c81 (mode 644)
--- /dev/null
+++ src/ngircd/sighandlers.c
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ *
+ * 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.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ */
+
+#include "portab.h"
+
+/**
+ * @file
+ * Signal Handlers: Actions to be performed when the program
+ * receives a signal.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "imp.h"
+#include "io.h"
+#include "log.h"
+#include "ngircd.h"
+#include "sighandlers.h"
+
+static int signalpipe[2];
+
+static void Signal_Block(int sig)
+{
+#ifdef HAVE_SIGPROCMASK
+ sigset_t set;
+
+ sigemptyset(&set);
+ sigaddset(&set, sig);
+
+ sigprocmask(SIG_BLOCK, &set, NULL);
+#endif
+}
+
+
+static void Signal_Unblock(int sig)
+{
+#ifdef HAVE_SIGPROCMASK
+ sigset_t set;
+
+ sigemptyset(&set);
+ sigaddset(&set, sig);
+
+ sigprocmask(SIG_UNBLOCK, &set, NULL);
+#endif
+}
+
+
+/**
+ * Signal handler of ngIRCd.
+ * This function is called whenever ngIRCd catches a signal sent by the
+ * user and/or the system to it. For example SIGTERM and SIGHUP.
+ *
+ * It blocks the signal and queues it for later execution by Signal_Handler_BH.
+ * @param Signal Number of the signal to handle.
+ */
+static void Signal_Handler(int Signal)
+{
+ switch (Signal) {
+ case SIGTERM:
+ case SIGINT:
+ case SIGQUIT:
+ /* shut down sever */
+ NGIRCd_SignalQuit = true;
+ return;
+ case SIGHUP:
+ /* re-read configuration */
+ NGIRCd_SignalRehash = true;
+ return;
+ case SIGCHLD:
+ /* child-process exited, avoid zombies */
+ while (waitpid( -1, NULL, WNOHANG) > 0)
+ ;
+ return;
+ }
+
+ /*
+ * other signal: queue for later execution.
+ * This has the advantage that we are not restricted
+ * to functions that can be called safely from signal handlers.
+ */
+ if (write(signalpipe[1], &Signal, sizeof(Signal)) != -1)
+ Signal_Block(Signal);
+} /* Signal_Handler */
+
+
+/**
+ * Signal processing handler of ngIRCd.
+ * This function is called from the main conn event loop in (io_dispatch)
+ * whenever ngIRCd has queued a signal.
+ *
+ * This function runs in normal context, not from the real signal handler,
+ * thus its not necessary to only use functions that are signal safe.
+ * @param Signal Number of the signal that was queued.
+ */
+static void Signal_Handler_BH(int Signal)
+{
+ switch (Signal) {
+#ifdef DEBUG
+ default:
+ Log(LOG_DEBUG, "Got signal %d! Ignored.", Signal);
+#endif
+ }
+ Signal_Unblock(Signal);
+}
+
+static void Sig_callback(int fd, short UNUSED what)
+{
+ int sig, ret;
+ (void) what;
+
+ do {
+ ret = read(fd, &sig, sizeof(sig));
+ if (ret == sizeof(int))
+ Signal_Handler_BH(sig);
+ } while (ret == sizeof(int));
+
+ if (ret == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ return;
+
+ Log(LOG_EMERG, "read from signal pipe: %s", strerror(errno));
+ exit(1);
+ }
+
+ Log(LOG_EMERG, "EOF on signal pipe");
+ exit(1);
+}
+
+
+static const int signals_catch[] = { SIGINT, SIGQUIT, SIGTERM, SIGHUP, SIGCHLD, SIGUSR1, SIGUSR2 };
+/**
+ * Initialize the signal handlers, catch
+ * those signals we are interested in and sets SIGPIPE to be ignored.
+ * @return true if initialization was sucessful.
+ */
+bool Signals_Init(void)
+{
+ size_t i;
+#ifdef HAVE_SIGACTION
+ struct sigaction saction;
+#endif
+
+ if (pipe(signalpipe))
+ return false;
+
+ if (!io_setnonblock(signalpipe[0]) ||
+ !io_setnonblock(signalpipe[1]))
+ return false;
+ if (!io_setcloexec(signalpipe[0]) ||
+ !io_setcloexec(signalpipe[1]))
+ return false;
+#ifdef HAVE_SIGACTION
+ memset( &saction, 0, sizeof( saction ));
+ saction.sa_handler = Signal_Handler;
+#ifdef SA_RESTART
+ saction.sa_flags |= SA_RESTART;
+#endif
+#ifdef SA_NOCLDWAIT
+ saction.sa_flags |= SA_NOCLDWAIT;
+#endif
+
+ for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
+ sigaction(signals_catch[i], &saction, NULL);
+
+ /* we handle write errors properly; ignore SIGPIPE */
+ saction.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &saction, NULL);
+#else
+ for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
+ signal(signals_catch[i], Signal_Handler);
+
+ signal(SIGPIPE, SIG_IGN);
+#endif
+ return io_event_create(signalpipe[0], IO_WANTREAD,
+ Sig_callback);
+} /* Initialize_Signal_Handler */
+
+
+/**
+ * Restores signals to their default behaviour.
+ *
+ * This should be called after a fork() in the new
+ * child prodcess, especially when we are about to call
+ * 3rd party code (e.g. PAM).
+ */
+void Signals_Exit(void)
+{
+ size_t i;
+#ifdef HAVE_SIGACTION
+ struct sigaction saction;
+
+ memset(&saction, 0, sizeof(saction));
+ saction.sa_handler = SIG_DFL;
+
+ for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
+ sigaction(signals_catch[i], &saction, NULL);
+ sigaction(SIGPIPE, &saction, NULL);
+#else
+ for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
+ sigaction(signals_catch[i], &saction, NULL);
+ signal(SIGPIPE, SIG_DFL);
+#endif
+ close(signalpipe[1]);
+ close(signalpipe[0]);
+}
+
+/* -eof- */
blob - /dev/null
blob + 5df8f223439b7c0cd0196acc16e2600d1471f80c (mode 644)
--- /dev/null
+++ src/ngircd/sighandlers.h
+/*
+ * 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.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ */
+
+#ifndef signals_included_
+#define signals_included_
+
+#include "portab.h"
+
+bool Signals_Init(void);
+void Signals_Exit(void);
+
+
+#endif