]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modmanager_static.cpp
Replace printf(_c) with iostream
[user/henk/code/inspircd.git] / src / modmanager_static.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
5  *
6  * This file is part of InspIRCd.  InspIRCd is free software: you can
7  * redistribute it and/or modify it under the terms of the GNU General Public
8  * License as published by the Free Software Foundation, version 2.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
13  * details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19
20 #define MODNAME cmd_all
21
22 #include "inspircd.h"
23 #include "exitcodes.h"
24 #include <iostream>
25
26 #ifdef PURE_STATIC
27
28 typedef std::map<std::string, AllModuleList*> modmap;
29 static std::vector<AllCommandList::fn>* cmdlist = NULL;
30 static modmap* modlist = NULL;
31
32 AllCommandList::AllCommandList(fn cmd)
33 {
34         if (!cmdlist)
35                 cmdlist = new std::vector<AllCommandList::fn>();
36         cmdlist->push_back(cmd);
37 }
38
39 AllModuleList::AllModuleList(AllModuleList::fn mod, const std::string& Name) : init(mod), name(Name)
40 {
41         if (!modlist)
42                 modlist = new modmap();
43         modlist->insert(std::make_pair(Name, this));
44 }
45
46 class AllModule : public Module
47 {
48         std::vector<Command*> cmds;
49  public:
50         AllModule()
51         {
52                 if (!cmdlist)
53                         return;
54                 try
55                 {
56                         cmds.reserve(cmdlist->size());
57                         for(std::vector<AllCommandList::fn>::iterator i = cmdlist->begin(); i != cmdlist->end(); ++i)
58                         {
59                                 Command* c = (*i)(this);
60                                 cmds.push_back(c);
61                                 ServerInstance->AddCommand(c);
62                         }
63                 }
64                 catch (...)
65                 {
66                         this->AllModule::~AllModule();
67                         throw;
68                 }
69         }
70
71         ~AllModule()
72         {
73                 for(std::vector<Command*>::iterator i = cmds.begin(); i != cmds.end(); ++i)
74                         delete *i;
75         }
76
77         Version GetVersion()
78         {
79                 return Version("All commands", VF_VENDOR|VF_CORE);
80         }
81 };
82
83 MODULE_INIT(AllModule)
84
85 bool ModuleManager::Load(const std::string& name, bool defer)
86 {
87         modmap::iterator it = modlist->find(name);
88         if (it == modlist->end())
89                 return false;
90         Module* mod = NULL;
91         try
92         {
93                 mod = (*it->second->init)();
94                 mod->ModuleSourceFile = name;
95                 mod->ModuleDLLManager = NULL;
96                 Modules[name] = mod;
97                 if (defer)
98                 {
99                         ServerInstance->Logs->Log("MODULE", DEFAULT,"New module introduced: %s", name.c_str());
100                         return true;
101                 }
102                 else
103                 {
104                         mod->init();
105                 }
106         }
107         catch (CoreException& modexcept)
108         {
109                 if (mod)
110                         DoSafeUnload(mod);
111                 ServerInstance->Logs->Log("MODULE", DEFAULT, "Unable to load " + name + ": " + modexcept.GetReason());
112                 return false;
113         }
114         FOREACH_MOD(I_OnLoadModule,OnLoadModule(mod));
115         /* We give every module a chance to re-prioritize when we introduce a new one,
116          * not just the one thats loading, as the new module could affect the preference
117          * of others
118          */
119         for(int tries = 0; tries < 20; tries++)
120         {
121                 prioritizationState = tries > 0 ? PRIO_STATE_LAST : PRIO_STATE_FIRST;
122                 for (std::map<std::string, Module*>::iterator n = Modules.begin(); n != Modules.end(); ++n)
123                         n->second->Prioritize();
124
125                 if (prioritizationState == PRIO_STATE_LAST)
126                         break;
127                 if (tries == 19)
128                         ServerInstance->Logs->Log("MODULE", DEFAULT, "Hook priority dependency loop detected while loading " + name);
129         }
130
131         ServerInstance->BuildISupport();
132         return true;
133 }
134
135 namespace {
136         struct UnloadAction : public HandlerBase0<void>
137         {
138                 Module* const mod;
139                 UnloadAction(Module* m) : mod(m) {}
140                 void Call()
141                 {
142                         ServerInstance->Modules->DoSafeUnload(mod);
143                         ServerInstance->GlobalCulls.Apply();
144                         ServerInstance->GlobalCulls.AddItem(this);
145                 }
146         };
147
148         struct ReloadAction : public HandlerBase0<void>
149         {
150                 Module* const mod;
151                 HandlerBase1<void, bool>* const callback;
152                 ReloadAction(Module* m, HandlerBase1<void, bool>* c)
153                         : mod(m), callback(c) {}
154                 void Call()
155                 {
156                         std::string name = mod->ModuleSourceFile;
157                         ServerInstance->Modules->DoSafeUnload(mod);
158                         ServerInstance->GlobalCulls.Apply();
159                         bool rv = ServerInstance->Modules->Load(name.c_str());
160                         callback->Call(rv);
161                         ServerInstance->GlobalCulls.AddItem(this);
162                 }
163         };
164 }
165
166 bool ModuleManager::Unload(Module* mod)
167 {
168         if (!CanUnload(mod))
169                 return false;
170         ServerInstance->AtomicActions.AddAction(new UnloadAction(mod));
171         return true;
172 }
173
174 void ModuleManager::Reload(Module* mod, HandlerBase1<void, bool>* callback)
175 {
176         if (CanUnload(mod))
177                 ServerInstance->AtomicActions.AddAction(new ReloadAction(mod, callback));
178         else
179                 callback->Call(false);
180 }
181
182 void ModuleManager::LoadAll()
183 {
184         Load("cmd_all", true);
185         Load("cmd_whowas.so", true);
186
187         ConfigTagList tags = ServerInstance->Config->ConfTags("module");
188         for(ConfigIter i = tags.first; i != tags.second; ++i)
189         {
190                 ConfigTag* tag = i->second;
191                 std::string name = tag->getString("name");
192                 std::cout << "[" << con_green << "*" << con_reset << "] Loading module:\t" << con_green << name << con_reset << std::endl;
193
194                 if (!this->Load(name, true))
195                 {
196                         ServerInstance->Logs->Log("MODULE", DEFAULT, this->LastError());
197                         std::cout << std::endl << "[" << con_red << "*" << con_reset << "]" << this->LastError() << std::endl << std::endl;
198                         ServerInstance->Exit(EXIT_STATUS_MODULE);
199                 }
200         }
201
202         for(std::map<std::string, Module*>::iterator i = Modules.begin(); i != Modules.end(); i++)
203         {
204                 Module* mod = i->second;
205                 try 
206                 {
207                         mod->init();
208                 }
209                 catch (CoreException& modexcept)
210                 {
211                         LastModuleError = "Unable to initialize " + mod->ModuleSourceFile + ": " + modexcept.GetReason();
212                         ServerInstance->Logs->Log("MODULE", DEFAULT, LastModuleError);
213                         std::cout << std::endl << "[" << con_red << "*" << con_reset << "]" << LastModuleError << std::endl << std::endl;
214                         ServerInstance->Exit(EXIT_STATUS_MODULE);
215                 }
216         }
217
218         /* We give every module a chance to re-prioritize when we introduce a new one,
219          * not just the one thats loading, as the new module could affect the preference
220          * of others
221          */
222         for(int tries = 0; tries < 20; tries++)
223         {
224                 prioritizationState = tries > 0 ? PRIO_STATE_LAST : PRIO_STATE_FIRST;
225                 for (std::map<std::string, Module*>::iterator n = Modules.begin(); n != Modules.end(); ++n)
226                         n->second->Prioritize();
227
228                 if (prioritizationState == PRIO_STATE_LAST)
229                         break;
230                 if (tries == 19)
231                 {
232                         ServerInstance->Logs->Log("MODULE", DEFAULT, "Hook priority dependency loop detected");
233                         ServerInstance->Exit(EXIT_STATUS_MODULE);
234                 }
235         }
236 }
237
238 #endif