0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-26 05:48:20 +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);
});
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([limits], [LIMITS])
RB_CHK_SYSHEADER([type_traits], [TYPE_TRAITS])
RB_CHK_SYSHEADER([typeindex], [TYPEINDEX])
RB_CHK_SYSHEADER([utility], [UTILITY])
RB_CHK_SYSHEADER([functional], [FUNCTIONAL])
RB_CHK_SYSHEADER([algorithm], [ALGORITHM])

View file

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

View file

@ -46,8 +46,6 @@ namespace fs {
constexpr auto DPATH = IRCD_PREFIX;
constexpr auto BINPATH = IRCD_PREFIX "/bin";
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 LOGPATH = RB_LOG_DIR;
constexpr auto UHPATH = RB_HELP_DIR "/users";
@ -71,7 +69,6 @@ namespace path
LOG,
LIBEXEC,
MODULES,
AUTOLOAD_MODULES,
USERHELP,
OPERHELP,
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.
*
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid 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
* it under the terms of the GNU General Public License as published by
@ -25,173 +27,160 @@
#pragma once
#define HAVE_IRCD_MODULES_H
#define MAPI_CHARYBDIS 2
typedef struct lt__handle *lt_dlhandle;
#ifdef __cplusplus
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;
const char *path;
const char *version;
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;
std::function<void (mod &, const std::string &sym)> loader;
std::function<void (mod &, const std::string &sym)> unloader;
std::function<void (mod &, const std::string &sym)> reloader;
};
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)
#define MAPI_V2 (MAPI_MAGIC_HDR | 0x2)
#define MAPI_V3 (MAPI_MAGIC_HDR | 0x3)
// Dump object data
std::vector<std::string> symbols(const std::string &fullpath, const std::string &section);
std::vector<std::string> symbols(const std::string &fullpath);
std::vector<std::string> sections(const std::string &fullpath);
#define MAPI_MAGIC(x) ((x) & 0xffff0000)
#define MAPI_VERSION(x) ((x) & 0x0000ffff)
// Checks if loadable module containing a mapi header (does not verify the magic)
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;
int *hapi_id;
} mapi_hlist_av1;
return has(make_index<T>());
}
typedef struct
template<class T>
bool
del()
{
const char *hapi_name;
hookfn fn;
} mapi_hfn_list_av1;
return del(make_index<T>());
}
#define MAPI_CAP_CLIENT 1
#define MAPI_CAP_SERVER 2
typedef struct
template<class T,
class... type_handlers>
bool
add(type_handlers&&... handlers)
{
int cap_index; /* Which cap index does this belong to? */
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;
return add(make_index<T>(), {std::forward<type_handlers>(handlers)...});
}
struct mapi_mheader_av1
template<class T>
std::type_index
make_index()
{
int mapi_version; /* Module API version */
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) */
};
return typeid(typename std::add_pointer<T>::type);
}
#define MAPI_ORIGIN_UNKNOWN 0 /* Unknown provenance (AV1 etc.) */
#define MAPI_ORIGIN_EXTENSION 1 /* Charybdis extension */
#define MAPI_ORIGIN_CORE 2 /* Charybdis core module */
struct mapi_mheader_av2
template<class T>
T &
get(mod &mod,
const std::string &symbol)
{
int mapi_version; /* Module API version */
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 */
};
return *reinterpret_cast<T *>(ptr(mod, symbol));
}
#define DECLARE_MODULE_AV1(name, reg, unreg, cl, hl, hfnlist, v) \
struct mapi_mheader_av1 _mheader = { MAPI_V1, reg, unreg, cl, hl, hfnlist, v}
#define DECLARE_MODULE_AV2(name, reg, unreg, cl, hl, hfnlist, caplist, v, desc) \
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
template<class T>
T *
ptr(mod &mod,
const std::string &symbol)
{
#define MAPI_V3_KEY_MAXLEN 16 /* Maximum length for a key string */
return reinterpret_cast<T *>(ptr(mod, symbol));
}
const char *key;
union { const void *cvalue; void *value; int (*init)(void); void (*fini)(void); };
};
struct mapi_mheader_av3
template<class T>
const T &
get(const mod &mod,
const std::string &symbol)
{
int mapi_version; // Module API version
struct mapi_av3_attr **attrs; // A vector of attributes, NULL terminated
};
return *reinterpret_cast<const T *>(ptr(mod, symbol));
}
#define MOD_ATTR &(struct mapi_av3_attr)
#define MOD_HOOK &(mapi_hlist_av1)
#define MOD_HOOKFN &(mapi_hfn_list_av1)
#define DECLARE_MODULE_AV3(...) \
struct mapi_mheader_av3 _mheader = \
{ \
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;
template<class T>
const T *
ptr(const mod &mod,
const std::string &symbol)
{
return reinterpret_cast<const T *>(ptr(mod, symbol));
}
} // namespace mods
} // namespace ircd
#endif // __cplusplus

View file

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

View file

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

View file

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

View file

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

View file

@ -276,9 +276,9 @@ loadmodule:
char *m_bn;
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);

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
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(findmodule_byname(m_bn) == NULL)
load_one_module((char *) data, MAPI_ORIGIN_EXTENSION, false);
rb_free(m_bn);
if(!mods::loaded(m_bn))
mods::load((const char *)data);
}
static void
conf_set_modules_path(void *data)
{
mod_add_path((char *) data);
mods::path_add((char *) data, std::nothrow);
}
struct mode_table_

View file

@ -23,6 +23,23 @@
* 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 {
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();
/* clean out module paths */
mod_clear_paths();
mod_add_path(fs::MODULE_DIR);
mod_add_path(fs::AUTOMODPATH);
mods::path_clear();
mods::path_add(fs::MODPATH);
/* clean out ServerInfo */
rb_free(ServerInfo.description);

View file

@ -1,11 +1,11 @@
AUTOMAKE_OPTIONS = subdir-objects
auto_load_moddir=@moduledir@/autoload
moduledir=@moduledir@
AM_CPPFLAGS = \
-I$(top_srcdir)/include \
$(LTDLINCL) \
@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 = \
-L$(top_srcdir)/ircd \
@ -18,8 +18,9 @@ AM_LDFLAGS += \
-export-dynamic \
-avoid-version \
-no-undefined \
--no-allow-shlib-undefined \
-export-symbols-regex _mheader
--no-allow-shlib-undefined
# -export-symbols-regex IRCD_MODULE*
# -export-symbols-regex *
AM_LDFLAGS += \
-lircd \
@ -27,181 +28,171 @@ AM_LDFLAGS += \
@LIBLTDL@ \
@BOOST_LIBS@
cap_account_tag_la_SOURCES = cap_account_tag.cc
cap_server_time_la_SOURCES = cap_server_time.cc
chm_nocolour_la_SOURCES = chm_nocolour.cc
chm_noctcp_la_SOURCES = chm_noctcp.cc
m_accept_la_SOURCES = m_accept.cc
m_admin_la_SOURCES = m_admin.cc
m_alias_la_SOURCES = m_alias.cc
m_away_la_SOURCES = m_away.cc
m_cap_la_SOURCES = m_cap.cc
m_capab_la_SOURCES = m_capab.cc
m_certfp_la_SOURCES = m_certfp.cc
m_challenge_la_SOURCES = m_challenge.cc
m_chghost_la_SOURCES = m_chghost.cc
m_close_la_SOURCES = m_close.cc
m_connect_la_SOURCES = m_connect.cc
m_dline_la_SOURCES = m_dline.cc
m_encap_la_SOURCES = m_encap.cc
m_etrace_la_SOURCES = m_etrace.cc
m_grant_la_SOURCES = m_grant.cc
m_help_la_SOURCES = m_help.cc
m_info_la_SOURCES = m_info.cc
m_invite_la_SOURCES = m_invite.cc
m_ison_la_SOURCES = m_ison.cc
m_kline_la_SOURCES = m_kline.cc
m_knock_la_SOURCES = m_knock.cc
m_links_la_SOURCES = m_links.cc
m_list_la_SOURCES = m_list.cc
m_lusers_la_SOURCES = m_lusers.cc
m_map_la_SOURCES = m_map.cc
m_monitor_la_SOURCES = m_monitor.cc
m_motd_la_SOURCES = m_motd.cc
m_names_la_SOURCES = m_names.cc
m_oper_la_SOURCES = m_oper.cc
m_operspy_la_SOURCES = m_operspy.cc
m_pass_la_SOURCES = m_pass.cc
m_ping_la_SOURCES = m_ping.cc
m_pong_la_SOURCES = m_pong.cc
m_post_la_SOURCES = m_post.cc
m_privs_la_SOURCES = m_privs.cc
m_rehash_la_SOURCES = m_rehash.cc
m_restart_la_SOURCES = m_restart.cc
m_resv_la_SOURCES = m_resv.cc
m_sasl_la_SOURCES = m_sasl.cc
m_scan_la_SOURCES = m_scan.cc
m_services_la_SOURCES = m_services.cc
m_set_la_SOURCES = m_set.cc
m_signon_la_SOURCES = m_signon.cc
m_snote_la_SOURCES = m_snote.cc
m_starttls_la_SOURCES = m_starttls.cc
m_stats_la_SOURCES = m_stats.cc
m_svinfo_la_SOURCES = m_svinfo.cc
m_tb_la_SOURCES = m_tb.cc
m_testline_la_SOURCES = m_testline.cc
m_testmask_la_SOURCES = m_testmask.cc
m_tginfo_la_SOURCES = m_tginfo.cc
m_time_la_SOURCES = m_time.cc
m_topic_la_SOURCES = m_topic.cc
m_trace_la_SOURCES = m_trace.cc
m_unreject_la_SOURCES = m_unreject.cc
m_user_la_SOURCES = m_user.cc
m_userhost_la_SOURCES = m_userhost.cc
m_users_la_SOURCES = m_users.cc
m_version_la_SOURCES = m_version.cc
m_wallops_la_SOURCES = m_wallops.cc
m_who_la_SOURCES = m_who.cc
m_whois_la_SOURCES = m_whois.cc
m_whowas_la_SOURCES = m_whowas.cc
m_xline_la_SOURCES = m_xline.cc
sno_routing_la_SOURCES = sno_routing.cc
auto_load_mod_LTLIBRARIES = \
cap_account_tag.la \
cap_server_time.la \
chm_nocolour.la \
chm_noctcp.la \
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
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
#m_ban_la_SOURCES = m_ban.cc
#m_die_la_SOURCES = m_die.cc
#m_error_la_SOURCES = m_error.cc
#m_join_la_SOURCES = m_join.cc
#m_kick_la_SOURCES = m_kick.cc
#m_kill_la_SOURCES = m_kill.cc
#m_message_la_SOURCES = m_message.cc
#m_mode_la_SOURCES = m_mode.cc
m_modules_la_SOURCES = m_modules.cc
#m_nick_la_SOURCES = m_nick.cc
#m_part_la_SOURCES = m_part.cc
#m_quit_la_SOURCES = m_quit.cc
#m_server_la_SOURCES = m_server.cc
#m_squit_la_SOURCES = m_squit.cc
#cap_account_tag_la_SOURCES = cap_account_tag.cc
#cap_server_time_la_SOURCES = cap_server_time.cc
#chm_nocolour_la_SOURCES = chm_nocolour.cc
#chm_noctcp_la_SOURCES = chm_noctcp.cc
#m_accept_la_SOURCES = m_accept.cc
#m_admin_la_SOURCES = m_admin.cc
#m_alias_la_SOURCES = m_alias.cc
#m_away_la_SOURCES = m_away.cc
#m_cap_la_SOURCES = m_cap.cc
#m_capab_la_SOURCES = m_capab.cc
#m_certfp_la_SOURCES = m_certfp.cc
#m_challenge_la_SOURCES = m_challenge.cc
#m_chghost_la_SOURCES = m_chghost.cc
#m_close_la_SOURCES = m_close.cc
#m_connect_la_SOURCES = m_connect.cc
#m_dline_la_SOURCES = m_dline.cc
#m_encap_la_SOURCES = m_encap.cc
#m_etrace_la_SOURCES = m_etrace.cc
#m_grant_la_SOURCES = m_grant.cc
#m_help_la_SOURCES = m_help.cc
#m_info_la_SOURCES = m_info.cc
#m_invite_la_SOURCES = m_invite.cc
#m_ison_la_SOURCES = m_ison.cc
#m_kline_la_SOURCES = m_kline.cc
#m_knock_la_SOURCES = m_knock.cc
#m_links_la_SOURCES = m_links.cc
#m_list_la_SOURCES = m_list.cc
#m_lusers_la_SOURCES = m_lusers.cc
#m_map_la_SOURCES = m_map.cc
#m_monitor_la_SOURCES = m_monitor.cc
#m_motd_la_SOURCES = m_motd.cc
#m_names_la_SOURCES = m_names.cc
#m_oper_la_SOURCES = m_oper.cc
#m_operspy_la_SOURCES = m_operspy.cc
#m_pass_la_SOURCES = m_pass.cc
#m_ping_la_SOURCES = m_ping.cc
#m_pong_la_SOURCES = m_pong.cc
#m_post_la_SOURCES = m_post.cc
#m_privs_la_SOURCES = m_privs.cc
#m_rehash_la_SOURCES = m_rehash.cc
#m_restart_la_SOURCES = m_restart.cc
#m_resv_la_SOURCES = m_resv.cc
#m_sasl_la_SOURCES = m_sasl.cc
#m_scan_la_SOURCES = m_scan.cc
#m_services_la_SOURCES = m_services.cc
#m_set_la_SOURCES = m_set.cc
#m_signon_la_SOURCES = m_signon.cc
#m_snote_la_SOURCES = m_snote.cc
#m_starttls_la_SOURCES = m_starttls.cc
#m_stats_la_SOURCES = m_stats.cc
#m_svinfo_la_SOURCES = m_svinfo.cc
#m_tb_la_SOURCES = m_tb.cc
#m_testline_la_SOURCES = m_testline.cc
#m_testmask_la_SOURCES = m_testmask.cc
#m_tginfo_la_SOURCES = m_tginfo.cc
#m_time_la_SOURCES = m_time.cc
#m_topic_la_SOURCES = m_topic.cc
#m_trace_la_SOURCES = m_trace.cc
#m_unreject_la_SOURCES = m_unreject.cc
#m_user_la_SOURCES = m_user.cc
#m_userhost_la_SOURCES = m_userhost.cc
#m_users_la_SOURCES = m_users.cc
#m_version_la_SOURCES = m_version.cc
#m_wallops_la_SOURCES = m_wallops.cc
#m_who_la_SOURCES = m_who.cc
#m_whois_la_SOURCES = m_whois.cc
#m_whowas_la_SOURCES = m_whowas.cc
#m_xline_la_SOURCES = m_xline.cc
#sno_routing_la_SOURCES = sno_routing.cc
module_LTLIBRARIES = \
core/m_ban.la \
core/m_die.la \
core/m_error.la \
core/m_join.la \
core/m_kick.la \
core/m_kill.la \
core/m_message.la \
core/m_mode.la \
core/m_modules.la \
core/m_nick.la \
core/m_part.la \
core/m_quit.la \
core/m_server.la \
core/m_squit.la
mrproper-local:
rm -rf core/.deps
rm -f core/.dirstamp
m_modules.la
# m_ban.la \
# m_die.la \
# m_error.la \
# m_join.la \
# m_kick.la \
# m_kill.la \
# m_message.la \
# m_mode.la \
# m_nick.la \
# m_part.la \
# m_quit.la \
# m_server.la \
# m_squit.la \
# cap_account_tag.la \
# cap_server_time.la \
# chm_nocolour.la \
# chm_noctcp.la \
# 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
*
* Copyright (c) 2016 Charybdis Development Team
* 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
* purpose with or without fee is hereby granted, provided that the above
@ -20,8 +23,6 @@
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 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_modrestart(struct MsgBuf *, client::client &, client::client &, int, const char **);
static void do_modload(client::client &, const char *);
static void do_modunload(client::client &, const char *);
static void do_modreload(client::client &, const char *);
static void do_modlist(client::client &, const char *);
static void do_modload(client::client &, const std::string &);
static void do_modunload(client::client &, const std::string &);
static void do_modreload(client::client &, const std::string &);
static void do_modlist(client::client &, const std::string &);
static void do_modrestart(client::client &);
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}}
};
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
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
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]);
}
/* unload and load in one! */
// unload and load in one!
static void
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]);
}
/* list modules .. */
// list modules ..
static void
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]);
}
/* unload and reload all modules */
// unload and reload all modules
static void
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
do_modload(client::client &source, const char *module)
do_modload(client::client &source,
const std::string &name)
try
{
char *m_bn = rb_basename(module);
int origin;
if(findmodule_byname(m_bn) != NULL)
{
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);
mods::load(name);
}
catch(const std::exception &e)
{
sendto_one_notice(&source, "%s", e.what());
}
static void
do_modunload(client::client &source, const char *module)
do_modunload(client::client &source,
const std::string &name)
try
{
struct module *mod;
char *m_bn = rb_basename(module);
if((mod = findmodule_byname(m_bn)) == NULL)
if(!mods::loaded(name))
{
sendto_one_notice(&source, ":Module %s is not loaded", m_bn);
rb_free(m_bn);
sendto_one_notice(&source, ":%s is not loaded", name.c_str());
return;
}
if(mod->core)
{
sendto_one_notice(&source, ":Module %s is a core module and may not be unloaded", m_bn);
rb_free(m_bn);
return;
}
if(unload_one_module(m_bn, true) == false)
sendto_one_notice(&source, ":Module %s is not loaded", m_bn);
rb_free(m_bn);
mods::unload(name);
}
catch(const std::exception &e)
{
sendto_one_notice(&source, "%s", e.what());
}
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
do_modrestart(client::client &source)
{
/*
unsigned int modnum = 0;
rb_dlink_node *ptr, *nptr;
@ -339,65 +307,36 @@ do_modrestart(client::client &source)
}
load_all_modules(false);
load_core_modules(false);
rehash(false);
sendto_realops_snomask(sno::GENERAL, L_NETWIDE,
"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
do_modlist(client::client &source, const char *pattern)
do_modlist(client::client &source, const std::string &pattern)
{
rb_dlink_node *ptr;
int i;
RB_DLINK_FOREACH(ptr, module_list.head)
for(const auto &pit : mods::loaded())
{
struct module *mod = (module *)ptr->data;
bool display = false;
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
const auto &mod(*pit.second);
if(pattern.empty() || match(pattern, name(mod)))
{
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);
me.name,
source.name,
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);
}