Delete commands and features on unloading
authorMyhailo Danylenko <isbear@ukrpost.net>
Mon, 23 Feb 2009 17:05:43 +0200
changeset 2 a88a395e6868
parent 1 7d87d323c889
child 3 a5f864d4207f
Delete commands and features on unloading
TODO
main.c
--- a/TODO	Mon Feb 23 04:05:05 2009 +0200
+++ b/TODO	Mon Feb 23 17:05:43 2009 +0200
@@ -4,5 +4,5 @@
 settings list?
 non-setting settings?
 set package searching paths?
-register commands inside of lua object too, then unregister them on exit
+do uninitialization of commands and features with objects?
 
--- a/main.c	Mon Feb 23 04:05:05 2009 +0200
+++ b/main.c	Mon Feb 23 17:05:43 2009 +0200
@@ -6,6 +6,7 @@
 #include <lualib.h>
 #include <stdio.h>
 #include <stdlib.h>    // getenv
+#include <string.h>    // strcmp
 
 #include "util.h"
 #include "logprint.h"  // scr_LogPrint
@@ -152,72 +153,6 @@
 	return 1;
 }
 
-/// main.add_feature
-/// Adds xmlns to disco#info features list.
-/// A: string (xmlns)
-static int lua_main_add_feature (lua_State *L)
-{
-	xmpp_add_feature (luaL_checkstring (L, 1));
-	return 0;
-}
-
-/// main.del_feature
-/// Removes xmlns from disco#info features list.
-/// A: stirng (xmlns)
-static int lua_main_del_feature (lua_State *L)
-{
-	xmpp_del_feature (luaL_checkstring (L, 1));
-	return 0;
-}
-
-typedef struct {
-	int        reference;
-	lua_State *L;
-} lua_command_callback_t;
-
-/// command function
-/// Function to handle newly registered command.
-/// A: string (arguments)
-void lua_main_command_handler (char *args, lua_command_callback_t *cb)
-{
-	lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
-	lua_pushstring (cb->L, args);
-	if (lua_pcall (cb->L, 1, 0, 0)) {
-		scr_LogPrint (LPRINT_LOGNORM, "lua: Command execution error: %s", lua_tostring (cb->L, -1));
-		lua_pop (cb->L, 1);
-	}
-}
-
-/// main.add_command
-/// Associates mcabber command name with lua function.
-/// A: string (command name), command function
-static int lua_main_add_command (lua_State *L)
-{
-	const char             *name = luaL_checkstring (L, 1);
-	lua_command_callback_t *cb;
-	luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected");
-
-	cb = luaL_malloc (L, sizeof (lua_command_callback_t));
-	cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
-	cb->L         = L;
-	cmd_add (name, "", 0, 0, (void (*) (char *p)) lua_main_command_handler, cb);
-	return 0;
-}
-
-/// main.del_command
-/// Removes command from a list of commands.
-/// A: string (command name)
-static int lua_main_del_command (lua_State *L)
-{
-	const char *name = luaL_checkstring (L, 1);
-	lua_command_callback_t *cb = cmd_del (name);
-	if (cb) {
-		luaL_unref (L, LUA_REGISTRYINDEX, cb->reference);
-		luaL_free (L, cb);
-	}
-	return 0;
-}
-
 /// main.print_info
 /// Prints a system message to buddy's window.
 /// A: string (jid), string (message)
@@ -347,6 +282,94 @@
 	return 1;
 }
 
+// XMPP DISCO FEATURES
+
+GSList *lua_added_features = NULL;
+
+/// main.add_feature
+/// Adds xmlns to disco#info features list.
+/// A: string (xmlns)
+static int lua_main_add_feature (lua_State *L)
+{
+	const char *xmlns = luaL_checkstring (L, 1);
+	xmpp_add_feature (xmlns);
+	lua_added_features = g_slist_prepend (lua_added_features, g_strdup (xmlns));
+	return 0;
+}
+
+/// main.del_feature
+/// Removes xmlns from disco#info features list.
+/// A: stirng (xmlns)
+static int lua_main_del_feature (lua_State *L)
+{
+	const char *xmlns = luaL_checkstring (L, 1);
+	GSList     *el    = g_slist_find_custom (lua_added_features, xmlns, (GCompareFunc) strcmp);
+	xmpp_del_feature (xmlns);
+	if (el) {
+		g_free (el->data);
+		lua_added_features = g_slist_delete_link (lua_added_features, el);
+	}
+	return 0;
+}
+
+// MCABBER COMMANDS
+
+typedef struct {
+	int        reference;
+	lua_State *L;
+} lua_command_callback_t;
+
+static GSList *lua_added_commands = NULL;
+
+/// command function
+/// Function to handle newly registered command.
+/// A: string (arguments)
+void lua_main_command_handler (char *args, lua_command_callback_t *cb)
+{
+	lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
+	lua_pushstring (cb->L, args);
+	if (lua_pcall (cb->L, 1, 0, 0)) {
+		scr_LogPrint (LPRINT_LOGNORM, "lua: Command execution error: %s", lua_tostring (cb->L, -1));
+		lua_pop (cb->L, 1);
+	}
+}
+
+/// main.add_command
+/// Associates mcabber command name with lua function.
+/// A: string (command name), command function
+static int lua_main_add_command (lua_State *L)
+{
+	const char             *name = luaL_checkstring (L, 1);
+	lua_command_callback_t *cb;
+	luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected");
+
+	cb = luaL_malloc (L, sizeof (lua_command_callback_t));
+	cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
+	cb->L         = L;
+	cmd_add (name, "", 0, 0, (void (*) (char *p)) lua_main_command_handler, cb);
+	lua_added_commands = g_slist_prepend (lua_added_commands, g_strdup (name));
+	return 0;
+}
+
+/// main.del_command
+/// Removes command from a list of commands.
+/// A: string (command name)
+static int lua_main_del_command (lua_State *L)
+{
+	const char             *name = luaL_checkstring (L, 1);
+	GSList                 *el   = g_slist_find_custom (lua_added_commands, name, (GCompareFunc) strcmp);
+	lua_command_callback_t *cb   = cmd_del (name);
+	if (cb) {
+		luaL_unref (cb->L, LUA_REGISTRYINDEX, cb->reference);
+		luaL_free (cb->L, cb);
+	}
+	if (el) {
+		g_free (el->data);
+		lua_added_commands = g_slist_delete_link (lua_added_commands, el);
+	}
+	return 0;
+}
+
 // TIMER
 
 #define LUA_TIMER_PRIORITY ( G_PRIORITY_HIGH_IDLE )
@@ -595,6 +618,22 @@
 	return NULL;
 }
 
+static void lua_features_destroy (char *xmlns, gpointer ignore)
+{
+	xmpp_del_feature (xmlns);
+	g_free (xmlns);
+}
+
+static void lua_commands_destroy (char *name, gpointer ignore)
+{
+	lua_command_callback_t *cb = cmd_del (name);
+	if (cb) {
+		luaL_unref (cb->L, LUA_REGISTRYINDEX, cb->reference);
+		luaL_free (cb->L, cb);
+	}
+	g_free (name);
+}
+
 void g_module_unload (GModule *module)
 {
 	if (lua) {
@@ -605,9 +644,17 @@
 			scr_LogPrint (LPRINT_NORMAL, "lua: Error in hook_quit: %s", lua_tostring (lua, -1));
 			lua_pop (lua, 1);
 		}
-	
+
 		hk_del_handler ((hk_handler_t) lua_hook, lua);
 
+		g_slist_foreach (lua_added_features, (GFunc) lua_features_destroy, NULL);
+		g_slist_free (lua_added_features);
+		lua_added_features = NULL;
+
+		g_slist_foreach (lua_added_commands, (GFunc) lua_commands_destroy, NULL);
+		g_slist_free (lua_added_commands);
+		lua_added_commands = NULL;
+
 		lua_close (lua);
 		lua = NULL;
 	}