/// <summary> /// This is used to handle UNIX signals /// </summary> /// <param name='sender'>Sender</param> /// <param name='args'>Arguments</param> protected static void SigInt(object sender, ConsoleCancelEventArgs args) { if (!Core.IsRunning) { // in case that user hit ctrl + c multiple times, we don't want to // call this, once is just enough return; } Syslog.WriteNow("SIGINT - Shutting down", true); try { Core.Kill(); } catch (Exception fail) { Core.HandleException(fail); } Syslog.WriteNow("Terminated (emergency)"); Process.GetCurrentProcess().Kill(); }
private static void Restart(CommandParams parameters) { IRC.DeliverMessage("System is shutting down, requested by " + parameters.User.Nick + " from " + parameters.SourceChannel.Name, Configuration.System.DebugChan, libirc.Defs.Priority.High); Syslog.Log("System is shutting down, requested by " + parameters.User.Nick + " from " + parameters.SourceChannel.Name); Core.Kill(); }
/// <summary> /// The entry point of the program, where the program control starts and ends. /// </summary> /// <param name='args'> /// The command-line arguments. /// </param> private static void Main(string[] args) { try { Configuration.System.UpTime = DateTime.Now; Core.KernelThread = Thread.CurrentThread; Core.KernelThread.Name = "Kernel"; Configuration.System.Version += " [libirc v. " + libirc.Defs.Version.ToString() + "]"; Thread logger = new Thread(Logging.Exec) { Name = "Logger" }; Core.ThreadManager.RegisterThread(logger); ParseArgs(args); Syslog.WriteNow(Configuration.System.Version); Syslog.WriteNow("Loading..."); logger.Start(); Console.CancelKeyPress += SigInt; messages.LoadLD(); if (Configuration.Load() != 0) { Syslog.WriteNow("Error while loading the config file, exiting", true); Environment.Exit(-2); } Terminal.Init(); Core.Help.CreateHelp(); Core.WriterThread = new Thread(StorageWriter.Exec); Core.ThreadManager.RegisterThread(Core.WriterThread); Core.WriterThread.Name = "Writer"; Core.WriterThread.Start(); if (WMIBMySQL.IsAvailable) { Syslog.Log("Initializing MySQL"); Core.MysqlDB = new WMIBMySQL(); } else { Syslog.Log("Mysql is not configured, not using"); } if (PostgreSQL.IsAvailable) { Syslog.Log("Opening connection to PostgreDB"); Core.PostgreDB = new PostgreSQL(); Core.PostgreDB.Connect(); } else { Syslog.Log("Postgres is not configured, not using"); } // let's use postgre as default if (Core.PostgreDB != null) { Syslog.Log("Using Postgres as a default SQL provider"); Core.DB = Core.PostgreDB; } else if (Core.MysqlDB != null) { Syslog.Log("Using MySQL as a default SQL"); Core.DB = Core.MysqlDB; } // register all commands Commands.InitAdminCommands(); Syslog.Log("Loading modules"); ExtensionHandler.SearchMods(); Security.Init(); Security.Global(); Syslog.Log("Connecting"); IRC.Connect(); #if __MonoCS__ UnixSignal[] signals = { new UnixSignal(Signum.SIGINT), new UnixSignal(Signum.SIGTERM), new UnixSignal(Signum.SIGQUIT), new UnixSignal(Signum.SIGHUP) }; #endif while (Core.IsRunning) { #if __MonoCS__ int index = UnixSignal.WaitAny(signals, -1); Signum signal = signals [index].Signum; switch (signal) { case Signum.SIGINT: SigInt(null, null); goto exit; case Signum.SIGTERM: Syslog.WriteNow("SIGTERM - Shutting down", true); Core.Kill(); goto exit; } #endif Thread.Sleep(200); } #if __MonoCS__ exit: #endif // memory cleanup if (Core.DB != null) { ((WMIBMySQL)Core.DB).Dispose(); } } catch (Exception fatal) { Syslog.WriteNow("bot crashed, bellow is debugging information", Syslog.Type.Error); Console.WriteLine("------------------------------------------------------------------------"); Console.WriteLine("Description: " + fatal.Message); Console.WriteLine("Stack trace: " + fatal.StackTrace); Environment.Exit(-2); } }
public void ThreadExec(object data) { try { this.connection = (TcpClient)data; Syslog.DebugLog("Incoming connection from: " + connection.Client.RemoteEndPoint); this.connection.NoDelay = true; this.networkStream = connection.GetStream(); this.streamReader = new StreamReader(networkStream); this.streamWriter = new StreamWriter(networkStream); // login Write("Enter username:"******"Enter password:"******"Invalid user or password, bye"); return; } if (!Security.IsGloballyApproved(user, "terminal")) { Disconnect("No permissions, bye"); return; } Write("Successfuly logged in to wm-bot, I have " + SessionList.Count.ToString() + " users logged in"); while (connection.Connected && !streamReader.EndOfStream && Core.IsRunning) { string text = streamReader.ReadLine(); string command = text; List <string> list = new List <string>(); string parameters = ""; if (command.Contains(" ")) { parameters = command.Substring(command.IndexOf(" ") + 1); command = command.Substring(0, command.IndexOf(" ")); if (parameters.Contains(" ")) { list.AddRange(parameters.Split(' ')); } } switch (command.ToLower()) { case "exit": case "quit": Disconnect("Good bye"); return; case "info": string result = "Uptime: " + Core.getUptime() + " Version: " + Configuration.System.Version + "\n\nBuffer information:\nUnwritten lines (file storage): " + StorageWriter.Count + "\n"; // we flush it early so that we can see where it gets stuck in case of a dead lock Write(result); result = ""; if (Core.DB != null) { result += "Unwritten rows (MySQL): " + Core.DB.CacheSize() + "\n"; } result += "\nThreads:\n"; foreach (Thread thread in Core.ThreadManager.ThreadList) { result += "Thread: " + FormatToSpecSize(thread.Name, 20) + " status: " + FormatToSpecSize(thread.ThreadState.ToString(), 20) + " id: " + FormatToSpecSize(thread.ManagedThreadId.ToString(), 8) + "\n"; } Write(result); Write("Instances:"); result = ""; Syslog.DebugLog("Retrieving information for user " + username + " in system"); foreach (Instance instance in Instance.Instances.Values) { Syslog.DebugLog("Retrieving information for user " + username + " of instance " + instance.Nick, 2); result += instance.Nick + " channels: " + instance.ChannelCount + " connected: " + instance.IsConnected + " working: " + instance.IsWorking + " queue: " + instance.QueueSize() + "\n"; } Write(result); break; case "help": Write("Commands:\n" + "exit - shutdown connection\n" + "verbosity++\nverbosity--\n" + "info - print information about system\n" + "halt - shutdown bot\n" + "reauth [instance] - resend password to nickserv\n" + "traffic-on - turn on traffic logs\n" + "traffic-off - turn off traffic logs\n" + "send [instance] [text] - deliver a RAW text to IRC server on a given bot\n" + "kill [instance] - disconnect selected instance\n" + "conn [instance] - connect instance\n"); break; case "halt": Disconnect("Shutting down"); Core.Kill(); return; case "reauth": if (Instance.Instances.ContainsKey(parameters)) { Instance.Instances[parameters].Protocol.Authenticate(false); Write("Sent a password to nickserv on " + parameters); break; } Write("Unknown instance: " + parameters); break; case "traffic-on": Configuration.Network.Logging = true; Write("Dumping traffic into datafile"); break; case "verbosity++": Configuration.System.SelectedVerbosity++; break; case "verbosity--": Configuration.System.SelectedVerbosity--; break; case "traffic-off": Configuration.Network.Logging = false; Write("Disabled traffic"); break; case "kill": if (Instance.Instances.ContainsKey(parameters)) { Instance.Instances[parameters].ShutDown(); Write("Killed: " + parameters); break; } Write("Unknown instance: " + parameters); break; case "conn": if (Instance.Instances.ContainsKey(parameters)) { if (Instance.Instances[parameters].IsConnected) { Write("Refusing to connect instance which is already connected: " + parameters); break; } Instance.Instances[parameters].Init(); Write("Initializing: " + parameters); int curr = 0; while (curr < 10 && !Instance.Instances[parameters].IsWorking) { curr++; Thread.Sleep(1000); } if (!Instance.Instances[parameters].IsWorking) { Write("Failed to initialize instance (timeout)"); break; } Write("Joining channels"); Instance.Instances[parameters].ChannelsJoined = false; Instance.Instances[parameters].Join(); curr = 0; while (curr < Instance.Instances[parameters].ChannelCount && !Instance.Instances[parameters].ChannelsJoined) { curr++; Thread.Sleep(6000); } if (!Instance.Instances[parameters].ChannelsJoined) { Write("Failed to rejoin all channels in time"); break; } Write("Instance is online: " + parameters); break; } Write("Unknown instance: " + parameters); break; case "send": if (!parameters.Contains(" ")) { Write("This command requires 2 parameters"); break; } string to = parameters.Substring(0, parameters.IndexOf(" ")); if (Instance.Instances.ContainsKey(to)) { if (!Instance.Instances[to].IsConnected) { Write("Refusing to send data using instance which is not connected: " + to); break; } Instance.Instances[to].Network.Transfer(parameters.Substring(parameters.IndexOf(" ") + 1)); break; } Write("I have no such instance dude"); break; default: Write("Unknown command, try help"); break; } } } catch (Exception fail) { Core.HandleException(fail); } Disconnect(); }