* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
- * $Id: modules.c 3161 2007-01-25 07:23:01Z nenolod $
*/
#include "stdinc.h"
#include "numeric.h"
#include "parse.h"
#include "ircd_defs.h"
-#include "irc_string.h"
-#include "sprintf_irc.h"
+#include "match.h"
+#include "s_serv.h"
struct module **modlist = NULL;
static const char *core_module_table[] = {
+ "m_ban",
"m_die",
"m_error",
"m_join",
"m_kick",
"m_kill",
"m_message",
+ "m_metadata",
"m_mode",
"m_nick",
"m_part",
static int mo_modunload(struct Client *, struct Client *, int, const char **);
static int mo_modrestart(struct Client *, struct Client *, int, const char **);
+static int me_modload(struct Client *, struct Client *, int, const char **);
+static int me_modlist(struct Client *, struct Client *, int, const char **);
+static int me_modreload(struct Client *, struct Client *, int, const char **);
+static int me_modunload(struct Client *, struct Client *, int, const char **);
+static int me_modrestart(struct Client *, struct Client *, int, const char **);
+
+static int do_modload(struct Client *, const char *);
+static int do_modunload(struct Client *, const char *);
+static int do_modreload(struct Client *, const char *);
+static int do_modlist(struct Client *, const char *);
+static int do_modrestart(struct Client *);
+
struct Message modload_msgtab = {
"MODLOAD", 0, 0, 0, MFLG_SLOW,
- {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_modload, 2}}
+ {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modload, 2}, {mo_modload, 2}}
};
struct Message modunload_msgtab = {
"MODUNLOAD", 0, 0, 0, MFLG_SLOW,
- {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_modunload, 2}}
+ {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modunload, 2}, {mo_modunload, 2}}
};
struct Message modreload_msgtab = {
"MODRELOAD", 0, 0, 0, MFLG_SLOW,
- {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_modreload, 2}}
+ {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modreload, 2}, {mo_modreload, 2}}
};
struct Message modlist_msgtab = {
"MODLIST", 0, 0, 0, MFLG_SLOW,
- {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_modlist, 0}}
+ {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modlist, 0}, {mo_modlist, 0}}
};
struct Message modrestart_msgtab = {
"MODRESTART", 0, 0, 0, MFLG_SLOW,
- {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_modrestart, 0}}
+ {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modrestart, 0}, {mo_modrestart, 0}}
};
-extern struct Message error_msgtab;
-
void
modules_init(void)
{
mod_paths.length = 0;
}
-/* irc_basename
- *
- * input -
- * output -
- * side effects -
- */
-char *
-irc_basename(const char *path)
-{
- char *mod_basename = rb_malloc(strlen(path) + 1);
- const char *s;
-
- if(!(s = strrchr(path, '/')))
- s = path;
- else
- s++;
-
- (void) strcpy(mod_basename, s);
- return mod_basename;
-}
-
/* findmodule_byname
*
* input -
}
}
- sendto_realops_snomask(SNO_GENERAL, L_ALL, "Cannot locate module %s", path);
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Cannot locate module %s", path);
return -1;
}
static int
mo_modload(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
- char *m_bn;
-
if(!IsOperAdmin(source_p))
{
sendto_one(source_p, form_str(ERR_NOPRIVS),
return 0;
}
- m_bn = irc_basename(parv[1]);
+ if(parc > 2)
+ {
+ sendto_match_servs(source_p, parv[2], CAP_ENCAP, NOCAPS,
+ "ENCAP %s MODLOAD %s", parv[2], parv[1]);
+ if (match(parv[2], me.name) == 0)
+ return 0;
+ }
+
+ return do_modload(source_p, parv[1]);
+}
+
+static int
+me_modload(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
+{
+ if(!find_shared_conf(source_p->username, source_p->host, source_p->servptr->name, SHARED_MODULE))
+ {
+ sendto_one_notice(source_p, ":*** You do not have an appropriate shared block "
+ "to load modules on this server.");
+ return 0;
+ }
+
+ return do_modload(source_p, parv[1]);
+}
+
+static int
+do_modload(struct Client *source_p, const char *module)
+{
+ char *m_bn = rb_basename(module);
if(findmodule_byname(m_bn) != -1)
{
return 0;
}
- load_one_module(parv[1], 0);
+ load_one_module(module, 0);
rb_free(m_bn);
static int
mo_modunload(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
- char *m_bn;
- int modindex;
-
if(!IsOperAdmin(source_p))
{
sendto_one(source_p, form_str(ERR_NOPRIVS),
return 0;
}
- m_bn = irc_basename(parv[1]);
+ if(parc > 2)
+ {
+ sendto_match_servs(source_p, parv[2], CAP_ENCAP, NOCAPS,
+ "ENCAP %s MODUNLOAD %s", parv[2], parv[1]);
+ if (match(parv[2], me.name) == 0)
+ return 0;
+ }
+
+ return do_modunload(source_p, parv[1]);
+}
+
+static int
+me_modunload(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
+{
+ if(!find_shared_conf(source_p->username, source_p->host, source_p->servptr->name, SHARED_MODULE))
+ {
+ sendto_one_notice(source_p, ":*** You do not have an appropriate shared block "
+ "to load modules on this server.");
+ return 0;
+ }
+
+ return do_modunload(source_p, parv[1]);
+}
+
+static int
+do_modunload(struct Client *source_p, const char *module)
+{
+ int modindex;
+ char *m_bn = rb_basename(module);
if((modindex = findmodule_byname(m_bn)) == -1)
{
static int
mo_modreload(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
- char *m_bn;
- int modindex;
- int check_core;
-
if(!IsOperAdmin(source_p))
{
sendto_one(source_p, form_str(ERR_NOPRIVS),
return 0;
}
- m_bn = irc_basename(parv[1]);
+ if(parc > 2)
+ {
+ sendto_match_servs(source_p, parv[2], CAP_ENCAP, NOCAPS,
+ "ENCAP %s MODRELOAD %s", parv[2], parv[1]);
+ if (match(parv[2], me.name) == 0)
+ return 0;
+ }
+
+ return do_modreload(source_p, parv[1]);
+}
+
+static int
+me_modreload(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
+{
+ if(!find_shared_conf(source_p->username, source_p->host, source_p->servptr->name, SHARED_MODULE))
+ {
+ sendto_one_notice(source_p, ":*** You do not have an appropriate shared block "
+ "to load modules on this server.");
+ return 0;
+ }
+
+ return do_modreload(source_p, parv[1]);
+}
+
+static int
+do_modreload(struct Client *source_p, const char *module)
+{
+ int modindex;
+ int check_core;
+ char *m_bn = rb_basename(module);
if((modindex = findmodule_byname(m_bn)) == -1)
{
return 0;
}
- if((load_one_module(parv[1], check_core) == -1) && check_core)
+ if((load_one_module(m_bn, check_core) == -1) && check_core)
{
- sendto_realops_snomask(SNO_GENERAL, L_ALL,
- "Error reloading core module: %s: terminating ircd", parv[1]);
- ilog(L_MAIN, "Error loading core module %s: terminating ircd", parv[1]);
+ 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);
}
static int
mo_modlist(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
- int i;
-
if(!IsOperAdmin(source_p))
{
sendto_one(source_p, form_str(ERR_NOPRIVS),
return 0;
}
+ if(parc > 2)
+ {
+ sendto_match_servs(source_p, parv[2], CAP_ENCAP, NOCAPS,
+ "ENCAP %s MODLIST %s", parv[2], parv[1]);
+ if (match(parv[2], me.name) == 0)
+ return 0;
+ }
+
+ return do_modlist(source_p, parc > 1 ? parv[1] : 0);
+}
+
+static int
+me_modlist(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
+{
+ if(!find_shared_conf(source_p->username, source_p->host, source_p->servptr->name, SHARED_MODULE))
+ {
+ sendto_one_notice(source_p, ":*** You do not have an appropriate shared block "
+ "to load modules on this server.");
+ return 0;
+ }
+
+ return do_modlist(source_p, parv[1]);
+}
+
+static int
+do_modlist(struct Client *source_p, const char *pattern)
+{
+ int i;
+
for (i = 0; i < num_mods; i++)
{
- if(parc > 1)
+ if(pattern)
{
- if(match(parv[1], modlist[i]->name))
+ if(match(pattern, modlist[i]->name))
{
sendto_one(source_p, form_str(RPL_MODLIST),
me.name, source_p->name,
static int
mo_modrestart(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
- int modnum;
-
if(!IsOperAdmin(source_p))
{
sendto_one(source_p, form_str(ERR_NOPRIVS),
return 0;
}
+ if(parc > 1)
+ {
+ sendto_match_servs(source_p, parv[1], CAP_ENCAP, NOCAPS,
+ "ENCAP %s MODRESTART", parv[1]);
+ if (match(parv[1], me.name) == 0)
+ return 0;
+ }
+
+ return do_modrestart(source_p);
+}
+
+static int
+me_modrestart(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
+{
+ if(!find_shared_conf(source_p->username, source_p->host, source_p->servptr->name, SHARED_MODULE))
+ {
+ sendto_one_notice(source_p, ":*** You do not have an appropriate shared block "
+ "to load modules on this server.");
+ return 0;
+ }
+
+ return do_modrestart(source_p);
+}
+
+static int
+do_modrestart(struct Client *source_p)
+{
+ int modnum;
+
sendto_one_notice(source_p, ":Reloading all modules");
modnum = num_mods;
load_core_modules(0);
rehash(0);
- sendto_realops_snomask(SNO_GENERAL, L_ALL,
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"Module Restart: %d modules unloaded, %d modules loaded",
modnum, num_mods);
ilog(L_MAIN, "Module Restart: %d modules unloaded, %d modules loaded", modnum, num_mods);
#define RTLD_NOW RTLD_LAZY /* openbsd deficiency */
#endif
+#ifndef RTLD_LOCAL
+#define RTLD_LOCAL 0
+#endif
+
#ifdef CHARYBDIS_PROFILE
# ifndef RTLD_PROFILE
# warning libdl may not support profiling, sucks. :(
void
undefinedErrorHandler(const char *symbolName)
{
- sendto_realops_snomask(SNO_GENERAL, L_ALL, "Undefined symbol: %s", symbolName);
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Undefined symbol: %s", symbolName);
ilog(L_MAIN, "Undefined symbol: %s", symbolName);
return;
}
** This results in substantial leaking of memory... Should free one
** module, maybe?
*/
- sendto_realops_snomask(SNO_GENERAL, L_ALL,
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"Symbol `%s' found in `%s' and `%s'",
NSNameOfSymbol(s), NSNameOfModule(old), NSNameOfModule(new));
ilog(L_MAIN, "Symbol `%s' found in `%s' and `%s'",
linkEditErrorHandler(NSLinkEditErrors errorClass, int errnum,
const char *fileName, const char *errorString)
{
- sendto_realops_snomask(SNO_GENERAL, L_ALL,
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"Link editor error: %s for %s", errorString, fileName);
ilog(L_MAIN, "Link editor error: %s for %s", errorString, fileName);
return;
break;
}
default:
- sendto_realops_snomask(SNO_GENERAL, L_ALL,
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"Unknown/unsupported MAPI version %d when unloading %s!",
modlist[modindex]->mapi_version, modlist[modindex]->name);
ilog(L_MAIN, "Unknown/unsupported MAPI version %d when unloading %s!",
dlclose(modlist[modindex]->address);
rb_free(modlist[modindex]->name);
- memcpy(&modlist[modindex], &modlist[modindex + 1],
+ memmove(&modlist[modindex], &modlist[modindex + 1],
sizeof(struct module) * ((num_mods - 1) - modindex));
if(num_mods != 0)
if(warn == 1)
{
ilog(L_MAIN, "Module %s unloaded", name);
- sendto_realops_snomask(SNO_GENERAL, L_ALL, "Module %s unloaded", name);
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Module %s unloaded", name);
}
return 0;
int *mapi_version;
- mod_basename = irc_basename(path);
+ mod_basename = rb_basename(path);
#ifdef CHARYBDIS_PROFILE
- tmpptr = dlopen(path, RTLD_NOW | RTLD_PROFILE);
+ tmpptr = dlopen(path, RTLD_NOW | RTLD_LOCAL | RTLD_PROFILE);
#else
- tmpptr = dlopen(path, RTLD_NOW);
+ tmpptr = dlopen(path, RTLD_NOW | RTLD_LOCAL);
#endif
if(tmpptr == NULL)
{
const char *err = dlerror();
- sendto_realops_snomask(SNO_GENERAL, L_ALL,
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"Error loading module %s: %s", mod_basename, err);
ilog(L_MAIN, "Error loading module %s: %s", mod_basename, err);
rb_free(mod_basename);
&& (mapi_version = (int *) (uintptr_t) dlsym(tmpptr, "__mheader")) == NULL)
|| MAPI_MAGIC(*mapi_version) != MAPI_MAGIC_HDR)
{
- sendto_realops_snomask(SNO_GENERAL, L_ALL,
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"Data format error: module %s has no MAPI header.",
mod_basename);
ilog(L_MAIN, "Data format error: module %s has no MAPI header.", mod_basename);
{
ilog(L_MAIN, "Module %s indicated failure during load.",
mod_basename);
- sendto_realops_snomask(SNO_GENERAL, L_ALL,
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"Module %s indicated failure during load.",
mod_basename);
dlclose(tmpptr);
default:
ilog(L_MAIN, "Module %s has unknown/unsupported MAPI version %d.",
mod_basename, MAPI_VERSION(*mapi_version));
- sendto_realops_snomask(SNO_GENERAL, L_ALL,
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"Module %s has unknown/unsupported MAPI version %d.",
mod_basename, *mapi_version);
dlclose(tmpptr);
if(warn == 1)
{
- sendto_realops_snomask(SNO_GENERAL, L_ALL,
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"Module %s [version: %s; MAPI version: %d] loaded at 0x%lx",
mod_basename, ver, MAPI_VERSION(*mapi_version),
(unsigned long) tmpptr);