diff options
| author | Adam <Adam@Anope.org> | 2010-05-25 00:57:25 -0500 |
|---|---|---|
| committer | Adam <Adam@anope.org> | 2010-06-18 21:04:07 -0400 |
| commit | 4a2b9ebcf38d6c0a2860b966421b3af125438488 (patch) | |
| tree | e4af4e59fd29352138db0fb0ff614d50233850b8 /src/main.c | |
| parent | 2fba686904e6f78ebab35df171c5757afeebf05d (diff) | |
Renamed all of source files from .c to .cpp
Diffstat (limited to 'src/main.c')
| -rw-r--r-- | src/main.c | 587 |
1 files changed, 0 insertions, 587 deletions
diff --git a/src/main.c b/src/main.c deleted file mode 100644 index d4746cf93..000000000 --- a/src/main.c +++ /dev/null @@ -1,587 +0,0 @@ -/* Services -- main source file. - * - * (C) 2003-2010 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - * - * 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. - * - * 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 (see the file COPYING); if not, write to the - * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - */ - -#include "services.h" -#include "timers.h" -#include "version.h" -#include "modules.h" - -// getrlimit. -#ifndef _WIN32 -# include <sys/time.h> -# include <sys/resource.h> -#endif - - -/******** Global variables! ********/ - -/* Command-line options: (note that configuration variables are in config.c) */ -std::string services_dir; /* -dir dirname */ -std::string services_bin; /* Binary as specified by the user */ -std::string orig_cwd; /* Original current working directory */ -std::string log_filename = "services.log"; /* -log filename */ -int debug = 0; /* -debug */ -int readonly = 0; /* -readonly */ -bool LogChan = false; /* -logchan */ -int nofork = 0; /* -nofork */ -int forceload = 0; /* -forceload */ -int nothird = 0; /* -nothrid */ -int noexpire = 0; /* -noexpire */ -int protocoldebug = 0; /* -protocoldebug */ - -std::string binary_dir; /* Used to store base path for Anope */ -#ifdef _WIN32 -#include <process.h> -#define execve _execve -#endif - -/* Set to 1 if we are to quit */ -int quitting = 0; - -/* Set to 1 if we are to quit after saving databases */ -int shutting_down = 0; - -/* Contains a message as to why services is terminating */ -const char *quitmsg = NULL; - -/* Should we update the databases now? */ -int save_data = 0; - -/* At what time were we started? */ -time_t start_time; - -/* Parameters and environment */ -char **my_av, **my_envp; - -/* Moved here from version.h */ -const char version_number[] = VERSION_STRING; -const char version_number_dotted[] = VERSION_STRING_DOTTED; -const char version_build[] = - "build #" BUILD ", compiled " __DATE__ " " __TIME__; -/* the space is needed cause if you build with nothing it will complain */ - -/******** Local variables! ********/ - -/* Set to 1 after we've set everything up */ -static int started = 0; - -/*************************************************************************/ - -class ExpireTimer : public Timer -{ - public: - ExpireTimer(time_t timeout, time_t now) : Timer(timeout, now, true) { } - - void Tick(time_t) - { - if (!readonly && !noexpire) - expire_all(); - } -}; - -class UpdateTimer : public Timer -{ - public: - UpdateTimer(time_t timeout, time_t now) : Timer(timeout, now, true) { } - - void Tick(time_t) - { - if (!readonly) - save_databases(); - } -}; - -Socket *UplinkSock = NULL; - -class UplinkSocket : public Socket -{ - public: - UplinkSocket(const std::string &nTargetHost, int nPort, const std::string &nBindHost = "", bool nIPv6 = false) : Socket(nTargetHost, nPort, nBindHost, nIPv6) - { - UplinkSock = this; - } - - ~UplinkSocket() - { - UplinkSock = NULL; - } - - bool Read(const std::string &buf) - { - process(buf); - return true; - } -}; - -/*************************************************************************/ - -/* Run expiration routines */ - -extern void expire_all() -{ - if (noexpire || readonly) - { - // Definitely *do not* want. - return; - } - - FOREACH_MOD(I_OnPreDatabaseExpire, OnPreDatabaseExpire()); - - Alog(LOG_DEBUG) << "Running expire routines"; - expire_nicks(); - expire_chans(); - expire_requests(); - expire_exceptions(); - - FOREACH_MOD(I_OnDatabaseExpire, OnDatabaseExpire()); -} - -/*************************************************************************/ - -void save_databases() -{ - if (readonly) - return; - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnSaveDatabase, OnSaveDatabase()); - Alog(LOG_DEBUG) << "Saving FFF databases"; -} - -/*************************************************************************/ - -/* Restarts services */ -void do_restart_services() -{ - if (!readonly) { - expire_all(); - save_databases(); - } - Alog() << "Restarting"; - - FOREACH_MOD(I_OnPreRestart, OnPreRestart()); - - if (!quitmsg) - quitmsg = "Restarting"; - /* Send a quit for all of our bots */ - for (botinfo_map::const_iterator it = BotList.begin(); it != BotList.end(); ++it) - { - /* Don't use quitmsg here, it may contain information you don't want people to see */ - ircdproto->SendQuit(it->second, "Restarting"); - } - ircdproto->SendSquit(Config.ServerName, quitmsg); - /* Process to send the last bits of information before disconnecting */ - socketEngine.Process(); - delete UplinkSock; - close_log(); - /* First don't unload protocol module, then do so */ - ModuleManager::UnloadAll(false); - ModuleManager::UnloadAll(true); - chdir(binary_dir.c_str()); - execve(services_bin.c_str(), my_av, my_envp); - if (!readonly) { - open_log(); - log_perror("Restart failed"); - close_log(); - } - - FOREACH_MOD(I_OnRestart, OnRestart()); - - exit(1); -} - -/*************************************************************************/ - -/* Terminates services */ - -static void services_shutdown() -{ - FOREACH_MOD(I_OnPreShutdown, OnPreShutdown()); - - if (!quitmsg) - quitmsg = "Terminating, reason unknown"; - Alog() << quitmsg; - if (started && UplinkSock) - { - /* Send a quit for all of our bots */ - for (botinfo_map::const_iterator it = BotList.begin(); it != BotList.end(); ++it) - { - /* Don't use quitmsg here, it may contain information you don't want people to see */ - ircdproto->SendQuit(it->second, "Shutting down"); - } - - ircdproto->SendSquit(Config.ServerName, quitmsg); - - while (!UserListByNick.empty()) - { - delete UserListByNick.begin()->second; - } - } - /* Process to send the last bits of information before disconnecting */ - socketEngine.Process(); - delete UplinkSock; - FOREACH_MOD(I_OnShutdown, OnShutdown()); - /* First don't unload protocol module, then do so */ - ModuleManager::UnloadAll(false); - ModuleManager::UnloadAll(true); - /* just in case they weren't all removed at least run once */ - ModuleRunTimeDirCleanUp(); -} - -/*************************************************************************/ - -/* If we get a weird signal, come here. */ - -void sighandler(int signum) -{ - /* We set the quit message to something default, just to be sure it is - * always set when we need it. It seems some signals slip through to the - * QUIT code without having a valid quitmsg. -GD - */ - if (!quitmsg) - quitmsg = "Services terminating via a signal."; - - if (started) - { -#ifndef _WIN32 - if (signum == SIGHUP) - { - Alog() << "Received SIGHUP: Saving Databases & Rehash Configuration"; - - expire_all(); - save_databases(); - - if (!read_config(1)) - { - quitmsg = "Error Reading Configuration File (Received SIGHUP)"; - quitting = 1; - } - - FOREACH_MOD(I_OnReload, OnReload(true)); - return; - - } else -#endif - if (signum == SIGTERM) - { - signal(SIGTERM, SIG_IGN); -#ifndef _WIN32 - signal(SIGHUP, SIG_IGN); -#endif - - Alog() << "Received SIGTERM, exiting."; - - expire_all(); - save_databases(); - quitmsg = "Shutting down on SIGTERM"; - services_shutdown(); - exit(0); - } - else if (signum == SIGINT) - { - if (nofork) - { - signal(SIGINT, SIG_IGN); - Alog() << "Received SIGINT, exiting."; - expire_all(); - save_databases(); - quitmsg = "Shutting down on SIGINT"; - services_shutdown(); - exit(0); - } - } - } - - - /* Should we send the signum here as well? -GD */ - FOREACH_MOD(I_OnSignal, OnSignal(quitmsg)); - - if (started) - { - services_shutdown(); - exit(0); - } - else - { - if (isatty(2)) - { - fprintf(stderr, "%s\n", quitmsg); - } - else - { - Alog() << quitmsg; - } - - exit(1); - } -} - -/*************************************************************************/ - -/** The following comes from InspIRCd to get the full path of the Anope executable - */ -std::string GetFullProgDir(char *argv0) -{ - char buffer[PATH_MAX]; -#ifdef _WIN32 - /* Windows has specific API calls to get the EXE path that never fail. - * For once, Windows has something of use, compared to the POSIX code - * for this, this is positively neato. - */ - if (GetModuleFileName(NULL, buffer, PATH_MAX)) - { - std::string fullpath = buffer; - std::string::size_type n = fullpath.rfind("\\" SERVICES_BIN); - services_bin = fullpath.substr(n + 1, fullpath.size()); - return std::string(fullpath, 0, n); - } -#else - // Get the current working directory - if (getcwd(buffer, PATH_MAX)) - { - std::string remainder = argv0; - - /* Does argv[0] start with /? If so, it's a full path, use it */ - if (remainder[0] == '/') - { - std::string::size_type n = remainder.rfind("/" SERVICES_BIN); - services_bin = remainder.substr(n + 1, remainder.size()); - return std::string(remainder, 0, n); - } - - services_bin = remainder; - if (services_bin.substr(0, 2) == "./") - services_bin = services_bin.substr(2); - std::string fullpath = std::string(buffer) + "/" + remainder; - std::string::size_type n = fullpath.rfind("/" SERVICES_BIN); - return std::string(fullpath, 0, n); - } -#endif - return "/"; -} - -/*************************************************************************/ - -static bool Connect() -{ - /* Connect to the remote server */ - int servernum = 1; - for (std::list<Uplink *>::iterator curr_uplink = Config.Uplinks.begin(); curr_uplink != Config.Uplinks.end(); ++curr_uplink, ++servernum) - { - uplink_server = *curr_uplink; - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreServerConnect, OnPreServerConnect(*curr_uplink, servernum)); - if (MOD_RESULT != EVENT_CONTINUE) - { - if (MOD_RESULT == EVENT_STOP) - break; - return true; - } - - try - { - new UplinkSocket(uplink_server->host, uplink_server->port, Config.LocalHost ? Config.LocalHost : "", uplink_server->ipv6); - } - catch (SocketException& ex) - { - Alog() << "Unable to connect to server" << servernum << " (" << uplink_server->host << ":" << uplink_server->port << "), " << ex.GetReason(); - continue; - } - - Alog() << "Connected to Server " << servernum << " (" << uplink_server->host << ":" << uplink_server->port << ")"; - return true; - } - - uplink_server = NULL; - - return false; -} - -/*************************************************************************/ - -/* Main routine. (What does it look like? :-) ) */ - -int main(int ac, char **av, char **envp) -{ - int i; - - my_av = av; - my_envp = envp; - - char cwd[PATH_MAX] = ""; -#ifdef _WIN32 - GetCurrentDirectory(PATH_MAX, cwd); -#else - getcwd(cwd, PATH_MAX); -#endif - orig_cwd = cwd; - -#ifndef _WIN32 - /* If we're root, issue a warning now */ - if ((getuid() == 0) && (getgid() == 0)) { - fprintf(stderr, - "WARNING: You are currently running Anope as the root superuser. Anope does not\n"); - fprintf(stderr, - " require root privileges to run, and it is discouraged that you run Anope\n"); - fprintf(stderr, " as the root superuser.\n"); - } -#endif - - binary_dir = GetFullProgDir(av[0]); - if (binary_dir[binary_dir.size() - 1] == '.') - binary_dir = binary_dir.substr(0, binary_dir.size() - 2); -#ifdef _WIN32 - std::string::size_type n = binary_dir.rfind("\\"); - services_dir = binary_dir.substr(0, n) + "\\data"; -#else - std::string::size_type n = binary_dir.rfind("/"); - services_dir = binary_dir.substr(0, n) + "/data"; -#endif - - /* Clean out the module runtime directory prior to running, just in case files were left behind during a previous run */ - ModuleRunTimeDirCleanUp(); - - /* General initialization first */ - if ((i = init_primary(ac, av)) != 0) - return i; - - Alog(LOG_TERMINAL) << "Anope " << version_number << ", " << version_build; -#ifdef _WIN32 - Alog(LOG_TERMINAL) << "Using configuration file " << services_dir << "\\" << services_conf; -#else - Alog(LOG_TERMINAL) << "Using configuration file " << services_dir << "/" << services_conf; -#endif - - /* Initialization stuff. */ - if ((i = init_secondary(ac, av)) != 0) - return i; - - /* If the first connect fails give up, don't sit endlessly trying to reconnect */ - if (!Connect()) - fatal_perror("Can't connect to any servers"); - - ircdproto->SendConnect(); - FOREACH_MOD(I_OnServerConnect, OnServerConnect()); - - started = 1; - -#ifndef _WIN32 - if (Config.DumpCore) - { - rlimit rl; - if (getrlimit(RLIMIT_CORE, &rl) == -1) - { - Alog() << "Failed to getrlimit()!"; - } - else - { - rl.rlim_cur = rl.rlim_max; - if (setrlimit(RLIMIT_CORE, &rl) == -1) - { - Alog() << "setrlimit() failed, cannot increase coredump size"; - } - } - } -#endif - - /* Set up timers */ - time_t last_check = time(NULL); - ExpireTimer expireTimer(Config.ExpireTimeout, last_check); - UpdateTimer updateTimer(Config.UpdateTimeout, last_check); - - /*** Main loop. ***/ - while (!quitting) - { - while (!quitting && UplinkSock) - { - time_t t = time(NULL); - - Alog(LOG_DEBUG_2) << "Top of main loop"; - - if (!readonly && (save_data || shutting_down)) - { - if (!noexpire) - expire_all(); - if (shutting_down) - ircdproto->SendGlobops(NULL, "Updating databases on shutdown, please wait."); - save_databases(); - save_data = 0; - } - - if (shutting_down) - { - quitting = 1; - break; - } - - if (t - last_check >= Config.TimeoutCheck) - { - TimerManager::TickTimers(t); - last_check = t; - } - - /* Process any modes that need to be (un)set */ - ModeManager::ProcessModes(); - - /* Process the socket engine */ - socketEngine.Process(); - } - - if (quitting) - { - /* Disconnect and exit */ - services_shutdown(); - } - else - { - FOREACH_MOD(I_OnServerDisconnect, OnServerDisconnect()); - - unsigned j = 0; - for (; j < (Config.MaxRetries ? Config.MaxRetries : j + 1); ++j) - { - Alog() << "Disconnected from the server, retrying in " << Config.RetryWait << " seconds"; - - sleep(Config.RetryWait); - if (Connect()) - { - ircdproto->SendConnect(); - FOREACH_MOD(I_OnServerConnect, OnServerConnect()); - break; - } - } - if (Config.MaxRetries && j == Config.MaxRetries) - { - Alog() << "Max connection retry limit exceeded"; - quitting = 1; - } - } - } - - return 0; -} - |
