diff --git a/ekg/commands.c b/ekg/commands.c
index 7e3ab5e..8a8d1b5 100644
--- a/ekg/commands.c
+++ b/ekg/commands.c
@@ -1687,10 +1687,11 @@ static COMMAND(cmd_set)
 	}
 
 	if ((!arg || !val) && !unset) {
-		variable_t *v;
+		GSList *vl;
 		int displayed = 0;
 
-		for (v = variables; v; v = v->next) {
+		for (vl = variables; vl; vl = vl->next) {
+			variable_t *v = vl->data;
 			if ((!arg || !xstrcasecmp(arg, v->name)) && (v->display != 2 || xstrcmp(name, ("set")))) {
 				int value;
 
diff --git a/ekg/completion.c b/ekg/completion.c
index 6f0a349..9e29685 100644
--- a/ekg/completion.c
+++ b/ekg/completion.c
@@ -232,9 +232,10 @@ static void plugin_generator(const char *text, int len)
 
 static void variable_generator(const char *text, int len)
 {
-	variable_t *v;
+	GSList *vl;
 
-	for (v = variables; v; v = v->next) {
+	for (vl = variables; vl; vl = vl->next) {
+		variable_t *v = vl->data;
 		if (*text == '-') {
 			if (!xstrncasecmp(text + 1, v->name, len - 1))
 				array_add_check(&completions, 
diff --git a/ekg/configfile.c b/ekg/configfile.c
index 38b3ce0..f04e5db 100644
--- a/ekg/configfile.c
+++ b/ekg/configfile.c
@@ -390,9 +390,10 @@ static void config_write_main(FILE *f)
 		return;
 
 	{
-		variable_t *v;
+		GSList *vl;
 
-		for (v = variables; v; v = v->next) {
+		for (vl = variables; vl; vl = vl->next) {
+			variable_t *v = vl->data;
 			if (!v->plugin)
 				config_write_variable(f, v);
 		}
@@ -520,7 +521,7 @@ int config_write()
 	/* now plugins variables */
 	for (p = plugins; p; p = p->next) {
 		const char *tmp;
-		variable_t *v;
+		GSList *vl;
 
 		if (!(tmp = prepare_pathf("config-%s", p->name)))
 			return -1;
@@ -530,7 +531,8 @@ int config_write()
 
 		fchmod(fileno(f), 0600);
 
-		for (v = variables; v; v = v->next) {
+		for (vl = variables; vl; vl = vl->next) {
+			variable_t *v = vl->data;
 			if (p == v->plugin) {
 				config_write_variable(f, v);
 			}
@@ -704,7 +706,7 @@ void config_write_crash()
 
 	/* now plugins variables */
 	for (p = plugins; p; p = p->next) {
-		variable_t *v;
+		GSList *vl;
 
 		snprintf(name, sizeof(name), "config-%s.%d", p->name, (int) getpid());
 
@@ -713,7 +715,8 @@ void config_write_crash()
 	
 		chmod(name, 0400);
 
-		for (v = variables; v; v = v->next) {
+		for (vl = variables; vl; vl = vl->next) {
+			variable_t *v = vl->data;
 			if (p == v->plugin) {
 				config_write_variable(f, v);
 			}
diff --git a/ekg/dynstuff.c b/ekg/dynstuff.c
index 84fa3ed..affbc22 100644
--- a/ekg/dynstuff.c
+++ b/ekg/dynstuff.c
@@ -19,6 +19,8 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <glib.h>
+
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -1498,6 +1500,24 @@ void private_item_set_int(private_data_t **data, const char *item_name, int valu
 	private_item_set(data, item_name, value?itoa(value):NULL);
 }
 
+GSList *g_slist_destroy(GSList *list, GDestroyNotify free_func) {
+#if GLIB_CHECK_VERSION(2, 28, 0)
+	g_slist_free_full(list, free_func);
+#else
+	GSList *it;
+
+	for (it = list; it; it = it->next)
+		free_func(it->data);
+	g_slist_free(list);
+#endif
+	return NULL;
+}
+
+GSList *g_slist_remove_full(GSList *list, void *data, GDestroyNotify free_func) {
+	free_func(data);
+	return g_slist_remove(list, data);
+}
+
 /*
  * Local Variables:
  * mode: c
diff --git a/ekg/dynstuff.h b/ekg/dynstuff.h
index cbb262b..93dacac 100644
--- a/ekg/dynstuff.h
+++ b/ekg/dynstuff.h
@@ -22,6 +22,8 @@
 #ifndef __EKG_DYNSTUFF_H
 #define __EKG_DYNSTUFF_H
 
+#include <glib.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -208,6 +210,9 @@ void private_item_set_int(private_data_t **data, const char *item_name, int valu
 
 void private_items_destroy(private_data_t **data);
 
+GSList *g_slist_destroy(GSList *list, GDestroyNotify free_func);
+GSList *g_slist_remove_full(GSList *list, void *data, GDestroyNotify free_func);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/ekg/plugins.c b/ekg/plugins.c
index db4e06c..c71e225 100644
--- a/ekg/plugins.c
+++ b/ekg/plugins.c
@@ -524,7 +524,7 @@ int plugin_unregister(plugin_t *p)
 	struct timer *t;
 	session_t *s;
 	query_t **kk;
-	variable_t *v;
+	GSList *vl;
 	command_t *c;
 	list_t l;
 
@@ -564,9 +564,12 @@ int plugin_unregister(plugin_t *p)
 		}
 	}
 
-	for (v = variables; v; v = v->next) {
-		if (v->plugin == p) 
-			v = variables_removei(v);
+	for (vl = variables; vl;) {
+		variable_t *v = vl->data;
+
+		vl = vl->next;
+		if (v->plugin == p)
+			variables_removei(v);
 	}
 
 	for (c = commands; c; c = c->next) {
diff --git a/ekg/vars.c b/ekg/vars.c
index 1c4cb2e..c36c12c 100644
--- a/ekg/vars.c
+++ b/ekg/vars.c
@@ -48,10 +48,18 @@
 void changed_session_locks(const char *varname); /* sessions.c */
 char *console_charset;
 
-static LIST_ADD_COMPARE(variable_add_compare, variable_t *) { return xstrcasecmp(data1->name, data2->name); }
-static __DYNSTUFF_LIST_ADD_SORTED(variables, variable_t, variable_add_compare);	/* variables_add() */
+GSList *variables = NULL;
 
-variable_t *variables = NULL;
+static gint variable_compare(gconstpointer a, gconstpointer b) {
+	variable_t *data1 = (variable_t *) a;
+	variable_t *data2 = (variable_t *) b;
+
+	return xstrcasecmp(data1->name, data2->name);
+}
+
+static void variables_add(variable_t *v) {
+	variables = g_slist_insert_sorted(variables, v, variable_compare);
+}
 
 /*
  * dd_*()
@@ -204,7 +212,7 @@ void variable_set_default() {
  * - name.
  */
 variable_t *variable_find(const char *name) {
-	variable_t *v;
+	GSList *vl;
 	int hash;
 
 	if (!name)
@@ -212,7 +220,8 @@ variable_t *variable_find(const char *name) {
 
 	hash = variable_hash(name);
 
-	for (v = variables; v; v = v->next) {
+	for (vl = variables; vl; vl = vl->next) {
+		variable_t *v = vl->data;
 		if (v->name_hash == hash && !xstrcasecmp(v->name, name))
 			return v;
 	}
@@ -302,14 +311,15 @@ variable_t *variable_add(plugin_t *plugin, const char *name, int type, int displ
  */
 int variable_remove(plugin_t *plugin, const char *name) {
 	int hash;
-	variable_t *v;
+	GSList *vl;
 
 	if (!name)
 		return -1;
 
 	hash = ekg_hash(name);
 
-	for (v = variables; v; v = v->next) {
+	for (vl = variables; vl; vl = vl->next) {
+		variable_t *v = vl->data;
 		if (!v->name)
 			continue;
 		
@@ -509,7 +519,9 @@ int variable_set(const char *name, const char *value) {
 	return 0;
 }
 
-LIST_FREE_ITEM(variable_list_freeone, variable_t *) {
+static void variable_free(void *_data) {
+	variable_t *data = (variable_t *) _data;
+
 	xfree(data->name);
 
 	switch (data->type) {
@@ -535,8 +547,13 @@ LIST_FREE_ITEM(variable_list_freeone, variable_t *) {
 	}
 }
 
-__DYNSTUFF_LIST_REMOVE_ITER(variables, variable_t, variable_list_freeone);	/* variables_removei() */
-__DYNSTUFF_LIST_DESTROY(variables, variable_t, variable_list_freeone);	/* variables_destroy() */
+void variables_removei(variable_t *v) {
+	variables = g_slist_remove_full(variables, v, variable_free);
+}
+
+void variables_destroy(void) {
+	variables = g_slist_destroy(variables, variable_free);
+}
 
 /*
  * variable_help()
diff --git a/ekg/vars.h b/ekg/vars.h
index d669588..c2f90c3 100644
--- a/ekg/vars.h
+++ b/ekg/vars.h
@@ -20,6 +20,8 @@
 #ifndef __EKG_VARS_H
 #define __EKG_VARS_H
 
+#include <glib.h>
+
 #include "dynstuff.h"
 #include "plugins.h"
 
@@ -48,8 +50,6 @@ typedef void (variable_check_func_t)(const char *, const char *);
 typedef int (variable_display_func_t)(const char *);
 
 typedef struct variable {
-	struct variable *next;
-
 	char *name;		/* nazwa zmiennej */
 	plugin_t *plugin;	/* wstyczka obs³uguj±ca zmienn± */
 	int name_hash;		/* hash nazwy zmiennej */
@@ -69,7 +69,7 @@ typedef struct variable {
 
 #ifndef EKG2_WIN32_NOFUNCTION
 
-extern variable_t *variables;
+extern GSList *variables;
 
 void variable_init();
 void variable_set_default();
@@ -91,7 +91,7 @@ int variable_set(const char *name, const char *value);
 void variable_help(const char *name);
 int variable_remove(plugin_t *plugin, const char *name);
 
-variable_t *variables_removei(variable_t *v);
+void variables_removei(variable_t *v);
 void variables_destroy();
 
 #endif
diff --git a/plugins/jabber/commands.c b/plugins/jabber/commands.c
index 0c2f36c..125eb5c 100644
--- a/plugins/jabber/commands.c
+++ b/plugins/jabber/commands.c
@@ -1612,10 +1612,11 @@ static COMMAND(jabber_command_private) {
 			session_t *s;
 
 			for (p = plugins; p; p = p->next) {
-				variable_t *v;
+				GSList *vl;
 				watch_write(j->send_watch, "<plugin xmlns=\"ekg2:plugin\" name=\"%s\" prio=\"%d\">", p->name, p->prio);
 back:
-				for (v = variables; v; v = v->next) {
+				for (vl = variables; vl; vl = vl->next) {
+					variable_t *v = vl->data;
 					char *vname, *tname;
 					if (v->plugin != p) continue;
 					tname = vname = jabber_escape(v->name);
diff --git a/plugins/perl/common/Variable.xs b/plugins/perl/common/Variable.xs
index 32d295b..511913b 100644
--- a/plugins/perl/common/Variable.xs
+++ b/plugins/perl/common/Variable.xs
@@ -7,10 +7,10 @@ Ekg2::Variable variable_find(const char *name)
 
 void variables()
 PREINIT:
-        variable_t *v;
+        GSList *vl;
 PPCODE:
-        for (v = variables; v; v = v->next) {
-                XPUSHs(sv_2mortal(bless_variable( v )));
+        for (vl = variables; vl; vl = vl->next) {
+                XPUSHs(sv_2mortal(bless_variable( (variable_t *) vl->data )));
         }
 
 void variables_free()
diff --git a/plugins/perl/common/module.h b/plugins/perl/common/module.h
index 81b0785..fee48d3 100644
--- a/plugins/perl/common/module.h
+++ b/plugins/perl/common/module.h
@@ -7,6 +7,8 @@
 #define __EXTENSIONS__
 #endif
 
+#include <glib.h>
+
 #include <ekg/scripts.h>
 
 #include <ekg/debug.h>
diff --git a/plugins/python/python-config.c b/plugins/python/python-config.c
index 5a42b43..3c8e401 100644
--- a/plugins/python/python-config.c
+++ b/plugins/python/python-config.c
@@ -18,6 +18,9 @@
  */
 
 #include "ekg2-config.h"
+
+#include <glib.h>
+
 #include "python.h"
 
 #include <sys/types.h>
@@ -71,13 +74,7 @@ void ekg_config_dealloc(PyObject * o)
 
 int ekg_config_len(ekg_configObj * self)
 {
-	int cnt = 0;
-	variable_t *v;
-
-	for (v = variables; v; v = v->next) {
-		cnt++;
-	}
-	return cnt;
+	return g_slist_length(variables);
 }
 
 /**
@@ -90,10 +87,11 @@ int ekg_config_len(ekg_configObj * self)
 PyObject *ekg_config_get(ekg_configObj * self, PyObject * key)
 {
     char *name = PyString_AsString(key);
-    variable_t *v;
+    GSList *vl;
     debug("[python] Getting value for '%s' config option\n", name);
 
-    for (v = variables; v; v = v->next) {
+    for (vl = variables; vl; vl = vl->next) {
+		variable_t *v = vl->data;
 		if (!strcmp(v->name, name)) {
 			if (v->type == VAR_BOOL || v->type == VAR_INT
 					|| v->type == VAR_MAP) {
diff --git a/plugins/remote/remote.c b/plugins/remote/remote.c
index c255117..b0da1fb 100644
--- a/plugins/remote/remote.c
+++ b/plugins/remote/remote.c
@@ -410,11 +410,12 @@ static WATCHER_LINE(rc_input_handler_line) {
 
 /* synchronization ekg2-remote <==> ekg2 */
 		} else if (!xstrcmp(cmd, "REQCONFIG")) {
-			variable_t *v;
+			GSList *vl;
 
 			/* xxx, maybe send all variable which got (->display > 0) */
 
-			for (v = variables; v; v = v->next) {
+			for (vl = variables; vl; vl = vl->next) {
+				variable_t *v = vl->data;
 				const char *_val;
 
 				if (v->plugin == &remote_plugin)
