mirror of
https://github.com/irssi/irssi.git
synced 2024-12-04 14:46:39 -05:00
Module loading updates - /LOAD shows now also the statically loaded modules.
You can't /LOAD the same module twice. Syntax changed to /LOAD <module> [<submodule>], /UNLOAD <module> [<submodule>]. NOTE: all modules now need to call register_module() in their init() function. git-svn-id: http://svn.irssi.org/repos/irssi/trunk@1748 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
parent
f584c1013c
commit
803d805016
@ -32,6 +32,7 @@ libcore_a_SOURCES = \
|
|||||||
$(memdebug_src) \
|
$(memdebug_src) \
|
||||||
misc.c \
|
misc.c \
|
||||||
modules.c \
|
modules.c \
|
||||||
|
modules-load.c \
|
||||||
net-disconnect.c \
|
net-disconnect.c \
|
||||||
net-nonblock.c \
|
net-nonblock.c \
|
||||||
net-sendbuffer.c \
|
net-sendbuffer.c \
|
||||||
@ -78,6 +79,7 @@ noinst_HEADERS = \
|
|||||||
misc.h \
|
misc.h \
|
||||||
module.h \
|
module.h \
|
||||||
modules.h \
|
modules.h \
|
||||||
|
modules-load.h \
|
||||||
net-disconnect.h \
|
net-disconnect.h \
|
||||||
net-nonblock.h \
|
net-nonblock.h \
|
||||||
net-sendbuffer.h \
|
net-sendbuffer.h \
|
||||||
|
@ -212,6 +212,8 @@ void core_init(int argc, char *argv[])
|
|||||||
read_signals();
|
read_signals();
|
||||||
|
|
||||||
settings_check();
|
settings_check();
|
||||||
|
|
||||||
|
module_register("core", "core");
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_deinit(void)
|
void core_deinit(void)
|
||||||
|
388
src/core/modules-load.c
Normal file
388
src/core/modules-load.c
Normal file
@ -0,0 +1,388 @@
|
|||||||
|
/*
|
||||||
|
modules-load.c : irssi
|
||||||
|
|
||||||
|
Copyright (C) 1999-2001 Timo Sirainen
|
||||||
|
|
||||||
|
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
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "module.h"
|
||||||
|
#include "modules.h"
|
||||||
|
#include "modules-load.h"
|
||||||
|
#include "signals.h"
|
||||||
|
|
||||||
|
#include "settings.h"
|
||||||
|
#include "commands.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_GMODULE
|
||||||
|
|
||||||
|
/* Returns the module name without path, "lib" prefix or ".so" suffix */
|
||||||
|
static char *module_get_name(const char *path, int *start, int *end)
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
char *module_name, *ptr;
|
||||||
|
|
||||||
|
name = NULL;
|
||||||
|
if (g_path_is_absolute(path)) {
|
||||||
|
name = strrchr(path, G_DIR_SEPARATOR);
|
||||||
|
if (name != NULL) name++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name == NULL)
|
||||||
|
name = path;
|
||||||
|
|
||||||
|
if (strncmp(name, "lib", 3) == 0)
|
||||||
|
name += 3;
|
||||||
|
|
||||||
|
module_name = g_strdup(name);
|
||||||
|
ptr = strchr(module_name, '.');
|
||||||
|
if (ptr != NULL) *ptr = '\0';
|
||||||
|
|
||||||
|
*start = (int) (name-path);
|
||||||
|
*end = *start + (ptr == NULL ? strlen(name) :
|
||||||
|
(int) (ptr-module_name));
|
||||||
|
|
||||||
|
return module_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns the root module name for given submodule (eg. perl_core -> perl) */
|
||||||
|
static char *module_get_root(const char *name, char **prefixes)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
/* skip any of the prefixes.. */
|
||||||
|
while (*prefixes != NULL) {
|
||||||
|
len = strlen(*prefixes);
|
||||||
|
if (strncmp(name, *prefixes, len) == 0 && name[len] == '_') {
|
||||||
|
name += len+1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
prefixes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip the _core part */
|
||||||
|
len = strlen(name);
|
||||||
|
if (len > 5 && strcmp(name+len-5, "_core") == 0)
|
||||||
|
return g_strndup(name, len-5);
|
||||||
|
|
||||||
|
return g_strdup(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns the sub module name for given submodule (eg. perl_core -> core) */
|
||||||
|
static char *module_get_sub(const char *name, const char *root)
|
||||||
|
{
|
||||||
|
int rootlen, namelen;
|
||||||
|
|
||||||
|
namelen = strlen(name);
|
||||||
|
rootlen = strlen(root);
|
||||||
|
g_return_val_if_fail(namelen >= rootlen, g_strdup(name));
|
||||||
|
|
||||||
|
if (strncmp(name, root, rootlen) == 0 &&
|
||||||
|
strcmp(name+rootlen, "_core") == 0)
|
||||||
|
return g_strdup("core");
|
||||||
|
|
||||||
|
if (namelen+1 > rootlen && name[namelen-rootlen-1] == '_' &&
|
||||||
|
strcmp(name+namelen-rootlen, root) == 0)
|
||||||
|
return g_strndup(name, namelen-rootlen-1);
|
||||||
|
|
||||||
|
return g_strdup(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GModule *module_open(const char *name)
|
||||||
|
{
|
||||||
|
struct stat statbuf;
|
||||||
|
GModule *module;
|
||||||
|
char *path, *str;
|
||||||
|
|
||||||
|
if (g_path_is_absolute(name) ||
|
||||||
|
(*name == '.' && name[1] == G_DIR_SEPARATOR))
|
||||||
|
path = g_strdup(name);
|
||||||
|
else {
|
||||||
|
/* first try from home dir */
|
||||||
|
str = g_strdup_printf("%s/modules", get_irssi_dir());
|
||||||
|
path = g_module_build_path(str, name);
|
||||||
|
g_free(str);
|
||||||
|
|
||||||
|
if (stat(path, &statbuf) == 0) {
|
||||||
|
module = g_module_open(path, (GModuleFlags) 0);
|
||||||
|
g_free(path);
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* module not found from home dir, try global module dir */
|
||||||
|
g_free(path);
|
||||||
|
path = g_module_build_path(MODULEDIR, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
module = g_module_open(path, (GModuleFlags) 0);
|
||||||
|
g_free(path);
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define module_error(error, text, rootmodule, submodule) \
|
||||||
|
signal_emit("module error", 4, GINT_TO_POINTER(error), text, \
|
||||||
|
rootmodule, submodule)
|
||||||
|
|
||||||
|
static int module_load_name(const char *path, const char *rootmodule,
|
||||||
|
const char *submodule, int silent)
|
||||||
|
{
|
||||||
|
void (*module_init) (void);
|
||||||
|
GModule *gmodule;
|
||||||
|
MODULE_REC *module;
|
||||||
|
MODULE_FILE_REC *rec;
|
||||||
|
char *initfunc;
|
||||||
|
|
||||||
|
gmodule = module_open(path);
|
||||||
|
if (gmodule == NULL) {
|
||||||
|
if (!silent) {
|
||||||
|
module_error(MODULE_ERROR_LOAD, g_module_error(),
|
||||||
|
rootmodule, submodule);
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the module's init() function */
|
||||||
|
if (strcmp(submodule, "core") == 0)
|
||||||
|
initfunc = g_strconcat(rootmodule, "_core_init", NULL);
|
||||||
|
else {
|
||||||
|
initfunc = g_strconcat(submodule, "_",
|
||||||
|
rootmodule, "_init", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_module_symbol(gmodule, initfunc, (gpointer *) &module_init)) {
|
||||||
|
if (!silent)
|
||||||
|
module_error(MODULE_ERROR_INVALID, NULL,
|
||||||
|
rootmodule, submodule);
|
||||||
|
g_module_close(gmodule);
|
||||||
|
g_free(initfunc);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
g_free(initfunc);
|
||||||
|
|
||||||
|
/* Call the module's init() function - it should register itself
|
||||||
|
with module_register() function, abort if it doesn't. */
|
||||||
|
module_init();
|
||||||
|
|
||||||
|
module = module_find(rootmodule);
|
||||||
|
rec = module == NULL ? NULL : module_file_find(module, submodule);
|
||||||
|
if (rec == NULL) {
|
||||||
|
rec = module_register_full(rootmodule, submodule, NULL);
|
||||||
|
rec->gmodule = gmodule;
|
||||||
|
module_file_unload(rec);
|
||||||
|
|
||||||
|
module_error(MODULE_ERROR_INVALID, NULL,
|
||||||
|
rootmodule, submodule);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
rec->gmodule = gmodule;
|
||||||
|
rec->initialized = TRUE;
|
||||||
|
|
||||||
|
settings_check_module(rec->defined_module_name);
|
||||||
|
|
||||||
|
signal_emit("module loaded", 2, rec->root, rec);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int module_load_prefixes(const char *path, const char *module,
|
||||||
|
int start, int end, char **prefixes)
|
||||||
|
{
|
||||||
|
GString *realpath;
|
||||||
|
int ok;
|
||||||
|
|
||||||
|
/* load module_core */
|
||||||
|
realpath = g_string_new(path);
|
||||||
|
g_string_insert(realpath, end, "_core");
|
||||||
|
|
||||||
|
ok = module_load_name(realpath->str, module, "core", FALSE);
|
||||||
|
if (ok && prefixes != NULL) {
|
||||||
|
/* load all the "prefix modules", like the fe-common, irc,
|
||||||
|
etc. part of the module */
|
||||||
|
while (*prefixes != NULL) {
|
||||||
|
g_string_assign(realpath, path);
|
||||||
|
g_string_insert_c(realpath, start, '_');
|
||||||
|
g_string_insert(realpath, start, *prefixes);
|
||||||
|
|
||||||
|
module_load_name(realpath->str, module,
|
||||||
|
*prefixes, TRUE);
|
||||||
|
|
||||||
|
prefixes++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_string_free(realpath, TRUE);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int module_load_full(const char *path, const char *rootmodule,
|
||||||
|
const char *submodule, int start, int end,
|
||||||
|
char **prefixes)
|
||||||
|
{
|
||||||
|
MODULE_REC *module;
|
||||||
|
int ok, try_prefixes;
|
||||||
|
|
||||||
|
if (!g_module_supported())
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
module = module_find(rootmodule);
|
||||||
|
if (module != NULL && (strcmp(submodule, rootmodule) == 0 ||
|
||||||
|
module_file_find(module, submodule) != NULL)) {
|
||||||
|
/* module is already loaded */
|
||||||
|
module_error(MODULE_ERROR_ALREADY_LOADED, NULL,
|
||||||
|
rootmodule, submodule);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if the given module exists.. */
|
||||||
|
try_prefixes = strcmp(rootmodule, submodule) == 0;
|
||||||
|
ok = module_load_name(path, rootmodule, submodule, try_prefixes);
|
||||||
|
if (!ok && try_prefixes) {
|
||||||
|
/* nope, try loading the module_core,
|
||||||
|
fe_module, etc. */
|
||||||
|
ok = module_load_prefixes(path, rootmodule,
|
||||||
|
start, end, prefixes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load module - automatically tries to load also the related non-core
|
||||||
|
modules given in `prefixes' (like irc, fe, fe_text, ..) */
|
||||||
|
int module_load(const char *path, char **prefixes)
|
||||||
|
{
|
||||||
|
char *name, *submodule, *rootmodule;
|
||||||
|
int start, end, ret;
|
||||||
|
|
||||||
|
g_return_val_if_fail(path != NULL, FALSE);
|
||||||
|
|
||||||
|
name = module_get_name(path, &start, &end);
|
||||||
|
rootmodule = module_get_root(name, prefixes);
|
||||||
|
submodule = module_get_sub(name, rootmodule);
|
||||||
|
g_free(name);
|
||||||
|
|
||||||
|
ret = module_load_full(path, rootmodule, submodule,
|
||||||
|
start, end, prefixes);
|
||||||
|
|
||||||
|
g_free(rootmodule);
|
||||||
|
g_free(submodule);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load a sub module. */
|
||||||
|
int module_load_sub(const char *path, const char *submodule, char **prefixes)
|
||||||
|
{
|
||||||
|
GString *full_path;
|
||||||
|
char *name, *rootmodule;
|
||||||
|
int start, end, ret;
|
||||||
|
|
||||||
|
g_return_val_if_fail(path != NULL, FALSE);
|
||||||
|
g_return_val_if_fail(submodule != NULL, FALSE);
|
||||||
|
|
||||||
|
name = module_get_name(path, &start, &end);
|
||||||
|
rootmodule = module_get_root(name, prefixes);
|
||||||
|
g_free(name);
|
||||||
|
|
||||||
|
full_path = g_string_new(path);
|
||||||
|
if (strcmp(submodule, "core") == 0)
|
||||||
|
g_string_insert(full_path, end, "_core");
|
||||||
|
else {
|
||||||
|
g_string_insert_c(full_path, start, '_');
|
||||||
|
g_string_insert(full_path, start, submodule);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = module_load_full(full_path->str, rootmodule, submodule,
|
||||||
|
start, end, NULL);
|
||||||
|
|
||||||
|
g_string_free(full_path, TRUE);
|
||||||
|
g_free(rootmodule);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void module_file_deinit_gmodule(MODULE_FILE_REC *file)
|
||||||
|
{
|
||||||
|
void (*module_deinit) (void);
|
||||||
|
char *deinitfunc;
|
||||||
|
|
||||||
|
/* call the module's deinit() function */
|
||||||
|
if (strcmp(file->name, "core") == 0) {
|
||||||
|
deinitfunc = g_strconcat(file->root->name,
|
||||||
|
"_core_deinit", NULL);
|
||||||
|
} else {
|
||||||
|
deinitfunc = g_strconcat(file->name, "_",
|
||||||
|
file->root->name, "_deinit", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_module_symbol(file->gmodule, deinitfunc,
|
||||||
|
(gpointer *) &module_deinit))
|
||||||
|
module_deinit();
|
||||||
|
|
||||||
|
g_free(deinitfunc);
|
||||||
|
|
||||||
|
if (file->defined_module_name != NULL) {
|
||||||
|
settings_remove_module(file->defined_module_name);
|
||||||
|
commands_remove_module(file->defined_module_name);
|
||||||
|
signals_remove_module(file->defined_module_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_module_close(file->gmodule);
|
||||||
|
}
|
||||||
|
|
||||||
|
void module_file_unload(MODULE_FILE_REC *file)
|
||||||
|
{
|
||||||
|
MODULE_REC *root;
|
||||||
|
|
||||||
|
root = file->root;
|
||||||
|
root->files = g_slist_remove(root->files, file);
|
||||||
|
|
||||||
|
if (file->initialized)
|
||||||
|
signal_emit("module unloaded", 2, file->root, file);
|
||||||
|
|
||||||
|
if (file->gmodule != NULL)
|
||||||
|
module_file_deinit_gmodule(file);
|
||||||
|
|
||||||
|
g_free(file->name);
|
||||||
|
g_free(file->defined_module_name);
|
||||||
|
g_free(file);
|
||||||
|
|
||||||
|
if (root->files == NULL && g_slist_find(modules, root) != NULL)
|
||||||
|
module_unload(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
void module_unload(MODULE_REC *module)
|
||||||
|
{
|
||||||
|
g_return_if_fail(module != NULL);
|
||||||
|
|
||||||
|
modules = g_slist_remove(modules, module);
|
||||||
|
|
||||||
|
signal_emit("module unloaded", 1, module);
|
||||||
|
|
||||||
|
while (module->files != NULL)
|
||||||
|
module_file_unload(module->files->data);
|
||||||
|
|
||||||
|
g_free(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* !HAVE_GMODULE - modules are not supported */
|
||||||
|
|
||||||
|
int module_load(const char *path, char **prefixes)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void module_unload(MODULE_REC *module)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
16
src/core/modules-load.h
Normal file
16
src/core/modules-load.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef __MODULES_LOAD_H
|
||||||
|
#define __MODULES_LOAD_H
|
||||||
|
|
||||||
|
#include "modules.h"
|
||||||
|
|
||||||
|
/* Load module - automatically tries to load also the related non-core
|
||||||
|
modules given in `prefixes' (like irc, fe, fe_text, ..) */
|
||||||
|
int module_load(const char *path, char **prefixes);
|
||||||
|
|
||||||
|
/* Load a sub module. */
|
||||||
|
int module_load_sub(const char *path, const char *submodule, char **prefixes);
|
||||||
|
|
||||||
|
void module_unload(MODULE_REC *module);
|
||||||
|
void module_file_unload(MODULE_FILE_REC *file);
|
||||||
|
|
||||||
|
#endif
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
modules.c : irssi
|
modules.c : irssi
|
||||||
|
|
||||||
Copyright (C) 1999-2000 Timo Sirainen
|
Copyright (C) 1999-2001 Timo Sirainen
|
||||||
|
|
||||||
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
|
||||||
@ -22,9 +22,6 @@
|
|||||||
#include "modules.h"
|
#include "modules.h"
|
||||||
#include "signals.h"
|
#include "signals.h"
|
||||||
|
|
||||||
#include "commands.h"
|
|
||||||
#include "settings.h"
|
|
||||||
|
|
||||||
GSList *modules;
|
GSList *modules;
|
||||||
|
|
||||||
static GHashTable *uniqids, *uniqstrids;
|
static GHashTable *uniqids, *uniqstrids;
|
||||||
@ -201,6 +198,36 @@ void module_uniq_destroy(const char *module)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Register a new module. The `name' is the root module name, `submodule'
|
||||||
|
specifies the current module to be registered (eg. "perl", "fe").
|
||||||
|
The module is registered as statically loaded by default. */
|
||||||
|
MODULE_FILE_REC *module_register_full(const char *name, const char *submodule,
|
||||||
|
const char *defined_module_name)
|
||||||
|
{
|
||||||
|
MODULE_REC *module;
|
||||||
|
MODULE_FILE_REC *file;
|
||||||
|
|
||||||
|
module = module_find(name);
|
||||||
|
if (module == NULL) {
|
||||||
|
module = g_new0(MODULE_REC, 1);
|
||||||
|
module->name = g_strdup(name);
|
||||||
|
|
||||||
|
modules = g_slist_append(modules, module);
|
||||||
|
}
|
||||||
|
|
||||||
|
file = module_file_find(module, submodule);
|
||||||
|
if (file != NULL)
|
||||||
|
return file;
|
||||||
|
|
||||||
|
file = g_new0(MODULE_FILE_REC, 1);
|
||||||
|
file->root = module;
|
||||||
|
file->name = g_strdup(submodule);
|
||||||
|
file->defined_module_name = g_strdup(defined_module_name);
|
||||||
|
|
||||||
|
module->files = g_slist_append(module->files, file);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
MODULE_REC *module_find(const char *name)
|
MODULE_REC *module_find(const char *name)
|
||||||
{
|
{
|
||||||
GSList *tmp;
|
GSList *tmp;
|
||||||
@ -215,192 +242,18 @@ MODULE_REC *module_find(const char *name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_GMODULE
|
MODULE_FILE_REC *module_file_find(MODULE_REC *module, const char *name)
|
||||||
static char *module_get_name(const char *path, int *start, int *end)
|
|
||||||
{
|
{
|
||||||
const char *name;
|
GSList *tmp;
|
||||||
char *module_name, *ptr;
|
|
||||||
|
|
||||||
name = NULL;
|
for (tmp = module->files; tmp != NULL; tmp = tmp->next) {
|
||||||
if (g_path_is_absolute(path)) {
|
MODULE_FILE_REC *rec = tmp->data;
|
||||||
name = strrchr(path, G_DIR_SEPARATOR);
|
|
||||||
if (name != NULL) name++;
|
if (strcmp(rec->name, name) == 0)
|
||||||
|
return rec;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name == NULL)
|
return NULL;
|
||||||
name = path;
|
|
||||||
|
|
||||||
if (strncmp(name, "lib", 3) == 0)
|
|
||||||
name += 3;
|
|
||||||
|
|
||||||
module_name = g_strdup(name);
|
|
||||||
ptr = strchr(module_name, '.');
|
|
||||||
if (ptr != NULL) *ptr = '\0';
|
|
||||||
|
|
||||||
*start = (int) (name-path);
|
|
||||||
*end = *start + (ptr == NULL ? strlen(name) :
|
|
||||||
(int) (ptr-module_name));
|
|
||||||
|
|
||||||
return module_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GModule *module_open(const char *name)
|
|
||||||
{
|
|
||||||
struct stat statbuf;
|
|
||||||
GModule *module;
|
|
||||||
char *path, *str;
|
|
||||||
|
|
||||||
if (g_path_is_absolute(name) ||
|
|
||||||
(*name == '.' && name[1] == G_DIR_SEPARATOR))
|
|
||||||
path = g_strdup(name);
|
|
||||||
else {
|
|
||||||
/* first try from home dir */
|
|
||||||
str = g_strdup_printf("%s/modules", get_irssi_dir());
|
|
||||||
path = g_module_build_path(str, name);
|
|
||||||
g_free(str);
|
|
||||||
|
|
||||||
if (stat(path, &statbuf) == 0) {
|
|
||||||
module = g_module_open(path, (GModuleFlags) 0);
|
|
||||||
g_free(path);
|
|
||||||
return module;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* module not found from home dir, try global module dir */
|
|
||||||
g_free(path);
|
|
||||||
path = g_module_build_path(MODULEDIR, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
module = g_module_open(path, (GModuleFlags) 0);
|
|
||||||
g_free(path);
|
|
||||||
return module;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define module_error(error, module, text) \
|
|
||||||
signal_emit("module error", 3, GINT_TO_POINTER(error), module, text)
|
|
||||||
|
|
||||||
static int module_load_name(const char *path, const char *name, int silent)
|
|
||||||
{
|
|
||||||
void (*module_init) (void);
|
|
||||||
GModule *gmodule;
|
|
||||||
MODULE_REC *rec;
|
|
||||||
char *initfunc;
|
|
||||||
|
|
||||||
gmodule = module_open(path);
|
|
||||||
if (gmodule == NULL) {
|
|
||||||
if (!silent) {
|
|
||||||
module_error(MODULE_ERROR_LOAD, name,
|
|
||||||
g_module_error());
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get the module's init() function */
|
|
||||||
initfunc = g_strconcat(name, "_init", NULL);
|
|
||||||
if (!g_module_symbol(gmodule, initfunc, (gpointer *) &module_init)) {
|
|
||||||
if (!silent)
|
|
||||||
module_error(MODULE_ERROR_INVALID, name, NULL);
|
|
||||||
g_module_close(gmodule);
|
|
||||||
g_free(initfunc);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
g_free(initfunc);
|
|
||||||
|
|
||||||
rec = g_new0(MODULE_REC, 1);
|
|
||||||
rec->name = g_strdup(name);
|
|
||||||
rec->gmodule = gmodule;
|
|
||||||
modules = g_slist_append(modules, rec);
|
|
||||||
|
|
||||||
module_init();
|
|
||||||
settings_check_module(name);
|
|
||||||
|
|
||||||
signal_emit("module loaded", 1, rec);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Load module - automatically tries to load also the related non-core
|
|
||||||
modules given in `prefixes' (like irc, fe, fe_text, ..) */
|
|
||||||
int module_load(const char *path, char **prefixes)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_GMODULE
|
|
||||||
GString *realpath;
|
|
||||||
char *name, *pname;
|
|
||||||
int ret, start, end;
|
|
||||||
|
|
||||||
g_return_val_if_fail(path != NULL, FALSE);
|
|
||||||
|
|
||||||
if (!g_module_supported())
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
name = module_get_name(path, &start, &end);
|
|
||||||
if (module_find(name)) {
|
|
||||||
module_error(MODULE_ERROR_ALREADY_LOADED, name, NULL);
|
|
||||||
g_free(name);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* load "module_core" instead of "module" if it exists */
|
|
||||||
realpath = g_string_new(path);
|
|
||||||
g_string_insert(realpath, end, "_core");
|
|
||||||
|
|
||||||
pname = g_strconcat(name, "_core", NULL);
|
|
||||||
ret = module_load_name(realpath->str, pname, TRUE);
|
|
||||||
g_free(pname);
|
|
||||||
|
|
||||||
if (!ret) {
|
|
||||||
/* load "module" - complain if it's not found */
|
|
||||||
ret = module_load_name(path, name, FALSE);
|
|
||||||
} else if (prefixes != NULL) {
|
|
||||||
/* load all the "prefix modules", like the fe-common, irc,
|
|
||||||
etc. part of the module */
|
|
||||||
while (*prefixes != NULL) {
|
|
||||||
g_string_assign(realpath, path);
|
|
||||||
g_string_insert(realpath, start, "_");
|
|
||||||
g_string_insert(realpath, start, *prefixes);
|
|
||||||
|
|
||||||
pname = g_strconcat(*prefixes, "_", name, NULL);
|
|
||||||
module_load_name(realpath->str, pname, TRUE);
|
|
||||||
g_free(pname);
|
|
||||||
|
|
||||||
prefixes++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_string_free(realpath, TRUE);
|
|
||||||
g_free(name);
|
|
||||||
return ret;
|
|
||||||
#else
|
|
||||||
return FALSE;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void module_unload(MODULE_REC *module)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_GMODULE
|
|
||||||
void (*module_deinit) (void);
|
|
||||||
char *deinitfunc;
|
|
||||||
|
|
||||||
g_return_if_fail(module != NULL);
|
|
||||||
|
|
||||||
modules = g_slist_remove(modules, module);
|
|
||||||
|
|
||||||
signal_emit("module unloaded", 1, module);
|
|
||||||
|
|
||||||
/* call the module's deinit() function */
|
|
||||||
deinitfunc = g_strconcat(module->name, "_deinit", NULL);
|
|
||||||
if (g_module_symbol(module->gmodule, deinitfunc,
|
|
||||||
(gpointer *) &module_deinit))
|
|
||||||
module_deinit();
|
|
||||||
g_free(deinitfunc);
|
|
||||||
|
|
||||||
settings_remove_module(module->name);
|
|
||||||
commands_remove_module(module->name);
|
|
||||||
signals_remove_module(module->name);
|
|
||||||
|
|
||||||
g_module_close(module->gmodule);
|
|
||||||
g_free(module->name);
|
|
||||||
g_free(module);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void uniq_get_modules(char *key, void *value, GSList **list)
|
static void uniq_get_modules(char *key, void *value, GSList **list)
|
||||||
|
@ -13,27 +13,50 @@
|
|||||||
#define MODULE_DATA(rec) \
|
#define MODULE_DATA(rec) \
|
||||||
g_hash_table_lookup((rec)->module_data, MODULE_NAME)
|
g_hash_table_lookup((rec)->module_data, MODULE_NAME)
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_GMODULE
|
||||||
|
# define MODULE_IS_STATIC(rec) \
|
||||||
|
((rec)->gmodule == NULL)
|
||||||
|
#else
|
||||||
|
# define MODULE_IS_STATIC(rec) TRUE
|
||||||
|
#endif
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MODULE_ERROR_ALREADY_LOADED,
|
MODULE_ERROR_ALREADY_LOADED,
|
||||||
MODULE_ERROR_LOAD,
|
MODULE_ERROR_LOAD,
|
||||||
MODULE_ERROR_INVALID
|
MODULE_ERROR_INVALID
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct _MODULE_REC MODULE_REC;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
MODULE_REC *root;
|
||||||
char *name;
|
char *name;
|
||||||
|
char *defined_module_name;
|
||||||
|
|
||||||
#ifdef HAVE_GMODULE
|
#ifdef HAVE_GMODULE
|
||||||
GModule *gmodule;
|
GModule *gmodule; /* static, if NULL */
|
||||||
#endif
|
#endif
|
||||||
} MODULE_REC;
|
unsigned int initialized:1;
|
||||||
|
} MODULE_FILE_REC;
|
||||||
|
|
||||||
|
struct _MODULE_REC {
|
||||||
|
char *name;
|
||||||
|
GSList *files; /* list of modules that belong to this root module */
|
||||||
|
};
|
||||||
|
|
||||||
extern GSList *modules;
|
extern GSList *modules;
|
||||||
|
|
||||||
MODULE_REC *module_find(const char *name);
|
/* Register a new module. The `name' is the root module name, `submodule'
|
||||||
|
specifies the current module to be registered (eg. "perl", "fe").
|
||||||
|
The module is registered as statically loaded by default. */
|
||||||
|
MODULE_FILE_REC *module_register_full(const char *name, const char *submodule,
|
||||||
|
const char *defined_module_name);
|
||||||
|
#define module_register(name, submodule) \
|
||||||
|
module_register_full(name, submodule, MODULE_NAME)
|
||||||
|
|
||||||
/* Load module - automatically tries to load also the related non-core
|
MODULE_REC *module_find(const char *name);
|
||||||
modules given in `prefixes' (like irc, fe, fe_text, ..) */
|
MODULE_FILE_REC *module_file_find(MODULE_REC *module, const char *name);
|
||||||
int module_load(const char *path, char **prefixes);
|
|
||||||
void module_unload(MODULE_REC *module);
|
|
||||||
|
|
||||||
#define MODULE_CHECK_CAST(object, cast, type_field, id) \
|
#define MODULE_CHECK_CAST(object, cast, type_field, id) \
|
||||||
((cast *) module_check_cast(object, offsetof(cast, type_field), id))
|
((cast *) module_check_cast(object, offsetof(cast, type_field), id))
|
||||||
|
@ -206,6 +206,8 @@ void fe_common_core_init(void)
|
|||||||
signal_add_last("server disconnected", (SIGNAL_FUNC) sig_disconnected);
|
signal_add_last("server disconnected", (SIGNAL_FUNC) sig_disconnected);
|
||||||
signal_add_first("channel created", (SIGNAL_FUNC) sig_channel_created);
|
signal_add_first("channel created", (SIGNAL_FUNC) sig_channel_created);
|
||||||
signal_add_last("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
|
signal_add_last("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
|
||||||
|
|
||||||
|
module_register("core", "fe");
|
||||||
}
|
}
|
||||||
|
|
||||||
void fe_common_core_deinit(void)
|
void fe_common_core_deinit(void)
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
#include "modules.h"
|
#include "modules.h"
|
||||||
|
#include "modules-load.h"
|
||||||
#include "module-formats.h"
|
#include "module-formats.h"
|
||||||
#include "signals.h"
|
#include "signals.h"
|
||||||
#include "commands.h"
|
#include "commands.h"
|
||||||
@ -28,49 +29,99 @@
|
|||||||
|
|
||||||
#include "printtext.h"
|
#include "printtext.h"
|
||||||
|
|
||||||
static void sig_module_error(void *number, const char *module,
|
#ifdef HAVE_GMODULE
|
||||||
const char *data)
|
|
||||||
|
static void sig_module_error(void *number, const char *data,
|
||||||
|
const char *rootmodule, const char *submodule)
|
||||||
{
|
{
|
||||||
switch (GPOINTER_TO_INT(number)) {
|
switch (GPOINTER_TO_INT(number)) {
|
||||||
case MODULE_ERROR_ALREADY_LOADED:
|
case MODULE_ERROR_ALREADY_LOADED:
|
||||||
printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
|
printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
|
||||||
TXT_MODULE_ALREADY_LOADED, module);
|
TXT_MODULE_ALREADY_LOADED, rootmodule, submodule);
|
||||||
break;
|
break;
|
||||||
case MODULE_ERROR_LOAD:
|
case MODULE_ERROR_LOAD:
|
||||||
printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
|
printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
|
||||||
TXT_MODULE_LOAD_ERROR, module, data);
|
TXT_MODULE_LOAD_ERROR, rootmodule, submodule, data);
|
||||||
break;
|
break;
|
||||||
case MODULE_ERROR_INVALID:
|
case MODULE_ERROR_INVALID:
|
||||||
printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
|
printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
|
||||||
TXT_MODULE_INVALID, module);
|
TXT_MODULE_INVALID, rootmodule, submodule);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sig_module_loaded(MODULE_REC *rec)
|
static void sig_module_loaded(MODULE_REC *module, MODULE_FILE_REC *file)
|
||||||
{
|
{
|
||||||
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
|
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
|
||||||
TXT_MODULE_LOADED, rec->name);
|
TXT_MODULE_LOADED, module->name, file->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sig_module_unloaded(MODULE_REC *rec)
|
static void sig_module_unloaded(MODULE_REC *module, MODULE_FILE_REC *file)
|
||||||
{
|
{
|
||||||
|
if (file != NULL && file->gmodule != NULL) {
|
||||||
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
|
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
|
||||||
TXT_MODULE_UNLOADED, rec->name);
|
TXT_MODULE_UNLOADED, module->name, file->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int module_list_sub(MODULE_REC *module, int mark_type,
|
||||||
|
GString *submodules)
|
||||||
|
{
|
||||||
|
GSList *tmp;
|
||||||
|
int all_dynamic, dynamic;
|
||||||
|
|
||||||
|
g_string_truncate(submodules, 0);
|
||||||
|
|
||||||
|
all_dynamic = -1;
|
||||||
|
for (tmp = module->files; tmp != NULL; tmp = tmp->next) {
|
||||||
|
MODULE_FILE_REC *file = tmp->data;
|
||||||
|
|
||||||
|
/* if there's dynamic and static modules mixed, we'll need
|
||||||
|
to specify them separately */
|
||||||
|
if (!mark_type) {
|
||||||
|
dynamic = file->gmodule != NULL;
|
||||||
|
if (all_dynamic != -1 && all_dynamic != dynamic) {
|
||||||
|
return module_list_sub(module, TRUE,
|
||||||
|
submodules);
|
||||||
|
}
|
||||||
|
all_dynamic = dynamic;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (submodules->len > 0)
|
||||||
|
g_string_append_c(submodules, ' ');
|
||||||
|
g_string_append(submodules, file->name);
|
||||||
|
if (mark_type) {
|
||||||
|
g_string_append(submodules, file->gmodule == NULL ?
|
||||||
|
" (static)" : " (dynamic)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return all_dynamic;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cmd_load_list(void)
|
static void cmd_load_list(void)
|
||||||
{
|
{
|
||||||
GSList *tmp;
|
GSList *tmp;
|
||||||
|
GString *submodules;
|
||||||
|
const char *type;
|
||||||
|
int dynamic;
|
||||||
|
|
||||||
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_MODULE_HEADER);
|
submodules = g_string_new(NULL);
|
||||||
|
|
||||||
|
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_MODULE_HEADER);
|
||||||
for (tmp = modules; tmp != NULL; tmp = tmp->next) {
|
for (tmp = modules; tmp != NULL; tmp = tmp->next) {
|
||||||
MODULE_REC *rec = tmp->data;
|
MODULE_REC *rec = tmp->data;
|
||||||
|
|
||||||
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
|
dynamic = module_list_sub(rec, FALSE, submodules);
|
||||||
TXT_MODULE_LINE, rec->name);
|
type = dynamic == -1 ? "mixed" :
|
||||||
|
dynamic ? "dynamic" : "static";
|
||||||
|
|
||||||
|
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP,
|
||||||
|
TXT_MODULE_LINE, rec->name, type, submodules->str);
|
||||||
}
|
}
|
||||||
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_MODULE_FOOTER);
|
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_MODULE_FOOTER);
|
||||||
|
|
||||||
|
g_string_free(submodules, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char **module_prefixes_get(void)
|
static char **module_prefixes_get(void)
|
||||||
@ -108,36 +159,67 @@ static void module_prefixes_free(char **list)
|
|||||||
g_free(list);
|
g_free(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SYNTAX: LOAD <module> */
|
/* SYNTAX: LOAD <module> [<submodule>] */
|
||||||
static void cmd_load(const char *data)
|
static void cmd_load(const char *data)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_GMODULE
|
char *rootmodule, *submodule;
|
||||||
char **module_prefixes;
|
char **module_prefixes;
|
||||||
|
void *free_arg;
|
||||||
|
|
||||||
g_return_if_fail(data != NULL);
|
g_return_if_fail(data != NULL);
|
||||||
if (*data == '\0')
|
|
||||||
|
if (!cmd_get_params(data, &free_arg, 2 , &rootmodule, &submodule))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (*rootmodule == '\0')
|
||||||
cmd_load_list();
|
cmd_load_list();
|
||||||
else {
|
else {
|
||||||
module_prefixes = module_prefixes_get();
|
module_prefixes = module_prefixes_get();
|
||||||
module_load(data, module_prefixes);
|
if (*submodule == '\0')
|
||||||
|
module_load(rootmodule, module_prefixes);
|
||||||
|
else {
|
||||||
|
module_load_sub(rootmodule, submodule,
|
||||||
|
module_prefixes);
|
||||||
|
}
|
||||||
module_prefixes_free(module_prefixes);
|
module_prefixes_free(module_prefixes);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
|
cmd_params_free(free_arg);
|
||||||
"Dynamic modules loading not supported");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SYNTAX: UNLOAD <module> */
|
/* SYNTAX: UNLOAD <module> [<submodule>] */
|
||||||
static void cmd_unload(const char *data)
|
static void cmd_unload(const char *data)
|
||||||
{
|
{
|
||||||
MODULE_REC *rec;
|
MODULE_REC *module;
|
||||||
|
MODULE_FILE_REC *file;
|
||||||
|
char *rootmodule, *submodule;
|
||||||
|
void *free_arg;
|
||||||
|
|
||||||
g_return_if_fail(data != NULL);
|
g_return_if_fail(data != NULL);
|
||||||
if (*data == '\0') cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
|
|
||||||
|
|
||||||
rec = module_find(data);
|
if (!cmd_get_params(data, &free_arg, 2 , &rootmodule, &submodule))
|
||||||
if (rec != NULL) module_unload(rec);
|
return;
|
||||||
|
if (*rootmodule == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
|
||||||
|
|
||||||
|
module = module_find(rootmodule);
|
||||||
|
if (module != NULL) {
|
||||||
|
if (*submodule == '\0')
|
||||||
|
module_unload(module);
|
||||||
|
else {
|
||||||
|
file = module_file_find(module, submodule);
|
||||||
|
if (file != NULL)
|
||||||
|
module_file_unload(file);
|
||||||
|
else
|
||||||
|
module = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (module == NULL) {
|
||||||
|
printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
|
||||||
|
TXT_MODULE_NOT_LOADED, rootmodule, submodule);
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_params_free(free_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fe_modules_init(void)
|
void fe_modules_init(void)
|
||||||
@ -159,3 +241,22 @@ void fe_modules_deinit(void)
|
|||||||
command_unbind("load", (SIGNAL_FUNC) cmd_load);
|
command_unbind("load", (SIGNAL_FUNC) cmd_load);
|
||||||
command_unbind("unload", (SIGNAL_FUNC) cmd_unload);
|
command_unbind("unload", (SIGNAL_FUNC) cmd_unload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else /* !HAVE_GMODULE */
|
||||||
|
|
||||||
|
static void cmd_load(const char *data)
|
||||||
|
{
|
||||||
|
printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
|
||||||
|
"Dynamic modules loading not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
void fe_modules_init(void)
|
||||||
|
{
|
||||||
|
command_bind("load", NULL, (SIGNAL_FUNC) cmd_load);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fe_modules_deinit(void)
|
||||||
|
{
|
||||||
|
command_unbind("load", (SIGNAL_FUNC) cmd_load);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -179,14 +179,15 @@ FORMAT_REC fecommon_core_formats[] = {
|
|||||||
/* ---- */
|
/* ---- */
|
||||||
{ NULL, "Modules", 0 },
|
{ NULL, "Modules", 0 },
|
||||||
|
|
||||||
{ "module_header", "Loaded modules:", 0, },
|
{ "module_header", "Module Type Submodules", 0, },
|
||||||
{ "module_line", " $0", 1, { 0 } },
|
{ "module_line", "$[!20]0 $[7]1 $2", 3, { 0, 0, 0 } },
|
||||||
{ "module_footer", "", 0, },
|
{ "module_footer", "", 0, },
|
||||||
{ "module_already_loaded", "Module {hilight $0} already loaded", 1, { 0 } },
|
{ "module_already_loaded", "Module {hilight $0/$1} already loaded", 2, { 0, 0 } },
|
||||||
{ "module_load_error", "Error loading module {hilight $0}: $1", 2, { 0, 0 } },
|
{ "module_not_loaded", "Module {hilight $0/$1} is not loaded", 2, { 0, 0 } },
|
||||||
{ "module_invalid", "{hilight $0} isn't Irssi module", 1, { 0 } },
|
{ "module_load_error", "Error loading module {hilight $0/$1}: $2", 3, { 0, 0, 0 } },
|
||||||
{ "module_loaded", "Loaded module {hilight $0}", 1, { 0 } },
|
{ "module_invalid", "{hilight $0/$1} isn't Irssi module", 2, { 0, 0 } },
|
||||||
{ "module_unloaded", "Unloaded module {hilight $0}", 1, { 0 } },
|
{ "module_loaded", "Loaded module {hilight $0/$1}", 2, { 0, 0 } },
|
||||||
|
{ "module_unloaded", "Unloaded module {hilight $0/$1}", 2, { 0, 0 } },
|
||||||
|
|
||||||
/* ---- */
|
/* ---- */
|
||||||
{ NULL, "Commands", 0 },
|
{ NULL, "Commands", 0 },
|
||||||
|
@ -153,6 +153,7 @@ enum {
|
|||||||
TXT_MODULE_LINE,
|
TXT_MODULE_LINE,
|
||||||
TXT_MODULE_FOOTER,
|
TXT_MODULE_FOOTER,
|
||||||
TXT_MODULE_ALREADY_LOADED,
|
TXT_MODULE_ALREADY_LOADED,
|
||||||
|
TXT_MODULE_NOT_LOADED,
|
||||||
TXT_MODULE_LOAD_ERROR,
|
TXT_MODULE_LOAD_ERROR,
|
||||||
TXT_MODULE_INVALID,
|
TXT_MODULE_INVALID,
|
||||||
TXT_MODULE_LOADED,
|
TXT_MODULE_LOADED,
|
||||||
|
@ -139,6 +139,7 @@ void fe_irc_dcc_init(void)
|
|||||||
command_bind("dcc list", NULL, (SIGNAL_FUNC) cmd_dcc_list);
|
command_bind("dcc list", NULL, (SIGNAL_FUNC) cmd_dcc_list);
|
||||||
|
|
||||||
theme_register(fecommon_irc_dcc_formats);
|
theme_register(fecommon_irc_dcc_formats);
|
||||||
|
module_register("dcc", "fe-irc");
|
||||||
}
|
}
|
||||||
|
|
||||||
void fe_irc_dcc_deinit(void)
|
void fe_irc_dcc_deinit(void)
|
||||||
|
@ -85,8 +85,10 @@ void fe_common_irc_init(void)
|
|||||||
fe_netsplit_init();
|
fe_netsplit_init();
|
||||||
fe_netjoin_init();
|
fe_netjoin_init();
|
||||||
|
|
||||||
fe_irc_modules_init();
|
|
||||||
settings_check();
|
settings_check();
|
||||||
|
module_register("core", "fe-irc");
|
||||||
|
|
||||||
|
fe_irc_modules_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void fe_common_irc_deinit(void)
|
void fe_common_irc_deinit(void)
|
||||||
|
@ -250,6 +250,8 @@ void fe_irc_notifylist_init(void)
|
|||||||
signal_add("notifylist unidle", (SIGNAL_FUNC) notifylist_unidle);
|
signal_add("notifylist unidle", (SIGNAL_FUNC) notifylist_unidle);
|
||||||
|
|
||||||
command_set_options("notify", "list");
|
command_set_options("notify", "list");
|
||||||
|
|
||||||
|
module_register("notifylist", "fe-irc");
|
||||||
}
|
}
|
||||||
|
|
||||||
void fe_irc_notifylist_deinit(void)
|
void fe_irc_notifylist_deinit(void)
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
#include "module-formats.h"
|
#include "module-formats.h"
|
||||||
|
#include "modules-load.h"
|
||||||
#include "args.h"
|
#include "args.h"
|
||||||
#include "signals.h"
|
#include "signals.h"
|
||||||
#include "levels.h"
|
#include "levels.h"
|
||||||
@ -135,6 +136,7 @@ static void textui_finish_init(void)
|
|||||||
screen_refresh_thaw();
|
screen_refresh_thaw();
|
||||||
|
|
||||||
settings_check();
|
settings_check();
|
||||||
|
module_register("core", "fe-text");
|
||||||
|
|
||||||
fe_common_core_finish_init();
|
fe_common_core_finish_init();
|
||||||
|
|
||||||
|
@ -103,6 +103,8 @@ void irc_core_init(void)
|
|||||||
netsplit_init();
|
netsplit_init();
|
||||||
irc_rawlog_init();
|
irc_rawlog_init();
|
||||||
irc_expandos_init();
|
irc_expandos_init();
|
||||||
|
|
||||||
|
module_register("core", "irc");
|
||||||
}
|
}
|
||||||
|
|
||||||
void irc_core_deinit(void)
|
void irc_core_deinit(void)
|
||||||
|
@ -446,6 +446,8 @@ void irc_dcc_init(void)
|
|||||||
dcc_send_init();
|
dcc_send_init();
|
||||||
dcc_resume_init();
|
dcc_resume_init();
|
||||||
dcc_autoget_init();
|
dcc_autoget_init();
|
||||||
|
|
||||||
|
module_register("dcc", "irc");
|
||||||
}
|
}
|
||||||
|
|
||||||
void irc_dcc_deinit(void)
|
void irc_dcc_deinit(void)
|
||||||
|
@ -309,6 +309,7 @@ void irc_flood_init(void)
|
|||||||
signal_add("server disconnected", (SIGNAL_FUNC) flood_deinit_server);
|
signal_add("server disconnected", (SIGNAL_FUNC) flood_deinit_server);
|
||||||
|
|
||||||
autoignore_init();
|
autoignore_init();
|
||||||
|
module_register("flood", "irc");
|
||||||
}
|
}
|
||||||
|
|
||||||
void irc_flood_deinit(void)
|
void irc_flood_deinit(void)
|
||||||
|
@ -352,6 +352,8 @@ void irc_notifylist_init(void)
|
|||||||
signal_add("event join", (SIGNAL_FUNC) event_join);
|
signal_add("event join", (SIGNAL_FUNC) event_join);
|
||||||
signal_add("channel wholist", (SIGNAL_FUNC) sig_channel_wholist);
|
signal_add("channel wholist", (SIGNAL_FUNC) sig_channel_wholist);
|
||||||
signal_add("setup reread", (SIGNAL_FUNC) notifylist_read_config);
|
signal_add("setup reread", (SIGNAL_FUNC) notifylist_read_config);
|
||||||
|
|
||||||
|
module_register("notifylist", "irc");
|
||||||
}
|
}
|
||||||
|
|
||||||
void irc_notifylist_deinit(void)
|
void irc_notifylist_deinit(void)
|
||||||
|
@ -34,6 +34,7 @@ perl_fe_sources = \
|
|||||||
|
|
||||||
noinst_HEADERS = \
|
noinst_HEADERS = \
|
||||||
module.h \
|
module.h \
|
||||||
|
module-fe.h \
|
||||||
module-formats.h \
|
module-formats.h \
|
||||||
perl-core.h \
|
perl-core.h \
|
||||||
perl-common.h \
|
perl-common.h \
|
||||||
|
4
src/perl/module-fe.h
Normal file
4
src/perl/module-fe.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#include "module.h"
|
||||||
|
|
||||||
|
#undef MODULE_NAME
|
||||||
|
#define MODULE_NAME "fe-common/perl"
|
@ -18,4 +18,4 @@ extern PerlInterpreter *my_perl; /* must be called my_perl or some perl implemen
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#define MODULE_NAME "irssi-perl"
|
#define MODULE_NAME "perl/core"
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#define NEED_PERL_H
|
#define NEED_PERL_H
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
|
#include "modules.h"
|
||||||
#include "signals.h"
|
#include "signals.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
|
||||||
@ -363,6 +364,8 @@ void perl_core_init(void)
|
|||||||
|
|
||||||
perl_scripts_init();
|
perl_scripts_init();
|
||||||
perl_scripts_autorun();
|
perl_scripts_autorun();
|
||||||
|
|
||||||
|
module_register("perl", "core");
|
||||||
}
|
}
|
||||||
|
|
||||||
void perl_core_deinit(void)
|
void perl_core_deinit(void)
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "module.h"
|
#include "module-fe.h"
|
||||||
|
#include "modules.h"
|
||||||
#include "module-formats.h"
|
#include "module-formats.h"
|
||||||
#include "signals.h"
|
#include "signals.h"
|
||||||
#include "commands.h"
|
#include "commands.h"
|
||||||
@ -230,6 +231,8 @@ void fe_perl_init(void)
|
|||||||
signal_add("script error", (SIGNAL_FUNC) sig_script_error);
|
signal_add("script error", (SIGNAL_FUNC) sig_script_error);
|
||||||
signal_add("complete command script load", (SIGNAL_FUNC) sig_complete_load);
|
signal_add("complete command script load", (SIGNAL_FUNC) sig_complete_load);
|
||||||
signal_add("complete command script unload", (SIGNAL_FUNC) sig_complete_unload);
|
signal_add("complete command script unload", (SIGNAL_FUNC) sig_complete_unload);
|
||||||
|
|
||||||
|
module_register("perl", "fe");
|
||||||
}
|
}
|
||||||
|
|
||||||
void fe_perl_deinit(void)
|
void fe_perl_deinit(void)
|
||||||
|
Loading…
Reference in New Issue
Block a user