diff --git a/src/common.h b/src/common.h index 0cf951b3..966e28d0 100644 --- a/src/common.h +++ b/src/common.h @@ -6,6 +6,8 @@ #define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */ #define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */ +#define IRSSI_ABI_VERSION 1 + #define DEFAULT_SERVER_ADD_PORT 6667 #ifdef HAVE_CONFIG_H diff --git a/src/core/expandos.c b/src/core/expandos.c index 1fc517af..67aea837 100644 --- a/src/core/expandos.c +++ b/src/core/expandos.c @@ -414,6 +414,13 @@ static char *expando_releasetime(SERVER_REC *server, void *item, int *free_ret) return g_strdup_printf("%04d", IRSSI_VERSION_TIME); } +/* client abi */ +static char *expando_abiversion(SERVER_REC *server, void *item, int *free_ret) +{ + *free_ret = TRUE; + return g_strdup_printf("%d", IRSSI_ABI_VERSION); +} + /* current working directory */ static char *expando_workdir(SERVER_REC *server, void *item, int *free_ret) { @@ -658,6 +665,8 @@ void expandos_init(void) "", EXPANDO_NEVER, NULL); expando_create("versiontime", expando_releasetime, "", EXPANDO_NEVER, NULL); + expando_create("abiversion", expando_abiversion, + "", EXPANDO_NEVER, NULL); expando_create("W", expando_workdir, NULL); expando_create("Y", expando_realname, "window changed", EXPANDO_ARG_NONE, diff --git a/src/core/modules-load.c b/src/core/modules-load.c index 6086d9ae..9baac1d7 100644 --- a/src/core/modules-load.c +++ b/src/core/modules-load.c @@ -160,11 +160,14 @@ static int module_load_name(const char *path, const char *rootmodule, { void (*module_init) (void); void (*module_deinit) (void); + void (*module_version) (int *); GModule *gmodule; MODULE_REC *module; MODULE_FILE_REC *rec; + gpointer value_version = NULL; gpointer value1, value2 = NULL; - char *initfunc, *deinitfunc; + char *versionfunc, *initfunc, *deinitfunc; + int module_abi_version = 0; int found; gmodule = module_open(path, &found); @@ -176,6 +179,27 @@ static int module_load_name(const char *path, const char *rootmodule, return found ? 0 : -1; } + /* get the module's irssi abi version and bail out on mismatch */ + versionfunc = module_get_func(rootmodule, submodule, "abicheck"); + if (!g_module_symbol(gmodule, versionfunc, &value_version)) { + g_free(versionfunc); + module_error(MODULE_ERROR_VERSION_MISMATCH, "0", + rootmodule, submodule); + g_module_close(gmodule); + return 0; + } + g_free(versionfunc); + module_version = value_version; + module_version(&module_abi_version); + if (module_abi_version != IRSSI_ABI_VERSION) { + char *module_abi_versionstr = g_strdup_printf("%d", module_abi_version); + module_error(MODULE_ERROR_VERSION_MISMATCH, module_abi_versionstr, + rootmodule, submodule); + g_free(module_abi_versionstr); + g_module_close(gmodule); + return 0; + } + /* get the module's init() and deinit() functions */ initfunc = module_get_func(rootmodule, submodule, "init"); deinitfunc = module_get_func(rootmodule, submodule, "deinit"); diff --git a/src/core/modules.h b/src/core/modules.h index 75a77c77..b2fa2fa4 100644 --- a/src/core/modules.h +++ b/src/core/modules.h @@ -27,6 +27,7 @@ enum { MODULE_ERROR_ALREADY_LOADED, MODULE_ERROR_LOAD, + MODULE_ERROR_VERSION_MISMATCH, MODULE_ERROR_INVALID }; diff --git a/src/fe-common/core/fe-modules.c b/src/fe-common/core/fe-modules.c index df97ceb1..27b6b4c1 100644 --- a/src/fe-common/core/fe-modules.c +++ b/src/fe-common/core/fe-modules.c @@ -43,6 +43,10 @@ static void sig_module_error(void *number, const char *data, printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_MODULE_LOAD_ERROR, rootmodule, submodule, data); break; + case MODULE_ERROR_VERSION_MISMATCH: + printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, + TXT_MODULE_VERSION_MISMATCH, rootmodule, submodule, data); + break; case MODULE_ERROR_INVALID: printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_MODULE_INVALID, rootmodule, submodule); diff --git a/src/fe-common/core/module-formats.c b/src/fe-common/core/module-formats.c index 4ae26950..e6d32b6d 100644 --- a/src/fe-common/core/module-formats.c +++ b/src/fe-common/core/module-formats.c @@ -196,6 +196,7 @@ FORMAT_REC fecommon_core_formats[] = { { "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_version_mismatch", "{hilight $0/$1} is ABI version $2 but Irssi is version $abiversion, cannot load", 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 } }, diff --git a/src/fe-common/core/module-formats.h b/src/fe-common/core/module-formats.h index 18bf91f5..3f06bb97 100644 --- a/src/fe-common/core/module-formats.h +++ b/src/fe-common/core/module-formats.h @@ -166,6 +166,7 @@ enum { TXT_MODULE_ALREADY_LOADED, TXT_MODULE_NOT_LOADED, TXT_MODULE_LOAD_ERROR, + TXT_MODULE_VERSION_MISMATCH, TXT_MODULE_INVALID, TXT_MODULE_LOADED, TXT_MODULE_UNLOADED, diff --git a/src/irc/proxy/proxy.c b/src/irc/proxy/proxy.c index ce79e2b7..50a41b21 100644 --- a/src/irc/proxy/proxy.c +++ b/src/irc/proxy/proxy.c @@ -108,3 +108,8 @@ void irc_proxy_deinit(void) { proxy_listen_deinit(); } + +void irc_proxy_abicheck(int *version) +{ + *version = IRSSI_ABI_VERSION; +} diff --git a/src/perl/module.h b/src/perl/module.h index 2fd15137..3cbdf3d5 100644 --- a/src/perl/module.h +++ b/src/perl/module.h @@ -17,4 +17,4 @@ extern PerlInterpreter *my_perl; /* must be called my_perl or some perl implemen /* Change this every time when some API changes between irssi's perl module (or irssi itself) and irssi's perl libraries. */ -#define IRSSI_PERL_API_VERSION 20011214 +#define IRSSI_PERL_API_VERSION (20011214 + IRSSI_ABI_VERSION) diff --git a/src/perl/perl-core.c b/src/perl/perl-core.c index 1a864ef7..cb690906 100644 --- a/src/perl/perl-core.c +++ b/src/perl/perl-core.c @@ -479,3 +479,8 @@ void perl_core_deinit(void) signal_remove("script error", (SIGNAL_FUNC) sig_script_error); PERL_SYS_TERM(); } + +void perl_core_abicheck(int *version) +{ + *version = IRSSI_ABI_VERSION; +} diff --git a/src/perl/perl-fe.c b/src/perl/perl-fe.c index 2abc75c0..04305b63 100644 --- a/src/perl/perl-fe.c +++ b/src/perl/perl-fe.c @@ -278,3 +278,8 @@ void fe_perl_deinit(void) perl_core_print_script_error(TRUE); } + +void fe_perl_abicheck(int *version) +{ + *version = IRSSI_ABI_VERSION; +}