Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "services.h"
00014 #include "timers.h"
00015 #include "config.h"
00016 #include "bots.h"
00017 #include "socketengine.h"
00018 #include "uplink.h"
00019
00020 #ifndef _WIN32
00021 #include <limits.h>
00022 #else
00023 #include <process.h>
00024 #endif
00025
00026
00027 int Anope::Debug = 0;
00028 bool Anope::ReadOnly = false, Anope::NoFork = false, Anope::NoThird = false, Anope::NoExpire = false, Anope::ProtocolDebug = false;
00029 Anope::string Anope::ServicesDir;
00030 Anope::string Anope::ServicesBin;
00031
00032 int Anope::ReturnValue = 0;
00033 sig_atomic_t Anope::Signal = 0;
00034 bool Anope::Quitting = false;
00035 bool Anope::Restarting = false;
00036 Anope::string Anope::QuitReason;
00037
00038 static Anope::string BinaryDir;
00039
00040 time_t Anope::StartTime = time(NULL);
00041 time_t Anope::CurTime = time(NULL);
00042
00043 int Anope::CurrentUplink = -1;
00044
00045 class UpdateTimer : public Timer
00046 {
00047 public:
00048 UpdateTimer(time_t timeout) : Timer(timeout, Anope::CurTime, true) { }
00049
00050 void Tick(time_t)
00051 {
00052 Anope::SaveDatabases();
00053 }
00054 };
00055
00056 void Anope::SaveDatabases()
00057 {
00058 if (Anope::ReadOnly)
00059 return;
00060
00061 EventReturn MOD_RESULT;
00062 FOREACH_RESULT(I_OnSaveDatabase, OnSaveDatabase());
00063 Log(LOG_DEBUG) << "Saving databases";
00064 }
00065
00068 static Anope::string GetFullProgDir(const Anope::string &argv0)
00069 {
00070 char buffer[PATH_MAX];
00071 #ifdef _WIN32
00072
00073
00074
00075
00076 if (GetModuleFileName(NULL, buffer, PATH_MAX))
00077 {
00078 Anope::string fullpath = buffer;
00079 Anope::string::size_type n = fullpath.rfind("\\");
00080 Anope::ServicesBin = fullpath.substr(n + 1, fullpath.length());
00081 return fullpath.substr(0, n);
00082 }
00083 #else
00084
00085 if (getcwd(buffer, PATH_MAX))
00086 {
00087 Anope::string remainder = argv0;
00088
00089 Anope::ServicesBin = remainder;
00090 Anope::string::size_type n = Anope::ServicesBin.rfind("/");
00091 Anope::string fullpath;
00092 if (Anope::ServicesBin[0] == '/')
00093 fullpath = Anope::ServicesBin.substr(0, n);
00094 else
00095 fullpath = Anope::string(buffer) + "/" + Anope::ServicesBin.substr(0, n);
00096 Anope::ServicesBin = Anope::ServicesBin.substr(n + 1, remainder.length());
00097 return fullpath;
00098 }
00099 #endif
00100 return "/";
00101 }
00102
00103
00104
00105
00106
00107 int main(int ac, char **av, char **envp)
00108 {
00109 BinaryDir = GetFullProgDir(av[0]);
00110 if (BinaryDir[BinaryDir.length() - 1] == '.')
00111 BinaryDir = BinaryDir.substr(0, BinaryDir.length() - 2);
00112
00113 #ifdef _WIN32
00114 Anope::string::size_type n = BinaryDir.rfind('\\');
00115 #else
00116 Anope::string::size_type n = BinaryDir.rfind('/');
00117 #endif
00118 Anope::ServicesDir = BinaryDir.substr(0, n);
00119
00120
00121 ModuleManager::CleanupRuntimeDirectory();
00122
00123 #ifdef _WIN32
00124 OnStartup();
00125 #endif
00126
00127 try
00128 {
00129
00130 Anope::Init(ac, av);
00131 }
00132 catch (const CoreException &ex)
00133 {
00134 Log() << ex.GetReason();
00135 return -1;
00136 }
00137
00138 try
00139 {
00140 Uplink::Connect();
00141 }
00142 catch (const SocketException &ex)
00143 {
00144 Log(LOG_TERMINAL) << "Unable to connect to uplink #" << Anope::CurrentUplink << " (" << Config->Uplinks[Anope::CurrentUplink]->host << ":" << Config->Uplinks[Anope::CurrentUplink]->port << "): " << ex.GetReason();
00145 }
00146
00147
00148 time_t last_check = Anope::CurTime;
00149 UpdateTimer updateTimer(Config->UpdateTimeout);
00150
00151
00152 while (!Anope::Quitting)
00153 {
00154 Log(LOG_DEBUG_2) << "Top of main loop";
00155
00156
00157 if (Anope::CurTime - last_check >= Config->TimeoutCheck)
00158 {
00159 TimerManager::TickTimers(Anope::CurTime);
00160 last_check = Anope::CurTime;
00161 }
00162
00163
00164 SocketEngine::Process();
00165
00166 if (Anope::Signal)
00167 Anope::HandleSignal();
00168 }
00169
00170 if (Anope::Restarting)
00171 {
00172 FOREACH_MOD(I_OnRestart, OnRestart());
00173 }
00174 else
00175 {
00176 FOREACH_MOD(I_OnShutdown, OnShutdown());
00177 }
00178
00179 if (Anope::QuitReason.empty())
00180 Anope::QuitReason = "Terminating, reason unknown";
00181 Log() << Anope::QuitReason;
00182
00183 delete UplinkSock;
00184
00185 ModuleManager::UnloadAll();
00186 SocketEngine::Shutdown();
00187 for (Module *m; (m = ModuleManager::FindFirstOf(PROTOCOL)) != NULL;)
00188 ModuleManager::UnloadModule(m, NULL);
00189
00190 ModuleManager::CleanupRuntimeDirectory();
00191
00192 #ifdef _WIN32
00193 OnShutdown();
00194 #endif
00195
00196 if (Anope::Restarting)
00197 {
00198 chdir(BinaryDir.c_str());
00199 Anope::string sbin = "./" + Anope::ServicesBin;
00200 av[0] = const_cast<char *>(sbin.c_str());
00201 execve(Anope::ServicesBin.c_str(), av, envp);
00202 Log() << "Restart failed";
00203 Anope::ReturnValue = -1;
00204 }
00205
00206 return Anope::ReturnValue;
00207 }