2018-02-04 03:22:01 +01:00
|
|
|
// Matrix Construct
|
|
|
|
//
|
|
|
|
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
|
|
|
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
|
|
|
|
//
|
|
|
|
// Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
// purpose with or without fee is hereby granted, provided that the above
|
|
|
|
// copyright notice and this permission notice is present in all copies. The
|
|
|
|
// full license for this software is available in the LICENSE file.
|
2007-01-25 07:40:21 +01:00
|
|
|
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
#include <boost/filesystem.hpp>
|
|
|
|
#include <boost/dll.hpp>
|
|
|
|
|
|
|
|
namespace filesystem = boost::filesystem;
|
|
|
|
namespace load_mode = boost::dll::load_mode;
|
|
|
|
|
2017-12-02 22:07:55 +01:00
|
|
|
#include <ircd/asio.h>
|
2018-04-24 10:21:05 +02:00
|
|
|
#include <ircd/mods/mapi.h> // Module's internal API
|
2018-02-09 08:35:42 +01:00
|
|
|
#include "mods.h"
|
2017-12-02 22:07:55 +01:00
|
|
|
|
2018-12-09 00:17:13 +01:00
|
|
|
decltype(ircd::mods::enable)
|
|
|
|
ircd::mods::enable
|
|
|
|
{
|
|
|
|
{ "name", "ircd.mods.enable" },
|
|
|
|
{ "default", true },
|
2018-12-09 01:15:22 +01:00
|
|
|
{ "persist", false },
|
2018-12-09 00:17:13 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
decltype(ircd::mods::autoload)
|
|
|
|
ircd::mods::autoload
|
|
|
|
{
|
|
|
|
{ "name", "ircd.mods.autoload" },
|
|
|
|
{ "default", true },
|
2018-12-09 01:15:22 +01:00
|
|
|
{ "persist", false },
|
2018-12-09 00:17:13 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// mods.h
|
|
|
|
//
|
|
|
|
|
2017-12-02 22:07:55 +01:00
|
|
|
ircd::log::log
|
|
|
|
ircd::mods::log
|
|
|
|
{
|
|
|
|
"modules", 'M'
|
|
|
|
};
|
|
|
|
|
|
|
|
const filesystem::path
|
|
|
|
ircd::mods::suffix
|
|
|
|
{
|
|
|
|
boost::dll::shared_library::suffix()
|
|
|
|
};
|
|
|
|
|
2018-10-24 21:15:42 +02:00
|
|
|
//
|
|
|
|
// mods::mod
|
|
|
|
//
|
|
|
|
|
|
|
|
decltype(ircd::mods::mod::loading)
|
|
|
|
ircd::mods::mod::loading
|
|
|
|
{};
|
|
|
|
|
|
|
|
decltype(ircd::mods::mod::unloading)
|
|
|
|
ircd::mods::mod::unloading
|
|
|
|
{};
|
|
|
|
|
|
|
|
decltype(ircd::mods::mod::loaded)
|
|
|
|
ircd::mods::mod::loaded
|
|
|
|
{};
|
|
|
|
|
|
|
|
// Allows module to communicate static destruction is taking place when mapi::header
|
|
|
|
// destructs. If dlclose() returns without this being set, dlclose() lied about really
|
|
|
|
// unloading the module. That is considered a "stuck" module.
|
|
|
|
bool
|
|
|
|
ircd::mapi::static_destruction;
|
|
|
|
|
|
|
|
//
|
|
|
|
// mods::mod::mod
|
|
|
|
//
|
|
|
|
|
|
|
|
ircd::mods::mod::mod(const filesystem::path &path,
|
|
|
|
const load_mode::type &mode)
|
|
|
|
try
|
|
|
|
:path{path}
|
|
|
|
,mode{mode}
|
|
|
|
//,mangles{mods::mangles(path)}
|
|
|
|
,handle{[this, &path, &mode]
|
|
|
|
{
|
|
|
|
const auto ours([]
|
|
|
|
{
|
|
|
|
log::critical
|
|
|
|
{
|
|
|
|
log, "Error during the static construction of module (fatal) :%s",
|
|
|
|
what(std::current_exception())
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
const auto theirs
|
|
|
|
{
|
|
|
|
std::get_terminate()
|
|
|
|
};
|
|
|
|
|
|
|
|
const unwind reset{[this, &theirs]
|
|
|
|
{
|
|
|
|
assert(loading.front() == this);
|
|
|
|
loading.pop_front();
|
|
|
|
std::set_terminate(theirs);
|
|
|
|
}};
|
|
|
|
|
|
|
|
loading.emplace_front(this);
|
|
|
|
std::set_terminate(ours);
|
|
|
|
return boost::dll::shared_library{path, mode};
|
|
|
|
}()}
|
|
|
|
,_name
|
|
|
|
{
|
|
|
|
unpostfixed(handle.location().filename().string())
|
|
|
|
}
|
|
|
|
,_location
|
|
|
|
{
|
|
|
|
handle.location().string()
|
|
|
|
}
|
|
|
|
,header
|
|
|
|
{
|
|
|
|
&handle.get<mapi::header>(mapi::header_symbol_name)
|
|
|
|
}
|
|
|
|
{
|
|
|
|
log::debug
|
|
|
|
{
|
|
|
|
log, "Loaded static segment of '%s' @ `%s' with %zu symbols",
|
|
|
|
name(),
|
|
|
|
location(),
|
|
|
|
mangles.size()
|
|
|
|
};
|
|
|
|
|
|
|
|
if(unlikely(!header))
|
|
|
|
throw error
|
|
|
|
{
|
|
|
|
"Unexpected null header"
|
|
|
|
};
|
|
|
|
|
2018-10-25 22:03:07 +02:00
|
|
|
if(header->magic != IRCD_MAPI_MAGIC)
|
2018-10-24 21:15:42 +02:00
|
|
|
throw error
|
|
|
|
{
|
2018-10-25 22:03:07 +02:00
|
|
|
"Bad magic [%04x] need: [%04x]", header->magic, IRCD_MAPI_MAGIC
|
2018-10-24 21:15:42 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
// Tell the module where to find us.
|
|
|
|
header->self = this;
|
|
|
|
|
|
|
|
// Set some basic metadata
|
2018-10-25 22:03:07 +02:00
|
|
|
(*this)["name"] = name();
|
|
|
|
(*this)["location"] = location();
|
2018-10-24 21:15:42 +02:00
|
|
|
|
|
|
|
if(!loading.empty())
|
|
|
|
{
|
|
|
|
const auto &m(mod::loading.front());
|
|
|
|
m->children.emplace_back(this);
|
|
|
|
log::debug
|
|
|
|
{
|
|
|
|
log, "Module '%s' recursively loaded by '%s'",
|
|
|
|
name(),
|
|
|
|
m->path.filename().string()
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// Without init exception, the module is now considered loaded.
|
|
|
|
assert(!loaded.count(name()));
|
|
|
|
loaded.emplace(name(), this);
|
|
|
|
}
|
|
|
|
catch(const boost::system::system_error &e)
|
|
|
|
{
|
2018-11-09 06:18:39 +01:00
|
|
|
using std::errc;
|
|
|
|
|
|
|
|
const auto &ec(e.code());
|
|
|
|
if(system_category(ec)) switch(ec.value())
|
2018-10-24 21:15:42 +02:00
|
|
|
{
|
2018-11-09 06:18:39 +01:00
|
|
|
case int(errc::bad_file_descriptor):
|
2018-10-24 21:15:42 +02:00
|
|
|
{
|
|
|
|
const string_view what(e.what());
|
|
|
|
const auto pos(what.find("undefined symbol: "));
|
|
|
|
if(pos == std::string_view::npos)
|
|
|
|
break;
|
|
|
|
|
|
|
|
const string_view msg(what.substr(pos));
|
|
|
|
const std::string mangled(between(msg, ": ", ")"));
|
|
|
|
const std::string demangled(demangle(mangled));
|
|
|
|
throw error
|
|
|
|
{
|
|
|
|
"undefined symbol: '%s' (%s)", demangled, mangled
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-11-09 06:18:39 +01:00
|
|
|
throw_system_error(e);
|
2018-10-24 21:15:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ircd::mods::mod::~mod()
|
|
|
|
noexcept try
|
|
|
|
{
|
|
|
|
unload();
|
|
|
|
}
|
|
|
|
catch(const std::exception &e)
|
|
|
|
{
|
|
|
|
log::critical
|
|
|
|
{
|
|
|
|
log, "Module @%p unload: %s",
|
|
|
|
(const void *)this,
|
|
|
|
e.what()
|
|
|
|
};
|
|
|
|
|
|
|
|
if(!ircd::debugmode)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ircd::mods::mod::unload()
|
|
|
|
{
|
|
|
|
if(!handle.is_loaded())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if(mods::unloading(name()))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Mark this module in the unloading state.
|
|
|
|
unloading.emplace_front(this);
|
|
|
|
|
|
|
|
log::debug
|
|
|
|
{
|
|
|
|
log, "Attempting unload module '%s' @ `%s'",
|
|
|
|
name(),
|
|
|
|
location()
|
|
|
|
};
|
|
|
|
|
|
|
|
// Call the user's unloading function here.
|
2018-10-25 22:03:07 +02:00
|
|
|
assert(header);
|
|
|
|
assert(header->meta);
|
|
|
|
if(header->meta->fini)
|
|
|
|
header->meta->fini();
|
2018-10-24 21:15:42 +02:00
|
|
|
|
|
|
|
// Save the children! dlclose() does not like to be called recursively during static
|
|
|
|
// destruction of a module. The mod ctor recorded all of the modules loaded while this
|
|
|
|
// module was loading so we can reverse the record and unload them here.
|
|
|
|
// Note: If the user loaded more modules from inside their module they will have to dtor them
|
|
|
|
// before 'static destruction' does. They can also do that by adding them to this vector.
|
|
|
|
std::for_each(rbegin(this->children), rend(this->children), []
|
|
|
|
(mod *const &ptr)
|
|
|
|
{
|
|
|
|
// Only trigger an unload if there is one reference remaining to the module,
|
|
|
|
// in addition to the reference created by invoking shared_from() right here.
|
|
|
|
if(shared_from(*ptr).use_count() <= 2)
|
|
|
|
ptr->unload();
|
|
|
|
});
|
|
|
|
|
|
|
|
log::debug
|
|
|
|
{
|
|
|
|
log, "Attempting static unload for '%s' @ `%s'",
|
|
|
|
name(),
|
|
|
|
location()
|
|
|
|
};
|
|
|
|
|
|
|
|
mapi::static_destruction = false;
|
|
|
|
handle.unload();
|
|
|
|
assert(!handle.is_loaded());
|
|
|
|
loaded.erase(name());
|
|
|
|
unloading.remove(this);
|
|
|
|
if(!mapi::static_destruction)
|
|
|
|
{
|
|
|
|
log.critical("Module \"%s\" is stuck and failing to unload.", name());
|
|
|
|
log.critical("Module \"%s\" may result in undefined behavior if not fixed.", name());
|
|
|
|
}
|
|
|
|
else log::info
|
|
|
|
{
|
|
|
|
log, "Unloaded '%s'", name()
|
|
|
|
};
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-10-25 22:03:07 +02:00
|
|
|
ircd::string_view &
|
|
|
|
ircd::mods::mod::operator[](const string_view &key)
|
|
|
|
{
|
|
|
|
assert(header);
|
|
|
|
return header->operator[](key);
|
|
|
|
}
|
|
|
|
|
|
|
|
const ircd::string_view &
|
|
|
|
ircd::mods::mod::operator[](const string_view &key)
|
|
|
|
const
|
|
|
|
{
|
|
|
|
assert(header);
|
|
|
|
return header->operator[](key);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// mods/mapi.h
|
|
|
|
//
|
|
|
|
|
|
|
|
ircd::mapi::header::operator
|
|
|
|
mods::mod &()
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
return *self;
|
|
|
|
}
|
|
|
|
|
|
|
|
ircd::mapi::header::operator
|
|
|
|
const mods::mod &()
|
|
|
|
const
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
return *self;
|
|
|
|
}
|
|
|
|
|
|
|
|
ircd::string_view &
|
|
|
|
ircd::mapi::header::operator[](const string_view &key)
|
|
|
|
{
|
|
|
|
assert(meta);
|
|
|
|
return meta->meta[key];
|
|
|
|
}
|
|
|
|
|
|
|
|
const ircd::string_view &
|
|
|
|
ircd::mapi::header::operator[](const string_view &key)
|
|
|
|
const
|
|
|
|
{
|
|
|
|
assert(meta);
|
|
|
|
return meta->meta.at(key);
|
|
|
|
}
|
|
|
|
|
2018-03-24 04:31:09 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2018-02-09 08:35:42 +01:00
|
|
|
//
|
2018-03-24 05:40:20 +01:00
|
|
|
// mods/mods.h (misc util)
|
2018-03-24 04:31:09 +01:00
|
|
|
//
|
|
|
|
|
2018-03-24 05:40:20 +01:00
|
|
|
std::forward_list<std::string>
|
|
|
|
ircd::mods::available()
|
2018-03-24 04:31:09 +01:00
|
|
|
{
|
2018-03-24 05:40:20 +01:00
|
|
|
using filesystem::path;
|
|
|
|
using filesystem::directory_iterator;
|
2018-03-24 04:31:09 +01:00
|
|
|
|
2018-03-24 05:40:20 +01:00
|
|
|
std::forward_list<std::string> ret;
|
|
|
|
for(const auto &dir : paths) try
|
|
|
|
{
|
|
|
|
for(directory_iterator it(dir); it != directory_iterator(); ++it)
|
|
|
|
if(is_module(it->path(), std::nothrow))
|
|
|
|
ret.emplace_front(unpostfixed(relative(it->path(), dir).string()));
|
|
|
|
}
|
|
|
|
catch(const filesystem::filesystem_error &e)
|
|
|
|
{
|
2018-08-31 05:56:03 +02:00
|
|
|
log::warning
|
|
|
|
{
|
|
|
|
log, "Module path [%s]: %s",
|
|
|
|
dir,
|
|
|
|
e.what()
|
|
|
|
};
|
|
|
|
|
2018-03-24 05:40:20 +01:00
|
|
|
continue;
|
|
|
|
}
|
2018-03-24 04:31:09 +01:00
|
|
|
|
2018-03-24 05:40:20 +01:00
|
|
|
return ret;
|
|
|
|
}
|
2018-02-09 08:35:42 +01:00
|
|
|
|
2018-03-24 05:40:20 +01:00
|
|
|
filesystem::path
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::fullpath(const string_view &name)
|
2017-08-16 22:15:14 +02:00
|
|
|
{
|
2018-03-24 05:40:20 +01:00
|
|
|
std::vector<std::string> why;
|
|
|
|
const filesystem::path path(search(name, why));
|
|
|
|
if(path.empty())
|
2017-12-02 22:07:55 +01:00
|
|
|
{
|
2018-03-24 05:40:20 +01:00
|
|
|
for(const auto &str : why)
|
2018-08-31 05:56:03 +02:00
|
|
|
log::error
|
|
|
|
{
|
|
|
|
log, "candidate for module '%s' failed: %s",
|
|
|
|
name,
|
|
|
|
str
|
|
|
|
};
|
2017-12-02 22:07:55 +01:00
|
|
|
|
2018-03-24 05:40:20 +01:00
|
|
|
throw error
|
2017-12-02 22:07:55 +01:00
|
|
|
{
|
2018-03-24 05:40:20 +01:00
|
|
|
"No valid module by name `%s'", name
|
|
|
|
};
|
|
|
|
}
|
2017-12-02 22:07:55 +01:00
|
|
|
|
2018-03-24 05:40:20 +01:00
|
|
|
return path;
|
2017-12-02 22:07:55 +01:00
|
|
|
}
|
2018-03-24 05:40:20 +01:00
|
|
|
|
|
|
|
std::string
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::search(const string_view &name)
|
2017-12-02 22:07:55 +01:00
|
|
|
{
|
2018-03-24 05:40:20 +01:00
|
|
|
std::vector<std::string> why;
|
|
|
|
return search(name, why);
|
2017-12-02 22:07:55 +01:00
|
|
|
}
|
|
|
|
|
2018-03-24 05:40:20 +01:00
|
|
|
std::string
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::search(const string_view &name,
|
2018-03-24 05:40:20 +01:00
|
|
|
std::vector<std::string> &why)
|
|
|
|
{
|
|
|
|
using filesystem::path;
|
2016-09-05 23:27:35 +02:00
|
|
|
|
2018-03-25 23:32:24 +02:00
|
|
|
const path path
|
|
|
|
{
|
|
|
|
postfixed(name)
|
|
|
|
};
|
|
|
|
|
2018-03-24 05:40:20 +01:00
|
|
|
if(!path.is_relative())
|
2017-12-02 22:07:55 +01:00
|
|
|
{
|
2018-03-24 05:40:20 +01:00
|
|
|
why.resize(why.size() + 1);
|
2018-03-25 23:32:24 +02:00
|
|
|
return is_module(path, why.back())?
|
|
|
|
std::string{name}:
|
|
|
|
std::string{};
|
2017-12-02 22:07:55 +01:00
|
|
|
}
|
2018-03-24 05:40:20 +01:00
|
|
|
else for(const auto &dir : paths)
|
2017-12-02 22:07:55 +01:00
|
|
|
{
|
2018-03-24 05:40:20 +01:00
|
|
|
why.resize(why.size() + 1);
|
|
|
|
if(is_module(dir/path, why.back()))
|
|
|
|
return (dir/path).string();
|
|
|
|
}
|
2016-11-29 16:23:38 +01:00
|
|
|
|
2018-03-24 05:40:20 +01:00
|
|
|
return {};
|
|
|
|
}
|
2017-12-02 22:07:55 +01:00
|
|
|
|
2018-03-24 05:40:20 +01:00
|
|
|
bool
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::is_module(const string_view &fullpath)
|
2018-03-24 05:40:20 +01:00
|
|
|
{
|
2018-03-25 23:32:24 +02:00
|
|
|
return is_module(filesystem::path(std::string{fullpath}));
|
2018-03-24 05:40:20 +01:00
|
|
|
}
|
2017-12-02 22:07:55 +01:00
|
|
|
|
2018-03-24 05:40:20 +01:00
|
|
|
bool
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::is_module(const string_view &fullpath,
|
2018-03-24 05:40:20 +01:00
|
|
|
std::nothrow_t)
|
|
|
|
{
|
2018-03-25 23:32:24 +02:00
|
|
|
return is_module(filesystem::path(std::string{fullpath}), std::nothrow);
|
2017-12-02 22:07:55 +01:00
|
|
|
}
|
|
|
|
|
2018-03-24 05:40:20 +01:00
|
|
|
bool
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::is_module(const string_view &fullpath,
|
2018-03-24 05:40:20 +01:00
|
|
|
std::string &why)
|
|
|
|
{
|
2018-03-25 23:32:24 +02:00
|
|
|
return is_module(filesystem::path(std::string{fullpath}), why);
|
2018-03-24 05:40:20 +01:00
|
|
|
}
|
2017-12-02 22:07:55 +01:00
|
|
|
|
2018-03-24 05:40:20 +01:00
|
|
|
bool
|
|
|
|
ircd::mods::is_module(const filesystem::path &path,
|
|
|
|
std::nothrow_t)
|
|
|
|
try
|
2017-12-02 22:07:55 +01:00
|
|
|
{
|
2018-03-24 05:40:20 +01:00
|
|
|
return is_module(path);
|
2017-12-02 22:07:55 +01:00
|
|
|
}
|
|
|
|
catch(const std::exception &e)
|
|
|
|
{
|
2018-03-24 05:40:20 +01:00
|
|
|
return false;
|
2017-12-02 22:07:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2018-03-24 05:40:20 +01:00
|
|
|
ircd::mods::is_module(const filesystem::path &path,
|
|
|
|
std::string &why)
|
|
|
|
try
|
2017-12-02 22:07:55 +01:00
|
|
|
{
|
2018-03-24 05:40:20 +01:00
|
|
|
return is_module(path);
|
|
|
|
}
|
|
|
|
catch(const std::exception &e)
|
|
|
|
{
|
|
|
|
why = e.what();
|
|
|
|
return false;
|
|
|
|
}
|
2017-12-02 22:07:55 +01:00
|
|
|
|
2018-03-24 05:40:20 +01:00
|
|
|
bool
|
|
|
|
ircd::mods::is_module(const filesystem::path &path)
|
|
|
|
{
|
|
|
|
const auto syms(symbols(path));
|
|
|
|
const auto &header_name(mapi::header_symbol_name);
|
|
|
|
const auto it(std::find(begin(syms), end(syms), header_name));
|
|
|
|
if(it == end(syms))
|
|
|
|
throw error
|
|
|
|
{
|
|
|
|
"`%s': has no MAPI header (%s)", path.string(), header_name
|
|
|
|
};
|
2017-12-02 22:07:55 +01:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-03-24 05:40:20 +01:00
|
|
|
bool
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::available(const string_view &name)
|
2017-12-02 22:07:55 +01:00
|
|
|
{
|
2018-03-24 05:40:20 +01:00
|
|
|
using filesystem::path;
|
2017-12-02 22:07:55 +01:00
|
|
|
|
2018-03-24 05:40:20 +01:00
|
|
|
std::vector<std::string> why;
|
|
|
|
return !search(name, why).empty();
|
2017-12-02 22:07:55 +01:00
|
|
|
}
|
|
|
|
|
2018-10-23 19:59:16 +02:00
|
|
|
bool
|
|
|
|
ircd::mods::unloading(const string_view &name)
|
|
|
|
{
|
|
|
|
const auto &list(mod::unloading);
|
|
|
|
return end(list) != std::find_if(begin(list), end(list), [&name]
|
|
|
|
(const auto *const &mod)
|
|
|
|
{
|
|
|
|
assert(mod);
|
|
|
|
return mod->name() == name;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ircd::mods::loading(const string_view &name)
|
|
|
|
{
|
|
|
|
const auto &list(mod::loading);
|
|
|
|
return end(list) != std::find_if(begin(list), end(list), [&name]
|
|
|
|
(const auto *const &mod)
|
|
|
|
{
|
|
|
|
assert(mod);
|
|
|
|
return mod->name() == name;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-03-24 05:40:20 +01:00
|
|
|
bool
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::loaded(const string_view &name)
|
2017-12-02 22:07:55 +01:00
|
|
|
{
|
2018-03-24 05:40:20 +01:00
|
|
|
return mod::loaded.count(name);
|
2017-12-02 22:07:55 +01:00
|
|
|
}
|
|
|
|
|
2018-10-23 20:15:21 +02:00
|
|
|
template<> uint8_t *
|
|
|
|
ircd::mods::ptr<uint8_t>(mod &mod,
|
|
|
|
const string_view &sym)
|
|
|
|
{
|
|
|
|
return &mod.handle.get<uint8_t>(std::string{sym});
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
|
|
|
const uint8_t *
|
|
|
|
ircd::mods::ptr<const uint8_t>(const mod &mod,
|
|
|
|
const string_view &sym)
|
|
|
|
{
|
|
|
|
return &mod.handle.get<const uint8_t>(std::string{sym});
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ircd::mods::unloading(const mod &mod)
|
|
|
|
{
|
|
|
|
const auto &list(mod::unloading);
|
|
|
|
return end(list) != std::find(begin(list), end(list), &mod);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ircd::mods::loading(const mod &mod)
|
|
|
|
{
|
|
|
|
const auto &list(mod::loading);
|
|
|
|
return end(list) != std::find(begin(list), end(list), &mod);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ircd::mods::loaded(const mod &mod)
|
|
|
|
{
|
|
|
|
return mod.handle.is_loaded();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ircd::mods::has(const mod &mod,
|
|
|
|
const string_view &name)
|
|
|
|
{
|
|
|
|
return mod.handle.has(std::string{name});
|
|
|
|
}
|
|
|
|
|
|
|
|
ircd::string_view
|
|
|
|
ircd::mods::name(const mod &mod)
|
|
|
|
{
|
|
|
|
return mod.name();
|
|
|
|
}
|
|
|
|
|
|
|
|
ircd::string_view
|
|
|
|
ircd::mods::path(const mod &mod)
|
|
|
|
{
|
|
|
|
return mod.location();
|
|
|
|
}
|
|
|
|
|
2018-09-14 03:02:10 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// mods/import.h
|
|
|
|
//
|
|
|
|
|
|
|
|
decltype(ircd::mods::imports)
|
|
|
|
ircd::mods::imports
|
|
|
|
{};
|
|
|
|
|
2018-03-24 05:40:20 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// mods/sym_ptr.h
|
|
|
|
//
|
|
|
|
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::sym_ptr::sym_ptr(const string_view &modname,
|
|
|
|
const string_view &symname)
|
2018-03-24 05:40:20 +01:00
|
|
|
:sym_ptr
|
|
|
|
{
|
|
|
|
module(modname), symname
|
|
|
|
}
|
2017-12-02 22:07:55 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-03-26 00:25:32 +02:00
|
|
|
ircd::mods::sym_ptr::sym_ptr(mod &mod,
|
|
|
|
const string_view &symname)
|
|
|
|
:sym_ptr
|
|
|
|
{
|
|
|
|
module(shared_from(mod)), symname
|
|
|
|
}
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-03-24 05:40:20 +01:00
|
|
|
ircd::mods::sym_ptr::sym_ptr(module module,
|
2018-03-25 23:32:24 +02:00
|
|
|
const string_view &symname)
|
2018-03-24 05:40:20 +01:00
|
|
|
:std::weak_ptr<mod>
|
2017-12-02 22:07:55 +01:00
|
|
|
{
|
2018-03-24 05:40:20 +01:00
|
|
|
module
|
2017-12-02 22:07:55 +01:00
|
|
|
}
|
2018-03-25 23:32:24 +02:00
|
|
|
,ptr{[this, &module, &symname]
|
2018-03-24 05:40:20 +01:00
|
|
|
{
|
2018-03-25 23:32:24 +02:00
|
|
|
if(unlikely(!module.has(symname)))
|
2018-03-24 05:40:20 +01:00
|
|
|
throw undefined_symbol
|
|
|
|
{
|
|
|
|
"Could not find symbol '%s' (%s) in module '%s'",
|
2018-03-25 23:32:24 +02:00
|
|
|
demangle(symname),
|
2018-03-24 05:40:20 +01:00
|
|
|
symname,
|
2018-03-25 23:32:24 +02:00
|
|
|
module.name()
|
2018-03-24 05:40:20 +01:00
|
|
|
};
|
2017-12-02 22:07:55 +01:00
|
|
|
|
2018-03-25 23:32:24 +02:00
|
|
|
return module.ptr(symname);
|
2018-03-24 05:40:20 +01:00
|
|
|
}()}
|
2017-12-02 22:07:55 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-11-16 03:41:12 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
2018-03-24 05:40:20 +01:00
|
|
|
// mods/module.h
|
2016-11-16 03:41:12 +01:00
|
|
|
//
|
2016-09-10 01:14:29 +02:00
|
|
|
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::module::module(const string_view &name)
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
try
|
2016-11-16 03:41:12 +01:00
|
|
|
:std::shared_ptr<mod>{[&name]
|
2007-01-25 07:40:21 +01:00
|
|
|
{
|
2016-11-16 03:41:12 +01:00
|
|
|
// Search for loaded module and increment the reference counter for this handle if loaded.
|
2018-02-23 03:57:55 +01:00
|
|
|
auto it(mod::loaded.find(name));
|
2016-11-16 03:41:12 +01:00
|
|
|
if(it != end(mod::loaded))
|
2007-01-25 07:40:21 +01:00
|
|
|
{
|
2016-11-16 03:41:12 +01:00
|
|
|
auto &mod(*it->second);
|
|
|
|
return shared_from(mod);
|
2007-01-25 07:40:21 +01:00
|
|
|
}
|
|
|
|
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
static const load_mode::type flags
|
|
|
|
{
|
|
|
|
load_mode::rtld_local |
|
|
|
|
load_mode::rtld_now
|
|
|
|
};
|
|
|
|
|
2018-02-23 03:57:55 +01:00
|
|
|
const auto path(fullpath(name));
|
2018-08-31 05:56:03 +02:00
|
|
|
log::debug
|
|
|
|
{
|
|
|
|
log, "Attempting to load '%s' @ `%s'",
|
|
|
|
name,
|
|
|
|
path.string()
|
|
|
|
};
|
2018-03-25 23:32:24 +02:00
|
|
|
|
2018-03-26 00:42:52 +02:00
|
|
|
const auto ret
|
|
|
|
{
|
|
|
|
std::make_shared<mod>(path, flags)
|
|
|
|
};
|
|
|
|
|
|
|
|
// Call the user-supplied init function well after fully loading and
|
|
|
|
// construction of the module. This way the init function sees the module
|
|
|
|
// as loaded and can make shared_ptr references, etc.
|
2018-10-25 22:03:07 +02:00
|
|
|
assert(ret->header);
|
|
|
|
assert(ret->header->meta);
|
|
|
|
if(ret->header->meta->init)
|
|
|
|
ret->header->meta->init();
|
2018-03-26 00:42:52 +02:00
|
|
|
|
2018-08-31 05:56:03 +02:00
|
|
|
log::info
|
|
|
|
{
|
|
|
|
log, "Loaded module %s v%u \"%s\"",
|
|
|
|
ret->name(),
|
|
|
|
ret->header->version,
|
|
|
|
!ret->description().empty()?
|
|
|
|
ret->description():
|
2018-09-13 14:43:30 +02:00
|
|
|
"<no description>"_sv
|
2018-08-31 05:56:03 +02:00
|
|
|
};
|
2018-03-26 00:42:52 +02:00
|
|
|
|
|
|
|
return ret;
|
2016-11-16 03:41:12 +01:00
|
|
|
}()}
|
|
|
|
{
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
}
|
|
|
|
catch(const std::exception &e)
|
|
|
|
{
|
2018-08-31 05:56:03 +02:00
|
|
|
log::error
|
|
|
|
{
|
|
|
|
log, "Failed to load '%s': %s",
|
|
|
|
name,
|
|
|
|
e.what()
|
|
|
|
};
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
}
|
|
|
|
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::string_view
|
2016-11-29 16:23:38 +01:00
|
|
|
ircd::mods::module::path()
|
2016-11-16 03:41:12 +01:00
|
|
|
const
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
{
|
2018-03-26 00:25:32 +02:00
|
|
|
const mod &mod(*this);
|
|
|
|
return mods::path(mod);
|
2007-01-25 07:40:21 +01:00
|
|
|
}
|
|
|
|
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::string_view
|
2016-11-29 16:23:38 +01:00
|
|
|
ircd::mods::module::name()
|
2016-11-16 03:41:12 +01:00
|
|
|
const
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
{
|
2018-03-26 00:25:32 +02:00
|
|
|
const mod &mod(*this);
|
|
|
|
return mods::name(mod);
|
2016-11-29 16:23:38 +01:00
|
|
|
}
|
2007-01-25 07:40:21 +01:00
|
|
|
|
2016-11-29 16:23:38 +01:00
|
|
|
bool
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::module::has(const string_view &name)
|
2017-12-02 22:07:55 +01:00
|
|
|
const
|
|
|
|
{
|
2018-03-26 00:25:32 +02:00
|
|
|
const mod &mod(*this);
|
|
|
|
return mods::has(mod, name);
|
2017-03-21 04:38:34 +01:00
|
|
|
}
|
|
|
|
|
2016-11-16 03:41:12 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
2018-03-24 05:40:20 +01:00
|
|
|
// mods/symbols.h
|
2016-11-16 03:41:12 +01:00
|
|
|
//
|
|
|
|
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
std::vector<std::string>
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::find_symbol(const string_view &symbol)
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
{
|
|
|
|
std::vector<std::string> ret;
|
|
|
|
const auto av(available());
|
|
|
|
std::copy_if(begin(av), end(av), std::back_inserter(ret), [&symbol]
|
|
|
|
(const auto &name)
|
2007-01-25 07:40:21 +01:00
|
|
|
{
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
return has_symbol(name, symbol);
|
|
|
|
});
|
2016-06-18 07:52:16 +02:00
|
|
|
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
return ret;
|
|
|
|
}
|
2016-03-20 12:00:20 +01:00
|
|
|
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
bool
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::has_symbol(const string_view &name,
|
|
|
|
const string_view &symbol)
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
{
|
2018-02-23 03:57:55 +01:00
|
|
|
const auto path(fullpath(name));
|
|
|
|
if(path.empty())
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
return false;
|
2016-03-20 12:00:20 +01:00
|
|
|
|
2018-02-23 03:57:55 +01:00
|
|
|
const auto syms(symbols(path));
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
return std::find(begin(syms), end(syms), symbol) != end(syms);
|
2007-01-25 07:40:21 +01:00
|
|
|
}
|
|
|
|
|
2017-12-02 22:07:55 +01:00
|
|
|
std::unordered_map<std::string, std::string>
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::mangles(const string_view &fullpath)
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
{
|
2018-03-25 23:32:24 +02:00
|
|
|
return mangles(filesystem::path(std::string{fullpath}));
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
}
|
|
|
|
|
2017-12-02 22:07:55 +01:00
|
|
|
std::unordered_map<std::string, std::string>
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::mangles(const string_view &fullpath,
|
|
|
|
const string_view §ion)
|
2017-12-02 22:07:55 +01:00
|
|
|
{
|
2018-03-25 23:32:24 +02:00
|
|
|
return mangles(filesystem::path(std::string{fullpath}), section);
|
2017-12-02 22:07:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
std::unordered_map<std::string, std::string>
|
|
|
|
ircd::mods::mangles(const filesystem::path &path)
|
|
|
|
{
|
|
|
|
return mangles(mods::symbols(path));
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unordered_map<std::string, std::string>
|
|
|
|
ircd::mods::mangles(const filesystem::path &path,
|
2018-03-25 23:32:24 +02:00
|
|
|
const string_view §ion)
|
2017-12-02 22:07:55 +01:00
|
|
|
{
|
|
|
|
return mangles(mods::symbols(path, section));
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unordered_map<std::string, std::string>
|
|
|
|
ircd::mods::mangles(const std::vector<std::string> &symbols)
|
|
|
|
{
|
|
|
|
std::unordered_map<std::string, std::string> ret;
|
|
|
|
for(const auto &sym : symbols) try
|
|
|
|
{
|
|
|
|
ret.emplace(demangle(sym), sym);
|
|
|
|
}
|
|
|
|
catch(const not_mangled &e)
|
|
|
|
{
|
|
|
|
ret.emplace(sym, sym);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::string>
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::symbols(const string_view &fullpath)
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
{
|
2018-03-25 23:32:24 +02:00
|
|
|
return symbols(filesystem::path(std::string{fullpath}));
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::string>
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::symbols(const string_view &fullpath,
|
|
|
|
const string_view §ion)
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
{
|
2018-03-25 23:32:24 +02:00
|
|
|
return symbols(filesystem::path(std::string{fullpath}), std::string{section});
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::string>
|
2017-12-02 22:07:55 +01:00
|
|
|
ircd::mods::symbols(const filesystem::path &path)
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
{
|
2016-10-26 08:16:33 +02:00
|
|
|
return info<std::vector<std::string>>(path, []
|
|
|
|
(boost::dll::library_info &info)
|
|
|
|
{
|
2017-12-02 22:07:55 +01:00
|
|
|
return info.symbols();
|
2016-10-26 08:16:33 +02:00
|
|
|
});
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::string>
|
2017-12-02 22:07:55 +01:00
|
|
|
ircd::mods::symbols(const filesystem::path &path,
|
2018-03-25 23:32:24 +02:00
|
|
|
const string_view §ion)
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
{
|
2017-12-02 22:07:55 +01:00
|
|
|
return info<std::vector<std::string>>(path, [§ion]
|
2016-10-26 08:16:33 +02:00
|
|
|
(boost::dll::library_info &info)
|
|
|
|
{
|
2018-03-25 23:32:24 +02:00
|
|
|
return info.symbols(std::string{section});
|
2016-10-26 08:16:33 +02:00
|
|
|
});
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::string>
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::sections(const string_view &fullpath)
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
{
|
2018-03-25 23:32:24 +02:00
|
|
|
return sections(filesystem::path(std::string{fullpath}));
|
2017-12-02 22:07:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::string>
|
|
|
|
ircd::mods::sections(const filesystem::path &path)
|
|
|
|
{
|
|
|
|
return info<std::vector<std::string>>(path, []
|
2016-10-26 08:16:33 +02:00
|
|
|
(boost::dll::library_info &info)
|
|
|
|
{
|
2017-12-02 22:07:55 +01:00
|
|
|
return info.sections();
|
2016-10-26 08:16:33 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class R,
|
|
|
|
class F>
|
|
|
|
R
|
|
|
|
ircd::mods::info(const filesystem::path &path,
|
|
|
|
F&& closure)
|
|
|
|
{
|
|
|
|
if(!exists(path))
|
2018-03-25 23:32:24 +02:00
|
|
|
throw filesystem_error
|
|
|
|
{
|
|
|
|
"`%s' does not exist", path.string()
|
|
|
|
};
|
2016-10-26 08:16:33 +02:00
|
|
|
|
|
|
|
if(!is_regular_file(path))
|
2018-03-25 23:32:24 +02:00
|
|
|
throw filesystem_error
|
|
|
|
{
|
|
|
|
"`%s' is not a file", path.string()
|
|
|
|
};
|
2016-10-26 08:16:33 +02:00
|
|
|
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
boost::dll::library_info info(path);
|
2016-10-26 08:16:33 +02:00
|
|
|
return closure(info);
|
2007-01-25 07:40:21 +01:00
|
|
|
}
|
|
|
|
|
2016-11-16 03:41:12 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
2018-03-24 05:40:20 +01:00
|
|
|
// mods/paths.h
|
2016-11-16 03:41:12 +01:00
|
|
|
//
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
|
2017-12-02 22:07:55 +01:00
|
|
|
namespace ircd::mods
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
{
|
2018-03-24 05:40:20 +01:00
|
|
|
extern const filesystem::path modroot;
|
|
|
|
}
|
|
|
|
|
|
|
|
decltype(ircd::mods::modroot)
|
|
|
|
ircd::mods::modroot
|
|
|
|
{
|
2018-08-12 20:56:53 +02:00
|
|
|
std::string{ircd::fs::get(ircd::fs::MODULES)}
|
2018-03-24 05:40:20 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
decltype(ircd::mods::paths)
|
|
|
|
ircd::mods::paths
|
|
|
|
{};
|
|
|
|
|
|
|
|
std::string
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::unpostfixed(const string_view &name)
|
2018-03-24 05:40:20 +01:00
|
|
|
{
|
2018-03-25 23:32:24 +02:00
|
|
|
return unpostfixed(std::string{name});
|
2018-03-24 05:40:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::unpostfixed(std::string name)
|
2018-03-24 05:40:20 +01:00
|
|
|
{
|
2018-03-25 23:32:24 +02:00
|
|
|
return unpostfixed(filesystem::path(std::move(name))).string();
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string
|
|
|
|
ircd::mods::postfixed(const string_view &name)
|
|
|
|
{
|
|
|
|
return postfixed(std::string{name});
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string
|
|
|
|
ircd::mods::postfixed(std::string name)
|
|
|
|
{
|
|
|
|
return postfixed(filesystem::path(std::move(name))).string();
|
2018-03-24 05:40:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
filesystem::path
|
|
|
|
ircd::mods::unpostfixed(const filesystem::path &path)
|
|
|
|
{
|
|
|
|
if(extension(path) != suffix)
|
|
|
|
return path;
|
|
|
|
|
|
|
|
return filesystem::path(path).replace_extension();
|
|
|
|
}
|
|
|
|
|
|
|
|
filesystem::path
|
|
|
|
ircd::mods::postfixed(const filesystem::path &path)
|
|
|
|
{
|
|
|
|
if(extension(path) == suffix)
|
|
|
|
return path;
|
|
|
|
|
|
|
|
filesystem::path ret(path);
|
|
|
|
return ret += suffix;
|
|
|
|
}
|
2016-11-16 03:41:12 +01:00
|
|
|
|
2018-03-24 05:40:20 +01:00
|
|
|
filesystem::path
|
|
|
|
ircd::mods::prefix_if_relative(const filesystem::path &path)
|
|
|
|
{
|
|
|
|
return path.is_relative()? (modroot / path) : path;
|
2017-12-02 22:07:55 +01:00
|
|
|
}
|
2016-11-16 03:41:12 +01:00
|
|
|
|
2018-03-24 05:40:20 +01:00
|
|
|
//
|
|
|
|
// paths::paths
|
|
|
|
//
|
|
|
|
|
2016-11-16 03:41:12 +01:00
|
|
|
ircd::mods::paths::paths()
|
|
|
|
:std::vector<std::string>
|
|
|
|
{{
|
|
|
|
modroot.string()
|
|
|
|
}}
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::paths::add(const string_view &dir)
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
{
|
|
|
|
using filesystem::path;
|
|
|
|
|
2018-03-25 23:32:24 +02:00
|
|
|
const path path
|
|
|
|
{
|
|
|
|
prefix_if_relative(std::string{dir})
|
|
|
|
};
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
|
|
|
|
if(!exists(path))
|
2018-03-24 05:40:20 +01:00
|
|
|
throw filesystem_error
|
|
|
|
{
|
|
|
|
"path `%s' (%s) does not exist", dir, path.string()
|
|
|
|
};
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
|
|
|
|
if(!is_directory(path))
|
2018-03-24 05:40:20 +01:00
|
|
|
throw filesystem_error
|
|
|
|
{
|
|
|
|
"path `%s' (%s) is not a directory", dir, path.string()
|
|
|
|
};
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
|
2016-11-16 03:41:12 +01:00
|
|
|
if(added(dir))
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
return false;
|
|
|
|
|
2016-11-16 03:41:12 +01:00
|
|
|
emplace(begin(), dir);
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-11-16 03:41:12 +01:00
|
|
|
bool
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::paths::add(const string_view &dir,
|
2016-11-16 03:41:12 +01:00
|
|
|
std::nothrow_t)
|
|
|
|
try
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
{
|
2016-11-16 03:41:12 +01:00
|
|
|
return add(dir);
|
|
|
|
}
|
|
|
|
catch(const std::exception &e)
|
|
|
|
{
|
2018-08-31 05:56:03 +02:00
|
|
|
log::error
|
|
|
|
{
|
|
|
|
log, "Failed to add path: %s", e.what()
|
|
|
|
};
|
|
|
|
|
2016-11-16 03:41:12 +01:00
|
|
|
return false;
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::paths::del(const string_view &dir)
|
2007-01-25 07:40:21 +01:00
|
|
|
{
|
2018-03-25 23:32:24 +02:00
|
|
|
std::remove(begin(), end(), prefix_if_relative(std::string{dir}).string());
|
2016-11-16 03:41:12 +01:00
|
|
|
return true;
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
}
|
2007-01-25 07:40:21 +01:00
|
|
|
|
2016-11-16 03:41:12 +01:00
|
|
|
bool
|
2018-03-25 23:32:24 +02:00
|
|
|
ircd::mods::paths::added(const string_view &dir)
|
2016-11-16 03:41:12 +01:00
|
|
|
const
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
{
|
2016-11-16 03:41:12 +01:00
|
|
|
return std::find(begin(), end(), dir) != end();
|
MAPI IV. This iteration leverages the C++11 standardized RTTI.
* Simplifies the export declarations for module developers. While
MAPI III utilized a flexible key-value vector to eliminate positional
arguments in a header initializer, now the developer simply makes
a list of pointers to what they want to export for injection into
IRCd. Example:
mapi::header IRCD_MODULE
{
"mymod",
"My module adds a command, a hook, and a CLICAP",
&my_cmdtab,
&some_hook,
&clicaptab
};
* Distributes the handlers for items passed to the above vector.
Anyone can add a type-handler to the module system from anywhere in IRCd
(and other modules?) When your type is encountered a handler is called
providing the symbol name to read out of the module. Example in parser.cc:
mods::add_loader<Message>([]
(mod &loading, const std::string &symbol)
{
auto &msg(get<Message>(loading, symbol));
add_command(msg.name, msg);
});
2016-08-29 21:09:59 +02:00
|
|
|
}
|