0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-17 15:30:52 +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);
});
This commit is contained in:
Jason Volk 2016-08-29 12:09:59 -07:00
parent 638db81e09
commit 9d0a959bb5
30 changed files with 1521 additions and 888 deletions

View file

@ -317,6 +317,7 @@ RB_CHK_SYSHEADER([cstddef], [CSTDDEF])
RB_CHK_SYSHEADER([cstdint], [CSTDINT]) RB_CHK_SYSHEADER([cstdint], [CSTDINT])
RB_CHK_SYSHEADER([limits], [LIMITS]) RB_CHK_SYSHEADER([limits], [LIMITS])
RB_CHK_SYSHEADER([type_traits], [TYPE_TRAITS]) RB_CHK_SYSHEADER([type_traits], [TYPE_TRAITS])
RB_CHK_SYSHEADER([typeindex], [TYPEINDEX])
RB_CHK_SYSHEADER([utility], [UTILITY]) RB_CHK_SYSHEADER([utility], [UTILITY])
RB_CHK_SYSHEADER([functional], [FUNCTIONAL]) RB_CHK_SYSHEADER([functional], [FUNCTIONAL])
RB_CHK_SYSHEADER([algorithm], [ALGORITHM]) RB_CHK_SYSHEADER([algorithm], [ALGORITHM])

View file

@ -1,4 +1,4 @@
extensiondir=@moduledir@/extensions extensiondir=@moduledir@
AM_CPPFLAGS = \ AM_CPPFLAGS = \
-I$(top_srcdir)/include \ -I$(top_srcdir)/include \
@ -30,143 +30,144 @@ AM_LDFLAGS += \
@BOOST_LIBS@ @BOOST_LIBS@
chm_adminonly_la_SOURCES = chm_adminonly.cc #chm_adminonly_la_SOURCES = chm_adminonly.cc
chm_operonly_la_SOURCES = chm_operonly.cc #chm_operonly_la_SOURCES = chm_operonly.cc
chm_operonly_compat_la_SOURCES = chm_operonly_compat.cc #chm_operonly_compat_la_SOURCES = chm_operonly_compat.cc
chm_insecure_la_SOURCES = chm_insecure.cc #chm_insecure_la_SOURCES = chm_insecure.cc
chm_nonotice_la_SOURCES = chm_nonotice.cc #chm_nonotice_la_SOURCES = chm_nonotice.cc
chm_operpeace_la_SOURCES = chm_operpeace.cc #chm_operpeace_la_SOURCES = chm_operpeace.cc
chm_quietunreg_compat_la_SOURCES = chm_quietunreg_compat.cc #chm_quietunreg_compat_la_SOURCES = chm_quietunreg_compat.cc
chm_spamfilter_la_SOURCES = chm_spamfilter.cc #chm_spamfilter_la_SOURCES = chm_spamfilter.cc
chm_sslonly_la_SOURCES = chm_sslonly.cc #chm_sslonly_la_SOURCES = chm_sslonly.cc
chm_sslonly_compat_la_SOURCES = chm_sslonly_compat.cc #chm_sslonly_compat_la_SOURCES = chm_sslonly_compat.cc
createauthonly_la_SOURCES = createauthonly.cc #createauthonly_la_SOURCES = createauthonly.cc
createoperonly_la_SOURCES = createoperonly.cc #createoperonly_la_SOURCES = createoperonly.cc
extb_account_la_SOURCES = extb_account.cc #extb_account_la_SOURCES = extb_account.cc
extb_canjoin_la_SOURCES = extb_canjoin.cc #extb_canjoin_la_SOURCES = extb_canjoin.cc
extb_channel_la_SOURCES = extb_channel.cc #extb_channel_la_SOURCES = extb_channel.cc
extb_hostmask_la_SOURCES = extb_hostmask.cc #extb_hostmask_la_SOURCES = extb_hostmask.cc
extb_oper_la_SOURCES = extb_oper.cc #extb_oper_la_SOURCES = extb_oper.cc
extb_server_la_SOURCES = extb_server.cc #extb_server_la_SOURCES = extb_server.cc
extb_ssl_la_SOURCES = extb_ssl.cc #extb_ssl_la_SOURCES = extb_ssl.cc
extb_realname_la_SOURCES = extb_realname.cc #extb_realname_la_SOURCES = extb_realname.cc
extb_usermode_la_SOURCES = extb_usermode.cc #extb_usermode_la_SOURCES = extb_usermode.cc
extb_extgecos_la_SOURCES = extb_extgecos.cc #extb_extgecos_la_SOURCES = extb_extgecos.cc
extb_combi_la_SOURCES = extb_combi.cc #extb_combi_la_SOURCES = extb_combi.cc
force_user_invis_la_SOURCES = force_user_invis.cc #force_user_invis_la_SOURCES = force_user_invis.cc
helpops_la_SOURCES = helpops.cc #helpops_la_SOURCES = helpops.cc
hurt_la_SOURCES = hurt.cc #hurt_la_SOURCES = hurt.cc
ip_cloaking_la_SOURCES = ip_cloaking.cc #ip_cloaking_la_SOURCES = ip_cloaking.cc
override_la_SOURCES = override.cc #override_la_SOURCES = override.cc
restrict_unauthenticated_la_SOURCES = restrict-unauthenticated.cc #restrict_unauthenticated_la_SOURCES = restrict-unauthenticated.cc
sno_channelcreate_la_SOURCES = sno_channelcreate.cc #sno_channelcreate_la_SOURCES = sno_channelcreate.cc
sno_farconnect_la_SOURCES = sno_farconnect.cc #sno_farconnect_la_SOURCES = sno_farconnect.cc
sno_globalkline_la_SOURCES = sno_globalkline.cc #sno_globalkline_la_SOURCES = sno_globalkline.cc
sno_globalnickchange_la_SOURCES = sno_globalnickchange.cc #sno_globalnickchange_la_SOURCES = sno_globalnickchange.cc
sno_globaloper_la_SOURCES = sno_globaloper.cc #sno_globaloper_la_SOURCES = sno_globaloper.cc
sno_whois_la_SOURCES = sno_whois.cc #sno_whois_la_SOURCES = sno_whois.cc
umode_noctcp_la_SOURCES = umode_noctcp.cc #umode_noctcp_la_SOURCES = umode_noctcp.cc
m_adminwall_la_SOURCES = m_adminwall.cc #m_adminwall_la_SOURCES = m_adminwall.cc
m_echotags_la_SOURCES = m_echotags.cc #m_echotags_la_SOURCES = m_echotags.cc
m_extendchans_la_SOURCES = m_extendchans.cc #m_extendchans_la_SOURCES = m_extendchans.cc
m_findforwards_la_SOURCES = m_findforwards.cc #m_findforwards_la_SOURCES = m_findforwards.cc
m_identify_la_SOURCES = m_identify.cc #m_identify_la_SOURCES = m_identify.cc
m_locops_la_SOURCES = m_locops.cc #m_locops_la_SOURCES = m_locops.cc
m_mkpasswd_la_SOURCES = m_mkpasswd.cc #m_mkpasswd_la_SOURCES = m_mkpasswd.cc
m_ojoin_la_SOURCES = m_ojoin.cc #m_ojoin_la_SOURCES = m_ojoin.cc
m_okick_la_SOURCES = m_okick.cc #m_okick_la_SOURCES = m_okick.cc
m_omode_la_SOURCES = m_omode.cc #m_omode_la_SOURCES = m_omode.cc
m_opme_la_SOURCES = m_opme.cc #m_opme_la_SOURCES = m_opme.cc
m_sendbans_la_SOURCES = m_sendbans.cc #m_sendbans_la_SOURCES = m_sendbans.cc
m_webirc_la_SOURCES = m_webirc.cc #m_webirc_la_SOURCES = m_webirc.cc
m_remove_la_SOURCES = m_remove.cc #m_remove_la_SOURCES = m_remove.cc
m_roleplay_la_SOURCES = m_roleplay.cc #m_roleplay_la_SOURCES = m_roleplay.cc
hide_uncommon_channels_la_SOURCES = hide_uncommon_channels.cc #hide_uncommon_channels_la_SOURCES = hide_uncommon_channels.cc
no_kill_services_la_SOURCES = no_kill_services.cc #no_kill_services_la_SOURCES = no_kill_services.cc
no_locops_la_SOURCES = no_locops.cc #no_locops_la_SOURCES = no_locops.cc
no_oper_invis_la_SOURCES = no_oper_invis.cc #no_oper_invis_la_SOURCES = no_oper_invis.cc
spamfilter_nicks_la_SOURCES = spamfilter_nicks.cc #spamfilter_nicks_la_SOURCES = spamfilter_nicks.cc
spy_admin_notice_la_SOURCES = spy_admin_notice.cc #spy_admin_notice_la_SOURCES = spy_admin_notice.cc
spy_info_notice_la_SOURCES = spy_info_notice.cc #spy_info_notice_la_SOURCES = spy_info_notice.cc
spy_links_notice_la_SOURCES = spy_links_notice.cc #spy_links_notice_la_SOURCES = spy_links_notice.cc
spy_motd_notice_la_SOURCES = spy_motd_notice.cc #spy_motd_notice_la_SOURCES = spy_motd_notice.cc
spy_stats_notice_la_SOURCES = spy_stats_notice.cc #spy_stats_notice_la_SOURCES = spy_stats_notice.cc
spy_stats_p_notice_la_SOURCES = spy_stats_p_notice.cc #spy_stats_p_notice_la_SOURCES = spy_stats_p_notice.cc
spy_trace_notice_la_SOURCES = spy_trace_notice.cc #spy_trace_notice_la_SOURCES = spy_trace_notice.cc
example_module_la_SOURCES = example_module.cc #example_module_la_SOURCES = example_module.cc
extension_LTLIBRARIES = \ #extension_LTLIBRARIES = \
chm_adminonly.la \ # chm_adminonly.la \
chm_operonly.la \ # chm_operonly.la \
chm_operonly_compat.la \ # chm_operonly_compat.la \
chm_insecure.la \ # chm_insecure.la \
chm_nonotice.la \ # chm_nonotice.la \
chm_operpeace.la \ # chm_operpeace.la \
chm_quietunreg_compat.la \ # chm_quietunreg_compat.la \
chm_spamfilter.la \ # chm_spamfilter.la \
chm_sslonly.la \ # chm_sslonly.la \
chm_sslonly_compat.la \ # chm_sslonly_compat.la \
createauthonly.la \ # createauthonly.la \
createoperonly.la \ # createoperonly.la \
extb_account.la \ # extb_account.la \
extb_canjoin.la \ # extb_canjoin.la \
extb_channel.la \ # extb_channel.la \
extb_hostmask.la \ # extb_hostmask.la \
extb_oper.la \ # extb_oper.la \
extb_server.la \ # extb_server.la \
extb_ssl.la \ # extb_ssl.la \
extb_realname.la \ # extb_realname.la \
extb_usermode.la \ # extb_usermode.la \
extb_extgecos.la \ # extb_extgecos.la \
extb_combi.la \ # extb_combi.la \
force_user_invis.la \ # force_user_invis.la \
helpops.la \ # helpops.la \
hurt.la \ # hurt.la \
ip_cloaking.la \ # ip_cloaking.la \
override.la \ # override.la \
restrict-unauthenticated.la \ # restrict-unauthenticated.la \
sno_channelcreate.la \ # sno_channelcreate.la \
sno_farconnect.la \ # sno_farconnect.la \
sno_globalkline.la \ # sno_globalkline.la \
sno_globalnickchange.la \ # sno_globalnickchange.la \
sno_globaloper.la \ # sno_globaloper.la \
sno_whois.la \ # sno_whois.la \
umode_noctcp.la \ # umode_noctcp.la \
m_adminwall.la \ # m_adminwall.la \
m_echotags.la \ # m_echotags.la \
m_extendchans.la \ # m_extendchans.la \
m_findforwards.la \ # m_findforwards.la \
m_identify.la \ # m_identify.la \
m_locops.la \ # m_locops.la \
m_mkpasswd.la \ # m_mkpasswd.la \
m_ojoin.la \ # m_ojoin.la \
m_okick.la \ # m_okick.la \
m_omode.la \ # m_omode.la \
m_opme.la \ # m_opme.la \
m_sendbans.la \ # m_sendbans.la \
m_webirc.la \ # m_webirc.la \
m_remove.la \ # m_remove.la \
m_roleplay.la \ # m_roleplay.la \
hide_uncommon_channels.la \ # hide_uncommon_channels.la \
no_kill_services.la \ # no_kill_services.la \
no_locops.la \ # no_locops.la \
no_oper_invis.la \ # no_oper_invis.la \
spamfilter_nicks.la \ # spamfilter_nicks.la \
spy_admin_notice.la \ # spy_admin_notice.la \
spy_info_notice.la \ # spy_info_notice.la \
spy_links_notice.la \ # spy_links_notice.la \
spy_motd_notice.la \ # spy_motd_notice.la \
spy_stats_notice.la \ # spy_stats_notice.la \
spy_stats_p_notice.la \ # spy_stats_p_notice.la \
spy_trace_notice.la \ # spy_trace_notice.la \
example_module.la # example_module.la
#
if PCRE #if PCRE
#
extension_LTLIBRARIES += spamfilter_expr.la #extension_LTLIBRARIES += spamfilter_expr.la
spamfilter_expr_la_SOURCES = spamfilter_expr.cc #spamfilter_expr_la_SOURCES = spamfilter_expr.cc
spamfilter_expr_la_CPPFLAGS = $(AM_CPPFLAGS) $(PCRE_CFLAGS) #spamfilter_expr_la_CPPFLAGS = $(AM_CPPFLAGS) $(PCRE_CFLAGS)
spamfilter_expr_la_LIBADD = $(PCRE_LIBS) #spamfilter_expr_la_LIBADD = $(PCRE_LIBS)
#
endif #endif
#

View file

@ -46,8 +46,6 @@ namespace fs {
constexpr auto DPATH = IRCD_PREFIX; constexpr auto DPATH = IRCD_PREFIX;
constexpr auto BINPATH = IRCD_PREFIX "/bin"; constexpr auto BINPATH = IRCD_PREFIX "/bin";
constexpr auto MODPATH = RB_MODULE_DIR; constexpr auto MODPATH = RB_MODULE_DIR;
constexpr auto MODULE_DIR = RB_MODULE_DIR;
constexpr auto AUTOMODPATH = RB_MODULE_DIR "/autoload";
constexpr auto ETCPATH = RB_ETC_DIR; constexpr auto ETCPATH = RB_ETC_DIR;
constexpr auto LOGPATH = RB_LOG_DIR; constexpr auto LOGPATH = RB_LOG_DIR;
constexpr auto UHPATH = RB_HELP_DIR "/users"; constexpr auto UHPATH = RB_HELP_DIR "/users";
@ -71,7 +69,6 @@ namespace path
LOG, LOG,
LIBEXEC, LIBEXEC,
MODULES, MODULES,
AUTOLOAD_MODULES,
USERHELP, USERHELP,
OPERHELP, OPERHELP,
IRCD_CONF, IRCD_CONF,

116
include/ircd/mapi.h Normal file
View file

@ -0,0 +1,116 @@
/*
* Copyright (C) 2016 Charybdis Development Team
* Copyright (C) 2016 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#define HAVE_IRCD_MAPI_H
#ifdef __cplusplus
namespace ircd {
namespace mapi {
struct init
:std::function<void ()>
{
using std::function<void ()>::function;
};
struct fini
:std::function<void ()>
{
using std::function<void ()>::function;
};
enum flags
{
NO_FLAGS = 0x00,
RELAXED_INIT = 0x01,
};
// Associates RTTI keyed by object location
using export_vector = std::vector<std::pair<const void *, std::type_index>>;
struct exports
:export_vector
{
template<class... List> exports(List&&... list);
};
struct header
{
static const char *const sym_name;
static constexpr const magic_t MAGIC
{
0x4D41
};
magic_t magic; // The magic must match MAGIC
version_t version; // Version indicator
enum flags flags; // Option flags
int64_t timestamp; // Module's compile epoch
const char *desc;
struct exports exports;
template<class... Exports>
header(const char *const &desc,
const enum flags &flags,
Exports&&... exports);
};
template<class... Exports>
header::header(const char *const &desc,
const enum flags &flags,
Exports&&... exports)
:magic(MAGIC)
,version(4)
,flags(flags)
,timestamp(RB_DATECODE)
,desc(desc)
,exports{std::forward<Exports>(exports)...}
{
}
const char *const
header::sym_name
{
"IRCD_MODULE"
};
template<class... List>
exports::exports(List&&... list)
{
const std::vector<std::type_index> types
{
typeid(List)...
};
const std::vector<const void *> ptrs
{
std::forward<List>(list)...
};
assert(types.size() == ptrs.size());
for(size_t i(0); i < types.size(); ++i)
this->emplace_back(ptrs.at(i), types.at(i));
}
} // namespace mapi
} // namespace ircd
#endif // __cplusplus

View file

@ -1,10 +1,12 @@
/* /*
* ircd-ratbox: A slightly useful ircd. * IRCd (Charybdis): Pushing the envelope since '88
* modules.h: A header for the modules functions. * modules.h: A header for the modules functions.
* *
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid Development Team * Copyright (C) 1996-2002 Hybrid Development Team
* Copyright (C) 2002-2004 ircd-ratbox development team * Copyright (C) 2002-2004 ircd-ratbox development team
* Copyright (C) 2016 Charybdis Development Team
* Copyright (C) 2016 Jason Volk <jason@zemos.net>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -25,173 +27,160 @@
#pragma once #pragma once
#define HAVE_IRCD_MODULES_H #define HAVE_IRCD_MODULES_H
#define MAPI_CHARYBDIS 2
typedef struct lt__handle *lt_dlhandle;
#ifdef __cplusplus #ifdef __cplusplus
namespace ircd { namespace ircd {
namespace mapi {
struct module using magic_t = uint16_t;
using version_t = uint16_t;
struct header;
} // namespace mapi
namespace mods {
using mapi::magic_t;
using mapi::version_t;
IRCD_EXCEPTION(ircd::error, error)
IRCD_EXCEPTION(error, filesystem_error)
IRCD_EXCEPTION(error, invalid_export)
struct mod;
bool has(const mod &mod, const std::string &symbol);
const uint8_t *ptr(const mod &mod, const std::string &symbol);
uint8_t *ptr(mod &mod, const std::string &symbol);
template<class T> const T *ptr(const mod &mod, const std::string &symbol);
template<class T> const T &get(const mod &mod, const std::string &symbol);
template<class T> T *ptr(mod &mod, const std::string &symbol);
template<class T> T &get(mod &mod, const std::string &symbol);
const mapi::header &header(const mod &);
const char *const &desc(const mod &);
const version_t &version(const mod &);
const int64_t &timestamp(const mod &);
std::string location(const mod &);
std::string name(const mod &);
extern struct log::log log;
// Symbol handlers
struct type_handlers
{ {
const char *name; std::function<void (mod &, const std::string &sym)> loader;
const char *path; std::function<void (mod &, const std::string &sym)> unloader;
const char *version; std::function<void (mod &, const std::string &sym)> reloader;
const char *description;
lt_dlhandle address;
int core; /* This is int for backwards compat reasons */
int origin; /* Ditto */
int mapi_version;
void *mapi_header; /* actually struct mapi_mheader_av<mapi_version> */
rb_dlink_node node;
}; };
template<class T> std::type_index make_index();
bool add(const std::type_index &, const type_handlers &handlers);
bool del(const std::type_index &);
bool has(const std::type_index &);
template<class T, class... type_handlers> bool add(type_handlers&&... handlers);
template<class T> bool del();
template<class T> bool has();
#define MAPI_MAGIC_HDR 0x4D410000 // The search path vector
std::vector<std::string> paths();
bool path_added(const std::string &dir);
void path_del(const std::string &dir);
bool path_add(const std::string &dir, std::nothrow_t); // logs errors and returns false
bool path_add(const std::string &dir); // false if exists, throws other errors
void path_clear();
#define MAPI_V1 (MAPI_MAGIC_HDR | 0x1) // Dump object data
#define MAPI_V2 (MAPI_MAGIC_HDR | 0x2) std::vector<std::string> symbols(const std::string &fullpath, const std::string &section);
#define MAPI_V3 (MAPI_MAGIC_HDR | 0x3) std::vector<std::string> symbols(const std::string &fullpath);
std::vector<std::string> sections(const std::string &fullpath);
#define MAPI_MAGIC(x) ((x) & 0xffff0000) // Checks if loadable module containing a mapi header (does not verify the magic)
#define MAPI_VERSION(x) ((x) & 0x0000ffff) bool is_module(const std::string &fullpath, std::string &why);
bool is_module(const std::string &fullpath, std::nothrow_t);
bool is_module(const std::string &fullpath);
typedef struct Message* mapi_clist_av1; // returns dir/name of first dir containing 'name' (and this will be a loadable module)
// Unlike libltdl, the reason each individual candidate failed is presented in a vector.
std::string search(const std::string &name, std::vector<std::string> &why);
std::string search(const std::string &name);
typedef struct // Potential modules available to load
std::forward_list<std::string> available();
bool available(const std::string &name);
// Find module names where symbol resides
bool has_symbol(const std::string &name, const std::string &symbol);
std::vector<std::string> find_symbol(const std::string &symbol);
// Modules currently loaded
const std::map<std::string, std::unique_ptr<mod>> &loaded();
bool loaded(const std::string &name);
mod &get(const std::string &name);
bool reload(const std::string name);
bool unload(const std::string name);
bool load(const std::string &name);
void autoload();
template<class T>
bool
has()
{ {
const char *hapi_name; return has(make_index<T>());
int *hapi_id; }
} mapi_hlist_av1;
typedef struct template<class T>
bool
del()
{ {
const char *hapi_name; return del(make_index<T>());
hookfn fn; }
} mapi_hfn_list_av1;
template<class T,
#define MAPI_CAP_CLIENT 1 class... type_handlers>
#define MAPI_CAP_SERVER 2 bool
add(type_handlers&&... handlers)
typedef struct
{ {
int cap_index; /* Which cap index does this belong to? */ return add(make_index<T>(), {std::forward<type_handlers>(handlers)...});
const char *cap_name; /* Capability name */ }
void *cap_ownerdata; /* Not used much but why not... */
unsigned int *cap_id; /* May be set to non-NULL to store cap id */
} mapi_cap_list_av2;
struct mapi_mheader_av1 template<class T>
std::type_index
make_index()
{ {
int mapi_version; /* Module API version */ return typeid(typename std::add_pointer<T>::type);
int (*mapi_register)(void); /* Register function; ret -1 = failure (unload) */ }
void (*mapi_unregister)(void); /* Unregister function. */
mapi_clist_av1 *mapi_command_list; /* List of commands to add. */
mapi_hlist_av1 *mapi_hook_list; /* List of hooks to add. */
mapi_hfn_list_av1 *mapi_hfn_list; /* List of hook_add_hook's to do */
const char *mapi_module_version; /* Module's version (freeform) */
};
#define MAPI_ORIGIN_UNKNOWN 0 /* Unknown provenance (AV1 etc.) */ template<class T>
#define MAPI_ORIGIN_EXTENSION 1 /* Charybdis extension */ T &
#define MAPI_ORIGIN_CORE 2 /* Charybdis core module */ get(mod &mod,
const std::string &symbol)
struct mapi_mheader_av2
{ {
int mapi_version; /* Module API version */ return *reinterpret_cast<T *>(ptr(mod, symbol));
int (*mapi_register)(void); /* Register function; ret -1 = failure (unload) */ }
void (*mapi_unregister)(void); /* Unregister function. */
mapi_clist_av1 *mapi_command_list; /* List of commands to add. */
mapi_hlist_av1 *mapi_hook_list; /* List of hooks to add. */
mapi_hfn_list_av1 *mapi_hfn_list; /* List of hook_add_hook's to do */
mapi_cap_list_av2 *mapi_cap_list; /* List of CAPs to add */
const char *mapi_module_version; /* Module's version (freeform), replaced with ircd version if NULL */
const char *mapi_module_description; /* Module's description (freeform) */
time_t mapi_datecode; /* Unix timestamp of module's build */
};
#define DECLARE_MODULE_AV1(name, reg, unreg, cl, hl, hfnlist, v) \ template<class T>
struct mapi_mheader_av1 _mheader = { MAPI_V1, reg, unreg, cl, hl, hfnlist, v} T *
ptr(mod &mod,
#define DECLARE_MODULE_AV2(name, reg, unreg, cl, hl, hfnlist, caplist, v, desc) \ const std::string &symbol)
struct mapi_mheader_av2 _mheader = { MAPI_V2, reg, unreg, cl, hl, hfnlist, caplist, v, desc, RB_DATECODE}
/***
Version 3 modules utilize a flexible key/value vector.
Example:
DECLARE_MODULE_AV3
(
MOD_ATTR { "name", "mymodule" },
MOD_ATTR { "mtab", &message_foo },
MOD_ATTR { "mtab", &message_unfoo },
MOD_ATTR { "init", modinitfunc },
MOD_ATTR { "hook", MOD_HOOK { "myhook", &id } },
MOD_ATTR { "hookfn", MOD_HOOKFN { "myhook", hookfun } },
)
Notes:
- Multiple keys with the same name will have different behavior depending on the logic for that key.
- On load, the order in which keys are specified is the order they will be evaluated (top to bottom).
- On unload, the evaluation is the REVERSE order (bottom to top).
- If an init function returns false, or other error occurs, no further keys are evaluated and the
unload rolls back from that point.
***/
struct mapi_av3_attr
{ {
#define MAPI_V3_KEY_MAXLEN 16 /* Maximum length for a key string */ return reinterpret_cast<T *>(ptr(mod, symbol));
}
const char *key; template<class T>
union { const void *cvalue; void *value; int (*init)(void); void (*fini)(void); }; const T &
}; get(const mod &mod,
const std::string &symbol)
struct mapi_mheader_av3
{ {
int mapi_version; // Module API version return *reinterpret_cast<const T *>(ptr(mod, symbol));
struct mapi_av3_attr **attrs; // A vector of attributes, NULL terminated }
};
#define MOD_ATTR &(struct mapi_av3_attr) template<class T>
#define MOD_HOOK &(mapi_hlist_av1) const T *
#define MOD_HOOKFN &(mapi_hfn_list_av1) ptr(const mod &mod,
const std::string &symbol)
#define DECLARE_MODULE_AV3(...) \ {
struct mapi_mheader_av3 _mheader = \ return reinterpret_cast<const T *>(ptr(mod, symbol));
{ \ }
MAPI_V3, (struct mapi_av3_attr *[]) \
{ \
MOD_ATTR { "time", RB_DATECODE },\
__VA_ARGS__, \
NULL \
} \
};
// Prefixes your slog() message with module info
void module_log(struct module *mod, const char *fmt, ...) AFP(2, 3);
/* add a path */
void mod_add_path(const char *path);
void mod_clear_paths(void);
/* load a module */
extern void load_module(char *path);
/* load all modules */
extern void load_all_modules(bool warn);
/* load core modules */
extern void load_core_modules(bool);
extern bool unload_one_module(const char *, bool);
bool load_one_module(const char *, int, bool);
extern bool load_a_module(const char *, bool, int, bool);
struct module *findmodule_byname(const char *);
extern void init_modules(void);
extern rb_dlink_list module_list;
extern rb_dlink_list mod_paths;
} // namespace mods
} // namespace ircd } // namespace ircd
#endif // __cplusplus #endif // __cplusplus

View file

@ -32,6 +32,8 @@ namespace ircd
using std::begin; using std::begin;
using std::end; using std::end;
using std::get; using std::get;
using ostream = std::ostream;
using namespace std::string_literals;
} }
// Temp fwd decl scaffold // Temp fwd decl scaffold
@ -60,8 +62,6 @@ namespace ircd
struct ev_ctl; struct ev_ctl;
struct ws_ctl; struct ws_ctl;
struct server_conf; struct server_conf;
using ostream = std::ostream;
} }
#include "util.h" #include "util.h"

View file

@ -58,6 +58,7 @@ extern "C" {
#include <RB_INC_CSTDINT #include <RB_INC_CSTDINT
#include <RB_INC_LIMITS #include <RB_INC_LIMITS
#include <RB_INC_TYPE_TRAITS #include <RB_INC_TYPE_TRAITS
#include <RB_INC_TYPEINDEX
#include <RB_INC_CERRNO #include <RB_INC_CERRNO
#include <RB_INC_UTILITY #include <RB_INC_UTILITY
#include <RB_INC_FUNCTIONAL #include <RB_INC_FUNCTIONAL
@ -72,7 +73,7 @@ extern "C" {
#include <RB_INC_MAP #include <RB_INC_MAP
#include <RB_INC_SET #include <RB_INC_SET
#include <RB_INC_LIST #include <RB_INC_LIST
//#include <RB_INC_FORWARD_LIST #include <RB_INC_FORWARD_LIST
//#include <RB_INC_UNORDERED_MAP //#include <RB_INC_UNORDERED_MAP
//#include <RB_INC_DEQUE //#include <RB_INC_DEQUE
#include <RB_INC_SSTREAM #include <RB_INC_SSTREAM

View file

@ -35,7 +35,6 @@ auto paths = []
paths[PREFIX] = DPATH; paths[PREFIX] = DPATH;
paths[MODULES] = MODPATH; paths[MODULES] = MODPATH;
paths[AUTOLOAD_MODULES] = AUTOMODPATH;
paths[ETC] = ETCPATH; paths[ETC] = ETCPATH;
paths[LOG] = LOGPATH; paths[LOG] = LOGPATH;
paths[USERHELP] = UHPATH; paths[USERHELP] = UHPATH;
@ -62,7 +61,6 @@ auto pathnames = []
names[PREFIX] = "prefix"; names[PREFIX] = "prefix";
names[MODULES] = "modules"; names[MODULES] = "modules";
names[AUTOLOAD_MODULES] = "autoload modules";
names[ETC] = "config"; names[ETC] = "config";
names[LOG] = "log"; names[LOG] = "log";
names[USERHELP] = "user help"; names[USERHELP] = "user help";
@ -139,9 +137,6 @@ void relocate()
snprintf(workbuf, sizeof workbuf, "%s%cmodules", prefix, RB_PATH_SEPARATOR); snprintf(workbuf, sizeof workbuf, "%s%cmodules", prefix, RB_PATH_SEPARATOR);
paths[MODULES] = rb_strdup(workbuf); paths[MODULES] = rb_strdup(workbuf);
snprintf(workbuf, sizeof workbuf, "%s%cmodules%cautoload", prefix, RB_PATH_SEPARATOR, RB_PATH_SEPARATOR);
paths[AUTOLOAD_MODULES] = rb_strdup(workbuf);
snprintf(workbuf, sizeof workbuf, "%s%cetc", prefix, RB_PATH_SEPARATOR); snprintf(workbuf, sizeof workbuf, "%s%cetc", prefix, RB_PATH_SEPARATOR);
paths[ETC] = rb_strdup(workbuf); paths[ETC] = rb_strdup(workbuf);

View file

@ -549,7 +549,6 @@ charybdis_main(int argc, char * const argv[])
init_authd(); /* Start up authd. */ init_authd(); /* Start up authd. */
init_dns(); /* Start up DNS query system */ init_dns(); /* Start up DNS query system */
init_modules(); /* Start up modules system */
privilegeset_set_new("default", "", 0); privilegeset_set_new("default", "", 0);
@ -557,8 +556,7 @@ charybdis_main(int argc, char * const argv[])
fprintf(stderr, "\nBeginning config test\n"); fprintf(stderr, "\nBeginning config test\n");
read_conf_files(true); /* cold start init conf files */ read_conf_files(true); /* cold start init conf files */
load_all_modules(1); mods::autoload();
load_core_modules(1);
supported::init(); supported::init();

View file

@ -276,9 +276,9 @@ loadmodule:
char *m_bn; char *m_bn;
m_bn = rb_basename((char *) $2); m_bn = rb_basename((char *) $2);
if (ircd::findmodule_byname(m_bn) == NULL) if (!ircd::mods::loaded(m_bn))
{ {
ircd::load_one_module($2, MAPI_ORIGIN_EXTENSION, 0); ircd::mods::load($2);
} }
rb_free(m_bn); rb_free(m_bn);

191
ircd/mods_mod.h Normal file
View file

@ -0,0 +1,191 @@
/*
* Copyright (C) 2016 Charybdis Development Team
* Copyright (C) 2016 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#define HAVE_IRCD_MODS_MOD_H
#ifdef __cplusplus
namespace ircd {
namespace mods {
struct sym
{
std::type_index type;
sym(const std::type_index &type)
:type{type}
{
}
};
struct mod
{
boost::dll::shared_library handle;
const mapi::header *header;
std::map<std::string, sym> handled;
std::multimap<std::type_index, std::string> unhandled;
bool has(const std::string &name) const;
template<class T> const T &get(const std::string &name) const;
template<class T> T &get(const std::string &name);
template<class T = uint8_t> const T *ptr(const std::string &name) const;
template<class T = uint8_t> T *ptr(const std::string &name);
mod(const filesystem::path &, const load_mode::type &);
~mod() noexcept;
};
mod::mod(const filesystem::path &path,
const load_mode::type &type)
try
:handle
{
path, type
}
,header
{
&handle.get<mapi::header>(mapi::header::sym_name)
}
{
if(unlikely(!header))
throw error("Unexpected null header");
if(header->magic != mapi::header::MAGIC)
throw error("Bad magic [%04x] need: [%04x]",
header->magic,
mapi::header::MAGIC);
}
catch(const boost::system::system_error &e)
{
throw error("%s", e.what());
}
mod::~mod()
noexcept
{
}
template<class T>
T *
mod::ptr(const std::string &name)
{
return &handle.get<T>(name);
}
template<class T>
const T *
mod::ptr(const std::string &name)
const
{
return &handle.get<T>(name);
}
template<class T>
T &
mod::get(const std::string &name)
{
handle.get<T>(name);
}
template<class T>
const T &
mod::get(const std::string &name)
const
{
handle.get<T>(name);
}
bool
mod::has(const std::string &name)
const
{
return handle.has(name);
}
std::string
name(const mod &mod)
{
return mod.handle.location().filename().string();
}
std::string
location(const mod &mod)
{
return mod.handle.location().string();
}
const version_t &
version(const mod &mod)
{
return header(mod).version;
}
const char *const &
desc(const mod &mod)
{
return header(mod).desc;
}
const mapi::exports &
exports(const mod &mod)
{
return header(mod).exports;
}
const mapi::flags &
flags(const mod &mod)
{
return header(mod).flags;
}
const mapi::header &
header(const mod &mod)
{
if(unlikely(!mod.header))
throw error("Header unavailable");
return *mod.header;
}
uint8_t *
ptr(mod &mod,
const std::string &name)
{
return mod.ptr<uint8_t>(name);
}
const uint8_t *
ptr(const mod &mod,
const std::string &name)
{
return mod.ptr<uint8_t>(name);
}
bool
has(const mod &mod,
const std::string &name)
{
return mod.has(name);
}
} // namespace mods
} // namespace ircd
#endif // __cplusplus

File diff suppressed because it is too large Load diff

View file

@ -276,20 +276,17 @@ conf_set_serverinfo_nicklen(void *data)
static void static void
conf_set_modules_module(void *data) conf_set_modules_module(void *data)
{ {
char *m_bn; char *const m_bn = rb_basename((char *) data);
const scope free([&m_bn] { rb_free(m_bn); });
m_bn = rb_basename((char *) data); if(!mods::loaded(m_bn))
mods::load((const char *)data);
if(findmodule_byname(m_bn) == NULL)
load_one_module((char *) data, MAPI_ORIGIN_EXTENSION, false);
rb_free(m_bn);
} }
static void static void
conf_set_modules_path(void *data) conf_set_modules_path(void *data)
{ {
mod_add_path((char *) data); mods::path_add((char *) data, std::nothrow);
} }
struct mode_table_ struct mode_table_

View file

@ -23,6 +23,23 @@
* USA * USA
*/ */
/*
make_index<Message>(),
{
[](mod &mod, const std::string &name)
{
auto &tab(get<Message>(mod, name));
mod_add_cmd(&tab);
},
[](mod &mod, const std::string &name)
{
auto &tab(get<Message>(mod, name));
mod_del_cmd(&tab);
}
}
*/
namespace ircd { namespace ircd {
std::map<std::string, std::shared_ptr<alias_entry>, case_insensitive_less> alias_dict; std::map<std::string, std::shared_ptr<alias_entry>, case_insensitive_less> alias_dict;

View file

@ -1398,9 +1398,8 @@ clear_out_old_conf(void)
clear_s_newconf(); clear_s_newconf();
/* clean out module paths */ /* clean out module paths */
mod_clear_paths(); mods::path_clear();
mod_add_path(fs::MODULE_DIR); mods::path_add(fs::MODPATH);
mod_add_path(fs::AUTOMODPATH);
/* clean out ServerInfo */ /* clean out ServerInfo */
rb_free(ServerInfo.description); rb_free(ServerInfo.description);

View file

@ -1,11 +1,11 @@
AUTOMAKE_OPTIONS = subdir-objects moduledir=@moduledir@
auto_load_moddir=@moduledir@/autoload
AM_CPPFLAGS = \ AM_CPPFLAGS = \
-I$(top_srcdir)/include \ -I$(top_srcdir)/include \
$(LTDLINCL) \ $(LTDLINCL) \
@BOOST_CPPFLAGS@ \ @BOOST_CPPFLAGS@ \
-include $(top_srcdir)/include/ircd/ircd.h -include $(top_srcdir)/include/ircd/ircd.h \
-include $(top_srcdir)/include/ircd/mapi.h
AM_LDFLAGS = \ AM_LDFLAGS = \
-L$(top_srcdir)/ircd \ -L$(top_srcdir)/ircd \
@ -18,8 +18,9 @@ AM_LDFLAGS += \
-export-dynamic \ -export-dynamic \
-avoid-version \ -avoid-version \
-no-undefined \ -no-undefined \
--no-allow-shlib-undefined \ --no-allow-shlib-undefined
-export-symbols-regex _mheader # -export-symbols-regex IRCD_MODULE*
# -export-symbols-regex *
AM_LDFLAGS += \ AM_LDFLAGS += \
-lircd \ -lircd \
@ -27,181 +28,171 @@ AM_LDFLAGS += \
@LIBLTDL@ \ @LIBLTDL@ \
@BOOST_LIBS@ @BOOST_LIBS@
#m_ban_la_SOURCES = m_ban.cc
cap_account_tag_la_SOURCES = cap_account_tag.cc #m_die_la_SOURCES = m_die.cc
cap_server_time_la_SOURCES = cap_server_time.cc #m_error_la_SOURCES = m_error.cc
chm_nocolour_la_SOURCES = chm_nocolour.cc #m_join_la_SOURCES = m_join.cc
chm_noctcp_la_SOURCES = chm_noctcp.cc #m_kick_la_SOURCES = m_kick.cc
m_accept_la_SOURCES = m_accept.cc #m_kill_la_SOURCES = m_kill.cc
m_admin_la_SOURCES = m_admin.cc #m_message_la_SOURCES = m_message.cc
m_alias_la_SOURCES = m_alias.cc #m_mode_la_SOURCES = m_mode.cc
m_away_la_SOURCES = m_away.cc m_modules_la_SOURCES = m_modules.cc
m_cap_la_SOURCES = m_cap.cc #m_nick_la_SOURCES = m_nick.cc
m_capab_la_SOURCES = m_capab.cc #m_part_la_SOURCES = m_part.cc
m_certfp_la_SOURCES = m_certfp.cc #m_quit_la_SOURCES = m_quit.cc
m_challenge_la_SOURCES = m_challenge.cc #m_server_la_SOURCES = m_server.cc
m_chghost_la_SOURCES = m_chghost.cc #m_squit_la_SOURCES = m_squit.cc
m_close_la_SOURCES = m_close.cc #cap_account_tag_la_SOURCES = cap_account_tag.cc
m_connect_la_SOURCES = m_connect.cc #cap_server_time_la_SOURCES = cap_server_time.cc
m_dline_la_SOURCES = m_dline.cc #chm_nocolour_la_SOURCES = chm_nocolour.cc
m_encap_la_SOURCES = m_encap.cc #chm_noctcp_la_SOURCES = chm_noctcp.cc
m_etrace_la_SOURCES = m_etrace.cc #m_accept_la_SOURCES = m_accept.cc
m_grant_la_SOURCES = m_grant.cc #m_admin_la_SOURCES = m_admin.cc
m_help_la_SOURCES = m_help.cc #m_alias_la_SOURCES = m_alias.cc
m_info_la_SOURCES = m_info.cc #m_away_la_SOURCES = m_away.cc
m_invite_la_SOURCES = m_invite.cc #m_cap_la_SOURCES = m_cap.cc
m_ison_la_SOURCES = m_ison.cc #m_capab_la_SOURCES = m_capab.cc
m_kline_la_SOURCES = m_kline.cc #m_certfp_la_SOURCES = m_certfp.cc
m_knock_la_SOURCES = m_knock.cc #m_challenge_la_SOURCES = m_challenge.cc
m_links_la_SOURCES = m_links.cc #m_chghost_la_SOURCES = m_chghost.cc
m_list_la_SOURCES = m_list.cc #m_close_la_SOURCES = m_close.cc
m_lusers_la_SOURCES = m_lusers.cc #m_connect_la_SOURCES = m_connect.cc
m_map_la_SOURCES = m_map.cc #m_dline_la_SOURCES = m_dline.cc
m_monitor_la_SOURCES = m_monitor.cc #m_encap_la_SOURCES = m_encap.cc
m_motd_la_SOURCES = m_motd.cc #m_etrace_la_SOURCES = m_etrace.cc
m_names_la_SOURCES = m_names.cc #m_grant_la_SOURCES = m_grant.cc
m_oper_la_SOURCES = m_oper.cc #m_help_la_SOURCES = m_help.cc
m_operspy_la_SOURCES = m_operspy.cc #m_info_la_SOURCES = m_info.cc
m_pass_la_SOURCES = m_pass.cc #m_invite_la_SOURCES = m_invite.cc
m_ping_la_SOURCES = m_ping.cc #m_ison_la_SOURCES = m_ison.cc
m_pong_la_SOURCES = m_pong.cc #m_kline_la_SOURCES = m_kline.cc
m_post_la_SOURCES = m_post.cc #m_knock_la_SOURCES = m_knock.cc
m_privs_la_SOURCES = m_privs.cc #m_links_la_SOURCES = m_links.cc
m_rehash_la_SOURCES = m_rehash.cc #m_list_la_SOURCES = m_list.cc
m_restart_la_SOURCES = m_restart.cc #m_lusers_la_SOURCES = m_lusers.cc
m_resv_la_SOURCES = m_resv.cc #m_map_la_SOURCES = m_map.cc
m_sasl_la_SOURCES = m_sasl.cc #m_monitor_la_SOURCES = m_monitor.cc
m_scan_la_SOURCES = m_scan.cc #m_motd_la_SOURCES = m_motd.cc
m_services_la_SOURCES = m_services.cc #m_names_la_SOURCES = m_names.cc
m_set_la_SOURCES = m_set.cc #m_oper_la_SOURCES = m_oper.cc
m_signon_la_SOURCES = m_signon.cc #m_operspy_la_SOURCES = m_operspy.cc
m_snote_la_SOURCES = m_snote.cc #m_pass_la_SOURCES = m_pass.cc
m_starttls_la_SOURCES = m_starttls.cc #m_ping_la_SOURCES = m_ping.cc
m_stats_la_SOURCES = m_stats.cc #m_pong_la_SOURCES = m_pong.cc
m_svinfo_la_SOURCES = m_svinfo.cc #m_post_la_SOURCES = m_post.cc
m_tb_la_SOURCES = m_tb.cc #m_privs_la_SOURCES = m_privs.cc
m_testline_la_SOURCES = m_testline.cc #m_rehash_la_SOURCES = m_rehash.cc
m_testmask_la_SOURCES = m_testmask.cc #m_restart_la_SOURCES = m_restart.cc
m_tginfo_la_SOURCES = m_tginfo.cc #m_resv_la_SOURCES = m_resv.cc
m_time_la_SOURCES = m_time.cc #m_sasl_la_SOURCES = m_sasl.cc
m_topic_la_SOURCES = m_topic.cc #m_scan_la_SOURCES = m_scan.cc
m_trace_la_SOURCES = m_trace.cc #m_services_la_SOURCES = m_services.cc
m_unreject_la_SOURCES = m_unreject.cc #m_set_la_SOURCES = m_set.cc
m_user_la_SOURCES = m_user.cc #m_signon_la_SOURCES = m_signon.cc
m_userhost_la_SOURCES = m_userhost.cc #m_snote_la_SOURCES = m_snote.cc
m_users_la_SOURCES = m_users.cc #m_starttls_la_SOURCES = m_starttls.cc
m_version_la_SOURCES = m_version.cc #m_stats_la_SOURCES = m_stats.cc
m_wallops_la_SOURCES = m_wallops.cc #m_svinfo_la_SOURCES = m_svinfo.cc
m_who_la_SOURCES = m_who.cc #m_tb_la_SOURCES = m_tb.cc
m_whois_la_SOURCES = m_whois.cc #m_testline_la_SOURCES = m_testline.cc
m_whowas_la_SOURCES = m_whowas.cc #m_testmask_la_SOURCES = m_testmask.cc
m_xline_la_SOURCES = m_xline.cc #m_tginfo_la_SOURCES = m_tginfo.cc
sno_routing_la_SOURCES = sno_routing.cc #m_time_la_SOURCES = m_time.cc
#m_topic_la_SOURCES = m_topic.cc
auto_load_mod_LTLIBRARIES = \ #m_trace_la_SOURCES = m_trace.cc
cap_account_tag.la \ #m_unreject_la_SOURCES = m_unreject.cc
cap_server_time.la \ #m_user_la_SOURCES = m_user.cc
chm_nocolour.la \ #m_userhost_la_SOURCES = m_userhost.cc
chm_noctcp.la \ #m_users_la_SOURCES = m_users.cc
m_accept.la \ #m_version_la_SOURCES = m_version.cc
m_admin.la \ #m_wallops_la_SOURCES = m_wallops.cc
m_alias.la \ #m_who_la_SOURCES = m_who.cc
m_away.la \ #m_whois_la_SOURCES = m_whois.cc
m_cap.la \ #m_whowas_la_SOURCES = m_whowas.cc
m_capab.la \ #m_xline_la_SOURCES = m_xline.cc
m_certfp.la \ #sno_routing_la_SOURCES = sno_routing.cc
m_challenge.la \
m_chghost.la \
m_close.la \
m_connect.la \
m_dline.la \
m_encap.la \
m_etrace.la \
m_grant.la \
m_help.la \
m_info.la \
m_invite.la \
m_ison.la \
m_kline.la \
m_knock.la \
m_links.la \
m_list.la \
m_lusers.la \
m_map.la \
m_monitor.la \
m_motd.la \
m_names.la \
m_oper.la \
m_operspy.la \
m_pass.la \
m_ping.la \
m_pong.la \
m_post.la \
m_privs.la \
m_rehash.la \
m_restart.la \
m_resv.la \
m_sasl.la \
m_scan.la \
m_services.la \
m_set.la \
m_signon.la \
m_snote.la \
m_starttls.la \
m_stats.la \
m_svinfo.la \
m_tb.la \
m_testline.la \
m_testmask.la \
m_tginfo.la \
m_time.la \
m_topic.la \
m_trace.la \
m_unreject.la \
m_user.la \
m_userhost.la \
m_users.la \
m_version.la \
m_wallops.la \
m_who.la \
m_whois.la \
m_whowas.la \
m_xline.la \
sno_routing.la
core_m_ban_la_SOURCES = core/m_ban.cc
core_m_die_la_SOURCES = core/m_die.cc
core_m_error_la_SOURCES = core/m_error.cc
core_m_join_la_SOURCES = core/m_join.cc
core_m_kick_la_SOURCES = core/m_kick.cc
core_m_kill_la_SOURCES = core/m_kill.cc
core_m_message_la_SOURCES = core/m_message.cc
core_m_mode_la_SOURCES = core/m_mode.cc
core_m_modules_la_SOURCES = core/m_modules.cc
core_m_nick_la_SOURCES = core/m_nick.cc
core_m_part_la_SOURCES = core/m_part.cc
core_m_quit_la_SOURCES = core/m_quit.cc
core_m_server_la_SOURCES = core/m_server.cc
core_m_squit_la_SOURCES = core/m_squit.cc
module_LTLIBRARIES = \ module_LTLIBRARIES = \
core/m_ban.la \ m_modules.la
core/m_die.la \ # m_ban.la \
core/m_error.la \ # m_die.la \
core/m_join.la \ # m_error.la \
core/m_kick.la \ # m_join.la \
core/m_kill.la \ # m_kick.la \
core/m_message.la \ # m_kill.la \
core/m_mode.la \ # m_message.la \
core/m_modules.la \ # m_mode.la \
core/m_nick.la \ # m_nick.la \
core/m_part.la \ # m_part.la \
core/m_quit.la \ # m_quit.la \
core/m_server.la \ # m_server.la \
core/m_squit.la # m_squit.la \
# cap_account_tag.la \
# cap_server_time.la \
mrproper-local: # chm_nocolour.la \
rm -rf core/.deps # chm_noctcp.la \
rm -f core/.dirstamp # m_accept.la \
# m_admin.la \
# m_alias.la \
# m_away.la \
# m_cap.la \
# m_capab.la \
# m_certfp.la \
# m_challenge.la \
# m_chghost.la \
# m_close.la \
# m_connect.la \
# m_dline.la \
# m_encap.la \
# m_etrace.la \
# m_grant.la \
# m_help.la \
# m_info.la \
# m_invite.la \
# m_ison.la \
# m_kline.la \
# m_knock.la \
# m_links.la \
# m_list.la \
# m_lusers.la \
# m_map.la \
# m_monitor.la \
# m_motd.la \
# m_names.la \
# m_oper.la \
# m_operspy.la \
# m_pass.la \
# m_ping.la \
# m_pong.la \
# m_post.la \
# m_privs.la \
# m_rehash.la \
# m_restart.la \
# m_resv.la \
# m_sasl.la \
# m_scan.la \
# m_services.la \
# m_set.la \
# m_signon.la \
# m_snote.la \
# m_starttls.la \
# m_stats.la \
# m_svinfo.la \
# m_tb.la \
# m_testline.la \
# m_testmask.la \
# m_tginfo.la \
# m_time.la \
# m_topic.la \
# m_trace.la \
# m_unreject.la \
# m_user.la \
# m_userhost.la \
# m_users.la \
# m_version.la \
# m_wallops.la \
# m_who.la \
# m_whois.la \
# m_whowas.la \
# m_xline.la \
# sno_routing.la

View file

@ -1,5 +1,8 @@
/* modules/m_modules.c - module for module loading /* modules/m_modules.c - module for module loading
*
* Copyright (c) 2016 Charybdis Development Team
* Copyright (c) 2016 Elizabeth Myers <elizabeth@interlinked.me> * Copyright (c) 2016 Elizabeth Myers <elizabeth@interlinked.me>
* Copyright (c) 2016 Jason Volk <jason@zemos.net>
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -20,8 +23,6 @@
using namespace ircd; using namespace ircd;
static const char modules_desc[] = "Provides module management commands";
static void m_modlist(struct MsgBuf *, client::client &, client::client &, int, const char **); static void m_modlist(struct MsgBuf *, client::client &, client::client &, int, const char **);
static void mo_modload(struct MsgBuf *, client::client &, client::client &, int, const char **); static void mo_modload(struct MsgBuf *, client::client &, client::client &, int, const char **);
@ -35,10 +36,10 @@ static void me_modreload(struct MsgBuf *, client::client &, client::client &, in
static void me_modunload(struct MsgBuf *, client::client &, client::client &, int, const char **); static void me_modunload(struct MsgBuf *, client::client &, client::client &, int, const char **);
static void me_modrestart(struct MsgBuf *, client::client &, client::client &, int, const char **); static void me_modrestart(struct MsgBuf *, client::client &, client::client &, int, const char **);
static void do_modload(client::client &, const char *); static void do_modload(client::client &, const std::string &);
static void do_modunload(client::client &, const char *); static void do_modunload(client::client &, const std::string &);
static void do_modreload(client::client &, const char *); static void do_modreload(client::client &, const std::string &);
static void do_modlist(client::client &, const char *); static void do_modlist(client::client &, const std::string &);
static void do_modrestart(client::client &); static void do_modrestart(client::client &);
struct Message modload_msgtab = { struct Message modload_msgtab = {
@ -66,11 +67,19 @@ struct Message modrestart_msgtab = {
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modrestart, 0}, {mo_modrestart, 0}} {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modrestart, 0}, {mo_modrestart, 0}}
}; };
mapi_clist_av1 modules_clist[] = { &modload_msgtab, &modunload_msgtab, &modreload_msgtab, &modlist_msgtab, &modrestart_msgtab, NULL };
DECLARE_MODULE_AV2(modules, NULL, NULL, modules_clist, NULL, NULL, NULL, NULL, modules_desc); mapi::header IRCD_MODULE
{
"Provides module management commands",
mapi::NO_FLAGS,
&modload_msgtab,
&modunload_msgtab,
&modreload_msgtab,
&modlist_msgtab,
&modrestart_msgtab,
};
/* load a module .. */ // load a module ..
static void static void
mo_modload(struct MsgBuf *msgbuf_p, client::client &client, client::client &source, int parc, const char **parv) mo_modload(struct MsgBuf *msgbuf_p, client::client &client, client::client &source, int parc, const char **parv)
{ {
@ -106,7 +115,7 @@ me_modload(struct MsgBuf *msgbuf_p, client::client &client, client::client &sour
} }
/* unload a module .. */ // unload a module ..
static void static void
mo_modunload(struct MsgBuf *msgbuf_p, client::client &client, client::client &source, int parc, const char **parv) mo_modunload(struct MsgBuf *msgbuf_p, client::client &client, client::client &source, int parc, const char **parv)
{ {
@ -141,7 +150,7 @@ me_modunload(struct MsgBuf *msgbuf_p, client::client &client, client::client &so
do_modunload(source, parv[1]); do_modunload(source, parv[1]);
} }
/* unload and load in one! */ // unload and load in one!
static void static void
mo_modreload(struct MsgBuf *msgbuf_p, client::client &client, client::client &source, int parc, const char **parv) mo_modreload(struct MsgBuf *msgbuf_p, client::client &client, client::client &source, int parc, const char **parv)
{ {
@ -176,7 +185,7 @@ me_modreload(struct MsgBuf *msgbuf_p, client::client &client, client::client &so
do_modreload(source, parv[1]); do_modreload(source, parv[1]);
} }
/* list modules .. */ // list modules ..
static void static void
m_modlist(struct MsgBuf *msgbuf_p, client::client &client, client::client &source, int parc, const char **parv) m_modlist(struct MsgBuf *msgbuf_p, client::client &client, client::client &source, int parc, const char **parv)
{ {
@ -197,7 +206,7 @@ me_modlist(struct MsgBuf *msgbuf_p, client::client &client, client::client &sour
do_modlist(source, parv[1]); do_modlist(source, parv[1]);
} }
/* unload and reload all modules */ // unload and reload all modules
static void static void
mo_modrestart(struct MsgBuf *msgbuf_p, client::client &client, client::client &source, int parc, const char **parv) mo_modrestart(struct MsgBuf *msgbuf_p, client::client &client, client::client &source, int parc, const char **parv)
{ {
@ -233,87 +242,46 @@ me_modrestart(struct MsgBuf *msgbuf_p, client::client &client, client::client &s
} }
static void static void
do_modload(client::client &source, const char *module) do_modload(client::client &source,
const std::string &name)
try
{ {
char *m_bn = rb_basename(module); mods::load(name);
int origin; }
catch(const std::exception &e)
if(findmodule_byname(m_bn) != NULL) {
{ sendto_one_notice(&source, "%s", e.what());
sendto_one_notice(&source, ":Module %s is already loaded", m_bn);
rb_free(m_bn);
return;
}
origin = strcmp(module, m_bn) == 0 ? MAPI_ORIGIN_CORE : MAPI_ORIGIN_EXTENSION;
load_one_module(module, origin, false);
rb_free(m_bn);
} }
static void static void
do_modunload(client::client &source, const char *module) do_modunload(client::client &source,
const std::string &name)
try
{ {
struct module *mod; if(!mods::loaded(name))
char *m_bn = rb_basename(module);
if((mod = findmodule_byname(m_bn)) == NULL)
{ {
sendto_one_notice(&source, ":Module %s is not loaded", m_bn); sendto_one_notice(&source, ":%s is not loaded", name.c_str());
rb_free(m_bn);
return; return;
} }
if(mod->core) mods::unload(name);
{ }
sendto_one_notice(&source, ":Module %s is a core module and may not be unloaded", m_bn); catch(const std::exception &e)
rb_free(m_bn); {
return; sendto_one_notice(&source, "%s", e.what());
}
if(unload_one_module(m_bn, true) == false)
sendto_one_notice(&source, ":Module %s is not loaded", m_bn);
rb_free(m_bn);
} }
static void static void
do_modreload(client::client &source, const char *module) do_modreload(client::client &source,
const std::string &name)
{ {
struct module *mod;
int check_core;
char *m_bn = rb_basename(module);
if((mod = findmodule_byname(m_bn)) == NULL)
{
sendto_one_notice(&source, ":Module %s is not loaded", m_bn);
rb_free(m_bn);
return;
}
check_core = mod->core;
if(unload_one_module(m_bn, true) == false)
{
sendto_one_notice(&source, ":Module %s is not loaded", m_bn);
rb_free(m_bn);
return;
}
if((load_one_module(m_bn, mod->origin, check_core) == false) && check_core)
{
sendto_realops_snomask(sno::GENERAL, L_NETWIDE,
"Error reloading core module: %s: terminating ircd", m_bn);
ilog(L_MAIN, "Error loading core module %s: terminating ircd", m_bn);
exit(0);
}
rb_free(m_bn);
} }
static void static void
do_modrestart(client::client &source) do_modrestart(client::client &source)
{ {
/*
unsigned int modnum = 0; unsigned int modnum = 0;
rb_dlink_node *ptr, *nptr; rb_dlink_node *ptr, *nptr;
@ -339,65 +307,36 @@ do_modrestart(client::client &source)
} }
load_all_modules(false); load_all_modules(false);
load_core_modules(false);
rehash(false); rehash(false);
sendto_realops_snomask(sno::GENERAL, L_NETWIDE, sendto_realops_snomask(sno::GENERAL, L_NETWIDE,
"Module Restart: %u modules unloaded, %lu modules loaded", "Module Restart: %u modules unloaded, %lu modules loaded",
modnum, rb_dlink_list_length(&module_list)); modnum, rb_dlink_list_length(&module_list));
ilog(L_MAIN, "Module Restart: %u modules unloaded, %lu modules loaded", modnum, rb_dlink_list_length(&module_list)); ilog(L_MAIN, "Module Restart: %u modules unloaded, %lu modules loaded", modnum, rb_dlink_list_length(&module_list));
*/
} }
static void static void
do_modlist(client::client &source, const char *pattern) do_modlist(client::client &source, const std::string &pattern)
{ {
rb_dlink_node *ptr; for(const auto &pit : mods::loaded())
int i;
RB_DLINK_FOREACH(ptr, module_list.head)
{ {
struct module *mod = (module *)ptr->data; const auto &mod(*pit.second);
bool display = false; if(pattern.empty() || match(pattern, name(mod)))
const char *origin;
switch (mod->origin)
{
case MAPI_ORIGIN_EXTENSION:
origin = "extension";
display = true;
break;
case MAPI_ORIGIN_CORE:
origin = "builtin";
display = is(source, umode::OPER);
break;
default:
origin = "unknown";
display = is(source, umode::OPER);
break;
}
if(!display)
continue;
if(pattern)
{
if(match(pattern, mod->name))
{
sendto_one(&source, form_str(RPL_MODLIST),
me.name, source.name,
mod->name,
(unsigned long)(uintptr_t)mod->address, origin,
mod->core ? " (core)" : "", mod->version, mod->description);
}
}
else
{ {
sendto_one(&source, form_str(RPL_MODLIST), sendto_one(&source, form_str(RPL_MODLIST),
me.name, source.name, mod->name, me.name,
(unsigned long)(uintptr_t)mod->address, origin, source.name,
mod->core ? " (core)" : "", mod->version, mod->description); name(mod).c_str(),
ulong(0),
"*",
"*",
"*", //version(mod),
desc(mod));
} }
} }
sendto_one(&source, form_str(RPL_ENDOFMODLIST), me.name, source.name); sendto_one(&source, form_str(RPL_ENDOFMODLIST),
me.name,
source.name);
} }