diff options
author | Timo Sirainen <cras@irssi.org> | 2001-08-14 00:41:59 +0000 |
---|---|---|
committer | cras <cras@dbcabf3a-b0e7-0310-adc4-f8d773084564> | 2001-08-14 00:41:59 +0000 |
commit | 803d8050164eaaefdd52fd4ae967c1e038b3c571 (patch) | |
tree | 615ff88add7d3682beebed692f41f5135c799713 | |
parent | f584c1013c74a98bfb43b79280c4ee20b775970a (diff) | |
download | irssi-803d8050164eaaefdd52fd4ae967c1e038b3c571.zip |
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
-rw-r--r-- | src/core/Makefile.am | 2 | ||||
-rw-r--r-- | src/core/core.c | 4 | ||||
-rw-r--r-- | src/core/modules-load.c | 388 | ||||
-rw-r--r-- | src/core/modules-load.h | 16 | ||||
-rw-r--r-- | src/core/modules.c | 219 | ||||
-rw-r--r-- | src/core/modules.h | 37 | ||||
-rw-r--r-- | src/fe-common/core/fe-common-core.c | 2 | ||||
-rw-r--r-- | src/fe-common/core/fe-modules.c | 155 | ||||
-rw-r--r-- | src/fe-common/core/module-formats.c | 15 | ||||
-rw-r--r-- | src/fe-common/core/module-formats.h | 1 | ||||
-rw-r--r-- | src/fe-common/irc/dcc/fe-dcc.c | 1 | ||||
-rw-r--r-- | src/fe-common/irc/fe-common-irc.c | 4 | ||||
-rw-r--r-- | src/fe-common/irc/notifylist/fe-notifylist.c | 2 | ||||
-rw-r--r-- | src/fe-text/irssi.c | 2 | ||||
-rw-r--r-- | src/irc/core/irc-core.c | 2 | ||||
-rw-r--r-- | src/irc/dcc/dcc.c | 2 | ||||
-rw-r--r-- | src/irc/flood/flood.c | 1 | ||||
-rw-r--r-- | src/irc/notifylist/notifylist.c | 2 | ||||
-rw-r--r-- | src/perl/Makefile.am | 1 | ||||
-rw-r--r-- | src/perl/module-fe.h | 4 | ||||
-rw-r--r-- | src/perl/module.h | 2 | ||||
-rw-r--r-- | src/perl/perl-core.c | 3 | ||||
-rw-r--r-- | src/perl/perl-fe.c | 5 |
23 files changed, 642 insertions, 228 deletions
diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 042ca8c6..ae932aa6 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -32,6 +32,7 @@ libcore_a_SOURCES = \ $(memdebug_src) \ misc.c \ modules.c \ + modules-load.c \ net-disconnect.c \ net-nonblock.c \ net-sendbuffer.c \ @@ -78,6 +79,7 @@ noinst_HEADERS = \ misc.h \ module.h \ modules.h \ + modules-load.h \ net-disconnect.h \ net-nonblock.h \ net-sendbuffer.h \ diff --git a/src/core/core.c b/src/core/core.c index c4600993..e3d3bebc 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -211,7 +211,9 @@ void core_init(int argc, char *argv[]) signal_add("setup changed", (SIGNAL_FUNC) read_signals); read_signals(); - settings_check(); + settings_check(); + + module_register("core", "core"); } void core_deinit(void) diff --git a/src/core/modules-load.c b/src/core/modules-load.c new file mode 100644 index 00000000..f55cdef3 --- /dev/null +++ b/src/core/modules-load.c @@ -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 diff --git a/src/core/modules-load.h b/src/core/modules-load.h new file mode 100644 index 00000000..42e14382 --- /dev/null +++ b/src/core/modules-load.h @@ -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 diff --git a/src/core/modules.c b/src/core/modules.c index f450f39d..dc373189 100644 --- a/src/core/modules.c +++ b/src/core/modules.c @@ -1,7 +1,7 @@ /* 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 it under the terms of the GNU General Public License as published by @@ -22,9 +22,6 @@ #include "modules.h" #include "signals.h" -#include "commands.h" -#include "settings.h" - GSList *modules; static GHashTable *uniqids, *uniqstrids; @@ -201,206 +198,62 @@ void module_uniq_destroy(const char *module) } } -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) { - GSList *tmp; + MODULE_REC *module; + MODULE_FILE_REC *file; - for (tmp = modules; tmp != NULL; tmp = tmp->next) { - MODULE_REC *rec = tmp->data; + module = module_find(name); + if (module == NULL) { + module = g_new0(MODULE_REC, 1); + module->name = g_strdup(name); - if (g_strcasecmp(rec->name, name) == 0) - return rec; + modules = g_slist_append(modules, module); } - return NULL; -} - -#ifdef HAVE_GMODULE -static char *module_get_name(const char *path, int *start, int *end) -{ - const char *name; - char *module_name, *ptr; + file = module_file_find(module, submodule); + if (file != NULL) + return file; - name = NULL; - if (g_path_is_absolute(path)) { - name = strrchr(path, G_DIR_SEPARATOR); - if (name != NULL) name++; - } + file = g_new0(MODULE_FILE_REC, 1); + file->root = module; + file->name = g_strdup(submodule); + file->defined_module_name = g_strdup(defined_module_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; + module->files = g_slist_append(module->files, file); + return file; } -static GModule *module_open(const char *name) +MODULE_REC *module_find(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) + GSList *tmp; -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; - } + for (tmp = modules; tmp != NULL; tmp = tmp->next) { + MODULE_REC *rec = tmp->data; - /* 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; + if (g_strcasecmp(rec->name, name) == 0) + return rec; } - 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; + return NULL; } -#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) +MODULE_FILE_REC *module_file_find(MODULE_REC *module, const char *name) { -#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; + GSList *tmp; - name = module_get_name(path, &start, &end); - if (module_find(name)) { - module_error(MODULE_ERROR_ALREADY_LOADED, name, NULL); - g_free(name); - return FALSE; - } + for (tmp = module->files; tmp != NULL; tmp = tmp->next) { + MODULE_FILE_REC *rec = tmp->data; - /* 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++; - } + if (strcmp(rec->name, name) == 0) + return rec; } - 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 + return NULL; } static void uniq_get_modules(char *key, void *value, GSList **list) diff --git a/src/core/modules.h b/src/core/modules.h index 7a83819f..bf2dba31 100644 --- a/src/core/modules.h +++ b/src/core/modules.h @@ -13,27 +13,50 @@ #define MODULE_DATA(rec) \ 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 { MODULE_ERROR_ALREADY_LOADED, MODULE_ERROR_LOAD, MODULE_ERROR_INVALID }; +typedef struct _MODULE_REC MODULE_REC; + typedef struct { + MODULE_REC *root; char *name; + char *defined_module_name; + #ifdef HAVE_GMODULE - GModule *gmodule; + GModule *gmodule; /* static, if NULL */ #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; -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 - modules given in `prefixes' (like irc, fe, fe_text, ..) */ -int module_load(const char *path, char **prefixes); -void module_unload(MODULE_REC *module); +MODULE_REC *module_find(const char *name); +MODULE_FILE_REC *module_file_find(MODULE_REC *module, const char *name); #define MODULE_CHECK_CAST(object, cast, type_field, id) \ ((cast *) module_check_cast(object, offsetof(cast, type_field), id)) diff --git a/src/fe-common/core/fe-common-core.c b/src/fe-common/core/fe-common-core.c index 66a2e602..0f5ce6ea 100644 --- a/src/fe-common/core/fe-common-core.c +++ b/src/fe-common/core/fe-common-core.c @@ -206,6 +206,8 @@ void fe_common_core_init(void) signal_add_last("server disconnected", (SIGNAL_FUNC) sig_disconnected); signal_add_first("channel created", (SIGNAL_FUNC) sig_channel_created); signal_add_last("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed); + + module_register("core", "fe"); } void fe_common_core_deinit(void) diff --git a/src/fe-common/core/fe-modules.c b/src/fe-common/core/fe-modules.c index e351dc71..5bbcf0b5 100644 --- a/src/fe-common/core/fe-modules.c +++ b/src/fe-common/core/fe-modules.c @@ -20,6 +20,7 @@ #include "module.h" #include "modules.h" +#include "modules-load.h" #include "module-formats.h" #include "signals.h" #include "commands.h" @@ -28,49 +29,99 @@ #include "printtext.h" -static void sig_module_error(void *number, const char *module, - const char *data) +#ifdef HAVE_GMODULE + +static void sig_module_error(void *number, const char *data, + const char *rootmodule, const char *submodule) { switch (GPOINTER_TO_INT(number)) { case MODULE_ERROR_ALREADY_LOADED: printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, - TXT_MODULE_ALREADY_LOADED, module); + TXT_MODULE_ALREADY_LOADED, rootmodule, submodule); break; case MODULE_ERROR_LOAD: printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, - TXT_MODULE_LOAD_ERROR, module, data); + TXT_MODULE_LOAD_ERROR, rootmodule, submodule, data); break; case MODULE_ERROR_INVALID: printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, - TXT_MODULE_INVALID, module); + TXT_MODULE_INVALID, rootmodule, submodule); 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, - 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) { - printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, - TXT_MODULE_UNLOADED, rec->name); + if (file != NULL && file->gmodule != NULL) { + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, + 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) { GSList *tmp; + GString *submodules; + const char *type; + int dynamic; + + submodules = g_string_new(NULL); - printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_MODULE_HEADER); + printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_MODULE_HEADER); for (tmp = modules; tmp != NULL; tmp = tmp->next) { MODULE_REC *rec = tmp->data; - printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, - TXT_MODULE_LINE, rec->name); + dynamic = module_list_sub(rec, FALSE, submodules); + 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) @@ -108,36 +159,67 @@ static void module_prefixes_free(char **list) g_free(list); } -/* SYNTAX: LOAD <module> */ +/* SYNTAX: LOAD <module> [<submodule>] */ static void cmd_load(const char *data) { -#ifdef HAVE_GMODULE + char *rootmodule, *submodule; char **module_prefixes; + void *free_arg; 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(); else { 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); } -#else - printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, - "Dynamic modules loading not supported"); -#endif + + cmd_params_free(free_arg); } -/* SYNTAX: UNLOAD <module> */ +/* SYNTAX: UNLOAD <module> [<submodule>] */ 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); - if (*data == '\0') cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS); - rec = module_find(data); - if (rec != NULL) module_unload(rec); + if (!cmd_get_params(data, &free_arg, 2 , &rootmodule, &submodule)) + 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) @@ -159,3 +241,22 @@ void fe_modules_deinit(void) command_unbind("load", (SIGNAL_FUNC) cmd_load); 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 diff --git a/src/fe-common/core/module-formats.c b/src/fe-common/core/module-formats.c index 46fe4de0..dbb8bb3e 100644 --- a/src/fe-common/core/module-formats.c +++ b/src/fe-common/core/module-formats.c @@ -179,14 +179,15 @@ FORMAT_REC fecommon_core_formats[] = { /* ---- */ { NULL, "Modules", 0 }, - { "module_header", "Loaded modules:", 0, }, - { "module_line", " $0", 1, { 0 } }, + { "module_header", "Module Type Submodules", 0, }, + { "module_line", "$[!20]0 $[7]1 $2", 3, { 0, 0, 0 } }, { "module_footer", "", 0, }, - { "module_already_loaded", "Module {hilight $0} already loaded", 1, { 0 } }, - { "module_load_error", "Error loading module {hilight $0}: $1", 2, { 0, 0 } }, - { "module_invalid", "{hilight $0} isn't Irssi module", 1, { 0 } }, - { "module_loaded", "Loaded module {hilight $0}", 1, { 0 } }, - { "module_unloaded", "Unloaded module {hilight $0}", 1, { 0 } }, + { "module_already_loaded", "Module {hilight $0/$1} already loaded", 2, { 0, 0 } }, + { "module_not_loaded", "Module {hilight $0/$1} is not loaded", 2, { 0, 0 } }, + { "module_load_error", "Error loading module {hilight $0/$1}: $2", 3, { 0, 0, 0 } }, + { "module_invalid", "{hilight $0/$1} isn't Irssi module", 2, { 0, 0 } }, + { "module_loaded", "Loaded module {hilight $0/$1}", 2, { 0, 0 } }, + { "module_unloaded", "Unloaded module {hilight $0/$1}", 2, { 0, 0 } }, /* ---- */ { NULL, "Commands", 0 }, diff --git a/src/fe-common/core/module-formats.h b/src/fe-common/core/module-formats.h index eacbc8aa..6e93f70c 100644 --- a/src/fe-common/core/module-formats.h +++ b/src/fe-common/core/module-formats.h @@ -153,6 +153,7 @@ enum { TXT_MODULE_LINE, TXT_MODULE_FOOTER, TXT_MODULE_ALREADY_LOADED, + TXT_MODULE_NOT_LOADED, TXT_MODULE_LOAD_ERROR, TXT_MODULE_INVALID, TXT_MODULE_LOADED, diff --git a/src/fe-common/irc/dcc/fe-dcc.c b/src/fe-common/irc/dcc/fe-dcc.c index 2989e3ab..afe230ec 100644 --- a/src/fe-common/irc/dcc/fe-dcc.c +++ b/src/fe-common/irc/dcc/fe-dcc.c @@ -139,6 +139,7 @@ void fe_irc_dcc_init(void) command_bind("dcc list", NULL, (SIGNAL_FUNC) cmd_dcc_list); theme_register(fecommon_irc_dcc_formats); + module_register("dcc", "fe-irc"); } void fe_irc_dcc_deinit(void) diff --git a/src/fe-common/irc/fe-common-irc.c b/src/fe-common/irc/fe-common-irc.c index aed6afac..5dfc2a25 100644 --- a/src/fe-common/irc/fe-common-irc.c +++ b/src/fe-common/irc/fe-common-irc.c @@ -85,8 +85,10 @@ void fe_common_irc_init(void) fe_netsplit_init(); fe_netjoin_init(); - fe_irc_modules_init(); settings_check(); + module_register("core", "fe-irc"); + + fe_irc_modules_init(); } void fe_common_irc_deinit(void) diff --git a/src/fe-common/irc/notifylist/fe-notifylist.c b/src/fe-common/irc/notifylist/fe-notifylist.c index 7253a042..b4532fb8 100644 --- a/src/fe-common/irc/notifylist/fe-notifylist.c +++ b/src/fe-common/irc/notifylist/fe-notifylist.c @@ -250,6 +250,8 @@ void fe_irc_notifylist_init(void) signal_add("notifylist unidle", (SIGNAL_FUNC) notifylist_unidle); command_set_options("notify", "list"); + + module_register("notifylist", "fe-irc"); } void fe_irc_notifylist_deinit(void) diff --git a/src/fe-text/irssi.c b/src/fe-text/irssi.c index cf6f974b..22f2b8d7 100644 --- a/src/fe-text/irssi.c +++ b/src/fe-text/irssi.c @@ -20,6 +20,7 @@ #include "module.h" #include "module-formats.h" +#include "modules-load.h" #include "args.h" #include "signals.h" #include "levels.h" @@ -135,6 +136,7 @@ static void textui_finish_init(void) screen_refresh_thaw(); settings_check(); + module_register("core", "fe-text"); fe_common_core_finish_init(); diff --git a/src/irc/core/irc-core.c b/src/irc/core/irc-core.c index b036d244..b203fe35 100644 --- a/src/irc/core/irc-core.c +++ b/src/irc/core/irc-core.c @@ -103,6 +103,8 @@ void irc_core_init(void) netsplit_init(); irc_rawlog_init(); irc_expandos_init(); + + module_register("core", "irc"); } void irc_core_deinit(void) diff --git a/src/irc/dcc/dcc.c b/src/irc/dcc/dcc.c index fa0853fb..49c68eb8 100644 --- a/src/irc/dcc/dcc.c +++ b/src/irc/dcc/dcc.c @@ -446,6 +446,8 @@ void irc_dcc_init(void) dcc_send_init(); dcc_resume_init(); dcc_autoget_init(); + + module_register("dcc", "irc"); } void irc_dcc_deinit(void) diff --git a/src/irc/flood/flood.c b/src/irc/flood/flood.c index 5381b1cc..aa383554 100644 --- a/src/irc/flood/flood.c +++ b/src/irc/flood/flood.c @@ -309,6 +309,7 @@ void irc_flood_init(void) signal_add("server disconnected", (SIGNAL_FUNC) flood_deinit_server); autoignore_init(); + module_register("flood", "irc"); } void irc_flood_deinit(void) diff --git a/src/irc/notifylist/notifylist.c b/src/irc/notifylist/notifylist.c index 2836d586..09a6f7c7 100644 --- a/src/irc/notifylist/notifylist.c +++ b/src/irc/notifylist/notifylist.c @@ -352,6 +352,8 @@ void irc_notifylist_init(void) signal_add("event join", (SIGNAL_FUNC) event_join); signal_add("channel wholist", (SIGNAL_FUNC) sig_channel_wholist); signal_add("setup reread", (SIGNAL_FUNC) notifylist_read_config); + + module_register("notifylist", "irc"); } void irc_notifylist_deinit(void) diff --git a/src/perl/Makefile.am b/src/perl/Makefile.am index 8ac1ffa7..e6208352 100644 --- a/src/perl/Makefile.am +++ b/src/perl/Makefile.am @@ -34,6 +34,7 @@ perl_fe_sources = \ noinst_HEADERS = \ module.h \ + module-fe.h \ module-formats.h \ perl-core.h \ perl-common.h \ diff --git a/src/perl/module-fe.h b/src/perl/module-fe.h new file mode 100644 index 00000000..2dc8c283 --- /dev/null +++ b/src/perl/module-fe.h @@ -0,0 +1,4 @@ +#include "module.h" + +#undef MODULE_NAME +#define MODULE_NAME "fe-common/perl" diff --git a/src/perl/module.h b/src/perl/module.h index 9c9f7399..0e95f13d 100644 --- a/src/perl/module.h +++ b/src/perl/module.h @@ -18,4 +18,4 @@ extern PerlInterpreter *my_perl; /* must be called my_perl or some perl implemen #include "common.h" -#define MODULE_NAME "irssi-perl" +#define MODULE_NAME "perl/core" diff --git a/src/perl/perl-core.c b/src/perl/perl-core.c index 0807fc72..914f6eff 100644 --- a/src/perl/perl-core.c +++ b/src/perl/perl-core.c @@ -20,6 +20,7 @@ #define NEED_PERL_H #include "module.h" +#include "modules.h" #include "signals.h" #include "misc.h" @@ -363,6 +364,8 @@ void perl_core_init(void) perl_scripts_init(); perl_scripts_autorun(); + + module_register("perl", "core"); } void perl_core_deinit(void) diff --git a/src/perl/perl-fe.c b/src/perl/perl-fe.c index cbdad663..27ac154b 100644 --- a/src/perl/perl-fe.c +++ b/src/perl/perl-fe.c @@ -18,7 +18,8 @@ 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 "signals.h" #include "commands.h" @@ -230,6 +231,8 @@ void fe_perl_init(void) 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 unload", (SIGNAL_FUNC) sig_complete_unload); + + module_register("perl", "fe"); } void fe_perl_deinit(void) |