1
0
mirror of https://github.com/irssi/irssi.git synced 2024-11-03 04:27:19 -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:
Timo Sirainen 2001-08-14 00:41:59 +00:00 committed by cras
parent f584c1013c
commit 803d805016
23 changed files with 645 additions and 231 deletions

View File

@ -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 \

View File

@ -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
View 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
View 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

View File

@ -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)

View File

@ -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))

View File

@ -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)

View File

@ -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

View File

@ -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 },

View File

@ -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,

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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();

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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
View File

@ -0,0 +1,4 @@
#include "module.h"
#undef MODULE_NAME
#define MODULE_NAME "fe-common/perl"

View File

@ -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"

View File

@ -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)

View File

@ -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)