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