/** * Copyright (C) 2013-2014 Justin James. * * This license must be preserved. * Any applications, libraries, or code which make any use of any * component of this program must not be commercial, unless explicit * permission is granted from the original author. The use of this * program for non-profit purposes is permitted. * * 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. * * In the event that this license restricts you from making desired use of this program, contact the original author. * Written by Justin James */ #include #include #include #include #include #include #include "Jupiter/Functions.h" #include "Jupiter/INIFile.h" #include "Jupiter/Queue.h" #include "Jupiter/Socket.h" #include "Jupiter/Plugin.h" #include "Jupiter/Timer.h" #include "IRC_Bot.h" #include "ServerManager.h" #include "Console_Command.h" #include "IRC_Command.h" Jupiter::Queue inputQueue; void onTerminate() { puts("Terminate signal received..."); } void onExit() { puts("Exit signal received; Cleaning up..."); Jupiter::Socket::cleanup(); puts("Clean-up complete. Closing..."); } void inputLoop() { const size_t inputSize = 1024; char *input = new char[inputSize]; while (ftell(stdin) != -1) // This can be expanded later to check for EBADF specifically. { fgets(input, inputSize, stdin); input[strcspn(input, "\r\n")] = 0; inputQueue.enqueue(input); } delete[] input; } int main(int argc, const char **args) { atexit(onExit); std::set_terminate(onTerminate); std::thread inputThread(inputLoop); srand((unsigned int) time(0)); puts(Jupiter::copyright); const char *configFileName = CONFIG_INI; for (int i = 1; i < argc; i++) { if (streqli(args[i], "-help")) { puts("Help coming soon, to a theatre near you!"); return 0; } else if (streqli(args[i], "-config") && ++i < argc) configFileName = args[i]; else if (streqli(args[i], "-pluginsdir") && ++i < argc) Jupiter::setPluginDirectory(Jupiter::ReferenceString(args[i])); else if (streqli(args[i], "-configFormat") && ++i < argc) puts("Feature not yet supported!"); else printf("Warning: Unknown command line argument \"%s\" specified. Ignoring...", args[i]); } puts("Loading config file..."); if (!Jupiter::IRC::Client::Config->readFile(configFileName)) { puts("Unable to read config file. Closing..."); exit(0); } fputs("Config loaded. ", stdout); const Jupiter::ReadableString &pDir = Jupiter::IRC::Client::Config->get(STRING_LITERAL_AS_REFERENCE("Config"), STRING_LITERAL_AS_REFERENCE("PluginsDirectory")); if (pDir.isEmpty() == false) { Jupiter::setPluginDirectory(pDir); printf("Plugins will be loaded from \"%.*s\"." ENDL, pDir.size(), pDir.ptr()); } puts("Loading plugins..."); const Jupiter::ReadableString &pluginList = Jupiter::IRC::Client::Config->get(STRING_LITERAL_AS_REFERENCE("Config"), STRING_LITERAL_AS_REFERENCE("Plugins")); if (pluginList.isEmpty()) puts("No plugins to load!"); else { unsigned int nPlugins = pluginList.wordCount(WHITESPACE); printf("Attempting to load %u plugins..." ENDL, nPlugins); for (unsigned int i = 0; i < nPlugins; i++) { Jupiter::ReferenceString plugin = Jupiter::ReferenceString::getWord(pluginList, i, WHITESPACE); if (Jupiter::loadPlugin(plugin) == nullptr) fprintf(stderr, "WARNING: Failed to load plugin \"%.*s\"!" ENDL, plugin.size(), plugin.ptr()); else printf("\"%.*s\" loaded successfully." ENDL, plugin.size(), plugin.ptr()); } } if (consoleCommands->size() > 0) printf("%u Console Commands have been initialized%s" ENDL, consoleCommands->size(), getConsoleCommand(STRING_LITERAL_AS_REFERENCE("help")) == nullptr ? "." : "; type \"help\" for more information."); if (IRCMasterCommandList->size() > 0) printf("%u IRC Commands have been loaded into the master list." ENDL, IRCMasterCommandList->size()); puts("Retreiving network list..."); const Jupiter::ReadableString &serverList = Jupiter::IRC::Client::Config->get(STRING_LITERAL_AS_REFERENCE("Config"), STRING_LITERAL_AS_REFERENCE("Servers")); if (serverList == nullptr) puts("Unable to find network list."); else { unsigned int nServers = serverList.wordCount(WHITESPACE); printf("Attempting to connect to %u servers..." ENDL, nServers); for (unsigned int i = 0; i < nServers; i++) serverManager->addServer(Jupiter::ReferenceString::getWord(serverList, i, WHITESPACE)); } puts("Sockets established."); while (1) { for (size_t i = 0; i < Jupiter::plugins->size(); i++) if (Jupiter::plugins->get(i)->shouldRemove() || Jupiter::plugins->get(i)->think() != 0) Jupiter::freePlugin(i); Jupiter_checkTimers(); serverManager->think(); Jupiter::ReferenceString input = (const char *)inputQueue.dequeue(); if (input != nullptr) { Jupiter::ReferenceString command = input.getWord(0, WHITESPACE); ConsoleCommand *cmd = getConsoleCommand(command); if (cmd != nullptr) cmd->trigger(input.gotoWord(1, WHITESPACE)); else printf("Error: Command \"%.*s\" not found." ENDL, command.size(), command.ptr()); } std::this_thread::sleep_for((std::chrono::milliseconds(1))); } return 0; }