ModuleReturn ModuleManager::LoadModule(const Anope::string &modname, User *u) { if (modname.empty()) return MOD_ERR_PARAMS; if (FindModule(modname)) return MOD_ERR_EXISTS; Log(LOG_DEBUG) << "trying to load [" << modname << "]"; /* Generate the filename for the temporary copy of the module */ Anope::string pbuf = services_dir + "/modules/runtime/" + modname + ".so.XXXXXX"; /* Don't skip return value checking! -GD */ ModuleReturn ret = moduleCopyFile(modname, pbuf); if (ret != MOD_ERR_OK) return ret; dlerror(); void *handle = dlopen(pbuf.c_str(), RTLD_LAZY); const char *err = dlerror(); if (!handle && err && *err) { Log() << err; return MOD_ERR_NOLOAD; } dlerror(); Module *(*func)(const Anope::string &, const Anope::string &) = function_cast<Module *(*)(const Anope::string &, const Anope::string &)>(dlsym(handle, "AnopeInit")); err = dlerror(); if (!func && err && *err) { Log() << "No init function found, not an Anope module"; dlclose(handle); return MOD_ERR_NOLOAD; } if (!func) throw CoreException("Couldn't find constructor, yet moderror wasn't set?"); /* Create module. */ Anope::string nick; if (u) nick = u->nick; Module *m; try { m = func(modname, nick); } catch (const ModuleException &ex) { Log() << "Error while loading " << modname << ": " << ex.GetReason(); return MOD_ERR_EXCEPTION; } m->filename = pbuf; m->handle = handle; Version v = m->GetVersion(); if (v.GetMajor() < Anope::VersionMajor() || (v.GetMajor() == Anope::VersionMajor() && v.GetMinor() < Anope::VersionMinor())) { Log() << "Module " << modname << " is compiled against an older version of Anope " << v.GetMajor() << "." << v.GetMinor() << ", this is " << Anope::VersionMajor() << "." << Anope::VersionMinor(); DeleteModule(m); return MOD_ERR_VERSION; } else if (v.GetMajor() > Anope::VersionMajor() || (v.GetMajor() == Anope::VersionMajor() && v.GetMinor() > Anope::VersionMinor())) { Log() << "Module " << modname << " is compiled against a newer version of Anope " << v.GetMajor() << "." << v.GetMinor() << ", this is " << Anope::VersionMajor() << "." << Anope::VersionMinor(); DeleteModule(m); return MOD_ERR_VERSION; } else if (v.GetBuild() < Anope::VersionBuild()) Log() << "Module " << modname << " is compiled against an older revision of Anope " << v.GetBuild() << ", this is " << Anope::VersionBuild(); else if (v.GetBuild() > Anope::VersionBuild()) Log() << "Module " << modname << " is compiled against a newer revision of Anope " << v.GetBuild() << ", this is " << Anope::VersionBuild(); else if (v.GetBuild() == Anope::VersionBuild()) Log(LOG_DEBUG) << "Module " << modname << " compiled against current version of Anope " << v.GetBuild(); if (m->type == PROTOCOL && ModuleManager::FindFirstOf(PROTOCOL) != m) { DeleteModule(m); Log() << "You cannot load two protocol modules"; return MOD_ERR_UNKNOWN; } FOREACH_MOD(I_OnModuleLoad, OnModuleLoad(u, m)); return MOD_ERR_OK; }