anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
main.cpp (5295B)
1 /* Services -- main source file. 2 * 3 * (C) 2003-2022 Anope Team 4 * Contact us at team@anope.org 5 * 6 * Please read COPYING and README for further details. 7 * 8 * Based on the original code of Epona by Lara. 9 * Based on the original code of Services by Andy Church. 10 */ 11 12 #include "services.h" 13 #include "timers.h" 14 #include "config.h" 15 #include "bots.h" 16 #include "socketengine.h" 17 #include "uplink.h" 18 19 #ifndef _WIN32 20 #include <limits.h> 21 #else 22 #include <process.h> 23 #endif 24 25 /* Command-line options: */ 26 int Anope::Debug = 0; 27 bool Anope::ReadOnly = false, Anope::NoFork = false, Anope::NoThird = false, Anope::NoExpire = false, Anope::ProtocolDebug = false; 28 Anope::string Anope::ServicesDir; 29 Anope::string Anope::ServicesBin; 30 31 int Anope::ReturnValue = 0; 32 sig_atomic_t Anope::Signal = 0; 33 bool Anope::Quitting = false; 34 bool Anope::Restarting = false; 35 Anope::string Anope::QuitReason; 36 37 static Anope::string BinaryDir; /* Full path to services bin directory */ 38 39 time_t Anope::StartTime = time(NULL); 40 time_t Anope::CurTime = time(NULL); 41 42 int Anope::CurrentUplink = -1; 43 44 class UpdateTimer : public Timer 45 { 46 public: 47 UpdateTimer(time_t timeout) : Timer(timeout, Anope::CurTime, true) { } 48 49 void Tick(time_t) anope_override 50 { 51 Anope::SaveDatabases(); 52 } 53 }; 54 55 class ExpireTimer : public Timer 56 { 57 public: 58 ExpireTimer(time_t timeout) : Timer(timeout, Anope::CurTime, true) { } 59 60 void Tick(time_t) anope_override 61 { 62 FOREACH_MOD(OnExpireTick, ()); 63 } 64 }; 65 66 void Anope::SaveDatabases() 67 { 68 if (Anope::ReadOnly) 69 return; 70 71 Log(LOG_DEBUG) << "Saving databases"; 72 FOREACH_MOD(OnSaveDatabase, ()); 73 } 74 75 /** The following comes from InspIRCd to get the full path of the Anope executable 76 */ 77 static Anope::string GetFullProgDir(const Anope::string &argv0) 78 { 79 char buffer[PATH_MAX]; 80 #ifdef _WIN32 81 /* Windows has specific API calls to get the EXE path that never fail. 82 * For once, Windows has something of use, compared to the POSIX code 83 * for this, this is positively neato. 84 */ 85 if (GetModuleFileName(NULL, buffer, PATH_MAX)) 86 { 87 Anope::string fullpath = buffer; 88 Anope::string::size_type n = fullpath.rfind("\\"); 89 Anope::ServicesBin = fullpath.substr(n + 1, fullpath.length()); 90 return fullpath.substr(0, n); 91 } 92 #else 93 // Get the current working directory 94 if (getcwd(buffer, PATH_MAX)) 95 { 96 Anope::string remainder = argv0; 97 98 Anope::ServicesBin = remainder; 99 Anope::string::size_type n = Anope::ServicesBin.rfind("/"); 100 Anope::string fullpath; 101 if (Anope::ServicesBin[0] == '/') 102 fullpath = Anope::ServicesBin.substr(0, n); 103 else 104 fullpath = Anope::string(buffer) + "/" + Anope::ServicesBin.substr(0, n); 105 Anope::ServicesBin = Anope::ServicesBin.substr(n + 1, remainder.length()); 106 return fullpath; 107 } 108 #endif 109 return "/"; 110 } 111 112 /* Main routine. (What does it look like? :-) ) */ 113 114 int main(int ac, char **av, char **envp) 115 { 116 /* String comparisons won't work until we build the case map cache, so do it first */ 117 Anope::CaseMapRebuild(); 118 119 BinaryDir = GetFullProgDir(av[0]); 120 if (BinaryDir[BinaryDir.length() - 1] == '.') 121 BinaryDir = BinaryDir.substr(0, BinaryDir.length() - 2); 122 123 #ifdef _WIN32 124 Anope::string::size_type n = BinaryDir.rfind('\\'); 125 #else 126 Anope::string::size_type n = BinaryDir.rfind('/'); 127 #endif 128 Anope::ServicesDir = BinaryDir.substr(0, n); 129 130 #ifdef _WIN32 131 /* Clean out the module runtime directory prior to running, just in case files were left behind during a previous run */ 132 ModuleManager::CleanupRuntimeDirectory(); 133 134 OnStartup(); 135 #endif 136 137 try 138 { 139 /* General initialization first */ 140 Anope::Init(ac, av); 141 } 142 catch (const CoreException &ex) 143 { 144 Log() << ex.GetReason(); 145 return -1; 146 } 147 148 try 149 { 150 Uplink::Connect(); 151 } 152 catch (const SocketException &ex) 153 { 154 Log(LOG_TERMINAL) << "Unable to connect to uplink #" << (Anope::CurrentUplink + 1) << " (" << Config->Uplinks[Anope::CurrentUplink].host << ":" << Config->Uplinks[Anope::CurrentUplink].port << "): " << ex.GetReason(); 155 } 156 157 /* Set up timers */ 158 time_t last_check = Anope::CurTime; 159 UpdateTimer updateTimer(Config->GetBlock("options")->Get<time_t>("updatetimeout", "5m")); 160 ExpireTimer expireTimer(Config->GetBlock("options")->Get<time_t>("expiretimeout", "30m")); 161 162 /*** Main loop. ***/ 163 while (!Anope::Quitting) 164 { 165 Log(LOG_DEBUG_2) << "Top of main loop"; 166 167 /* Process timers */ 168 if (Anope::CurTime - last_check >= Config->TimeoutCheck) 169 { 170 TimerManager::TickTimers(Anope::CurTime); 171 last_check = Anope::CurTime; 172 } 173 174 /* Process the socket engine */ 175 SocketEngine::Process(); 176 177 if (Anope::Signal) 178 Anope::HandleSignal(); 179 } 180 181 if (Anope::Restarting) 182 { 183 FOREACH_MOD(OnRestart, ()); 184 } 185 else 186 { 187 FOREACH_MOD(OnShutdown, ()); 188 } 189 190 if (Anope::QuitReason.empty()) 191 Anope::QuitReason = "Terminating, reason unknown"; 192 Log() << Anope::QuitReason; 193 194 delete UplinkSock; 195 196 ModuleManager::UnloadAll(); 197 SocketEngine::Shutdown(); 198 for (Module *m; (m = ModuleManager::FindFirstOf(PROTOCOL)) != NULL;) 199 ModuleManager::UnloadModule(m, NULL); 200 201 #ifdef _WIN32 202 ModuleManager::CleanupRuntimeDirectory(); 203 204 OnShutdown(); 205 #endif 206 207 if (Anope::Restarting) 208 { 209 chdir(BinaryDir.c_str()); 210 Anope::string sbin = "./" + Anope::ServicesBin; 211 av[0] = const_cast<char *>(sbin.c_str()); 212 execve(Anope::ServicesBin.c_str(), av, envp); 213 Log() << "Restart failed"; 214 Anope::ReturnValue = -1; 215 } 216 217 return Anope::ReturnValue; 218 }