0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2025-01-13 08:23:56 +01:00

ircd: Introduce ASIO; stub for signal handling and console UI.

This commit is contained in:
Jason Volk 2016-08-31 03:55:27 -07:00
parent baa60ed253
commit 5aeeb73e20
8 changed files with 379 additions and 523 deletions

View file

@ -20,15 +20,18 @@
*/
#include <ircd/ircd.h>
#include <boost/asio.hpp>
using namespace ircd;
namespace path = ircd::path;
using ircd::lgetopt;
bool printversion;
bool testing_conf;
lgetopt opts[] =
{
{ "help", NULL, lgetopt::USAGE, "Print this text" },
{ "version", &printversion, lgetopt::BOOL, "Print version and exit" },
{ "configfile", &ConfigFileEntry.configfile, lgetopt::STRING, "File to use for ircd.conf" },
{ "configfile", &ircd::ConfigFileEntry.configfile, lgetopt::STRING, "File to use for ircd.conf" },
{ "conftest", &testing_conf, lgetopt::YESNO, "Test the configuration files and exit" },
{ "debug", &ircd::debugmode, lgetopt::BOOL, "Enable options for debugging" },
{ NULL, NULL, lgetopt::STRING, NULL },
@ -51,17 +54,22 @@ const char *const usererrstr
%s
)"};
static void print_version();
static void handle_interruption();
static void sigfd_handler(const boost::system::error_code &, int);
static bool startup_checks();
static void print_version();
boost::asio::io_service ios;
boost::asio::signal_set sigs(ios);
int main(int argc, char *const *argv)
try
{
umask(077); // better safe than sorry --SRB
ConfigFileEntry.dpath = path::get(path::PREFIX);
ConfigFileEntry.configfile = path::get(path::IRCD_CONF); // Server configuration file
ConfigFileEntry.connect_timeout = 30; // Default to 30
ircd::ConfigFileEntry.dpath = path::get(path::PREFIX);
ircd::ConfigFileEntry.configfile = path::get(path::IRCD_CONF); // Server configuration file
ircd::ConfigFileEntry.connect_timeout = 30; // Default to 30
parseargs(&argc, &argv, opts);
if(!startup_checks())
@ -73,21 +81,34 @@ try
return 0;
}
return ircd::run();
sigs.add(SIGINT);
sigs.add(SIGQUIT);
sigs.async_wait(sigfd_handler);
ircd::init(ios);
ios.run(); // Blocks until a clean exit or an exception comes out of it.
}
catch(const std::exception &e)
{
if(ircd::debugmode)
throw;
/*
* Why EXIT_FAILURE here?
* Because if ircd_die_cb() is called it's because of a fatal
* error inside libcharybdis, and we don't know how to handle the
* exception, so it is logical to return a FAILURE exit code here.
* --nenolod
*
* left the comment but the code is gone -jzk
*/
fprintf(stderr, fatalerrstr, e.what());
return 1;
return EXIT_FAILURE;
}
void print_version()
{
printf("VERSION :%s\n",
info::version.c_str());
ircd::info::version.c_str());
#ifdef CUSTOM_BRANDING
printf("VERSION :based on %s-%s\n",
@ -103,10 +124,10 @@ try
{
#ifndef _WIN32
if(geteuid() == 0)
throw error("Don't run ircd as root!!!");
throw ircd::error("Don't run ircd as root!!!");
#endif
path::chdir(ConfigFileEntry.dpath);
path::chdir(ircd::ConfigFileEntry.dpath);
return true;
}
catch(const std::exception &e)
@ -114,3 +135,78 @@ catch(const std::exception &e)
fprintf(stderr, usererrstr, e.what());
return false;
}
void
sigfd_handler(const boost::system::error_code &ec,
int signum)
{
switch(ec.value())
{
using namespace boost::system::errc;
case success: break;
case operation_canceled: return;
default: throw std::runtime_error(ec.message());
}
switch(signum)
{
case SIGINT:
handle_interruption();
break;
case SIGQUIT:
printf("\nQUIT\n");
ios.stop();
break;
default:
break;
}
sigs.async_wait(sigfd_handler);
}
const char *const interruption_message
{R"(
*** Charybdis is now paused. A command line has been presented below.
*** This is actually an IRC client and your commands will originate from
*** the server itself. The server will resume when you hit enter.
***
*** - To exit cleanly, type DIE
*** - To exit quickly, type ctrl-\ [SIGQUIT]
*** - To exit immediately, type EXIT
*** - To generate a coredump for developers, type ABORT
***
*** This message will be skipped on the next interrupt.
)"};
void
handle_interruption()
{
static bool seen_the_message;
if(!seen_the_message)
{
seen_the_message = true;
std::cout << interruption_message;
}
std::string line;
std::cout << "\n> " << std::flush;
std::getline(std::cin, line);
if(std::cin.eof())
{
std::cout << std::endl;
std::cin.clear();
return;
}
if(line.empty())
return;
if(line == "ABORT")
abort();
if(line == "EXIT")
exit(0);
}

View file

@ -850,14 +850,14 @@ if [[ "$boost_linkage" = "shared" ]]; then
[
AC_SUBST(BOOST_LIBS, ["-lboost_filesystem-mgw53-1_61.dll -lboost_system-mgw53-1_61.dll"])
], [
AC_SUBST(BOOST_LIBS, ["-lboost_filesystem -lboost_system"])
AC_SUBST(BOOST_LIBS, ["-lboost_filesystem -lboost_system -lpthread"])
])
else
AM_COND_IF([MINGW],
[
AC_SUBST(BOOST_LIBS, ["$boost_libdir/libboost_filesystem-mgw53-1_61.dll.a $boost_libdir/libboost_system-mgw53-1_61.dll.a"])
], [
AC_SUBST(BOOST_LIBS, ["-lboost_filesystem -lboost_system"])
AC_SUBST(BOOST_LIBS, ["-lboost_filesystem -lboost_system -lpthread"])
dnl AC_SUBST(BOOST_LIBS, ["$boost_libdir/libboost_filesystem.a"])
dnl AC_SUBST(BOOST_LIBS, ["$boost_libdir/libboost_system.a"])
])

View file

@ -32,9 +32,19 @@
#endif
#ifdef __cplusplus
// Allow a reference to an ios to be passed to ircd
namespace boost {
namespace asio {
struct io_service;
}
}
namespace ircd {
extern bool debugmode;
extern boost::asio::io_service *ios;
struct SetOptions
{
@ -100,12 +110,10 @@ extern bool ircd_zlib_ok;
extern int maxconnections;
void restart(const char *) __attribute__((noreturn));
void ircd_shutdown() __attribute__((noreturn));
void server_reboot(void) __attribute__((noreturn));
void setup_signals();
void ircd_shutdown(const char *reason) __attribute__((noreturn));
int run();
void init(boost::asio::io_service &ios);
} // namespace ircd
#endif // __cplusplus

View file

@ -58,7 +58,6 @@ libircd_la_SOURCES = \
ircd.cc \
ircd_lexer.cc \
ircd_parser.cc \
ircd_signal.cc \
listener.cc \
logger.cc \
match.cc \

View file

@ -23,14 +23,10 @@
* USA
*/
bool ircd::debugmode;
#include <boost/asio.hpp>
namespace ircd {
static void
ircd_die_cb(const char *str) __attribute__((noreturn));
/* /quote set variables */
struct SetOptions GlobalSetOptions;
@ -44,6 +40,8 @@ struct admin_info AdminInfo;
struct Counter Count;
struct ServerStatistics ServerStats;
struct ev_entry *check_splitmode_ev;
int maxconnections;
client::client me; /* That's me */
struct LocalUser meLocalUser; /* That's also part of me */
@ -79,73 +77,6 @@ int split_users;
int split_servers;
int eob_count;
void
ircd_shutdown(const char *reason)
{
client::client *target_p;
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, lclient_list.head)
{
target_p = (client::client *)ptr->data;
sendto_one(target_p, ":%s NOTICE %s :Server Terminating. %s",
me.name, target_p->name, reason);
}
RB_DLINK_FOREACH(ptr, serv_list.head)
{
target_p = (client::client *)ptr->data;
sendto_one(target_p, ":%s ERROR :Terminated by %s",
me.name, reason);
}
log::critical("Server Terminating. %s", reason);
log::close();
exit(0);
}
/*
* print_startup - print startup information
*/
static void
print_startup(const pid_t &pid)
{
log::notice("Server started @ %s pid[%d]",
ConfigFileEntry.dpath,
pid);
}
/*
* init_sys
*
* inputs - boot_daemon flag
* output - none
* side effects - if boot_daemon flag is not set, don't daemonize
*/
static void
init_sys(void)
{
#if !defined(_WIN32) && defined(RLIMIT_NOFILE) && defined(HAVE_SYS_RESOURCE_H)
struct rlimit limit;
if(!getrlimit(RLIMIT_NOFILE, &limit))
{
maxconnections = limit.rlim_cur;
if(maxconnections <= MAX_BUFFER)
{
fprintf(stderr, "ERROR: Shell FD limits are too low.\n");
fprintf(stderr, "ERROR: charybdis reserves %d FDs, shell limits must be above this\n", MAX_BUFFER);
exit(EXIT_FAILURE);
}
return;
}
#endif /* RLIMIT_FD_MAX */
maxconnections = MAXCONNECTIONS;
}
static void
check_rehash(void *unused)
{
@ -220,84 +151,182 @@ initialize_global_set_options(void)
/* memset( &ConfigChannel, 0, sizeof(ConfigChannel)); */
/* End of global set options */
}
/*
* initialize_server_capabs
*
* inputs - none
* output - none
*/
static void
initialize_server_capabs(void)
{
default_server_capabs &= ~CAP_ZIP;
}
/*
* setup_corefile
*
* inputs - nothing
* output - nothing
* side effects - setups corefile to system limits.
* -kre
*/
static void
setup_corefile(void)
{
#ifdef HAVE_SYS_RESOURCE_H
struct rlimit rlim; /* resource limits */
bool debugmode;
boost::asio::io_service *ios;
/* Set corefilesize to maximum */
if(!getrlimit(RLIMIT_CORE, &rlim))
static void sigfd_handler(const boost::system::error_code &, int);
std::unique_ptr<boost::asio::signal_set> sigfd;
static void seed_random();
static void init_sigs();
static void init_sys();
} // namespace ircd
/*
* This function sets up the IRCd, handlers, and then returns without blocking.
* Pass your io_service instance, it will share it with the rest of your program.
* An exception will be thrown on error.
*/
void
ircd::init(boost::asio::io_service &io_service)
{
ircd::ios = &io_service;
init_sys();
init_sigs();
// The log is available, but it is console-only until conf opens files.
log::init();
log::mark("log started");
// initialise operhash fairly early.
//init_operhash();
me.localClient = &meLocalUser;
//rb_dlinkAddTail(&me, &me.node, &global_client_list);
//init_builtin_capabs();
//default_server_capabs = CAP_MASK;
//newconf_init();
//init_s_conf();
//init_s_newconf();
//init_hash();
//init_host_hash();
//client::init();
//init_hook();
//chan::init();
//initclass();
//whowas::init();
//init_reject();
//cache::init();
//init_monitor();
//chan::mode::init();
//init_authd(); /* Start up authd. */
//init_dns(); /* Start up DNS query system */
//privilegeset_set_new("default", "", 0);
//read_conf_files(true); /* cold start init conf files */
//mods::autoload();
//supported::init();
//init_bandb();
//init_ssld();
//init_wsockd();
//rehash_bans();
//default_server_capabs &= ~CAP_ZIP; // Set up default_server_capabs
//initialize_global_set_options();
/*
if(ServerInfo.name == NULL)
throw error("no server name specified in serverinfo block.");
rb_strlcpy(me.name, ServerInfo.name, sizeof(me.name));
if(ServerInfo.sid[0] == '\0')
throw error("no server sid specified in serverinfo block.");
rb_strlcpy(me.id, ServerInfo.sid, sizeof(me.id));
//client::init_uid();
// serverinfo{} description must exist. If not, error out.
if(ServerInfo.description == NULL)
throw error("no server description specified in serverinfo block.");
rb_strlcpy(me.info, ServerInfo.description, sizeof(me.info));
*/
/*
if(ServerInfo.ssl_cert != NULL)
{
rlim.rlim_cur = rlim.rlim_max;
setrlimit(RLIMIT_CORE, &rlim);
// just do the rb_setup_ssl_server to validate the config
if(!rb_setup_ssl_server(ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list))
{
ilog(L_MAIN, "WARNING: Unable to setup SSL.");
ircd_ssl_ok = false;
}
else
ircd_ssl_ok = true;
}
#endif
}
*/
static void
ircd_log_cb(const char *str)
{
ilog(L_MAIN, "librb reports: %s", str);
}
//me.from = &me;
//me.servptr = &me;
//set_me(me);
//make_serv(me);
//add_to_client_hash(me.name, &me);
//add_to_id_hash(me.id, &me);
//nameinfo(serv(me)) = cache::serv::connect(me.name, me.info);
static void
ircd_restart_cb(const char *str)
{
inotice("librb has called the restart callback: %s", str);
restart(str);
//rb_dlinkAddAlloc(&me, &global_serv_list);
//check_class();
//cache::help::load();
//configure_authd();
/* We want try_connections to be called as soon as possible now! -- adrian */
/* No, 'cause after a restart it would cause all sorts of nick collides */
/* um. by waiting even longer, that just means we have even *more*
* nick collisions. what a stupid idea. set an event for the IO loop --fl
*/
// rb_event_addish("try_connections", try_connections, NULL, STARTUP_CONNECTIONS_TIME);
// rb_event_addonce("try_connections_startup", try_connections, NULL, 2);
// rb_event_add("check_rehash", check_rehash, NULL, 3);
// rb_event_addish("reseed_srand", seed_random, NULL, 300); /* reseed every 10 minutes */
// if(splitmode)
// check_splitmode_ev = rb_event_add("check_splitmode", chan::check_splitmode, NULL, 5);
log::info("IRCd initialization completed successfully.");
}
/*
* Why EXIT_FAILURE here?
* Because if ircd_die_cb() is called it's because of a fatal
* error inside libcharybdis, and we don't know how to handle the
* exception, so it is logical to return a FAILURE exit code here.
* --nenolod
* init_sys
*
* inputs - boot_daemon flag
* output - none
* side effects - if boot_daemon flag is not set, don't daemonize
*/
static void
ircd_die_cb(const char *str)
void
ircd::init_sys()
{
if(str != NULL)
{
/* Try to get the message out to currently logged in operators. */
sendto_realops_snomask(sno::GENERAL, L_NETWIDE, "librb has called the die callback..aborting: %s", str);
inotice("librb has called the die callback..aborting: %s", str);
}
else
inotice("librb has called the die callback..aborting");
exit(EXIT_FAILURE);
/*
* Setup corefile size immediately after boot -kre
*/
#ifdef HAVE_SYS_RESOURCE_H
struct rlimit rlim; /* resource limits */
/* Set corefilesize to maximum */
if(!getrlimit(RLIMIT_CORE, &rlim))
{
rlim.rlim_cur = rlim.rlim_max;
setrlimit(RLIMIT_CORE, &rlim);
}
#endif
#if !defined(_WIN32) && defined(RLIMIT_NOFILE) && defined(HAVE_SYS_RESOURCE_H)
struct rlimit limit;
if(!getrlimit(RLIMIT_NOFILE, &limit))
maxconnections = limit.rlim_cur;
else
maxconnections = MAXCONNECTIONS;
#else
maxconnections = MAXCONNECTIONS;
#endif
rb_set_time();
rb_init_prng(NULL, RB_PRNG_DEFAULT);
seed_random();
}
struct ev_entry *check_splitmode_ev = NULL;
static int
seed_with_urandom(void)
static bool
seed_with_urandom()
{
unsigned int seed;
int fd;
@ -309,15 +338,15 @@ seed_with_urandom(void)
{
close(fd);
srand(seed);
return 1;
return true;
}
close(fd);
}
return 0;
return false;
}
static void
seed_with_clock(void)
seed_with_clock()
{
const struct timeval *tv;
rb_set_time();
@ -325,8 +354,8 @@ seed_with_clock(void)
srand(tv->tv_sec ^ (tv->tv_usec | (getpid() << 20)));
}
static void
seed_random(void *unused)
void
ircd::seed_random()
{
unsigned int seed;
if(rb_get_random(&seed, sizeof(seed)) == -1)
@ -338,177 +367,67 @@ seed_random(void *unused)
srand(seed);
}
/*
* main
*
* Initializes the IRCd.
*
* Inputs - number of commandline args, args themselves
* Outputs - none
* Side Effects - this is where the ircd gets going right now
*/
int
run()
static void
sigfd_handle_sigusr2()
{
init_sys();
rb_set_time();
/*
* Setup corefile size immediately after boot -kre
*/
setup_corefile();
/* initialise operhash fairly early. */
init_operhash();
me.localClient = &meLocalUser;
rb_dlinkAddTail(&me, &me.node, &global_client_list);
memset(&Count, 0, sizeof(Count));
memset(&ServerInfo, 0, sizeof(ServerInfo));
memset(&AdminInfo, 0, sizeof(AdminInfo));
memset(&ServerStats, 0, sizeof(struct ServerStatistics));
setup_signals();
server_state_foreground = true;
/* Check if there is pidfile and daemon already running */
if(!testing_conf)
{
inotice("starting %s ...", info::version.c_str());
inotice("%s", rb_lib_version());
}
/* Init the event subsystem */
rb_lib_init(ircd_log_cb, ircd_restart_cb, ircd_die_cb, false, maxconnections, DNODE_HEAP_SIZE, FD_HEAP_SIZE);
rb_linebuf_init(LINEBUF_HEAP_SIZE);
rb_init_prng(NULL, RB_PRNG_DEFAULT);
seed_random(NULL);
init_builtin_capabs();
default_server_capabs = CAP_MASK;
newconf_init();
init_s_conf();
init_s_newconf();
log::init();
log::mark("log started");
init_hash();
init_host_hash();
client::init();
init_hook();
chan::init();
initclass();
whowas::init();
init_reject();
cache::init();
init_monitor();
chan::mode::init();
init_authd(); /* Start up authd. */
init_dns(); /* Start up DNS query system */
privilegeset_set_new("default", "", 0);
if (testing_conf)
fprintf(stderr, "\nBeginning config test\n");
read_conf_files(true); /* cold start init conf files */
mods::autoload();
supported::init();
init_bandb();
init_ssld();
init_wsockd();
rehash_bans();
initialize_server_capabs(); /* Set up default_server_capabs */
initialize_global_set_options();
if(ServerInfo.name == NULL)
{
ierror("no server name specified in serverinfo block.");
return -1;
}
rb_strlcpy(me.name, ServerInfo.name, sizeof(me.name));
if(ServerInfo.sid[0] == '\0')
{
ierror("no server sid specified in serverinfo block.");
return -2;
}
rb_strlcpy(me.id, ServerInfo.sid, sizeof(me.id));
client::init_uid();
/* serverinfo{} description must exist. If not, error out. */
if(ServerInfo.description == NULL)
{
ierror("no server description specified in serverinfo block.");
return -3;
}
rb_strlcpy(me.info, ServerInfo.description, sizeof(me.info));
if(ServerInfo.ssl_cert != NULL)
{
/* just do the rb_setup_ssl_server to validate the config */
if(!rb_setup_ssl_server(ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list))
{
ilog(L_MAIN, "WARNING: Unable to setup SSL.");
ircd_ssl_ok = false;
}
else
ircd_ssl_ok = true;
}
if (testing_conf)
{
fprintf(stderr, "\nConfig testing complete.\n");
fflush(stderr);
return 0; /* Why? We want the launcher to exit out. */
}
me.from = &me;
me.servptr = &me;
set_me(me);
make_serv(me);
add_to_client_hash(me.name, &me);
add_to_id_hash(me.id, &me);
nameinfo(serv(me)) = cache::serv::connect(me.name, me.info);
rb_dlinkAddAlloc(&me, &global_serv_list);
check_class();
cache::help::load();
log::open();
configure_authd();
/* We want try_connections to be called as soon as possible now! -- adrian */
/* No, 'cause after a restart it would cause all sorts of nick collides */
/* um. by waiting even longer, that just means we have even *more*
* nick collisions. what a stupid idea. set an event for the IO loop --fl
*/
rb_event_addish("try_connections", try_connections, NULL, STARTUP_CONNECTIONS_TIME);
rb_event_addonce("try_connections_startup", try_connections, NULL, 2);
rb_event_add("check_rehash", check_rehash, NULL, 3);
rb_event_addish("reseed_srand", seed_random, NULL, 300); /* reseed every 10 minutes */
if(splitmode)
check_splitmode_ev = rb_event_add("check_splitmode", chan::check_splitmode, NULL, 5);
print_startup(getpid());
rb_lib_loop(0);
return 0;
// dorehashbans
// doremotd
}
} // namespace ircd
static void
sigfd_handle_sigusr1()
{
// dorehash (no longer hangup!)
}
static void
sigfd_handle_sigquit()
{
}
static void
sigfd_handle_sigterm()
{
}
void
ircd::sigfd_handler(const boost::system::error_code &ec,
int signum)
{
switch(ec.value())
{
using namespace boost::system::errc;
case success: break;
case operation_canceled: return;
default:
throw error("Signal handler (%d): %s",
signum,
ec.message().c_str());
}
switch(signum)
{
case SIGTERM: sigfd_handle_sigterm(); return;
case SIGQUIT: sigfd_handle_sigquit(); return;
case SIGUSR1: sigfd_handle_sigusr1(); break;
case SIGUSR2: sigfd_handle_sigusr2(); break;
default: break;
}
if(sigfd)
sigfd->async_wait(sigfd_handler);
}
void
ircd::init_sigs()
{
sigfd.reset(new boost::asio::signal_set(*ios));
sigfd->add(SIGTERM);
sigfd->add(SIGQUIT);
sigfd->add(SIGUSR1);
sigfd->add(SIGUSR2);
sigfd->async_wait(sigfd_handler);
}

View file

@ -1,193 +0,0 @@
/************************************************************************
* IRC - Internet Relay Chat, src/ircd_signal.c
* Copyright (C) 1990 Jarkko Oikarinen and
* University of Oulu, Computing Center
*
* 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _WIN32
#include <sys/types.h>
#include <sys/wait.h>
#endif
namespace ircd {
#ifndef _WIN32
/*
* dummy_handler - don't know if this is really needed but if alarm is still
* being used we probably will
*/
static void
dummy_handler(int sig)
{
/* Empty */
}
static void
sigchld_handler(int sig)
{
int status, olderrno;
olderrno = errno;
while (waitpid(-1, &status, WNOHANG) > 0)
;
errno = olderrno;
}
/*
* sigterm_handler - exit the server
*/
static void
sigterm_handler(int sig) __attribute__((noreturn));
static void
sigterm_handler(int sig)
{
ircd_shutdown("Received SIGTERM");
}
/*
* sighup_handler - reread the server configuration
*/
static void
sighup_handler(int sig)
{
dorehash = true;
}
/*
* sigusr1_handler - reread the motd file
*/
static void
sigusr1_handler(int sig)
{
doremotd = true;
}
static void
sigusr2_handler(int sig)
{
dorehashbans = true;
}
/*
* sigint_handler - restart the server
*/
static void
sigint_handler(int sig)
{
static bool restarting = false;
if(server_state_foreground)
{
log::critical("Server exiting on SIGINT");
exit(0);
}
else
{
log::critical("Server Restarting on SIGINT");
if(!restarting)
{
restarting = true;
server_reboot();
}
}
}
/*
* setup_signals - initialize signal handlers for server
*/
void
setup_signals()
{
sigset_t sigs;
struct sigaction act;
sigemptyset(&sigs);
act.sa_flags = 0;
act.sa_handler = SIG_IGN;
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, SIGPIPE);
sigaddset(&act.sa_mask, SIGALRM);
#ifdef SIGTRAP
sigaddset(&act.sa_mask, SIGTRAP);
#endif
# ifdef SIGWINCH
sigaddset(&act.sa_mask, SIGWINCH);
sigaction(SIGWINCH, &act, 0);
# endif
sigaction(SIGPIPE, &act, 0);
#ifdef SIGTRAP
sigaction(SIGTRAP, &act, 0);
#endif
act.sa_handler = dummy_handler;
sigaction(SIGALRM, &act, 0);
sigaddset(&sigs, SIGALRM);
act.sa_handler = sighup_handler;
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, SIGHUP);
sigaction(SIGHUP, &act, 0);
sigaddset(&sigs, SIGHUP);
act.sa_handler = sigint_handler;
sigaddset(&act.sa_mask, SIGINT);
sigaction(SIGINT, &act, 0);
sigaddset(&sigs, SIGINT);
act.sa_handler = sigterm_handler;
sigaddset(&act.sa_mask, SIGTERM);
sigaction(SIGTERM, &act, 0);
sigaddset(&sigs, SIGTERM);
act.sa_handler = sigusr1_handler;
sigaddset(&act.sa_mask, SIGUSR1);
sigaction(SIGUSR1, &act, 0);
sigaddset(&sigs, SIGUSR1);
act.sa_handler = sigusr2_handler;
sigaddset(&act.sa_mask, SIGUSR2);
sigaction(SIGUSR2, &act, 0);
sigaddset(&sigs, SIGUSR2);
act.sa_handler = sigchld_handler;
sigaddset(&act.sa_mask, SIGCHLD);
sigaction(SIGCHLD, &act, 0);
sigaddset(&sigs, SIGCHLD);
sigprocmask(SIG_UNBLOCK, &sigs, NULL);
}
#else
void
setup_signals()
{
/* this is a stub for mingw32 */
}
void
setup_reboot_signals()
{
/* this is a stub for mingw32 */
}
#endif // _WIN32
} // namespace ircd

View file

@ -74,7 +74,7 @@ log::init()
{
//TODO: XXX: config + cmd control + other fancy stuff
add_top_conf("log", NULL, NULL, conf_log_table);
//add_top_conf("log", NULL, NULL, conf_log_table);
console_err[CRITICAL] = true;
console_err[ERROR] = true;
@ -115,7 +115,7 @@ log::init()
void
log::fini()
{
remove_top_conf("log");
//remove_top_conf("log");
}
void

View file

@ -73,5 +73,32 @@ server_reboot(void)
exit(-1);
}
void
ircd_shutdown(const char *reason)
{
client::client *target_p;
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, lclient_list.head)
{
target_p = (client::client *)ptr->data;
sendto_one(target_p, ":%s NOTICE %s :Server Terminating. %s",
me.name, target_p->name, reason);
}
RB_DLINK_FOREACH(ptr, serv_list.head)
{
target_p = (client::client *)ptr->data;
sendto_one(target_p, ":%s ERROR :Terminated by %s",
me.name, reason);
}
log::critical("Server Terminating. %s", reason);
log::close();
exit(0);
}
} // namespace ircd