+/* signal.c - NeonServ v5.3
+ * Copyright (C) 2011-2012 Philipp Kreil (pk910)
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+#include "signal.h"
+#include "bots.h"
+#include "ChanNode.h"
+#include "ClientSocket.h"
+#include "ConfigParser.h"
+
+static void sigcrash();
+static void sigexit();
+
+void sighandler(int signum) {
+ signal(signum, SIG_DFL);
+ switch(signum) {
+ case SIGABRT:
+ case SIGTERM:
+ case SIGINT:
+ //normal shutdown
+ sigexit(signum);
+ break;
+ case SIGSEGV:
+ case SIGFPE:
+ case SIGILL:
+ //crash
+ sigcrash(signum);
+ break;
+ }
+ kill(getpid(), signum);
+}
+
+static void sigcrash(int signum) {
+ char *coregen = "";
+ #ifndef WIN32
+ char gcore[50];
+ sprintf(gcore, "gcore %u", getpid());
+ system(gcore); //generate core file
+ coregen = "core file generated.";
+ #endif
+ char *signame;
+ switch(signum) {
+ case SIGSEGV:
+ signame = "SIGSEGV";
+ break;
+ case SIGFPE:
+ signame = "SIGFPE";
+ break;
+ case SIGILL:
+ signame = "SIGILL";
+ break;
+ default:
+ signame = "SIGUNKNOWN";
+ break;
+ }
+ char *alertchan = get_string_field("General.alertchan");
+ if(alertchan) {
+ struct ChanNode *channel = getChanByName(alertchan);
+ struct ClientSocket *client;
+ if(channel && (client = getChannelBot(channel, 0))) {
+ putsock(client, "PRIVMSG %s :\00304NeonServ received signal %d (%s). %s", alertchan, signum, signame, coregen);
+ }
+ }
+ //close all bots
+ struct ClientSocket *bot;
+ for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+ if((bot->flags & SOCKET_FLAG_CONNECTED)) {
+ close(bot->sock);
+ bot->flags &= SOCKET_FLAG_CONNECTED;
+ }
+ }
+ sleep(1);
+ //hard restart
+ restart_process();
+}
+
+static void sigexit(int signum) {
+ cleanup();
+}