Index: bitlbee.h
===================================================================
--- bitlbee.h (revision 0e48e549e7693f665b43bcad5e14ef26447bfe5b)
+++ bitlbee.h (revision d28fe1c4f463314a79f0a71f6f8a01db53e37253)
@@ -40,4 +40,5 @@
#define BITLBEE_VER(a, b, c) (((a) << 16) + ((b) << 8) + (c))
#define BITLBEE_VERSION_CODE BITLBEE_VER(3, 4, 2)
+#define BITLBEE_ABI_VERSION_CODE 1
#define MAX_STRING 511
Index: doc/user-guide/commands.xml
===================================================================
--- doc/user-guide/commands.xml (revision 0e48e549e7693f665b43bcad5e14ef26447bfe5b)
+++ doc/user-guide/commands.xml (revision d28fe1c4f463314a79f0a71f6f8a01db53e37253)
@@ -1835,4 +1835,16 @@
+
+ List all the external plugins
+ plugins
+
+
+
+ This gives you a list of all the external plugins.
+
+
+
+
+
List all the unanswered questions root asked
Index: otr.c
===================================================================
--- otr.c (revision 0e48e549e7693f665b43bcad5e14ef26447bfe5b)
+++ otr.c (revision d28fe1c4f463314a79f0a71f6f8a01db53e37253)
@@ -267,4 +267,20 @@
register_irc_plugin(&otr_plugin);
}
+
+#ifndef OTR_BI
+struct plugin_info *init_plugin_info(void)
+{
+ static struct plugin_info info = {
+ BITLBEE_ABI_VERSION_CODE,
+ "otr",
+ BITLBEE_VERSION,
+ "Off-the-Record communication",
+ NULL,
+ NULL
+ };
+
+ return &info;
+}
+#endif
gboolean otr_irc_new(irc_t *irc)
Index: protocols/nogaim.c
===================================================================
--- protocols/nogaim.c (revision 0e48e549e7693f665b43bcad5e14ef26447bfe5b)
+++ protocols/nogaim.c (revision d28fe1c4f463314a79f0a71f6f8a01db53e37253)
@@ -40,9 +40,24 @@
#ifdef WITH_PLUGINS
+GList *plugins = NULL;
+
+static gint pluginscmp(gconstpointer a, gconstpointer b, gpointer data)
+{
+ const struct plugin_info *ia = a;
+ const struct plugin_info *ib = b;
+
+ return g_strcasecmp(ia->name, ib->name);
+}
+
gboolean load_plugin(char *path)
{
+ GList *l;
+ struct plugin_info *i;
+ struct plugin_info *info;
+ struct plugin_info * (*info_function) (void) = NULL;
void (*init_function) (void);
GModule *mod = g_module_open(path, G_MODULE_BIND_LAZY);
+ gboolean loaded = FALSE;
if (!mod) {
@@ -51,11 +66,56 @@
}
+ if (g_module_symbol(mod, "init_plugin_info", (gpointer *) &info_function)) {
+ info = info_function();
+
+ if (info->abiver != BITLBEE_ABI_VERSION_CODE) {
+ log_message(LOGLVL_ERROR,
+ "`%s' uses ABI %u but %u is required\n",
+ path, info->abiver,
+ BITLBEE_ABI_VERSION_CODE);
+ g_module_close(mod);
+ return FALSE;
+ }
+
+ if (!info->name || !info->version) {
+ log_message(LOGLVL_ERROR,
+ "Name or version missing from the "
+ "plugin info in `%s'\n", path);
+ g_module_close(mod);
+ return FALSE;
+ }
+
+ for (l = plugins; l; l = l->next) {
+ i = l->data;
+
+ if (g_strcasecmp(i->name, info->name) == 0) {
+ loaded = TRUE;
+ break;
+ }
+ }
+
+ if (loaded) {
+ log_message(LOGLVL_WARNING,
+ "%s plugin already loaded\n",
+ info->name);
+ g_module_close(mod);
+ return FALSE;
+ }
+ } else {
+ log_message(LOGLVL_WARNING, "Can't find function `init_plugin_info' in `%s'\n", path);
+ }
+
if (!g_module_symbol(mod, "init_plugin", (gpointer *) &init_function)) {
log_message(LOGLVL_WARNING, "Can't find function `init_plugin' in `%s'\n", path);
+ g_module_close(mod);
return FALSE;
}
+ if (info_function) {
+ plugins = g_list_insert_sorted_with_data(plugins, info,
+ pluginscmp, NULL);
+ }
+
init_function();
-
return TRUE;
}
@@ -86,4 +146,9 @@
g_dir_close(dir);
}
+}
+
+GList *get_plugins()
+{
+ return plugins;
}
#endif
Index: protocols/nogaim.h
===================================================================
--- protocols/nogaim.h (revision 0e48e549e7693f665b43bcad5e14ef26447bfe5b)
+++ protocols/nogaim.h (revision d28fe1c4f463314a79f0a71f6f8a01db53e37253)
@@ -271,4 +271,18 @@
};
+struct plugin_info
+{
+ guint abiver;
+ const char *name;
+ const char *version;
+ const char *description;
+ const char *author;
+ const char *url;
+};
+
+#ifdef WITH_PLUGINS
+G_MODULE_EXPORT GList *get_plugins();
+#endif
+
/* im_api core stuff. */
void nogaim_init();
Index: protocols/skype/skype.c
===================================================================
--- protocols/skype/skype.c (revision 0e48e549e7693f665b43bcad5e14ef26447bfe5b)
+++ protocols/skype/skype.c (revision d28fe1c4f463314a79f0a71f6f8a01db53e37253)
@@ -1763,2 +1763,16 @@
register_protocol(ret);
}
+
+struct plugin_info *init_plugin_info(void)
+{
+ static struct plugin_info info = {
+ BITLBEE_ABI_VERSION_CODE,
+ "skype",
+ BITLBEE_VERSION,
+ "Skype protocol plugin",
+ NULL,
+ NULL
+ };
+
+ return &info;
+}
Index: root_commands.c
===================================================================
--- root_commands.c (revision 0e48e549e7693f665b43bcad5e14ef26447bfe5b)
+++ root_commands.c (revision d28fe1c4f463314a79f0a71f6f8a01db53e37253)
@@ -1106,4 +1106,34 @@
}
}
+
+#ifdef WITH_PLUGINS
+static void cmd_plugins(irc_t *irc, char **cmd)
+{
+ GList *l;
+ struct plugin_info *info;
+
+ for (l = get_plugins(); l; l = l->next) {
+ info = l->data;
+ irc_rootmsg(irc, "%s:", info->name);
+ irc_rootmsg(irc, " Version: %s", info->version);
+
+ if (info->description) {
+ irc_rootmsg(irc, " Description: %s", info->description);
+ }
+
+ if (info->author) {
+ irc_rootmsg(irc, " Author: %s", info->author);
+ }
+
+ if (info->url) {
+ irc_rootmsg(irc, " URL: %s", info->url);
+ }
+
+ if (l->next) {
+ irc_rootmsg(irc, "");
+ }
+ }
+}
+#endif
static void cmd_qlist(irc_t *irc, char **cmd)
@@ -1358,4 +1388,7 @@
{ "nick", 1, cmd_nick, 0 },
{ "no", 0, cmd_yesno, 0 },
+#ifdef WITH_PLUGINS
+ { "plugins", 0, cmd_plugins, 0 },
+#endif
{ "qlist", 0, cmd_qlist, 0 },
{ "register", 0, cmd_register, 0 },