00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "inspircd.h"
00017 #include "xline.h"
00018 #include "socket.h"
00019 #include "socketengine.h"
00020 #include "command_parse.h"
00021 #include "dns.h"
00022 #include "exitcodes.h"
00023
00024 #ifndef WIN32
00025 #include <dirent.h>
00026 #endif
00027
00028
00029 Version::Version(const std::string &sversion, int flags, int api_ver)
00030 : version(sversion), Flags(flags), API(api_ver)
00031 {
00032 }
00033
00034 Request::Request(char* anydata, Module* src, Module* dst)
00035 : data(anydata), source(src), dest(dst)
00036 {
00037
00038
00039
00040 id = '\0';
00041 }
00042
00043 Request::Request(Module* src, Module* dst, const char* idstr)
00044 : id(idstr), source(src), dest(dst)
00045 {
00046 }
00047
00048 char* Request::GetData()
00049 {
00050 return this->data;
00051 }
00052
00053 const char* Request::GetId()
00054 {
00055 return this->id;
00056 }
00057
00058 Module* Request::GetSource()
00059 {
00060 return this->source;
00061 }
00062
00063 Module* Request::GetDest()
00064 {
00065 return this->dest;
00066 }
00067
00068 const char* Request::Send()
00069 {
00070 if (this->dest)
00071 {
00072 return dest->OnRequest(this);
00073 }
00074 else
00075 {
00076 return NULL;
00077 }
00078 }
00079
00080 Event::Event(char* anydata, Module* src, const std::string &eventid) : data(anydata), source(src), id(eventid) { }
00081
00082 char* Event::GetData()
00083 {
00084 return (char*)this->data;
00085 }
00086
00087 Module* Event::GetSource()
00088 {
00089 return this->source;
00090 }
00091
00092 char* Event::Send(InspIRCd* ServerInstance)
00093 {
00094 FOREACH_MOD(I_OnEvent,OnEvent(this));
00095 return NULL;
00096 }
00097
00098 std::string Event::GetEventID()
00099 {
00100 return this->id;
00101 }
00102
00103
00104
00105
00106 Module::Module(InspIRCd* Me) : ServerInstance(Me) { }
00107 Module::~Module() { }
00108
00109 int Module::OnSendSnotice(char &snomask, std::string &type, const std::string &message) { return 0; }
00110 void Module::OnUserConnect(User*) { }
00111 void Module::OnUserQuit(User*, const std::string&, const std::string&) { }
00112 void Module::OnUserDisconnect(User*) { }
00113 void Module::OnUserJoin(User*, Channel*, bool, bool&) { }
00114 void Module::OnPostJoin(User*, Channel*) { }
00115 void Module::OnUserPart(User*, Channel*, std::string&, bool&) { }
00116 void Module::OnRehash(User*, const std::string&) { }
00117 void Module::OnServerRaw(std::string&, bool, User*) { }
00118 int Module::OnUserPreJoin(User*, Channel*, const char*, std::string&, const std::string&) { return 0; }
00119 void Module::OnMode(User*, void*, int, const std::string&) { }
00120 Version Module::GetVersion() { return Version("Misconfigured", VF_VENDOR, -1); }
00121 void Module::OnOper(User*, const std::string&) { }
00122 void Module::OnPostOper(User*, const std::string&, const std::string &) { }
00123 void Module::OnInfo(User*) { }
00124 void Module::OnWhois(User*, User*) { }
00125 int Module::OnUserPreInvite(User*, User*, Channel*, time_t) { return 0; }
00126 int Module::OnUserPreMessage(User*, void*, int, std::string&, char, CUList&) { return 0; }
00127 int Module::OnUserPreNotice(User*, void*, int, std::string&, char, CUList&) { return 0; }
00128 int Module::OnUserPreNick(User*, const std::string&) { return 0; }
00129 void Module::OnUserPostNick(User*, const std::string&) { }
00130 int Module::OnAccessCheck(User*, User*, Channel*, int) { return ACR_DEFAULT; }
00131 void Module::On005Numeric(std::string&) { }
00132 int Module::OnKill(User*, User*, const std::string&) { return 0; }
00133 void Module::OnLoadModule(Module*, const std::string&) { }
00134 void Module::OnUnloadModule(Module*, const std::string&) { }
00135 void Module::OnBackgroundTimer(time_t) { }
00136 int Module::OnPreCommand(std::string&, std::vector<std::string>&, User *, bool, const std::string&) { return 0; }
00137 void Module::OnPostCommand(const std::string&, const std::vector<std::string>&, User *, CmdResult, const std::string&) { }
00138 bool Module::OnCheckReady(User*) { return true; }
00139 int Module::OnUserRegister(User*) { return 0; }
00140 int Module::OnUserPreKick(User*, User*, Channel*, const std::string&) { return 0; }
00141 void Module::OnUserKick(User*, User*, Channel*, const std::string&, bool&) { }
00142 int Module::OnRawMode(User*, Channel*, const char, const std::string &, bool, int, bool) { return 0; }
00143 int Module::OnCheckInvite(User*, Channel*) { return 0; }
00144 int Module::OnCheckKey(User*, Channel*, const std::string&) { return 0; }
00145 int Module::OnCheckLimit(User*, Channel*) { return 0; }
00146 int Module::OnCheckBan(User*, Channel*) { return 0; }
00147 int Module::OnCheckExtBan(User *, Channel *, char) { return 0; }
00148 int Module::OnCheckStringExtBan(const std::string &s, Channel *c, char type) { return 0; }
00149 int Module::OnStats(char, User*, string_list&) { return 0; }
00150 int Module::OnChangeLocalUserHost(User*, const std::string&) { return 0; }
00151 int Module::OnChangeLocalUserGECOS(User*, const std::string&) { return 0; }
00152 int Module::OnLocalTopicChange(User*, Channel*, const std::string&) { return 0; }
00153 void Module::OnEvent(Event*) { return; }
00154 const char* Module::OnRequest(Request*) { return NULL; }
00155 int Module::OnPassCompare(Extensible* ex, const std::string &password, const std::string &input, const std::string& hashtype) { return 0; }
00156 void Module::OnGlobalOper(User*) { }
00157 void Module::OnPostConnect(User*) { }
00158 int Module::OnAddBan(User*, Channel*, const std::string &) { return 0; }
00159 int Module::OnDelBan(User*, Channel*, const std::string &) { return 0; }
00160 void Module::OnRawSocketAccept(int, const std::string&, int) { }
00161 int Module::OnRawSocketWrite(int, const char*, int) { return 0; }
00162 void Module::OnRawSocketClose(int) { }
00163 void Module::OnRawSocketConnect(int) { }
00164 int Module::OnRawSocketRead(int, char*, unsigned int, int&) { return 0; }
00165 void Module::OnUserMessage(User*, void*, int, const std::string&, char, const CUList&) { }
00166 void Module::OnUserNotice(User*, void*, int, const std::string&, char, const CUList&) { }
00167 void Module::OnRemoteKill(User*, User*, const std::string&, const std::string&) { }
00168 void Module::OnUserInvite(User*, User*, Channel*, time_t) { }
00169 void Module::OnPostLocalTopicChange(User*, Channel*, const std::string&) { }
00170 void Module::OnGetServerDescription(const std::string&, std::string&) { }
00171 void Module::OnSyncUser(User*, Module*, void*) { }
00172 void Module::OnSyncChannel(Channel*, Module*, void*) { }
00173 void Module::ProtoSendMode(void*, int, void*, const std::string&) { }
00174 void Module::OnSyncChannelMetaData(Channel*, Module*, void*, const std::string&, bool) { }
00175 void Module::OnSyncUserMetaData(User*, Module*, void*, const std::string&, bool) { }
00176 void Module::OnSyncOtherMetaData(Module*, void*, bool) { }
00177 void Module::OnDecodeMetaData(int, void*, const std::string&, const std::string&) { }
00178 void Module::ProtoSendMetaData(void*, int, void*, const std::string&, const std::string&) { }
00179 void Module::OnWallops(User*, const std::string&) { }
00180 void Module::OnChangeHost(User*, const std::string&) { }
00181 void Module::OnChangeName(User*, const std::string&) { }
00182 void Module::OnAddLine(User*, XLine*) { }
00183 void Module::OnDelLine(User*, XLine*) { }
00184 void Module::OnExpireLine(XLine*) { }
00185 void Module::OnCleanup(int, void*) { }
00186 int Module::OnChannelPreDelete(Channel*) { return 0; }
00187 void Module::OnChannelDelete(Channel*) { }
00188 int Module::OnSetAway(User*, const std::string &) { return 0; }
00189 int Module::OnUserList(User*, Channel*, CUList*&) { return 0; }
00190 int Module::OnWhoisLine(User*, User*, int&, std::string&) { return 0; }
00191 void Module::OnBuildExemptList(MessageType, Channel*, User*, char, CUList&, const std::string&) { }
00192 void Module::OnGarbageCollect() { }
00193 void Module::OnBufferFlushed(User*) { }
00194 void Module::OnText(User*, void*, int, const std::string&, char, CUList&) { }
00195 void Module::OnRunTestSuite() { }
00196 void Module::OnNamesListItem(User*, User*, Channel*, std::string&, std::string&) { }
00197 int Module::OnNumeric(User*, unsigned int, const std::string&) { return 0; }
00198 void Module::OnHookUserIO(User*, const std::string&) { }
00199 bool Module::OnHostCycle(User* user) { return false; }
00200
00201 ModuleManager::ModuleManager(InspIRCd* Ins) : ModCount(0), Instance(Ins)
00202 {
00203 }
00204
00205 ModuleManager::~ModuleManager()
00206 {
00207 }
00208
00209 bool ModuleManager::Attach(Implementation i, Module* mod)
00210 {
00211 if (std::find(EventHandlers[i].begin(), EventHandlers[i].end(), mod) != EventHandlers[i].end())
00212 return false;
00213
00214 EventHandlers[i].push_back(mod);
00215 return true;
00216 }
00217
00218 bool ModuleManager::Detach(Implementation i, Module* mod)
00219 {
00220 EventHandlerIter x = std::find(EventHandlers[i].begin(), EventHandlers[i].end(), mod);
00221
00222 if (x == EventHandlers[i].end())
00223 return false;
00224
00225 EventHandlers[i].erase(x);
00226 return true;
00227 }
00228
00229 void ModuleManager::Attach(Implementation* i, Module* mod, size_t sz)
00230 {
00231 for (size_t n = 0; n < sz; ++n)
00232 Attach(i[n], mod);
00233 }
00234
00235 void ModuleManager::DetachAll(Module* mod)
00236 {
00237 for (size_t n = I_BEGIN + 1; n != I_END; ++n)
00238 Detach((Implementation)n, mod);
00239 }
00240
00241 bool ModuleManager::SetPriority(Module* mod, PriorityState s)
00242 {
00243 for (size_t n = I_BEGIN + 1; n != I_END; ++n)
00244 SetPriority(mod, (Implementation)n, s);
00245
00246 return true;
00247 }
00248
00249 bool ModuleManager::SetPriority(Module* mod, Implementation i, PriorityState s, Module** modules, size_t sz)
00250 {
00257 size_t swap_pos = 0;
00258 size_t source = 0;
00259 bool swap = true;
00260 bool found = false;
00261
00262
00263
00264
00265 for (size_t x = 0; x != EventHandlers[i].size(); ++x)
00266 {
00267 if (EventHandlers[i][x] == mod)
00268 {
00269 source = x;
00270 found = true;
00271 break;
00272 }
00273 }
00274
00275
00276
00277
00278 if (!found)
00279 return false;
00280
00281 switch (s)
00282 {
00283
00284 case PRIO_DONTCARE:
00285 swap = false;
00286 break;
00287
00288 case PRIO_FIRST:
00289 swap_pos = 0;
00290 break;
00291
00292 case PRIO_LAST:
00293 if (EventHandlers[i].empty())
00294 swap_pos = 0;
00295 else
00296 swap_pos = EventHandlers[i].size() - 1;
00297 break;
00298
00299 case PRIO_AFTER:
00300 {
00301
00302 swap_pos = 0;
00303 swap = false;
00304 for (size_t x = 0; x != EventHandlers[i].size(); ++x)
00305 {
00306 for (size_t n = 0; n < sz; ++n)
00307 {
00308 if ((modules[n]) && (EventHandlers[i][x] == modules[n]) && (x >= swap_pos) && (source <= swap_pos))
00309 {
00310 swap_pos = x;
00311 swap = true;
00312 }
00313 }
00314 }
00315 }
00316 break;
00317
00318 case PRIO_BEFORE:
00319 {
00320 swap_pos = EventHandlers[i].size() - 1;
00321 swap = false;
00322 for (size_t x = 0; x != EventHandlers[i].size(); ++x)
00323 {
00324 for (size_t n = 0; n < sz; ++n)
00325 {
00326 if ((modules[n]) && (EventHandlers[i][x] == modules[n]) && (x <= swap_pos) && (source >= swap_pos))
00327 {
00328 swap = true;
00329 swap_pos = x;
00330 }
00331 }
00332 }
00333 }
00334 break;
00335 }
00336
00337
00338 if (swap && (swap_pos != source))
00339 {
00340
00341 int incrmnt = 1;
00342
00343 if (source > swap_pos)
00344 incrmnt = -1;
00345
00346 for (unsigned int j = source; j != swap_pos; j += incrmnt)
00347 {
00348 if (( j + incrmnt > EventHandlers[i].size() - 1) || (j + incrmnt < 0))
00349 continue;
00350
00351 std::swap(EventHandlers[i][j], EventHandlers[i][j+incrmnt]);
00352 }
00353 }
00354
00355 return true;
00356 }
00357
00358 std::string& ModuleManager::LastError()
00359 {
00360 return LastModuleError;
00361 }
00362
00363 bool ModuleManager::Load(const char* filename)
00364 {
00365
00366
00367
00368
00369 if (strchr(filename,'*') || (strchr(filename,'?')))
00370 {
00371 int n_match = 0;
00372 DIR* library = opendir(Instance->Config->ModPath);
00373 if (library)
00374 {
00375
00376 dirent* entry = NULL;
00377 while (0 != (entry = readdir(library)))
00378 {
00379 if (InspIRCd::Match(entry->d_name, filename, NULL))
00380 {
00381 if (!this->Load(entry->d_name))
00382 n_match++;
00383 }
00384 }
00385 closedir(library);
00386 }
00387
00388
00389
00390
00391 return (n_match > 0);
00392 }
00393
00394 char modfile[MAXBUF];
00395 snprintf(modfile,MAXBUF,"%s/%s",Instance->Config->ModPath,filename);
00396 std::string filename_str = filename;
00397
00398 if (!ServerConfig::DirValid(modfile))
00399 {
00400 LastModuleError = "Module " + std::string(filename) + " is not in the module directory that i am configured to look in (is "+Instance->Config->ModPath+" really a symlink?)";
00401 Instance->Logs->Log("MODULE", DEFAULT, LastModuleError);
00402 return false;
00403 }
00404
00405 if (!ServerConfig::FileExists(modfile))
00406 {
00407 LastModuleError = "Module file could not be found: " + filename_str;
00408 Instance->Logs->Log("MODULE", DEFAULT, LastModuleError);
00409 return false;
00410 }
00411
00412 if (Modules.find(filename_str) != Modules.end())
00413 {
00414 LastModuleError = "Module " + filename_str + " is already loaded, cannot load a module twice!";
00415 Instance->Logs->Log("MODULE", DEFAULT, LastModuleError);
00416 return false;
00417 }
00418
00419 Module* newmod = NULL;
00420 ircd_module* newhandle = NULL;
00421
00422 try
00423 {
00424
00425
00426
00427 newhandle = new ircd_module(Instance, modfile, "init_module");
00428 newmod = newhandle->CallInit();
00429
00430 if (newmod)
00431 {
00432 Version v = newmod->GetVersion();
00433
00434 if (v.API != API_VERSION)
00435 {
00436 DetachAll(newmod);
00437 delete newmod;
00438 delete newhandle;
00439 LastModuleError = "Unable to load " + filename_str + ": Incorrect module API version: " + ConvToStr(v.API) + " (our version: " + ConvToStr(API_VERSION) + ")";
00440 Instance->Logs->Log("MODULE", DEFAULT, LastModuleError);
00441 return false;
00442 }
00443 else
00444 {
00445 Instance->Logs->Log("MODULE", DEFAULT,"New module introduced: %s (API version %d, Module version %s)%s", filename, v.API, v.version.c_str(), (!(v.Flags & VF_VENDOR) ? " [3rd Party]" : " [Vendor]"));
00446 }
00447
00448 Modules[filename_str] = std::make_pair(newhandle, newmod);
00449 }
00450 else
00451 {
00452 delete newhandle;
00453 LastModuleError = "Unable to load " + filename_str + ": Probably missing init_module() entrypoint, but dlsym() didn't notice a problem";
00454 Instance->Logs->Log("MODULE", DEFAULT, LastModuleError);
00455 return false;
00456 }
00457 }
00459 catch (LoadModuleException& modexcept)
00460 {
00461 DetachAll(newmod);
00462 if (newmod)
00463 delete newmod;
00464 if (newhandle)
00465 delete newhandle;
00466 LastModuleError = "Unable to load " + filename_str + ": Error when loading: " + modexcept.GetReason();
00467 Instance->Logs->Log("MODULE", DEFAULT, LastModuleError);
00468 return false;
00469 }
00470 catch (FindSymbolException& modexcept)
00471 {
00472 DetachAll(newmod);
00473 if (newmod)
00474 delete newmod;
00475 if (newhandle)
00476 delete newhandle;
00477 LastModuleError = "Unable to load " + filename_str + ": Error finding symbol: " + modexcept.GetReason();
00478 Instance->Logs->Log("MODULE", DEFAULT, LastModuleError);
00479 return false;
00480 }
00481 catch (CoreException& modexcept)
00482 {
00483 DetachAll(newmod);
00484 if (newmod)
00485 delete newmod;
00486 if (newhandle)
00487 delete newhandle;
00488 LastModuleError = "Unable to load " + filename_str + ": " + modexcept.GetReason();
00489 Instance->Logs->Log("MODULE", DEFAULT, LastModuleError);
00490 return false;
00491 }
00492
00493 this->ModCount++;
00494 FOREACH_MOD_I(Instance,I_OnLoadModule,OnLoadModule(newmod, filename_str));
00495
00496
00497
00498
00499
00500 for (std::map<std::string, std::pair<ircd_module*, Module*> >::iterator n = Modules.begin(); n != Modules.end(); ++n)
00501 n->second.second->Prioritize();
00502
00503 Instance->BuildISupport();
00504 return true;
00505 }
00506
00507 bool ModuleManager::Unload(const char* filename)
00508 {
00509 std::string filename_str(filename);
00510 std::map<std::string, std::pair<ircd_module*, Module*> >::iterator modfind = Modules.find(filename);
00511
00512 if (modfind != Modules.end())
00513 {
00514 if (modfind->second.second->GetVersion().Flags & VF_STATIC)
00515 {
00516 LastModuleError = "Module " + filename_str + " not unloadable (marked static)";
00517 Instance->Logs->Log("MODULE", DEFAULT, LastModuleError);
00518 return false;
00519 }
00520 std::pair<int,std::string> intercount = GetInterfaceInstanceCount(modfind->second.second);
00521 if (intercount.first > 0)
00522 {
00523 LastModuleError = "Failed to unload module " + filename_str + ", being used by " + ConvToStr(intercount.first) + " other(s) via interface '" + intercount.second + "'";
00524 Instance->Logs->Log("MODULE", DEFAULT, LastModuleError);
00525 return false;
00526 }
00527
00528
00529 for (chan_hash::iterator c = Instance->chanlist->begin(); c != Instance->chanlist->end(); c++)
00530 {
00531 modfind->second.second->OnCleanup(TYPE_CHANNEL,c->second);
00532 }
00533 for (user_hash::iterator u = Instance->Users->clientlist->begin(); u != Instance->Users->clientlist->end(); u++)
00534 {
00535 modfind->second.second->OnCleanup(TYPE_USER,u->second);
00536 }
00537
00538
00539 Instance->Res->CleanResolvers(modfind->second.second);
00540
00541
00542 FOREACH_MOD_I(Instance,I_OnUnloadModule,OnUnloadModule(modfind->second.second, modfind->first));
00543
00544 this->DetachAll(modfind->second.second);
00545
00546 Instance->Parser->RemoveCommands(filename);
00547
00548 delete modfind->second.second;
00549 delete modfind->second.first;
00550 Modules.erase(modfind);
00551
00552 Instance->Logs->Log("MODULE", DEFAULT,"Module %s unloaded",filename);
00553 this->ModCount--;
00554 Instance->BuildISupport();
00555 return true;
00556 }
00557
00558 LastModuleError = "Module " + filename_str + " is not loaded, cannot unload it!";
00559 Instance->Logs->Log("MODULE", DEFAULT, LastModuleError);
00560 return false;
00561 }
00562
00563
00564 void ModuleManager::LoadAll()
00565 {
00566 char configToken[MAXBUF];
00567 ModCount = -1;
00568
00569 for(int count = 0; count < Instance->Config->ConfValueEnum(Instance->Config->config_data, "module"); count++)
00570 {
00571 Instance->Config->ConfValue(Instance->Config->config_data, "module", "name", count, configToken, MAXBUF);
00572 printf_c("[\033[1;32m*\033[0m] Loading module:\t\033[1;32m%s\033[0m\n",configToken);
00573
00574 if (!this->Load(configToken))
00575 {
00576 Instance->Logs->Log("MODULE", DEFAULT, this->LastError());
00577 printf_c("\n[\033[1;31m*\033[0m] %s\n\n", this->LastError().c_str());
00578 Instance->Exit(EXIT_STATUS_MODULE);
00579 }
00580 }
00581 }
00582
00583 bool ModuleManager::PublishFeature(const std::string &FeatureName, Module* Mod)
00584 {
00585 if (Features.find(FeatureName) == Features.end())
00586 {
00587 Features[FeatureName] = Mod;
00588 return true;
00589 }
00590 return false;
00591 }
00592
00593 bool ModuleManager::UnpublishFeature(const std::string &FeatureName)
00594 {
00595 featurelist::iterator iter = Features.find(FeatureName);
00596
00597 if (iter == Features.end())
00598 return false;
00599
00600 Features.erase(iter);
00601 return true;
00602 }
00603
00604 Module* ModuleManager::FindFeature(const std::string &FeatureName)
00605 {
00606 featurelist::iterator iter = Features.find(FeatureName);
00607
00608 if (iter == Features.end())
00609 return NULL;
00610
00611 return iter->second;
00612 }
00613
00614 bool ModuleManager::PublishInterface(const std::string &InterfaceName, Module* Mod)
00615 {
00616 interfacelist::iterator iter = Interfaces.find(InterfaceName);
00617
00618 if (iter == Interfaces.end())
00619 {
00620 modulelist ml;
00621 ml.push_back(Mod);
00622 Interfaces[InterfaceName] = std::make_pair(0, ml);
00623 }
00624 else
00625 {
00626 iter->second.second.push_back(Mod);
00627 }
00628 return true;
00629 }
00630
00631 bool ModuleManager::UnpublishInterface(const std::string &InterfaceName, Module* Mod)
00632 {
00633 interfacelist::iterator iter = Interfaces.find(InterfaceName);
00634
00635 if (iter == Interfaces.end())
00636 return false;
00637
00638 for (modulelist::iterator x = iter->second.second.begin(); x != iter->second.second.end(); x++)
00639 {
00640 if (*x == Mod)
00641 {
00642 iter->second.second.erase(x);
00643 if (iter->second.second.empty())
00644 Interfaces.erase(InterfaceName);
00645 return true;
00646 }
00647 }
00648 return false;
00649 }
00650
00651 modulelist* ModuleManager::FindInterface(const std::string &InterfaceName)
00652 {
00653 interfacelist::iterator iter = Interfaces.find(InterfaceName);
00654 if (iter == Interfaces.end())
00655 return NULL;
00656 else
00657 return &(iter->second.second);
00658 }
00659
00660 bool ModuleManager::ModuleHasInterface(Module* mod, const std::string& InterfaceName)
00661 {
00662 interfacelist::iterator iter = Interfaces.find(InterfaceName);
00663 if (iter == Interfaces.end())
00664 return false;
00665 else
00666 {
00667 modulelist& ml = iter->second.second;
00668 modulelist::iterator mi = std::find(ml.begin(), ml.end(), mod);
00669 return (mi != ml.end());
00670 }
00671 }
00672
00673 void ModuleManager::UseInterface(const std::string &InterfaceName)
00674 {
00675 interfacelist::iterator iter = Interfaces.find(InterfaceName);
00676 if (iter != Interfaces.end())
00677 iter->second.first++;
00678
00679 }
00680
00681 void ModuleManager::DoneWithInterface(const std::string &InterfaceName)
00682 {
00683 interfacelist::iterator iter = Interfaces.find(InterfaceName);
00684 if (iter != Interfaces.end())
00685 iter->second.first--;
00686 }
00687
00688 std::pair<int,std::string> ModuleManager::GetInterfaceInstanceCount(Module* m)
00689 {
00690 for (interfacelist::iterator iter = Interfaces.begin(); iter != Interfaces.end(); iter++)
00691 {
00692 for (modulelist::iterator x = iter->second.second.begin(); x != iter->second.second.end(); x++)
00693 {
00694 if (*x == m)
00695 {
00696 return std::make_pair(iter->