Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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 module: " << modname;

#ifdef _WIN32
	/* Generate the filename for the temporary copy of the module */
	Anope::string pbuf = Anope::DataDir + "/runtime/" + modname + ".so.XXXXXX";

	/* Don't skip return value checking! -GD */
	ModuleReturn ret = moduleCopyFile(modname, pbuf);
	if (ret != MOD_ERR_OK)
	{
		if (ret == MOD_ERR_NOEXIST)
			Log(LOG_TERMINAL) << "Error while loading " << modname << " (file does not exist)";
		else if (ret == MOD_ERR_FILE_IO)
			Log(LOG_TERMINAL) << "Error while loading " << modname << " (file IO error, check file permissions and diskspace)";
		return ret;
	}
#else
	Anope::string pbuf = Anope::ModuleDir + "/modules/" + modname + ".so";
#endif

	dlerror();
	void *handle = dlopen(pbuf.c_str(), RTLD_NOW);
	const char *err = dlerror();
	if (!handle)
	{
		if (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)
	{
		Log() << "No init function found, not an Anope module";
		if (err && *err)
			Log(LOG_DEBUG) << err;
		dlclose(handle);
		return MOD_ERR_NOLOAD;
	}
	
	/* Create module. */
	Anope::string nick;
	if (u)
		nick = u->nick;

	Module *m;

	ModuleReturn moderr = MOD_ERR_OK;
	try
	{
		m = func(modname, nick);
	}
	catch (const ModuleException &ex)
	{
		Log() << "Error while loading " << modname << ": " << ex.GetReason();
		moderr = MOD_ERR_EXCEPTION;
	}
	
	if (moderr != MOD_ERR_OK)
	{
		if (dlclose(handle))
			Log() << dlerror();
		return moderr;
	}

	m->filename = pbuf;
	m->handle = handle;

	ModuleVersion 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::VersionShort();
		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::VersionShort();
		DeleteModule(m);
		return MOD_ERR_VERSION;
	}
	else if (v.GetPatch() < Anope::VersionPatch())
	{
		Log() << "Module " << modname << " is compiled against an older version of Anope, " << v.GetMajor() << "." << v.GetMinor() << "." << v.GetPatch() << ", this is " << Anope::VersionShort();
		DeleteModule(m);
		return MOD_ERR_VERSION;
	}
	else if (v.GetPatch() > Anope::VersionPatch())
	{
		Log() << "Module " << modname << " is compiled against a newer version of Anope, " << v.GetMajor() << "." << v.GetMinor() << "." << v.GetPatch() << ", this is " << Anope::VersionShort();
		DeleteModule(m);
		return MOD_ERR_VERSION;
	}
	else
		Log(LOG_DEBUG_2) << "Module " << modname << " is compiled against current version of Anope " << Anope::VersionShort();

	/* Initialize config */
	try
	{
		m->OnReload(Config);
	}
	catch (const ModuleException &ex)
	{
		Log() << "Module " << modname << " couldn't load:" << ex.GetReason();
		moderr = MOD_ERR_EXCEPTION;
	}
	catch (const ConfigException &ex)
	{
		Log() << "Module " << modname << " couldn't load due to configuration problems: " << ex.GetReason();
		moderr = MOD_ERR_EXCEPTION;
	}
	catch (const NotImplementedException &ex)
	{
	}
	
	if (moderr != MOD_ERR_OK)
	{
		DeleteModule(m);
		return moderr;
	}

	Log(LOG_DEBUG) << "Module " << modname << " loaded.";

	/* Attach module to all events */
	for (unsigned i = 0; i < I_SIZE; ++i)
		EventHandlers[i].push_back(m);

	FOREACH_MOD(OnModuleLoad, (u, m));

	return MOD_ERR_OK;
}