Created SILC Runtime Toolkit git repository Part I.
[runtime.git] / apps / irssi / src / core / commands.c
diff --git a/apps/irssi/src/core/commands.c b/apps/irssi/src/core/commands.c
deleted file mode 100644 (file)
index d9dc67a..0000000
+++ /dev/null
@@ -1,998 +0,0 @@
-/*
- commands.c : irssi
-
-    Copyright (C) 1999-2000 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 "signals.h"
-#include "commands.h"
-#include "misc.h"
-#include "special-vars.h"
-#include "window-item-def.h"
-
-#include "servers.h"
-#include "channels.h"
-
-#include "lib-config/iconfig.h"
-#include "settings.h"
-
-GSList *commands;
-char *current_command;
-
-static int signal_default_command;
-
-static GSList *alias_runstack;
-
-COMMAND_REC *command_find(const char *cmd)
-{
-       GSList *tmp;
-
-       g_return_val_if_fail(cmd != NULL, NULL);
-
-       for (tmp = commands; tmp != NULL; tmp = tmp->next) {
-               COMMAND_REC *rec = tmp->data;
-
-               if (g_strcasecmp(rec->cmd, cmd) == 0)
-                       return rec;
-       }
-
-       return NULL;
-}
-
-static COMMAND_MODULE_REC *command_module_find(COMMAND_REC *rec,
-                                              const char *module)
-{
-       GSList *tmp;
-
-       g_return_val_if_fail(rec != NULL, NULL);
-       g_return_val_if_fail(module != NULL, NULL);
-
-       for (tmp = rec->modules; tmp != NULL; tmp = tmp->next) {
-               COMMAND_MODULE_REC *rec = tmp->data;
-
-               if (g_strcasecmp(rec->name, module) == 0)
-                       return rec;
-       }
-
-       return NULL;
-}
-
-static COMMAND_MODULE_REC *
-command_module_find_and_remove(COMMAND_REC *rec, SIGNAL_FUNC func)
-{
-       GSList *tmp, *tmp2;
-
-       g_return_val_if_fail(rec != NULL, NULL);
-       g_return_val_if_fail(func != NULL, NULL);
-
-       for (tmp = rec->modules; tmp != NULL; tmp = tmp->next) {
-               COMMAND_MODULE_REC *rec = tmp->data;
-
-               for (tmp2 = rec->callbacks; tmp2 != NULL; tmp2 = tmp2->next) {
-                       COMMAND_CALLBACK_REC *cb = tmp2->data;
-
-                       if (cb->func == func) {
-                               rec->callbacks =
-                                       g_slist_remove(rec->callbacks, cb);
-                               g_free(cb);
-                               return rec;
-                       }
-               }
-       }
-
-       return NULL;
-}
-
-int command_have_sub(const char *command)
-{
-       GSList *tmp;
-       int len;
-
-       g_return_val_if_fail(command != NULL, FALSE);
-
-       /* find "command "s */
-        len = strlen(command);
-       for (tmp = commands; tmp != NULL; tmp = tmp->next) {
-               COMMAND_REC *rec = tmp->data;
-
-               if (g_strncasecmp(rec->cmd, command, len) == 0 &&
-                   rec->cmd[len] == ' ')
-                       return TRUE;
-       }
-
-       return FALSE;
-}
-
-static COMMAND_MODULE_REC *
-command_module_get(COMMAND_REC *rec, const char *module, int protocol)
-{
-        COMMAND_MODULE_REC *modrec;
-
-       g_return_val_if_fail(rec != NULL, NULL);
-
-       modrec = command_module_find(rec, module);
-       if (modrec == NULL) {
-               modrec = g_new0(COMMAND_MODULE_REC, 1);
-               modrec->name = g_strdup(module);
-                modrec->protocol = -1;
-               rec->modules = g_slist_append(rec->modules, modrec);
-       }
-
-        if (protocol != -1)
-               modrec->protocol = protocol;
-
-        return modrec;
-}
-
-void command_bind_full(const char *module, int priority, const char *cmd,
-                      int protocol, const char *category, SIGNAL_FUNC func,
-                      void *user_data)
-{
-       COMMAND_REC *rec;
-       COMMAND_MODULE_REC *modrec;
-        COMMAND_CALLBACK_REC *cb;
-       char *str;
-
-       g_return_if_fail(module != NULL);
-       g_return_if_fail(cmd != NULL);
-
-       rec = command_find(cmd);
-       if (rec == NULL) {
-               rec = g_new0(COMMAND_REC, 1);
-               rec->cmd = g_strdup(cmd);
-               rec->category = category == NULL ? NULL : g_strdup(category);
-               commands = g_slist_append(commands, rec);
-       }
-        modrec = command_module_get(rec, module, protocol);
-
-       cb = g_new0(COMMAND_CALLBACK_REC, 1);
-       cb->func = func;
-       cb->user_data = user_data;
-       modrec->callbacks = g_slist_append(modrec->callbacks, cb);
-
-       if (func != NULL) {
-               str = g_strconcat("command ", cmd, NULL);
-               signal_add_full(module, priority, str, func, user_data);
-               g_free(str);
-       }
-
-       signal_emit("commandlist new", 1, rec);
-}
-
-static void command_free(COMMAND_REC *rec)
-{
-       commands = g_slist_remove(commands, rec);
-       signal_emit("commandlist remove", 1, rec);
-
-       g_free_not_null(rec->category);
-       g_strfreev(rec->options);
-       g_free(rec->cmd);
-       g_free(rec);
-}
-
-static void command_module_free(COMMAND_MODULE_REC *modrec, COMMAND_REC *rec)
-{
-       rec->modules = g_slist_remove(rec->modules, modrec);
-
-       g_slist_foreach(modrec->callbacks, (GFunc) g_free, NULL);
-       g_slist_free(modrec->callbacks);
-        g_free(modrec->name);
-        g_free_not_null(modrec->options);
-        g_free(modrec);
-}
-
-static void command_module_destroy(COMMAND_REC *rec,
-                                  COMMAND_MODULE_REC *modrec)
-{
-       GSList *tmp, *freelist;
-
-        command_module_free(modrec, rec);
-
-       /* command_set_options() might have added module declaration of it's
-          own without any signals .. check if they're the only ones left
-          and if so, destroy them. */
-        freelist = NULL;
-       for (tmp = rec->modules; tmp != NULL; tmp = tmp->next) {
-               COMMAND_MODULE_REC *rec = tmp->data;
-
-               if (rec->callbacks == NULL)
-                       freelist = g_slist_append(freelist, rec);
-               else {
-                        g_slist_free(freelist);
-                        freelist = NULL;
-                       break;
-               }
-       }
-
-       g_slist_foreach(freelist, (GFunc) command_module_free, rec);
-       g_slist_free(freelist);
-
-       if (rec->modules == NULL)
-               command_free(rec);
-}
-
-void command_unbind_full(const char *cmd, SIGNAL_FUNC func, void *user_data)
-{
-       COMMAND_REC *rec;
-       COMMAND_MODULE_REC *modrec;
-       char *str;
-
-       g_return_if_fail(cmd != NULL);
-       g_return_if_fail(func != NULL);
-
-       rec = command_find(cmd);
-       if (rec != NULL) {
-               modrec = command_module_find_and_remove(rec, func);
-               g_return_if_fail(modrec != NULL);
-
-               if (modrec->callbacks == NULL)
-                       command_module_destroy(rec, modrec);
-       }
-
-       str = g_strconcat("command ", cmd, NULL);
-       signal_remove_data(str, func, user_data);
-       g_free(str);
-}
-
-/* Expand `cmd' - returns `cmd' if not found, NULL if more than one
-   match is found */
-static const char *command_expand(char *cmd)
-{
-       GSList *tmp;
-       const char *match;
-       int len, multiple;
-
-       g_return_val_if_fail(cmd != NULL, NULL);
-
-       multiple = FALSE;
-       match = NULL;
-       len = strlen(cmd);
-       for (tmp = commands; tmp != NULL; tmp = tmp->next) {
-               COMMAND_REC *rec = tmp->data;
-
-               if (g_strncasecmp(rec->cmd, cmd, len) == 0 &&
-                   strchr(rec->cmd+len, ' ') == NULL) {
-                       if (rec->cmd[len] == '\0') {
-                               /* full match */
-                               return rec->cmd;
-                       }
-
-                       if (match != NULL) {
-                               /* multiple matches, we still need to check
-                                  if there's some command left that is a
-                                  full match.. */
-                               multiple = TRUE;
-                       }
-
-                       /* check that this is the only match */
-                       match = rec->cmd;
-               }
-       }
-
-       if (multiple) {
-               signal_emit("error command", 2,
-                           GINT_TO_POINTER(CMDERR_AMBIGUOUS), cmd);
-               return NULL;
-       }
-
-       return match != NULL ? match : cmd;
-}
-
-void command_runsub(const char *cmd, const char *data,
-                   void *server, void *item)
-{
-       const char *newcmd;
-       char *orig, *subcmd, *defcmd, *args;
-
-       g_return_if_fail(data != NULL);
-
-        while (*data == ' ') data++;
-
-       if (*data == '\0') {
-                /* no subcommand given - list the subcommands */
-               signal_emit("list subcommands", 2, cmd);
-               return;
-       }
-
-       /* get command.. */
-       orig = subcmd = g_strdup_printf("command %s %s", cmd, data);
-       args = strchr(subcmd+8 + strlen(cmd)+1, ' ');
-       if (args != NULL) *args++ = '\0'; else args = "";
-       while (*args == ' ') args++;
-
-       /* check if this command can be expanded */
-       newcmd = command_expand(subcmd+8);
-       if (newcmd == NULL) {
-                /* ambiguous command */
-               g_free(orig);
-               return;
-       }
-
-       subcmd = g_strconcat("command ", newcmd, NULL);
-
-       g_strdown(subcmd);
-       if (!signal_emit(subcmd, 3, args, server, item)) {
-               defcmd = g_strdup_printf("default command %s", cmd);
-               if (!signal_emit(defcmd, 3, data, server, item)) {
-                       signal_emit("error command", 2,
-                                   GINT_TO_POINTER(CMDERR_UNKNOWN), subcmd+8);
-               }
-                g_free(defcmd);
-       }
-
-       g_free(subcmd);
-       g_free(orig);
-}
-
-static GSList *optlist_find(GSList *optlist, const char *option)
-{
-       while (optlist != NULL) {
-               char *name = optlist->data;
-               if (iscmdtype(*name)) name++;
-
-               if (g_strcasecmp(name, option) == 0)
-                       return optlist;
-
-               optlist = optlist->next;
-       }
-
-       return NULL;
-}
-
-int command_have_option(const char *cmd, const char *option)
-{
-       COMMAND_REC *rec;
-       char **tmp;
-
-       g_return_val_if_fail(cmd != NULL, FALSE);
-       g_return_val_if_fail(option != NULL, FALSE);
-
-        rec = command_find(cmd);
-       g_return_val_if_fail(rec != NULL, FALSE);
-
-       if (rec->options == NULL)
-               return FALSE;
-
-       for (tmp = rec->options; *tmp != NULL; tmp++) {
-               char *name = iscmdtype(**tmp) ? (*tmp)+1 : *tmp;
-
-               if (g_strcasecmp(name, option) == 0)
-                       return TRUE;
-       }
-
-       return FALSE;
-}
-
-static void command_calc_options(COMMAND_REC *rec, const char *options)
-{
-       char **optlist, **tmp, *name, *str;
-       GSList *list, *oldopt;
-
-       optlist = g_strsplit(options, " ", -1);
-
-       if (rec->options == NULL) {
-                /* first call - use specified args directly */
-               rec->options = optlist;
-               return;
-       }
-
-       /* save old options to linked list */
-       list = NULL;
-       for (tmp = rec->options; *tmp != NULL; tmp++)
-                list = g_slist_append(list, g_strdup(*tmp));
-       g_strfreev(rec->options);
-
-       /* merge the options */
-       for (tmp = optlist; *tmp != NULL; tmp++) {
-               name = iscmdtype(**tmp) ? (*tmp)+1 : *tmp;
-
-               oldopt = optlist_find(list, name);
-               if (oldopt != NULL) {
-                        /* already specified - overwrite old defination */
-                       g_free(oldopt->data);
-                       oldopt->data = g_strdup(*tmp);
-               } else {
-                       /* new option, append to list */
-                        list = g_slist_append(list, g_strdup(*tmp));
-               }
-       }
-       g_strfreev(optlist);
-
-       /* linked list -> string[] */
-       str = gslist_to_string(list, " ");
-       rec->options = g_strsplit(str, " ", -1);
-        g_free(str);
-
-        g_slist_foreach(list, (GFunc) g_free, NULL);
-       g_slist_free(list);
-}
-
-/* recalculate options to command from options in all modules */
-static void command_update_options(COMMAND_REC *rec)
-{
-       GSList *tmp;
-
-       g_strfreev(rec->options);
-       rec->options = NULL;
-
-       for (tmp = rec->modules; tmp != NULL; tmp = tmp->next) {
-               COMMAND_MODULE_REC *modrec = tmp->data;
-
-               if (modrec->options != NULL)
-                       command_calc_options(rec, modrec->options);
-       }
-}
-
-void command_set_options_module(const char *module,
-                               const char *cmd, const char *options)
-{
-       COMMAND_REC *rec;
-       COMMAND_MODULE_REC *modrec;
-        int reload;
-
-       g_return_if_fail(module != NULL);
-       g_return_if_fail(cmd != NULL);
-       g_return_if_fail(options != NULL);
-
-        rec = command_find(cmd);
-       g_return_if_fail(rec != NULL);
-        modrec = command_module_get(rec, module, -1);
-
-       reload = modrec->options != NULL;
-        if (reload) {
-               /* options already set for the module ..
-                  we need to recalculate everything */
-               g_free(modrec->options);
-       }
-
-       modrec->options = g_strdup(options);
-
-        if (reload)
-               command_update_options(rec);
-        else
-               command_calc_options(rec, options);
-}
-
-char *cmd_get_param(char **data)
-{
-       char *pos;
-
-       g_return_val_if_fail(data != NULL, NULL);
-       g_return_val_if_fail(*data != NULL, NULL);
-
-       while (**data == ' ') (*data)++;
-       pos = *data;
-
-       while (**data != '\0' && **data != ' ') (*data)++;
-       if (**data == ' ') *(*data)++ = '\0';
-
-       return pos;
-}
-
-char *cmd_get_quoted_param(char **data)
-{
-       char *pos, quote;
-
-       g_return_val_if_fail(data != NULL, NULL);
-       g_return_val_if_fail(*data != NULL, NULL);
-
-       while (**data == ' ') (*data)++;
-       if (**data != '\'' && **data != '"')
-               return cmd_get_param(data);
-
-       quote = **data; (*data)++;
-
-       pos = *data;
-       while (**data != '\0' && (**data != quote ||
-                                 ((*data)[1] != ' ' && (*data)[1] != '\0'))) {
-               if (**data == '\\' && (*data)[1] != '\0')
-                        g_memmove(*data, (*data)+1, strlen(*data));
-               (*data)++;
-       }
-
-       if (**data == quote) {
-               *(*data)++ = '\0';
-               if (**data == ' ')
-                       (*data)++;
-       }
-
-       return pos;
-}
-
-/* Find specified option from list of options - the `option' might be
-   shortened version of the full command. Returns index where the
-   option was found, -1 if not found or -2 if there was multiple matches. */
-static int option_find(char **array, const char *option)
-{
-       char **tmp;
-       int index, found, len, multiple;
-
-       g_return_val_if_fail(array != NULL, -1);
-       g_return_val_if_fail(option != NULL, -1);
-
-       len = strlen(option);
-
-       found = -1; index = 0; multiple = FALSE;
-       for (tmp = array; *tmp != NULL; tmp++, index++) {
-               const char *text = *tmp + iscmdtype(**tmp);
-
-               if (g_strncasecmp(text, option, len) == 0) {
-                       if (text[len] == '\0') {
-                               /* full match */
-                               return index;
-                       }
-
-                       if (found != -1) {
-                               /* multiple matches - we still need to check
-                                  if there's a full match left.. */
-                               multiple = TRUE;
-                       }
-
-                       /* partial match, check that it's the only one */
-                       found = index;
-               }
-       }
-
-       if (multiple)
-               return -2;
-
-       return found;
-}
-
-static int get_cmd_options(char **data, int ignore_unknown,
-                          const char *cmd, GHashTable *options)
-{
-       COMMAND_REC *rec;
-       char *option, *arg, **optlist;
-       int pos;
-
-       /* get option definations */
-       rec = cmd == NULL ? NULL : command_find(cmd);
-       optlist = rec == NULL ? NULL : rec->options;
-
-       option = NULL; pos = -1;
-       for (;;) {
-               if (**data == '-') {
-                       if (option != NULL && *optlist[pos] == '+') {
-                               /* required argument missing! */
-                                *data = optlist[pos] + 1;
-                               return CMDERR_OPTION_ARG_MISSING;
-                       }
-
-                       (*data)++;
-                       if (**data == '-' && (*data)[1] == ' ') {
-                               /* -- option means end of options even
-                                  if next word starts with - */
-                               (*data)++;
-                               while (**data == ' ') (*data)++;
-                               break;
-                       }
-
-                       if (**data == '\0')
-                               option = "-";
-                       else if (**data != ' ')
-                               option = cmd_get_param(data);
-                       else {
-                               option = "-";
-                               (*data)++;
-                       }
-
-                       /* check if this option can have argument */
-                       pos = optlist == NULL ? -1 :
-                               option_find(optlist, option);
-
-                       if (pos == -1 && optlist != NULL &&
-                           is_numeric(option, '\0')) {
-                               /* check if we want -<number> option */
-                               pos = option_find(optlist, "#");
-                               if (pos != -1) {
-                                       g_hash_table_insert(options, "#",
-                                                           option);
-                                        pos = -3;
-                               }
-                       }
-
-                       if (pos == -1 && !ignore_unknown) {
-                               /* unknown option! */
-                                *data = option;
-                               return CMDERR_OPTION_UNKNOWN;
-                       }
-                       if (pos == -2 && !ignore_unknown) {
-                                /* multiple matches */
-                               *data = option;
-                               return CMDERR_OPTION_AMBIGUOUS;
-                       }
-                       if (pos >= 0) {
-                               /* if we used a shortcut of parameter, put
-                                  the whole parameter name in options table */
-                               option = optlist[pos] +
-                                       iscmdtype(*optlist[pos]);
-                       }
-                       if (options != NULL && pos != -3)
-                               g_hash_table_insert(options, option, "");
-
-                       if (pos < 0 || !iscmdtype(*optlist[pos]) ||
-                           *optlist[pos] == '!')
-                               option = NULL;
-
-                       while (**data == ' ') (*data)++;
-                       continue;
-               }
-
-               if (option == NULL)
-                       break;
-
-               if (*optlist[pos] == '@' && !i_isdigit(**data))
-                       break; /* expected a numeric argument */
-
-               /* save the argument */
-               arg = cmd_get_quoted_param(data);
-               if (options != NULL) {
-                       g_hash_table_remove(options, option);
-                       g_hash_table_insert(options, option, arg);
-               }
-               option = NULL;
-
-               while (**data == ' ') (*data)++;
-       }
-
-       return 0;
-}
-
-typedef struct {
-       char *data;
-        GHashTable *options;
-} CMD_TEMP_REC;
-
-static const char *
-get_optional_channel(WI_ITEM_REC *active_item, char **data, int require_name)
-{
-        CHANNEL_REC *chanrec;
-       const char *ret;
-       char *tmp, *origtmp, *channel;
-
-       if (active_item == NULL) {
-                /* no active channel in window, channel required */
-               return cmd_get_param(data);
-       }
-
-       origtmp = tmp = g_strdup(*data);
-       channel = cmd_get_param(&tmp);
-
-       if (strcmp(channel, "*") == 0 && !require_name) {
-                /* "*" means active channel */
-               cmd_get_param(data);
-               ret = window_item_get_target(active_item);
-       } else if (!server_ischannel(active_item->server, channel)) {
-                /* we don't have channel parameter - use active channel */
-               ret = window_item_get_target(active_item);
-       } else {
-               /* Find the channel first and use it's name if found.
-                  This allows automatic !channel -> !XXXXXchannel replaces. */
-                channel = cmd_get_param(data);
-
-               chanrec = channel_find(active_item->server, channel);
-               ret = chanrec == NULL ? channel : chanrec->name;
-       }
-
-       g_free(origtmp);
-        return ret;
-}
-
-int cmd_get_params(const char *data, gpointer *free_me, int count, ...)
-{
-        WI_ITEM_REC *item;
-       CMD_TEMP_REC *rec;
-       GHashTable **opthash;
-       char **str, *arg, *datad;
-       va_list args;
-       int cnt, error, ignore_unknown, require_name;
-
-       g_return_val_if_fail(data != NULL, FALSE);
-
-       va_start(args, count);
-
-       rec = g_new0(CMD_TEMP_REC, 1);
-       rec->data = g_strdup(data);
-       *free_me = rec;
-
-        datad = rec->data;
-       error = FALSE;
-
-       item = (count & PARAM_FLAG_OPTCHAN) == 0 ? NULL:
-               (WI_ITEM_REC *) va_arg(args, WI_ITEM_REC *);
-
-       if (count & PARAM_FLAG_OPTIONS) {
-               arg = (char *) va_arg(args, char *);
-               opthash = (GHashTable **) va_arg(args, GHashTable **);
-
-               rec->options = *opthash =
-                       g_hash_table_new((GHashFunc) g_istr_hash,
-                                        (GCompareFunc) g_istr_equal);
-
-               ignore_unknown = count & PARAM_FLAG_UNKNOWN_OPTIONS;
-               error = get_cmd_options(&datad, ignore_unknown,
-                                       arg, *opthash);
-       }
-
-       if (!error) {
-               /* and now handle the string */
-               cnt = PARAM_WITHOUT_FLAGS(count);
-               if (count & PARAM_FLAG_OPTCHAN) {
-                       /* optional channel as first parameter */
-                       require_name = (count & PARAM_FLAG_OPTCHAN_NAME) ==
-                               PARAM_FLAG_OPTCHAN_NAME;
-                       arg = (char *) get_optional_channel(item, &datad, require_name);
-
-                       str = (char **) va_arg(args, char **);
-                       if (str != NULL) *str = arg;
-                       cnt--;
-               }
-
-               while (cnt-- > 0) {
-                       if (cnt == 0 && count & PARAM_FLAG_GETREST) {
-                               /* get rest */
-                               arg = datad;
-                       } else {
-                               arg = (count & PARAM_FLAG_NOQUOTES) ?
-                                       cmd_get_param(&datad) :
-                                       cmd_get_quoted_param(&datad);
-                       }
-
-                       str = (char **) va_arg(args, char **);
-                       if (str != NULL) *str = arg;
-               }
-       }
-       va_end(args);
-
-       if (error) {
-                signal_emit("error command", 2, GINT_TO_POINTER(error), datad);
-               signal_stop();
-
-                cmd_params_free(rec);
-               *free_me = NULL;
-       }
-
-       return !error;
-}
-
-void cmd_params_free(void *free_me)
-{
-       CMD_TEMP_REC *rec = free_me;
-
-       if (rec->options != NULL) g_hash_table_destroy(rec->options);
-       g_free(rec->data);
-       g_free(rec);
-}
-
-static void command_module_unbind_all(COMMAND_REC *rec,
-                                     COMMAND_MODULE_REC *modrec)
-{
-       GSList *tmp, *next;
-
-       for (tmp = modrec->callbacks; tmp != NULL; tmp = next) {
-               COMMAND_CALLBACK_REC *cb = tmp->data;
-               next = tmp->next;
-
-               command_unbind_full(rec->cmd, cb->func, cb->user_data);
-       }
-
-       if (g_slist_find(commands, rec) != NULL) {
-               /* this module might have removed some options
-                  from command, update them. */
-               command_update_options(rec);
-       }
-}
-
-void commands_remove_module(const char *module)
-{
-       GSList *tmp, *next, *modlist;
-
-       g_return_if_fail(module != NULL);
-
-       for (tmp = commands; tmp != NULL; tmp = next) {
-               COMMAND_REC *rec = tmp->data;
-
-                next = tmp->next;
-               modlist = gslist_find_string(rec->modules, module);
-               if (modlist != NULL)
-                       command_module_unbind_all(rec, modlist->data);
-       }
-}
-
-static int cmd_protocol_match(COMMAND_REC *cmd, SERVER_REC *server)
-{
-       GSList *tmp;
-
-       for (tmp = cmd->modules; tmp != NULL; tmp = tmp->next) {
-               COMMAND_MODULE_REC *rec = tmp->data;
-
-               if (rec->protocol == -1) {
-                       /* at least one module accepts the command
-                          without specific protocol */
-                       return 1;
-               }
-
-               if (server != NULL && rec->protocol == server->chat_type) {
-                        /* matching protocol found */
-                        return 1;
-               }
-       }
-
-        return 0;
-}
-
-#define alias_runstack_push(alias) \
-       alias_runstack = g_slist_append(alias_runstack, alias)
-
-#define alias_runstack_pop(alias) \
-       alias_runstack = g_slist_remove(alias_runstack, alias)
-
-#define alias_runstack_find(alias) \
-        (gslist_find_icase_string(alias_runstack, alias) != NULL)
-
-static void parse_command(const char *command, int expand_aliases,
-                         SERVER_REC *server, void *item)
-{
-        COMMAND_REC *rec;
-       const char *alias, *newcmd;
-       char *cmd, *orig, *args, *oldcmd;
-
-       g_return_if_fail(command != NULL);
-
-       cmd = orig = g_strconcat("command ", command, NULL);
-       args = strchr(cmd+8, ' ');
-       if (args != NULL) *args++ = '\0'; else args = "";
-
-       /* check if there's an alias for command. Don't allow
-          recursive aliases */
-       alias = !expand_aliases || alias_runstack_find(cmd+8) ? NULL :
-               alias_find(cmd+8);
-       if (alias != NULL) {
-                alias_runstack_push(cmd+8);
-               eval_special_string(alias, args, server, item);
-                alias_runstack_pop(cmd+8);
-               g_free(orig);
-               return;
-       }
-
-       /* check if this command can be expanded */
-       newcmd = command_expand(cmd+8);
-       if (newcmd == NULL) {
-                /* ambiguous command */
-               g_free(orig);
-               return;
-       }
-
-       rec = command_find(newcmd);
-       if (rec != NULL && !cmd_protocol_match(rec, server)) {
-               g_free(orig);
-
-               signal_emit("error command", 2,
-                           GINT_TO_POINTER(server == NULL ?
-                                           CMDERR_NOT_CONNECTED :
-                                           CMDERR_ILLEGAL_PROTO));
-               return;
-       }
-
-       cmd = g_strconcat("command ", newcmd, NULL);
-       g_strdown(cmd);
-
-       oldcmd = current_command;
-       current_command = cmd+8;
-        if (server != NULL) server_ref(server);
-        if (!signal_emit(cmd, 3, args, server, item)) {
-               signal_emit_id(signal_default_command, 3,
-                              command, server, item);
-       }
-       if (server != NULL) {
-               if (server->connection_lost)
-                       server_disconnect(server);
-               server_unref(server);
-       }
-       current_command = oldcmd;
-
-       g_free(cmd);
-       g_free(orig);
-}
-
-static void event_command(const char *line, SERVER_REC *server, void *item)
-{
-       char *cmdchar;
-       int expand_aliases = TRUE;
-
-       g_return_if_fail(line != NULL);
-
-       cmdchar = *line == '\0' ? NULL :
-               strchr(settings_get_str("cmdchars"), *line);
-       if (cmdchar != NULL && line[1] == ' ') {
-               /* "/ text" = same as sending "text" to active channel. */
-               line += 2;
-               cmdchar = NULL;
-       }
-       if (cmdchar == NULL) {
-               /* non-command - let someone else handle this */
-               signal_emit("send text", 3, line, server, item);
-               return;
-       }
-
-       /* same cmdchar twice ignores aliases ignores aliases */
-       line++;
-       if (*line == *cmdchar) {
-               line++;
-               expand_aliases = FALSE;
-       }
-
-       /* ^command hides the output - we'll do this at fe-common but
-          we have to skip the ^ char here.. */
-       if (*line == '^') line++;
-
-       parse_command(line, expand_aliases, server, item);
-}
-
-static int eval_recursion_depth=0;
-/* SYNTAX: EVAL <command(s)> */
-static void cmd_eval(const char *data, SERVER_REC *server, void *item)
-{
-       g_return_if_fail(data != NULL);
-       if (eval_recursion_depth > 100) 
-               cmd_return_error(CMDERR_EVAL_MAX_RECURSE);
-
-       eval_recursion_depth++;
-       eval_special_string(data, "", server, item);
-       eval_recursion_depth--;
-}
-
-/* SYNTAX: CD <directory> */
-static void cmd_cd(const char *data)
-{
-       char *str;
-
-       g_return_if_fail(data != NULL);
-       if (*data == '\0') return;
-
-       str = convert_home(data);
-       chdir(str);
-       g_free(str);
-}
-
-void commands_init(void)
-{
-       commands = NULL;
-       current_command = NULL;
-       alias_runstack = NULL;
-
-       signal_default_command = signal_get_uniq_id("default command");
-
-       settings_add_str("misc", "cmdchars", "/");
-       signal_add("send command", (SIGNAL_FUNC) event_command);
-
-       command_bind("eval", NULL, (SIGNAL_FUNC) cmd_eval);
-       command_bind("cd", NULL, (SIGNAL_FUNC) cmd_cd);
-}
-
-void commands_deinit(void)
-{
-       g_free_not_null(current_command);
-
-       signal_remove("send command", (SIGNAL_FUNC) event_command);
-
-       command_unbind("eval", (SIGNAL_FUNC) cmd_eval);
-       command_unbind("cd", (SIGNAL_FUNC) cmd_cd);
-}