summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimo Sirainen <cras@irssi.org>2000-06-18 01:18:12 +0000
committercras <cras@dbcabf3a-b0e7-0310-adc4-f8d773084564>2000-06-18 01:18:12 +0000
commita5d31a195d1e3b682cd57d88a5db7ef0ffa5d492 (patch)
treee5c335b77da2d17293e87debeb17ab4c966e34c4
parentca4226cca692ee96109a46b3a1d381ac0d37cb6f (diff)
downloadirssi-a5d31a195d1e3b682cd57d88a5db7ef0ffa5d492.zip
Changed option handling in /commands. Irssi will now complain about
unknown options and missing option arguments. Renamed /SERVER -add, -remove and -list to /SERVER ADD, REMOVE and LIST. git-svn-id: http://svn.irssi.org/repos/irssi/trunk@365 dbcabf3a-b0e7-0310-adc4-f8d773084564
-rw-r--r--docs/formats.txt7
-rw-r--r--docs/manual.txt14
-rw-r--r--src/core/commands.c324
-rw-r--r--src/core/commands.h72
-rw-r--r--src/core/misc.c38
-rw-r--r--src/core/misc.h10
-rw-r--r--src/fe-common/core/fe-core-commands.c28
-rw-r--r--src/fe-common/core/fe-log.c36
-rw-r--r--src/fe-common/core/fe-settings.c25
-rw-r--r--src/fe-common/core/hilight-text.c35
-rw-r--r--src/fe-common/core/themes.c14
-rw-r--r--src/fe-common/irc/dcc/fe-dcc.c42
-rw-r--r--src/fe-common/irc/fe-channels.c37
-rw-r--r--src/fe-common/irc/fe-ignore.c37
-rw-r--r--src/fe-common/irc/fe-irc-commands.c52
-rw-r--r--src/fe-common/irc/fe-irc-server.c104
-rw-r--r--src/fe-common/irc/fe-ircnet.c68
-rw-r--r--src/fe-common/irc/irc-completion.c8
-rw-r--r--src/fe-text/gui-textwidget.c67
-rw-r--r--src/irc/bot/botnet-connection.c8
-rw-r--r--src/irc/bot/botnet-users.c49
-rw-r--r--src/irc/bot/botnet.c22
-rw-r--r--src/irc/core/bans.c9
-rw-r--r--src/irc/core/channels-query.c4
-rw-r--r--src/irc/core/channels.c8
-rw-r--r--src/irc/core/irc-commands.c253
-rw-r--r--src/irc/core/irc-special-vars.c8
-rw-r--r--src/irc/core/ircnet-setup.c4
-rw-r--r--src/irc/core/modes.c11
-rw-r--r--src/irc/core/netsplit.c9
-rw-r--r--src/irc/dcc/dcc-chat.c28
-rw-r--r--src/irc/dcc/dcc-files.c40
-rw-r--r--src/irc/dcc/dcc.c28
-rw-r--r--src/irc/notifylist/notify-commands.c26
34 files changed, 949 insertions, 576 deletions
diff --git a/docs/formats.txt b/docs/formats.txt
index 633b0e42..cda7d422 100644
--- a/docs/formats.txt
+++ b/docs/formats.txt
@@ -1,3 +1,6 @@
+
+ Irssi's colors that you can use in text formats etc. :
+
text text background
---------------------------------------------------------------------
%k %K %0 black bold black black
@@ -17,3 +20,7 @@
%| Marks the indentation position
%% A single %
+ MIRC colors that you can use when writing text to channel and with
+ hilighting text:
+
+ FIXME: list them :)
diff --git a/docs/manual.txt b/docs/manual.txt
index da5a4f9c..62ffa8df 100644
--- a/docs/manual.txt
+++ b/docs/manual.txt
@@ -394,7 +394,7 @@
network and Irssi will pick the server for you.
You don't need to specify the IRC network, password, nick, etc. if
- you setup the server using /SERVER -add (see next section). If the
+ you setup the server using /SERVER ADD (see next section). If the
settings can't be found there either, Irssi will use the defaults:
/SET default_nick = <nick>, defaults to user_name
@@ -424,9 +424,9 @@
5.4 Server settings
- /SERVER -add [-auto | -noauto] [-ircnet <ircnet>] [-host <hostname>]
- [-cmdspeed <ms>] [-cmdmax <count>] [-port <port>]
- <address> [<port> [<password>]]
+ /SERVER ADD [-auto | -noauto] [-ircnet <ircnet>] [-host <hostname>]
+ [-cmdspeed <ms>] [-cmdmax <count>] [-port <port>]
+ <address> [<port> [<password>]]
-auto: Automatically connect to server at startup (default)
-noauto: Don't connect to server at startup
@@ -437,9 +437,9 @@
-port: This is pretty much like the port argument later, except
this can be used to modify existing server's port.
- /SERVER -remove <address> [<port>]
+ /SERVER REMOVE <address> [<port>]
- /SERVER -list
+ /SERVER LIST
Servers are identified by their name and port. You can have multiple
entries for the same server name but in different ports. This is
@@ -450,7 +450,7 @@
-port command. For example if you had irc.server.org in port 6667
and you wanted to change it to port 6668, use command:
- /SERVER -add -port 6668 irc.server.org 6667
+ /SERVER ADD -port 6668 irc.server.org 6667
If you want to remove some settings from existing server, for
example hostname, just give -host "" parameters to it.
diff --git a/src/core/commands.c b/src/core/commands.c
index 225f8213..5e0a27ba 100644
--- a/src/core/commands.c
+++ b/src/core/commands.c
@@ -66,6 +66,7 @@ void command_free(COMMAND_REC *rec)
signal_emit("commandlist remove", 1, rec);
g_free_not_null(rec->category);
+ g_strfreev(rec->options);
g_free(rec->cmd);
g_free(rec);
}
@@ -93,7 +94,7 @@ void command_unbind(const char *cmd, SIGNAL_FUNC func)
}
}
-void command_runsub(const char *cmd, const char *data, void *p1, void *p2)
+void command_runsub(const char *cmd, const char *data, void *server, void *item)
{
char *subcmd, *defcmd, *args;
@@ -106,30 +107,101 @@ void command_runsub(const char *cmd, const char *data, void *p1, void *p2)
while (*args == ' ') args++;
g_strdown(subcmd);
- if (!signal_emit(subcmd, 3, args, p1, p2)) {
+ if (!signal_emit(subcmd, 3, args, server, item)) {
defcmd = g_strdup_printf("default command %s", cmd);
- if (!signal_emit(defcmd, 3, data, p1, p2))
- signal_emit("unknown command", 3, strchr(subcmd, ' ')+1, p1, p2);
+ if (!signal_emit(defcmd, 3, data, server, item))
+ signal_emit("unknown command", 3, strchr(subcmd, ' ')+1, server, item);
g_free(defcmd);
}
g_free(subcmd);
}
-COMMAND_REC *command_find(const char *command)
+COMMAND_REC *command_find(const char *cmd)
{
GSList *tmp;
- int len;
+
+ 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, command) == 0)
+ if (g_strcasecmp(rec->cmd, cmd) == 0)
return rec;
}
return NULL;
}
+#define iscmdtype(c) \
+ ((c) == '-' || (c) == '+' || (c) == '@')
+
+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;
+}
+
+void command_set_options(const char *cmd, const char *options)
+{
+ COMMAND_REC *rec;
+ char **optlist, **tmp, *name, *str;
+ GSList *list, *oldopt;
+
+ g_return_if_fail(cmd != NULL);
+ g_return_if_fail(options != NULL);
+
+ rec = command_find(cmd);
+ g_return_if_fail(rec != NULL);
+
+ 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[] */
+ g_free(rec->options);
+ 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);
+}
+
char *cmd_get_param(char **data)
{
char *pos;
@@ -146,7 +218,7 @@ char *cmd_get_param(char **data)
return pos;
}
-char *cmd_get_quoted_param(char **data)
+static char *cmd_get_quoted_param(char **data)
{
char *pos, quote;
@@ -171,67 +243,7 @@ char *cmd_get_quoted_param(char **data)
return pos;
}
-static char *get_opt_args(char **data)
-{
- /* -cmd1 -cmd2 -cmd3 ... */
- char *p, *ret;
- int stopnext;
-
- g_return_val_if_fail(data != NULL, NULL);
- g_return_val_if_fail(*data != NULL, NULL);
-
- stopnext = FALSE;
- ret = NULL;
- for (p = *data;;) {
- if (*p != '-' || stopnext) {
- if (p == *data) return "";
-
- ret = *data;
- *data = p;
-
- while (isspace(p[-1]) && p > ret) p--;
- if (*p != '\0') *p = '\0';
- return ret;
- }
-
- if (p[1] == '-') {
- /* -- argument means end of arguments even if
- next word starts with - */
- stopnext = TRUE;
- }
-
- while (!isspace(*p) && *p != '\0') p++;
- while (isspace(*p)) p++;
- }
-}
-
-static void cmd_params_pack(char ***subargs, char *end, char *start, char *newstart)
-{
- char ***tmp;
- char *data;
- int bufsize, datalen, len;
-
- bufsize = (int) (end-newstart)+1;
-
- data = g_malloc(bufsize); datalen = 0;
- for (tmp = subargs; *tmp != NULL; tmp++) {
- if (**tmp < start || **tmp > end)
- continue;
-
- len = strlen(**tmp)+1;
- if (datalen+len > bufsize)
- g_error("cmd_params_pack() : buffer overflow!");
-
- memcpy(data+datalen, **tmp, len);
- **tmp = newstart+datalen;
- datalen += len;
- }
-
- g_memmove(newstart, data, datalen);
- g_free(data);
-}
-
-int arg_find(char **array, const char *item)
+static int option_find(char **array, const char *item)
{
char **tmp;
int index;
@@ -241,101 +253,83 @@ int arg_find(char **array, const char *item)
index = 0;
for (tmp = array; *tmp != NULL; tmp++, index++) {
- if (g_strcasecmp(*tmp + (**tmp == '@'), item) == 0)
+ if (g_strcasecmp(*tmp + iscmdtype(**tmp), item) == 0)
return index;
}
return -1;
}
-static int get_multi_args(char **data, int checkonly, va_list va)
+static int get_cmd_options(char **data, int ignore_unknown,
+ const char *cmd, GHashTable *options)
{
- /* -cmd1 arg1 -cmd2 "argument two" -cmd3 */
- GString *returnargs;
- char **args, **arglist, *arg, *origdata;
- char **nextarg, ***subargs;
- int eat, pos;
-
- eat = 0;
- args = (char **) va_arg(va, char **);
- g_return_val_if_fail(args != NULL && *args != NULL && **args != '\0', 0);
-
- arglist = g_strsplit(*args, " ", -1);
- eat = strarray_length(arglist);
-
- subargs = g_new(char **, eat+1);
- for (pos = 0; pos < eat; pos++) {
- subargs[pos] = (char **) va_arg(va, char **);
- if (subargs[pos] == NULL) {
- g_free(subargs);
- g_warning("get_multi_args() : subargument == NULL");
- return eat;
- }
- *subargs[pos] = "";
- }
- subargs[eat] = NULL;
+ COMMAND_REC *rec;
+ char *option, *arg, **optlist;
+ int pos;
- origdata = *data;
- returnargs = g_string_new(NULL);
- nextarg = NULL;
+ /* 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 == '-') {
- /* -- argument means end of arguments even
+ /* -- option means end of options even
if next word starts with - */
(*data)++;
while (isspace(**data)) (*data)++;
break;
}
- arg = cmd_get_param(data);
- g_string_sprintfa(returnargs, "-%s ", arg);
+ option = cmd_get_param(data);
- /* check if this argument can have parameter */
- pos = arg_find(arglist, arg);
- nextarg = pos == -1 ? NULL : subargs[pos];
+ /* check if this option can have argument */
+ pos = optlist == NULL ? -1 : option_find(optlist, option);
+ if (pos == -1 && !ignore_unknown) {
+ /* unknown option! */
+ *data = option;
+ return CMDERR_OPTION_UNKNOWN;
+ }
+ if (pos != -1) {
+ /* if we used a shortcut of parameter, put
+ the whole parameter name in options table */
+ option = optlist[pos] + iscmdtype(*optlist[pos]);
+ }
+ if (options != NULL) g_hash_table_insert(options, option, "");
+
+ if (pos == -1 || !iscmdtype(*optlist[pos]))
+ option = NULL;
while (isspace(**data)) (*data)++;
continue;
}
- if (nextarg == NULL)
+ if (option == NULL)
break;
- if (*arglist[pos] == '@' && !isdigit(**data))
+ if (*optlist[pos] == '@' && !isdigit(**data))
break; /* expected a numeric argument */
- /* save the sub-argument to `nextarg' */
+ /* save the argument */
arg = cmd_get_quoted_param(data);
- *nextarg = arg; nextarg = NULL;
+ if (options != NULL) {
+ g_hash_table_remove(options, option);
+ g_hash_table_insert(options, option, arg);
+ }
+ option = NULL;
while (isspace(**data)) (*data)++;
}
- if (!checkonly) {
- /* ok, this is a bit stupid. this will pack the arguments in
- `data' like "-arg1 subarg -arg2 sub2\0" ->
- "-arg1 -arg2\0subarg\0sub2\0" this is because it's easier
- to free only _one_ string instead of two (`args') when
- using PARAM_FLAG_MULTIARGS. */
- if (returnargs->len == 0)
- *args = "";
- else {
- cmd_params_pack(subargs, **data == '\0' ? *data : (*data)-1,
- origdata, origdata+returnargs->len);
-
- g_string_truncate(returnargs, returnargs->len-1);
- strcpy(origdata, returnargs->str);
- *args = origdata;
- }
- }
-
- g_string_free(returnargs, TRUE);
- g_strfreev(arglist);
- g_free(subargs);
-
- return eat;
+ return 0;
}
char *cmd_get_callfuncs(const char *data, int *count, va_list *args)
@@ -356,34 +350,38 @@ char *cmd_get_callfuncs(const char *data, int *count, va_list *args)
return ret;
}
-char *cmd_get_params(const char *data, int count, ...)
+typedef struct {
+ char *data;
+ GHashTable *options;
+} CMD_TEMP_REC;
+
+int cmd_get_params(const char *data, gpointer *free_me, int count, ...)
{
+ CMD_TEMP_REC *rec;
+ GHashTable **opthash;
char **str, *arg, *datad, *old;
va_list args;
- int cnt, eat, len;
+ int cnt, error, len;
- g_return_val_if_fail(data != NULL, NULL);
+ g_return_val_if_fail(data != NULL, FALSE);
va_start(args, count);
- /* get the length of the arguments in string */
- if ((count & (PARAM_FLAG_MULTIARGS|PARAM_FLAG_OPTARGS)) == 0)
+ /* get the length of the options in string */
+ if ((count & PARAM_FLAG_OPTIONS) == 0)
len = 0;
else {
old = datad = g_strdup(data);
- if (count & PARAM_FLAG_MULTIARGS)
- get_multi_args(&datad, TRUE, args);
- else
- get_opt_args(&datad);
+ get_cmd_options(&datad, TRUE, NULL, NULL);
len = (int) (datad-old);
g_free(old);
}
- /* send the text to custom functions to handle - skip arguments */
+ /* send the text to custom functions to handle - skip options */
old = datad = cmd_get_callfuncs(data+len, &count, &args);
if (len > 0) {
- /* put the arguments + the new data to one string */
+ /* put the options + the new data to one string */
datad = g_malloc(len+1 + strlen(old)+1);
memcpy(datad, data, len);
datad[len] = ' ';
@@ -393,20 +391,25 @@ char *cmd_get_params(const char *data, int count, ...)
old = datad;
}
+ rec = g_new0(CMD_TEMP_REC, 1);
+ rec->data = old;
+ *free_me = rec;
+
/* and now handle the string */
+ error = FALSE;
cnt = PARAM_WITHOUT_FLAGS(count);
while (cnt-- > 0) {
- if (count & PARAM_FLAG_MULTIARGS) {
- eat = get_multi_args(&datad, FALSE, args)+1;
- count &= ~PARAM_FLAG_MULTIARGS;
+ if (count & PARAM_FLAG_OPTIONS) {
+ arg = (char *) va_arg(args, char *);
+ opthash = (GHashTable **) va_arg(args, GHashTable **);
- cnt -= eat-1;
- while (eat-- > 0)
- str = (char **) va_arg(args, char **);
+ rec->options = *opthash = g_hash_table_new((GHashFunc) g_istr_hash, (GCompareFunc) g_istr_equal);
+ error = get_cmd_options(&datad, count & PARAM_FLAG_UNKNOWN_OPTIONS, arg, *opthash);
+ if (error) break;
+
+ count &= ~PARAM_FLAG_OPTIONS;
+ cnt++;
continue;
- } else if (count & PARAM_FLAG_OPTARGS) {
- arg = get_opt_args(&datad);
- count &= ~PARAM_FLAG_OPTARGS;
} else if (cnt == 0 && count & PARAM_FLAG_GETREST) {
/* get rest */
arg = datad;
@@ -421,7 +424,24 @@ char *cmd_get_params(const char *data, int count, ...)
}
va_end(args);
- return old;
+ 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);
}
void cmd_get_add_func(CMD_GET_FUNC func)
diff --git a/src/core/commands.h b/src/core/commands.h
index 42fb20c0..a199a1f5 100644
--- a/src/core/commands.h
+++ b/src/core/commands.h
@@ -6,10 +6,13 @@
typedef struct {
char *category;
char *cmd;
-}
-COMMAND_REC;
+ char **options;
+} COMMAND_REC;
enum {
+ CMDERR_OPTION_UNKNOWN = -2, /* unknown -option */
+ CMDERR_OPTION_ARG_MISSING = -1, /* argument missing for -option */
+
CMDERR_ERRNO, /* get the error from errno */
CMDERR_NOT_ENOUGH_PARAMS, /* not enough parameters given */
CMDERR_NOT_CONNECTED, /* not connected to IRC server */
@@ -20,7 +23,7 @@ enum {
};
#define cmd_return_error(a) { signal_emit("error command", 1, GINT_TO_POINTER(a)); signal_stop(); return; }
-#define cmd_param_error(a) { g_free(params); cmd_return_error(a); }
+#define cmd_param_error(a) { cmd_params_free(free_arg); cmd_return_error(a); }
extern GSList *commands;
extern char *current_command;
@@ -29,12 +32,29 @@ void command_bind_to(int pos, const char *cmd, const char *category, SIGNAL_FUNC
#define command_bind(a, b, c) command_bind_to(1, a, b, c)
#define command_bind_first(a, b, c) command_bind_to(0, a, b, c)
#define command_bind_last(a, b, c) command_bind_to(2, a, b, c)
-
void command_unbind(const char *cmd, SIGNAL_FUNC func);
-void command_runsub(const char *cmd, const char *data, void *p1, void *p2);
+/* Run subcommand, `cmd' contains the base command, first word in `data'
+ contains the subcommand */
+void command_runsub(const char *cmd, const char *data, void *server, void *item);
+
+COMMAND_REC *command_find(const char *cmd);
+
+/* Specify options that command can accept. `options' contains list of
+ options separated with space, each option can contain a special
+ char in front of it:
+
+ '-': optional argument
+ '+': argument required
+ '@': optional numeric argument
-COMMAND_REC *command_find(const char *command);
+ for example if options = "save -file +nick", you can use
+ /command -save -file [<filename>] -nick <nickname>
+
+ You can call this command multiple times for same command, options
+ will be merged. If there's any conflicts with option types, the last
+ call will override the previous */
+void command_set_options(const char *cmd, const char *options);
/* count can have these flags: */
#define PARAM_WITHOUT_FLAGS(a) ((a) & 0x00ffffff)
@@ -42,30 +62,40 @@ COMMAND_REC *command_find(const char *command);
#define PARAM_FLAG_NOQUOTES 0x01000000
/* final argument gets all the rest of the arguments */
#define PARAM_FLAG_GETREST 0x02000000
-/* optional arguments (-cmd -cmd2 -cmd3) */
-#define PARAM_FLAG_OPTARGS 0x04000000
-/* arguments can have arguments too. Example:
+/* command contains options - first you need to specify them with
+ command_set_options() function. Example:
- -cmd arg -noargcmd -cmd2 "another arg -optnumarg rest of the text
+ -cmd requiredarg -noargcmd -cmd2 "another arg" -optnumarg rest of text
You would call this with:
- args = "cmd cmd2 @optnumarg";
- cmd_get_params(data, 5 | PARAM_FLAG_MULTIARGS | PARAM_FLAG_GETREST,
- &args, &arg_cmd, &arg_cmd2, &arg_optnum, &rest);
+ // only once in init
+ command_set_options("mycmd", "+cmd noargcmd -cmd2 @optnumarg");
+
+ GHashTable *optlist;
+
+ cmd_get_params(data, &free_me, 1 | PARAM_FLAG_OPTIONS |
+ PARAM_FLAG_GETREST, "mycmd", &optlist, &rest);
- The variables are filled as following:
+ The optlist hash table is filled:
- args = "-cmd -noargcmd -cmd2 -optnumarg"
- arg_cmd = "arg"
- arg_cmd2 = "another arg"
- rest = "rest of the text"
- arg_optnum = "" - this is because "rest" isn't a numeric value
+ "cmd" = "requiredarg"
+ "noargcmd" = ""
+ "cmd2" = "another arg"
+ "optnumarg" = "" - this is because "rest" isn't a numeric value
*/
-#define PARAM_FLAG_MULTIARGS 0x08000000
+#define PARAM_FLAG_OPTIONS 0x04000000
+/* don't complain about unknown options */
+#define PARAM_FLAG_UNKNOWN_OPTIONS 0x08000000
char *cmd_get_param(char **data);
-char *cmd_get_params(const char *data, int count, ...);
+/* get parameters from command - you should point free_me somewhere and
+ cmd_params_free() it after you don't use any of the parameters anymore.
+
+ Returns TRUE if all ok, FALSE if error occured. */
+int cmd_get_params(const char *data, gpointer *free_me, int count, ...);
+
+void cmd_params_free(void *free_me);
typedef char* (*CMD_GET_FUNC) (const char *data, int *count, va_list *args);
void cmd_get_add_func(CMD_GET_FUNC func);
diff --git a/src/core/misc.c b/src/core/misc.c
index bc73f5a0..952c7149 100644
--- a/src/core/misc.c
+++ b/src/core/misc.c
@@ -247,7 +247,8 @@ void *gslist_foreach_find(GSList *list, FOREACH_FIND_FUNC func, void *data)
return NULL;
}
-char *gslist_to_string(GSList *list, int offset, const char *delimiter)
+/* `list' contains pointer to structure with a char* to string. */
+char *gslistptr_to_string(GSList *list, int offset, const char *delimiter)
{
GString *str;
char **data, *ret;
@@ -266,6 +267,41 @@ char *gslist_to_string(GSList *list, int offset, const char *delimiter)
return ret;
}
+/* `list' contains char* */
+char *gslist_to_string(GSList *list, const char *delimiter)
+{
+ GString *str;
+ char *ret;
+
+ str = g_string_new(NULL);
+ while (list != NULL) {
+ if (str->len != 0) g_string_append(str, delimiter);
+ g_string_append(str, list->data);
+
+ list = list->next;
+ }
+
+ ret = str->str;
+ g_string_free(str, FALSE);
+ return ret;
+}
+
+void hash_save_key(char *key, void *value, GSList **list)
+{
+ *list = g_slist_append(*list, key);
+}
+
+/* save all keys in hash table to linked list - you shouldn't remove any
+ items while using this list, use g_slist_free() after you're done with it */
+GSList *hashtable_get_keys(GHashTable *hash)
+{
+ GSList *list;
+
+ list = NULL;
+ g_hash_table_foreach(hash, (GHFunc) hash_save_key, &list);
+ return list;
+}
+
GList *glist_find_string(GList *list, const char *key)
{
for (list = list; list != NULL; list = list->next)
diff --git a/src/core/misc.h b/src/core/misc.h
index 3df1dc94..7fa866df 100644
--- a/src/core/misc.h
+++ b/src/core/misc.h
@@ -25,7 +25,15 @@ GList *glist_find_string(GList *list, const char *key);
GList *glist_find_icase_string(GList *list, const char *key);
void *gslist_foreach_find(GSList *list, FOREACH_FIND_FUNC func, void *data);
-char *gslist_to_string(GSList *list, int offset, const char *delimiter);
+
+/* `list' contains pointer to structure with a char* to string. */
+char *gslistptr_to_string(GSList *list, int offset, const char *delimiter);
+/* `list' contains char* */
+char *gslist_to_string(GSList *list, const char *delimiter);
+
+/* save all keys in hash table to linked list - you shouldn't remove any
+ items while using this list, use g_slist_free() after you're done with it */
+GSList *hashtable_get_keys(GHashTable *hash);
/* strstr() with case-ignoring */
char *stristr(const char *data, const char *key);
diff --git a/src/fe-common/core/fe-core-commands.c b/src/fe-common/core/fe-core-commands.c
index 4de1ae6a..3b725bae 100644
--- a/src/fe-common/core/fe-core-commands.c
+++ b/src/fe-common/core/fe-core-commands.c
@@ -31,7 +31,7 @@
#include "windows.h"
static const char *ret_texts[] = {
- NULL,
+ NULL,
"Not enough parameters given",
"Not connected to IRC server yet",
"Not joined to any channels yet",
@@ -230,15 +230,18 @@ static void cmd_version(char *data)
static void cmd_cat(const char *data)
{
- char *params, *fname, *fposstr;
- char tmpbuf[1024], *str;
LINEBUF_REC *buffer = NULL;
+ char *fname, *fposstr;
+ char tmpbuf[1024], *str;
+ void *free_arg;
int f, ret, recvlen, fpos;
- params = cmd_get_params(data, 2, &fname, &fposstr);
+ if (!cmd_get_params(data, &free_arg, 2, &fname, &fposstr))
+ return;
+
fname = convert_home(fname);
fpos = atoi(fposstr);
- g_free(params);
+ cmd_params_free(free_arg);
f = open(fname, O_RDONLY);
g_free(fname);
@@ -301,15 +304,24 @@ static void event_default_command(const char *data, void *server, WI_ITEM_REC *i
cmd_unknown(data, server, item);
}
-static void event_cmderror(gpointer errorp)
+static void event_cmderror(gpointer errorp, const char *arg)
{
int error;
error = GPOINTER_TO_INT(errorp);
- if (error == CMDERR_ERRNO)
+ switch (error) {
+ case CMDERR_ERRNO:
printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, g_strerror(errno));
- else
+ break;
+ case CMDERR_OPTION_UNKNOWN:
+ printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Unknown argument: %s", arg);
+ break;
+ case CMDERR_OPTION_ARG_MISSING:
+ printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Missing required argument for: %s", arg);
+ break;
+ default:
printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, ret_texts[error]);
+ }
}
void fe_core_commands_init(void)
diff --git a/src/fe-common/core/fe-log.c b/src/fe-common/core/fe-log.c
index c66859b3..1da7e229 100644
--- a/src/fe-common/core/fe-log.c
+++ b/src/fe-common/core/fe-log.c
@@ -45,18 +45,24 @@ static void cmd_log_open(const char *data)
{
/* /LOG OPEN [-noopen] [-autoopen] [-targets <targets>] [-window]
[-rotate hour|day|week|month] <fname> [<levels>] */
- char *params, *args, *targetarg, *rotatearg, *fname, *levels;
+ GHashTable *optlist;
+ char *targetarg, *rotatearg, *fname, *levels;
+ void *free_arg;
char window[MAX_INT_STRLEN];
LOG_REC *log;
int level, rotate;
- args = "targets rotate";
- params = cmd_get_params(data, 5 | PARAM_FLAG_MULTIARGS | PARAM_FLAG_GETREST,
- &args, &targetarg, &rotatearg, &fname, &levels);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST,
+ "log open", &optlist, &fname, &levels))
+ return;
+
+ targetarg = g_hash_table_lookup(optlist, "targets");
+ rotatearg = g_hash_table_lookup(optlist, "rotate");
+
if (*fname == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
rotate = LOG_ROTATE_NEVER;
- if (stristr(args, "-rotate")) {
+ if (rotatearg != NULL) {
rotate = log_str2rotate(rotatearg);
if (rotate < 0) rotate = LOG_ROTATE_NEVER;
}
@@ -64,7 +70,7 @@ static void cmd_log_open(const char *data)
level = level2bits(levels);
if (level == 0) level = MSGLEVEL_ALL;
- if (stristr(args, "-window")) {
+ if (g_hash_table_lookup(optlist, "window")) {
/* log by window ref# */
ltoa(window, active_win->refnum);
targetarg = window;
@@ -72,12 +78,12 @@ static void cmd_log_open(const char *data)
log = log_create_rec(fname, level, targetarg);
if (log != NULL) {
- if (stristr(args, "-autoopen"))
+ if (g_hash_table_lookup(optlist, "autoopen"))
log->autoopen = TRUE;
log->rotate = rotate;
log_update(log);
- if (log->handle == -1 && stristr(args, "-noopen") == NULL) {
+ if (log->handle == -1 && g_hash_table_lookup(optlist, "noopen") == NULL) {
/* start logging */
if (log_start_logging(log)) {
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
@@ -88,7 +94,7 @@ static void cmd_log_open(const char *data)
}
}
- g_free(params);
+ cmd_params_free(free_arg);
}
static LOG_REC *log_find_from_data(const char *data)
@@ -191,10 +197,12 @@ static void cmd_window_log(const char *data)
{
/* /WINDOW LOG ON|OFF|TOGGLE [<filename>] */
LOG_REC *log;
- char *params, *set, *fname, window[MAX_INT_STRLEN];
+ char *set, *fname, window[MAX_INT_STRLEN];
+ void *free_arg;
int open_log, close_log;
- params = cmd_get_params(data, 2, &set, &fname);
+ if (!cmd_get_params(data, &free_arg, 2, &set, &fname))
+ return;
ltoa(window, active_win->refnum);
log = log_find_item(window);
@@ -209,7 +217,7 @@ static void cmd_window_log(const char *data)
close_log = log != NULL;
} else {
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOT_TOGGLE);
- g_free(params);
+ cmd_params_free(free_arg);
return;
}
@@ -232,7 +240,7 @@ static void cmd_window_log(const char *data)
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_LOG_CLOSED, log->fname);
}
- g_free(params);
+ cmd_params_free(free_arg);
}
/* Create log file entry to window, but don't start logging */
@@ -440,6 +448,8 @@ void fe_log_init(void)
signal_add("log create failed", (SIGNAL_FUNC) sig_log_create_failed);
signal_add("awaylog show", (SIGNAL_FUNC) sig_awaylog_show);
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
+
+ command_set_options("log open", "noopen autoopen -targets window -rotate");
}
void fe_log_deinit(void)
diff --git a/src/fe-common/core/fe-settings.c b/src/fe-common/core/fe-settings.c
index f05faad0..299f437e 100644
--- a/src/fe-common/core/fe-settings.c
+++ b/src/fe-common/core/fe-settings.c
@@ -66,10 +66,12 @@ static void set_boolean(const char *key, const char *value)
static void cmd_set(char *data)
{
GSList *sets, *tmp;
- char *params, *key, *value, *last_section;
+ char *key, *value, *last_section;
+ void *free_arg;
int found;
- params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &key, &value);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &key, &value))
+ return;
last_section = ""; found = 0;
sets = settings_get_sorted();
@@ -110,15 +112,17 @@ static void cmd_set(char *data)
if (!found)
printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Unknown setting %s", key);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_toggle(const char *data)
{
- char *params, *key, *value;
+ char *key, *value;
+ void *free_arg;
int type;
- params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &key, &value);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &key, &value))
+ return;
type = settings_get_type(key);
if (type == -1)
@@ -130,7 +134,7 @@ static void cmd_toggle(const char *data)
set_print(settings_get_record(key));
}
- g_free(params);
+ cmd_params_free(free_arg);
}
static void show_aliases(const char *alias)
@@ -173,11 +177,14 @@ static void alias_remove(const char *alias)
static void cmd_alias(const char *data)
{
- char *params, *alias, *value;
+ char *alias, *value;
+ void *free_arg;
g_return_if_fail(data != NULL);
- params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &alias, &value);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &alias, &value))
+ return;
+
if (*alias == '-') {
if (alias[1] != '\0') alias_remove(alias+1);
} else if (*alias == '\0' || *value == '\0')
@@ -186,7 +193,7 @@ static void cmd_alias(const char *data)
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_ALIAS_ADDED, alias);
iconfig_set_str("aliases", alias, value);
}
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_unalias(const char *data)
diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c
index f78d8904..d2da11cd 100644
--- a/src/fe-common/core/hilight-text.c
+++ b/src/fe-common/core/hilight-text.c
@@ -268,9 +268,11 @@ static void cmd_hilight_show(void)
static void cmd_hilight(const char *data)
{
/* /HILIGHT [-nick | -regexp | -word] [-color <color>] [-level <level>] [-channels <channels>] <text> */
- char *params, *args, *colorarg, *levelarg, *chanarg, *text;
- char **channels;
+ GHashTable *optlist;
HILIGHT_REC *rec;
+ char *colorarg, *levelarg, *chanarg, *text;
+ char **channels;
+ void *free_arg;
g_return_if_fail(data != NULL);
@@ -279,12 +281,17 @@ static void cmd_hilight(const char *data)
return;
}
- args = "color level channels";
- params = cmd_get_params(data, 5 | PARAM_FLAG_MULTIARGS | PARAM_FLAG_GETREST,
- &args, &colorarg, &levelarg, &chanarg, &text);
+ if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
+ PARAM_FLAG_GETREST, "hilight", &optlist, &text))
+ return;
+
+ chanarg = g_hash_table_lookup(optlist, "channels");
+ levelarg = g_hash_table_lookup(optlist, "level");
+ colorarg = g_hash_table_lookup(optlist, "color");
+
if (*text == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
- channels = *chanarg == '\0' ? NULL :
+ channels = (chanarg == NULL || *chanarg == '\0') ? NULL :
g_strsplit(replace_chars(chanarg, ',', ' '), " ", -1);
rec = hilight_find(text, channels);
@@ -302,17 +309,19 @@ static void cmd_hilight(const char *data)
}
hilights = g_slist_append(hilights, rec);
- rec->nickmask = stristr(args, "-nick") != NULL;
- rec->fullword = stristr(args, "-word") != NULL;
- rec->regexp = stristr(args, "-regexp") != NULL;
+ rec->nickmask = g_hash_table_lookup(optlist, "nick") != NULL;
+ rec->fullword = g_hash_table_lookup(optlist, "word") != NULL;
+ rec->regexp = g_hash_table_lookup(optlist, "regexp") != NULL;
- rec->level = level2bits(replace_chars(levelarg, ',', ' '));
- if (*colorarg != '\0') rec->color = g_strdup(colorarg);
+ rec->level = (levelarg == NULL || *levelarg == '\0') ? 0 :
+ level2bits(replace_chars(levelarg, ',', ' '));
+ if (colorarg != NULL && *colorarg != '\0')
+ rec->color = g_strdup(colorarg);
hilight_print(g_slist_index(hilights, rec)+1, rec);
hilight_add_config(rec);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_dehilight(const char *data)
@@ -349,6 +358,8 @@ void hilight_text_init(void)
signal_add("setup reread", (SIGNAL_FUNC) read_hilight_config);
command_bind("hilight", NULL, (SIGNAL_FUNC) cmd_hilight);
command_bind("dehilight", NULL, (SIGNAL_FUNC) cmd_dehilight);
+
+ command_set_options("hilight", "-color -level -channels nick word regexp");
}
void hilight_text_deinit(void)
diff --git a/src/fe-common/core/themes.c b/src/fe-common/core/themes.c
index 879f558c..efe905bf 100644
--- a/src/fe-common/core/themes.c
+++ b/src/fe-common/core/themes.c
@@ -348,17 +348,21 @@ static void theme_show(THEME_SEARCH_REC *rec, const char *key, const char *value
static void cmd_format(const char *data)
{
- char *params, *module, *key, *value;
GSList *tmp, *modules;
+ char *module, *key, *value;
+ void *free_arg;
/* /FORMAT [<module>] [<key> [<value>]] */
- params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &module, &key, &value);
+ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST,
+ &module, &key, &value))
+ return;
modules = get_sorted_modules();
if (*module != '\0' && theme_search(modules, module) == NULL) {
/* first argument isn't module.. */
- g_free(params);
- params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &key, &value);
+ cmd_params_free(free_arg);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &key, &value))
+ return;
module = "";
}
@@ -374,7 +378,7 @@ static void cmd_format(const char *data)
g_slist_foreach(modules, (GFunc) g_free, NULL);
g_slist_free(modules);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void module_save(const char *module, MODULE_THEME_REC *rec, CONFIG_NODE *fnode)
diff --git a/src/fe-common/irc/dcc/fe-dcc.c b/src/fe-common/irc/dcc/fe-dcc.c
index f67add7c..d128a332 100644
--- a/src/fe-common/irc/dcc/fe-dcc.c
+++ b/src/fe-common/irc/dcc/fe-dcc.c
@@ -231,24 +231,28 @@ static void dcc_error_close_not_found(const char *type, const char *nick, const
static void dcc_unknown_ctcp(const char *data, const char *sender)
{
- char *params, *type, *args;
+ char *type, *args;
+ void *free_arg;
g_return_if_fail(data != NULL);
- params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &type, &args);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &type, &args))
+ return;
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_UNKNOWN_CTCP, type, sender, args);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void dcc_unknown_reply(const char *data, const char *sender)
{
- char *params, *type, *args;
+ char *type, *args;
+ void *free_arg;
g_return_if_fail(data != NULL);
- params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &type, &args);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &type, &args))
+ return;
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_UNKNOWN_REPLY, type, sender, args);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void sig_dcc_destroyed(DCC_REC *dcc)
@@ -288,7 +292,8 @@ static void sig_query_destroyed(QUERY_REC *query)
static void cmd_msg(const char *data)
{
DCC_REC *dcc;
- char *params, *text, *target;
+ char *text, *target;
+ void *free_arg;
g_return_if_fail(data != NULL);
@@ -297,7 +302,8 @@ static void cmd_msg(const char *data)
return;
}
- params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &text);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &text))
+ return;
dcc = dcc_find_item(DCC_TYPE_CHAT, target+1, NULL);
if (dcc == NULL) {
@@ -309,7 +315,7 @@ static void cmd_msg(const char *data)
IRCTXT_OWN_DCC, dcc->mynick, text);
}
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_me(const char *data, SERVER_REC *server, WI_IRC_REC *item)
@@ -327,8 +333,9 @@ static void cmd_me(const char *data, SERVER_REC *server, WI_IRC_REC *item)
static void cmd_action(const char *data, SERVER_REC *server, WI_IRC_REC *item)
{
- char *params, *target, *text;
DCC_REC *dcc;
+ char *target, *text;
+ void *free_arg;
g_return_if_fail(data != NULL);
@@ -337,7 +344,8 @@ static void cmd_action(const char *data, SERVER_REC *server, WI_IRC_REC *item)
return;
}
- params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &text);
+ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &text))
+ return;
if (*target == '\0' || *text == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
dcc = dcc_find_item(DCC_TYPE_CHAT, target+1, NULL);
@@ -348,23 +356,25 @@ static void cmd_action(const char *data, SERVER_REC *server, WI_IRC_REC *item)
printformat(NULL, target, MSGLEVEL_DCC,
IRCTXT_OWN_DCC_ME, dcc->mynick, text);
}
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_ctcp(const char *data, SERVER_REC *server)
{
- char *params, *target, *ctcpcmd, *ctcpdata;
DCC_REC *dcc;
+ char *target, *ctcpcmd, *ctcpdata;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata);
+ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata))
+ return;
if (*target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
if (*target != '=') {
/* handle only DCC CTCPs */
- g_free(params);
+ cmd_params_free(free_arg);
return;
}
@@ -378,7 +388,7 @@ static void cmd_ctcp(const char *data, SERVER_REC *server)
target, ctcpcmd, ctcpdata);
}
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_dcc_list(const char *data)
diff --git a/src/fe-common/irc/fe-channels.c b/src/fe-common/irc/fe-channels.c
index 7cf4f5eb..c17325eb 100644
--- a/src/fe-common/irc/fe-channels.c
+++ b/src/fe-common/irc/fe-channels.c
@@ -192,12 +192,17 @@ static void cmd_channel(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *i
static void cmd_channel_add(const char *data)
{
- char *params, *args, *botarg, *botcmdarg, *ircnet, *channel, *password;
+ GHashTable *optlist;
SETUP_CHANNEL_REC *rec;
+ char *botarg, *botcmdarg, *ircnet, *channel, *password;
+ void *free_arg;
- args = "bots botcmd";
- params = cmd_get_params(data, 6 | PARAM_FLAG_MULTIARGS, &args,
- &botarg, &botcmdarg, &channel, &ircnet, &password);
+ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_OPTIONS,
+ "channel add", &optlist, &channel, &ircnet, &password))
+ return;
+
+ botarg = g_hash_table_lookup(optlist, "bots");
+ botcmdarg = g_hash_table_lookup(optlist, "botcmd");
if (*ircnet == '\0' || *channel == '\0')
cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
@@ -207,27 +212,29 @@ static void cmd_channel_add(const char *data)
rec->name = g_strdup(channel);
rec->ircnet = g_strdup(ircnet);
} else {
- if (stristr(args, "-bots")) g_free_and_null(rec->botmasks);
- if (stristr(args, "-botcmd")) g_free_and_null(rec->autosendcmd);
+ if (g_hash_table_lookup(optlist, "bots")) g_free_and_null(rec->botmasks);
+ if (g_hash_table_lookup(optlist, "botcmd")) g_free_and_null(rec->autosendcmd);
if (*password != '\0') g_free_and_null(rec->password);
}
- if (stristr(args, "-auto")) rec->autojoin = TRUE;
- if (stristr(args, "-noauto")) rec->autojoin = FALSE;
- if (*botarg != '\0') rec->botmasks = g_strdup(botarg);
- if (*botcmdarg != '\0') rec->autosendcmd = g_strdup(botcmdarg);
+ if (g_hash_table_lookup(optlist, "auto")) rec->autojoin = TRUE;
+ if (g_hash_table_lookup(optlist, "noauto")) rec->autojoin = FALSE;
+ if (botarg != NULL && *botarg != '\0') rec->botmasks = g_strdup(botarg);
+ if (botcmdarg != NULL && *botcmdarg != '\0') rec->autosendcmd = g_strdup(botcmdarg);
if (*password != '\0' && strcmp(password, "-") != 0) rec->password = g_strdup(password);
channels_setup_create(rec);
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_CHANSETUP_ADDED, channel, ircnet);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_channel_remove(const char *data)
{
- char *params, *ircnet, *channel;
SETUP_CHANNEL_REC *rec;
+ char *ircnet, *channel;
+ void *free_arg;
- params = cmd_get_params(data, 2, &channel, &ircnet);
+ if (!cmd_get_params(data, &free_arg, 2, &channel, &ircnet))
+ return;
if (*ircnet == '\0' || *channel == '\0')
cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
@@ -238,7 +245,7 @@ static void cmd_channel_remove(const char *data)
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_CHANSETUP_REMOVED, channel, ircnet);
channels_setup_destroy(rec);
}
- g_free(params);
+ cmd_params_free(free_arg);
}
void fe_channels_init(void)
@@ -257,6 +264,8 @@ void fe_channels_init(void)
command_bind("channel add", NULL, (SIGNAL_FUNC) cmd_channel_add);
command_bind("channel remove", NULL, (SIGNAL_FUNC) cmd_channel_remove);
command_bind("channel list", NULL, (SIGNAL_FUNC) cmd_channel_list);
+
+ command_set_options("channel add", "auto noauto -bots -botcmd");
}
void fe_channels_deinit(void)
diff --git a/src/fe-common/irc/fe-ignore.c b/src/fe-common/irc/fe-ignore.c
index cbd74244..6366dd98 100644
--- a/src/fe-common/irc/fe-ignore.c
+++ b/src/fe-common/irc/fe-ignore.c
@@ -137,14 +137,16 @@ static void cmd_ignore_show(void)
static void cmd_ignore(const char *data)
{
/* /IGNORE [-regexp | -word] [-pattern <pattern>] [-except]
- [-channels <channel>] <mask> <levels>
+ [-replies] [-channels <channel>] <mask> <levels>
OR
- /IGNORE [-regexp | -word] [-pattern <pattern>] [-except]
+ /IGNORE [-regexp | -word] [-pattern <pattern>] [-except] [-replies]
<channels> <levels> */
- char *params, *args, *patternarg, *chanarg, *mask, *levels, *key;
- char **channels;
+ GHashTable *optlist;
IGNORE_REC *rec;
+ char *patternarg, *chanarg, *mask, *levels, *key;
+ char **channels;
+ void *free_arg;
int new_ignore;
if (*data == '\0') {
@@ -152,16 +154,20 @@ static void cmd_ignore(const char *data)
return;
}
- args = "pattern channels";
- params = cmd_get_params(data, 5 | PARAM_FLAG_MULTIARGS | PARAM_FLAG_GETREST,
- &args, &patternarg, &chanarg, &mask, &levels);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST,
+ "ignore", &optlist, &mask, &levels))
+ return;
+
+ patternarg = g_hash_table_lookup(optlist, "pattern");
+ chanarg = g_hash_table_lookup(optlist, "channels");
+
if (*levels == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
if (ischannel(*mask)) {
chanarg = mask;
mask = "";
}
- channels = *chanarg == '\0' ? NULL :
+ channels = (chanarg == NULL || *chanarg == '\0') ? NULL :
g_strsplit(replace_chars(chanarg, ',', ' '), " ", -1);
rec = ignore_find(NULL, mask, channels);
@@ -177,16 +183,17 @@ static void cmd_ignore(const char *data)
g_strfreev(channels);
}
- if (stristr(args, "-except") != NULL) {
+ if (g_hash_table_lookup(optlist, "except") != NULL) {
rec->except_level = combine_level(rec->except_level, levels);
} else {
ignore_split_levels(levels, &rec->level, &rec->except_level);
}
- rec->pattern = *patternarg == '\0' ? NULL : g_strdup(patternarg);
- rec->regexp = stristr(args, "-regexp") != NULL;
- rec->fullword = stristr(args, "-word") != NULL;
- rec->replies = stristr(args, "-replies") != NULL;
+ rec->pattern = (patternarg == NULL || *patternarg == '\0') ?
+ NULL : g_strdup(patternarg);
+ rec->regexp = g_hash_table_lookup(optlist, "regexp") != NULL;
+ rec->fullword = g_hash_table_lookup(optlist, "word") != NULL;
+ rec->replies = g_hash_table_lookup(optlist, "replies") != NULL;
if (rec->level == 0 && rec->except_level == 0) {
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_UNIGNORED,
@@ -204,7 +211,7 @@ static void cmd_ignore(const char *data)
else
ignore_update_rec(rec);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_unignore(const char *data)
@@ -242,6 +249,8 @@ void fe_ignore_init(void)
{
command_bind("ignore", NULL, (SIGNAL_FUNC) cmd_ignore);
command_bind("unignore", NULL, (SIGNAL_FUNC) cmd_unignore);
+
+ command_set_options("ignore", "regexp word except replies -pattern -channels");
}
void fe_ignore_deinit(void)
diff --git a/src/fe-common/irc/fe-irc-commands.c b/src/fe-common/irc/fe-irc-commands.c
index 900b0a2c..0e8e111b 100644
--- a/src/fe-common/irc/fe-irc-commands.c
+++ b/src/fe-common/irc/fe-irc-commands.c
@@ -93,18 +93,20 @@ static void cmd_msg(gchar *data, IRC_SERVER_REC *server, WI_ITEM_REC *item)
WINDOW_REC *window;
CHANNEL_REC *channel;
NICK_REC *nickrec;
- char *params, *target, *msg, *nickmode, *freestr, *newtarget;
+ char *target, *msg, *nickmode, *freestr, *newtarget;
+ void *free_arg;
int free_ret;
g_return_if_fail(data != NULL);
- params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &msg))
+ return;
if (*target == '\0' || *msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
if (*target == '=')
{
/* dcc msg - handled in fe-dcc.c */
- g_free(params);
+ cmd_params_free(free_arg);
return;
}
@@ -119,7 +121,7 @@ static void cmd_msg(gchar *data, IRC_SERVER_REC *server, WI_ITEM_REC *item)
if (newtarget == NULL) {
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, *target == ',' ?
IRCTXT_NO_MSGS_GOT : IRCTXT_NO_MSGS_SENT);
- g_free(params);
+ cmd_params_free(free_arg);
signal_stop();
return;
}
@@ -160,7 +162,7 @@ static void cmd_msg(gchar *data, IRC_SERVER_REC *server, WI_ITEM_REC *item)
}
g_free_not_null(freestr);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_me(gchar *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
@@ -180,27 +182,31 @@ static void cmd_me(gchar *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
static void cmd_action(const char *data, IRC_SERVER_REC *server)
{
- char *params, *target, *text;
+ char *target, *text;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &text);
+ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &text))
+ return;
if (*target == '\0' || *text == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
printformat(server, target, MSGLEVEL_ACTIONS, IRCTXT_OWN_ME, server->nick, text);
irc_send_cmdv(server, "PRIVMSG %s :\001ACTION %s\001", target, text);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_notice(gchar *data, IRC_SERVER_REC *server)
{
- char *params, *target, *msg;
+ char *target, *msg;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &msg))
+ return;
if (*target == '\0' || *msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
if (*target == '@' && ischannel(target[1]))
@@ -209,17 +215,19 @@ static void cmd_notice(gchar *data, IRC_SERVER_REC *server)
printformat(server, target, MSGLEVEL_NOTICES | MSGLEVEL_NOHILIGHT,
IRCTXT_OWN_NOTICE, target, msg);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_ctcp(const char *data, IRC_SERVER_REC *server)
{
- char *params, *target, *ctcpcmd, *ctcpdata;
+ char *target, *ctcpcmd, *ctcpdata;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata);
+ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata))
+ return;
if (*target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
if (*target == '@' && ischannel(target[1]))
@@ -228,17 +236,19 @@ static void cmd_ctcp(const char *data, IRC_SERVER_REC *server)
g_strup(ctcpcmd);
printformat(server, target, MSGLEVEL_CTCPS, IRCTXT_OWN_CTCP, target, ctcpcmd, ctcpdata);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_nctcp(const char *data, IRC_SERVER_REC *server)
{
- gchar *params, *target, *ctcpcmd, *ctcpdata;
+ char *target, *ctcpcmd, *ctcpdata;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata);
+ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata))
+ return;
if (*target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
if (*target == '@' && ischannel(target[1]))
@@ -247,19 +257,21 @@ static void cmd_nctcp(const char *data, IRC_SERVER_REC *server)
g_strup(ctcpcmd);
printformat(server, target, MSGLEVEL_NOTICES, IRCTXT_OWN_NOTICE, target, ctcpcmd, ctcpdata);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
- char *params, *channame, *msg;
CHANNEL_REC *chanrec;
+ char *channame, *msg;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected || !irc_server_check(server))
cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, item, &channame, &msg);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, item, &channame, &msg))
+ return;
if (*msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
chanrec = channel_find(server, channame);
@@ -267,7 +279,7 @@ static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
printformat(server, chanrec->name, MSGLEVEL_NOTICES, IRCTXT_OWN_WALL, chanrec->name, msg);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_ban(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
diff --git a/src/fe-common/irc/fe-irc-server.c b/src/fe-common/irc/fe-irc-server.c
index 24c662b4..140284fd 100644
--- a/src/fe-common/irc/fe-irc-server.c
+++ b/src/fe-common/irc/fe-irc-server.c
@@ -78,17 +78,18 @@ static void print_reconnects(void)
}
}
-static void server_add(const char *data)
+static void cmd_server_add(const char *data)
{
+ GHashTable *optlist;
SETUP_SERVER_REC *rec;
- char *params, *args, *ircnet, *host, *cmdspeed, *cmdmax, *portarg;
- char *addr, *portstr, *password;
+ char *addr, *portstr, *password, *value;
+ void *free_arg;
int port;
- args = "ircnet host cmdspeed cmdmax port";
- params = cmd_get_params(data, 9 | PARAM_FLAG_MULTIARGS,
- &args, &ircnet, &host, &cmdspeed, &cmdmax,
- &portarg, &addr, &portstr, &password);
+ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_OPTIONS,
+ "server add", &optlist, &addr, &portstr, &password))
+ return;
+
if (*addr == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
port = *portstr == '\0' ? 6667 : atoi(portstr);
@@ -98,39 +99,48 @@ static void server_add(const char *data)
rec->address = g_strdup(addr);
rec->port = port;
} else {
- if (*portarg != '\0') rec->port = atoi(portarg);
- if (stristr(args, "-ircnet")) g_free_and_null(rec->ircnet);
+ value = g_hash_table_lookup(optlist, "port");
+ if (value != NULL && *value != '\0') rec->port = atoi(value);
+
+ if (g_hash_table_lookup(optlist, "ircnet")) g_free_and_null(rec->ircnet);
if (*password != '\0') g_free_and_null(rec->password);
- if (stristr(args, "-host")) {
+ if (g_hash_table_lookup(optlist, "host")) {
g_free_and_null(rec->own_host);
rec->own_ip = NULL;
}
}
- if (stristr(args, "-auto")) rec->autoconnect = TRUE;
- if (stristr(args, "-noauto")) rec->autoconnect = FALSE;
- if (*ircnet != '\0') rec->ircnet = g_strdup(ircnet);
+ if (g_hash_table_lookup(optlist, "auto")) rec->autoconnect = TRUE;
+ if (g_hash_table_lookup(optlist, "noauto")) rec->autoconnect = FALSE;
+
if (*password != '\0' && strcmp(password, "-") != 0) rec->password = g_strdup(password);
- if (*host != '\0') {
- rec->own_host = g_strdup(host);
+ value = g_hash_table_lookup(optlist, "ircnet");
+ if (value != NULL && *value != '\0') rec->ircnet = g_strdup(value);
+ value = g_hash_table_lookup(optlist, "host");
+ if (value != NULL && *value != '\0') {
+ rec->own_host = g_strdup(value);
rec->own_ip = NULL;
}
- if (*cmdspeed != '\0') rec->cmd_queue_speed = atoi(cmdspeed);
- if (*cmdmax != '\0') rec->max_cmds_at_once = atoi(cmdmax);
+ value = g_hash_table_lookup(optlist, "cmdspeed");
+ if (value != NULL && *value != '\0') rec->cmd_queue_speed = atoi(value);
+ value = g_hash_table_lookup(optlist, "cmdmax");
+ if (value != NULL && *value != '\0') rec->max_cmds_at_once = atoi(value);
server_setup_add(rec);
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_SETUPSERVER_ADDED, addr, port);
- g_free(params);
+ cmd_params_free(free_arg);
}
-static void server_remove(const char *data)
+static void cmd_server_remove(const char *data)
{
SETUP_SERVER_REC *rec;
- char *params, *args, *addr, *portstr;
+ char *addr, *portstr;
+ void *free_arg;
int port;
- params = cmd_get_params(data, 3 | PARAM_FLAG_OPTARGS, &args, &addr, &portstr);
+ if (!cmd_get_params(data, &free_arg, 2, &addr, &portstr))
+ return;
if (*addr == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
port = *portstr == '\0' ? 6667 : atoi(portstr);
@@ -142,10 +152,10 @@ static void server_remove(const char *data)
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_SETUPSERVER_REMOVED, addr, port);
}
- g_free(params);
+ cmd_params_free(free_arg);
}
-static void server_list(const char *data)
+static void cmd_server_list(const char *data)
{
GString *str;
GSList *tmp;
@@ -177,9 +187,11 @@ static void server_list(const char *data)
g_string_free(str, TRUE);
}
-static void cmd_server(const char *data)
+static void cmd_server(const char *data, IRC_SERVER_REC *server, void *item)
{
- char *params, *args, *ircnetarg, *hostarg, *addr;
+ GHashTable *optlist;
+ char *addr;
+ void *free_arg;
if (*data == '\0') {
print_servers();
@@ -190,36 +202,40 @@ static void cmd_server(const char *data)
return;
}
- args = "ircnet host"; /* should be same as in connect_server() in src/irc/core/irc-commands.c */
- params = cmd_get_params(data, 4 | PARAM_FLAG_MULTIARGS,
- &args, &ircnetarg, &hostarg, &addr);
-
- if (stristr(args, "-list") != NULL) {
- server_list(data);
- signal_stop();
- } else if (stristr(args, "-add") != NULL) {
- if (*addr == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
- server_add(data);
+ if (g_strncasecmp(data, "add ", 4) == 0 ||
+ g_strncasecmp(data, "remove ", 7) == 0 ||
+ g_strcasecmp(data, "list") == 0 ||
+ g_strncasecmp(data, "list ", 5) == 0) {
+ command_runsub("server", data, server, item);
signal_stop();
- } else if (stristr(args, "-remove") != NULL) {
- if (*addr == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
- server_remove(data);
- signal_stop();
- } else {
- if (*addr == '\0' || strcmp(addr, "+") == 0)
- cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
- if (*addr == '+') window_create(NULL, FALSE);
+ return;
}
- g_free(params);
+ if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS,
+ "connect", &optlist, &addr))
+ return;
+
+ if (*addr == '\0' || strcmp(addr, "+") == 0)
+ cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
+ if (*addr == '+') window_create(NULL, FALSE);
+
+ cmd_params_free(free_arg);
}
void fe_irc_server_init(void)
{
command_bind("server", NULL, (SIGNAL_FUNC) cmd_server);
+ command_bind("server add", NULL, (SIGNAL_FUNC) cmd_server_add);
+ command_bind("server remove", NULL, (SIGNAL_FUNC) cmd_server_remove);
+ command_bind("server list", NULL, (SIGNAL_FUNC) cmd_server_list);
+
+ command_set_options("server add", "auto noauto -ircnet -host -cmdspeed -cmdmax -port");
}
void fe_irc_server_deinit(void)
{
command_unbind("server", (SIGNAL_FUNC) cmd_server);
+ command_unbind("server add", (SIGNAL_FUNC) cmd_server_add);
+ command_unbind("server remove", (SIGNAL_FUNC) cmd_server_remove);
+ command_unbind("server list", (SIGNAL_FUNC) cmd_server_list);
}
diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c
index 88e1d806..adc4f03c 100644
--- a/src/fe-common/irc/fe-ircnet.c
+++ b/src/fe-common/irc/fe-ircnet.c
@@ -79,15 +79,14 @@ static void cmd_ircnet_list(void)
static void cmd_ircnet_add(const char *data)
{
- char *params, *args, *kicks, *msgs, *modes, *whois;
- char *cmdspeed, *cmdmax, *nick, *user, *realname, *host, *autosendcmd, *name;
+ GHashTable *optlist;
+ char *name, *value;
+ void *free_arg;
IRCNET_REC *rec;
- args = "kicks msgs modes whois cmdspeed cmdmax nick user realname host autosendcmd";
- params = cmd_get_params(data, 13 | PARAM_FLAG_MULTIARGS, &args,
- &kicks, &msgs, &modes, &whois, &cmdspeed,
- &cmdmax, &nick, &user, &realname, &host,
- &autosendcmd, &name);
+ if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS,
+ "ircnet add", &optlist, &name))
+ return;
if (*name == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
rec = ircnet_find(name);
@@ -95,37 +94,50 @@ static void cmd_ircnet_add(const char *data)
rec = g_new0(IRCNET_REC, 1);
rec->name = g_strdup(name);
} else {
- if (stristr(args, "-nick")) g_free_and_null(rec->nick);
- if (stristr(args, "-user")) g_free_and_null(rec->username);
- if (stristr(args, "-realname")) g_free_and_null(rec->realname);
- if (stristr(args, "-host")) {
+ if (g_hash_table_lookup(optlist, "nick")) g_free_and_null(rec->nick);
+ if (g_hash_table_lookup(optlist, "user")) g_free_and_null(rec->username);
+ if (g_hash_table_lookup(optlist, "realname")) g_free_and_null(rec->realname);
+ if (g_hash_table_lookup(optlist, "host")) {
g_free_and_null(rec->own_host);
rec->own_ip = NULL;
}
- if (stristr(args, "-autosendcmd")) g_free_and_null(rec->autosendcmd);
+ if (g_hash_table_lookup(optlist, "autosendcmd")) g_free_and_null(rec->autosendcmd);
}
- if (stristr(args, "-kicks")) rec->max_kicks = atoi(kicks);
- if (stristr(args, "-msgs")) rec->max_msgs = atoi(msgs);
- if (stristr(args, "-modes")) rec->max_modes = atoi(modes);
- if (stristr(args, "-whois")) rec->max_whois = atoi(whois);
-
- if (stristr(args, "-cmdspeed")) rec->cmd_queue_speed = atoi(cmdspeed);
- if (stristr(args, "-cmdmax")) rec->max_cmds_at_once = atoi(cmdmax);
-
- if (*nick != '\0') rec->nick = g_strdup(nick);
- if (*user != '\0') rec->username = g_strdup(user);
- if (*realname != '\0') rec->realname = g_strdup(realname);
- if (*host != '\0') {
- rec->own_host = g_strdup(host);
+ value = g_hash_table_lookup(optlist, "kicks");
+ if (value != NULL) rec->max_kicks = atoi(value);
+ value = g_hash_table_lookup(optlist, "msgs");
+ if (value != NULL) rec->max_msgs = atoi(value);
+ value = g_hash_table_lookup(optlist, "modes");
+ if (value != NULL) rec->max_modes = atoi(value);
+ value = g_hash_table_lookup(optlist, "whois");
+ if (value != NULL) rec->max_whois = atoi(value);
+
+ value = g_hash_table_lookup(optlist, "cmdspeed");
+ if (value != NULL) rec->cmd_queue_speed = atoi(value);
+ value = g_hash_table_lookup(optlist, "cmdmax");
+ if (value != NULL) rec->max_cmds_at_once = atoi(value);
+
+ value = g_hash_table_lookup(optlist, "nick");
+ if (value != NULL && *value != '\0') rec->nick = g_strdup(value);
+ value = g_hash_table_lookup(optlist, "user");
+ if (value != NULL && *value != '\0') rec->username = g_strdup(value);
+ value = g_hash_table_lookup(optlist, "realname");
+ if (value != NULL && *value != '\0') rec->realname = g_strdup(value);
+
+ value = g_hash_table_lookup(optlist, "host");
+ if (value != NULL && *value != '\0') {
+ rec->own_host = g_strdup(value);
rec->own_ip = NULL;
}
- if (*autosendcmd != '\0') rec->autosendcmd = g_strdup(autosendcmd);
+
+ value = g_hash_table_lookup(optlist, "autosendcmd");
+ if (value != NULL && *value != '\0') rec->autosendcmd = g_strdup(value);
ircnet_create(rec);
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_IRCNET_ADDED, name);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_ircnet_remove(const char *data)
@@ -149,6 +161,8 @@ void fe_ircnet_init(void)
command_bind("ircnet ", NULL, (SIGNAL_FUNC) cmd_ircnet_list);
command_bind("ircnet add", NULL, (SIGNAL_FUNC) cmd_ircnet_add);
command_bind("ircnet remove", NULL, (SIGNAL_FUNC) cmd_ircnet_remove);
+
+ command_set_options("ircnet add", "-kicks -msgs -modes -whois -cmdspeed -cmdmax -nick -user -realname -host -autosendcmd");
}
void fe_ircnet_deinit(void)
diff --git a/src/fe-common/irc/irc-completion.c b/src/fe-common/irc/irc-completion.c
index 45065aca..76f97c5c 100644
--- a/src/fe-common/irc/irc-completion.c
+++ b/src/fe-common/irc/irc-completion.c
@@ -167,17 +167,19 @@ static void event_privmsg(const char *data, IRC_SERVER_REC *server, const char *
static void cmd_msg(const char *data, IRC_SERVER_REC *server)
{
- char *params, *target, *msg;
+ char *target, *msg;
+ void *free_arg;
g_return_if_fail(data != NULL);
- params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &msg))
+ return;
if (*target != '\0' && *msg != '\0') {
if (!ischannel(*target) && *target != '=' && server != NULL)
add_private_msg(server, target);
}
- g_free(params);
+ cmd_params_free(free_arg);
}
static void sig_nick_removed(CHANNEL_REC *channel, NICK_REC *nick)
diff --git a/src/fe-text/gui-textwidget.c b/src/fe-text/gui-textwidget.c
index f00e2afd..6a5325d0 100644
--- a/src/fe-text/gui-textwidget.c
+++ b/src/fe-text/gui-textwidget.c
@@ -91,31 +91,43 @@ static gchar *gui_window_line2text(LINE_REC *line)
#define LASTLOG_FLAG_WORD 0x08
#define LASTLOG_FLAG_REGEXP 0x10
-static int lastlog_parse_args(char *args, int *flags)
+static int lastlog_parse_options(GHashTable *options, int *flags)
{
- char **arglist, **tmp;
- int level;
+ GSList *list, *tmp;
+ int level, optlevel;
+
+ /* move all keys from `options' to linked list */
+ list = hashtable_get_keys(options);
/* level can be specified in arguments.. */
level = 0; *flags = 0;
- arglist = g_strsplit(args, " ", -1);
- for (tmp = arglist; *tmp != NULL; tmp++) {
- if (strcmp(*tmp, "-") == 0)
+ for (tmp = list; tmp != NULL; tmp = tmp->next) {
+ char *opt = tmp->data;
+
+ if (strcmp(opt, "-") == 0)
*flags |= LASTLOG_FLAG_NOHEADERS;
- else if (g_strcasecmp(*tmp, "-new") == 0)
+ else if (g_strcasecmp(opt, "new") == 0)
*flags |= LASTLOG_FLAG_NEW_LAST;
- else if (g_strcasecmp(*tmp, "-away") == 0)
+ else if (g_strcasecmp(opt, "away") == 0)
*flags |= LASTLOG_FLAG_NEW_AWAY;
- else if (g_strcasecmp(*tmp, "-word") == 0)
+ else if (g_strcasecmp(opt, "word") == 0)
*flags |= LASTLOG_FLAG_WORD;
- else if (g_strcasecmp(*tmp, "-regexp") == 0)
+ else if (g_strcasecmp(opt, "regexp") == 0)
*flags |= LASTLOG_FLAG_REGEXP;
- else
- level |= level2bits(tmp[0]+1);
+ else {
+ optlevel = level2bits(opt);
+ if (optlevel != 0)
+ level |= optlevel;
+ else {
+ signal_emit("error command", 2, GINT_TO_POINTER(CMDERR_OPTION_UNKNOWN), opt);
+ level = -1;
+ break;
+ }
+ }
}
if (level == 0) level = MSGLEVEL_ALL;
- g_strfreev(arglist);
+ g_slist_free(list);
return level;
}
@@ -148,14 +160,19 @@ static GList *lastlog_find_startline(GList *list, int count, int start, int leve
static void cmd_lastlog(const char *data)
{
+ GHashTable *optlist;
GList *startline, *list, *tmp;
- char *params, *str, *args, *text, *countstr, *start;
+ char *str, *text, *countstr, *start;
+ void *free_arg;
struct tm *tm;
int level, flags, count;
g_return_if_fail(data != NULL);
- params = cmd_get_params(data, 4 | PARAM_FLAG_OPTARGS, &args, &text, &countstr, &start);
+ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_OPTIONS | PARAM_FLAG_UNKNOWN_OPTIONS,
+ "lastlog", &optlist, &text, &countstr, &start))
+ return;
+
if (*start == '\0' && is_numeric(text, 0)) {
if (is_numeric(countstr, 0))
start = countstr;
@@ -165,7 +182,12 @@ static void cmd_lastlog(const char *data)
count = atoi(countstr);
if (count == 0) count = -1;
- level = lastlog_parse_args(args, &flags);
+ level = lastlog_parse_options(optlist, &flags);
+ if (level == -1) {
+ /* error in options */
+ cmd_params_free(free_arg);
+ return;
+ }
if ((flags & LASTLOG_FLAG_NOHEADERS) == 0)
printformat(NULL, NULL, MSGLEVEL_LASTLOG, IRCTXT_LASTLOG_START);
@@ -207,7 +229,7 @@ static void cmd_lastlog(const char *data)
g_list_last(WINDOW_GUI(active_win)->bottom_startline);
g_list_free(list);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_scrollback(gchar *data, SERVER_REC *server, WI_ITEM_REC *item)
@@ -254,10 +276,12 @@ static void scrollback_goto_pos(WINDOW_REC *window, GList *pos)
static void cmd_scrollback_goto(gchar *data)
{
GList *pos;
- gchar *params, *arg1, *arg2;
+ gchar *arg1, *arg2;
+ void *free_arg;
gint lines;
- params = cmd_get_params(data, 2, &arg1, &arg2);
+ if (!cmd_get_params(data, &free_arg, 2, &arg1, &arg2))
+ return;
if (*arg2 == '\0' && (*arg1 == '-' || *arg1 == '+'))
{
/* go forward/backward n lines */
@@ -322,7 +346,7 @@ static void cmd_scrollback_goto(gchar *data)
if (stamp > time(NULL)) {
/* we're still looking into future, don't bother checking */
- g_free(params);
+ cmd_params_free(free_arg);
return;
}
@@ -338,7 +362,7 @@ static void cmd_scrollback_goto(gchar *data)
}
}
}
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_scrollback_home(gchar *data)
@@ -398,6 +422,7 @@ void gui_textwidget_init(void)
command_bind("scrollback goto", NULL, (SIGNAL_FUNC) cmd_scrollback_goto);
command_bind("scrollback home", NULL, (SIGNAL_FUNC) cmd_scrollback_home);
command_bind("scrollback end", NULL, (SIGNAL_FUNC) cmd_scrollback_end);
+ command_set_options("lastlog", "new away word regexp");
signal_add("away mode changed", (SIGNAL_FUNC) sig_away_changed);
}
diff --git a/src/irc/bot/botnet-connection.c b/src/irc/bot/botnet-connection.c
index 387cce45..988a9b5c 100644
--- a/src/irc/bot/botnet-connection.c
+++ b/src/irc/bot/botnet-connection.c
@@ -480,14 +480,16 @@ static BOT_REC *bot_add(BOTNET_REC *botnet, const char *nick, const char *parent
static void botnet_event_botinfo(BOT_REC *bot, const char *data, const char *sender)
{
- char *params, *nick, *parent, *priority;
+ char *nick, *parent, *priority;
+ void *free_arg;
BOT_REC *rec;
/*str = g_strdup_printf("BOTINFO %s", data);
botnet_broadcast(bot->botnet, bot, sender, str);
g_free(str);*/
- params = cmd_get_params(data, 3, &nick, &parent, &priority);
+ if (!cmd_get_params(data, &free_arg, 3, &nick, &parent, &priority))
+ return;
if (*parent == '-' && parent[1] == '\0')
parent = NULL;
@@ -503,7 +505,7 @@ static void botnet_event_botinfo(BOT_REC *bot, const char *data, const char *sen
if (rec != NULL) {
rec->priority = atoi(priority);
}
- g_free(params);
+ cmd_params_free(free_arg);
}
static void botnet_event_botquit(BOT_REC *bot, const char *data)
diff --git a/src/irc/bot/botnet-users.c b/src/irc/bot/botnet-users.c
index fda58723..3b366ac6 100644
--- a/src/irc/bot/botnet-users.c
+++ b/src/irc/bot/botnet-users.c
@@ -108,81 +108,94 @@ void botcmd_user_set_password(USER_REC *user, const char *password)
static void botnet_event_user_add(BOT_REC *bot, const char *data, const char *sender)
{
- char *params, *nick;
+ char *nick;
+ void *free_arg;
+
+ if (!cmd_get_params(data, &free_arg, 1, &nick))
+ return;
- params = cmd_get_params(data, 1, &nick);
botuser_add(nick);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void botnet_event_user_flags(BOT_REC *bot, const char *data, const char *sender)
{
USER_REC *user;
- char *params, *nick, *flags;
+ char *nick, *flags;
+ void *free_arg;
- params = cmd_get_params(data, 2, &nick, &flags);
+ if (!cmd_get_params(data, &free_arg, 2, &nick, &flags))
+ return;
user = botuser_find(nick, NULL);
if (user == NULL) user = botuser_add(nick);
botuser_set_flags(user, botuser_flags2value(flags));
- g_free(params);
+ cmd_params_free(free_arg);
}
static void botnet_event_user_chan_flags(BOT_REC *bot, const char *data, const char *sender)
{
USER_REC *user;
- char *params, *nick, *channel, *flags;
+ char *nick, *channel, *flags;
+ void *free_arg;
- params = cmd_get_params(data, 3, &nick, &channel, &flags);
+ if (!cmd_get_params(data, &free_arg, 3, &nick, &channel, &flags))
+ return;
user = botuser_find(nick, NULL);
if (user == NULL) user = botuser_add(nick);
botuser_set_channel_flags(user, channel, botuser_flags2value(flags));
- g_free(params);
+ cmd_params_free(free_arg);
}
static void botnet_event_user_add_mask(BOT_REC *bot, const char *data, const char *sender)
{
USER_REC *user;
- char *params, *nick, *mask;
+ char *nick, *mask;
+ void *free_arg;
- params = cmd_get_params(data, 2, &nick, &mask);
+ if (!cmd_get_params(data, &free_arg, 2, &nick, &mask))
+ return;
user = botuser_find(nick, NULL);
if (user == NULL) user = botuser_add(nick);
botuser_add_mask(user, mask);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void botnet_event_user_mask_notflags(BOT_REC *bot, const char *data, const char *sender)
{
USER_REC *user;
- char *params, *nick, *mask, *not_flags;
+ char *nick, *mask, *not_flags;
+ void *free_arg;
- params = cmd_get_params(data, 3, &nick, &mask, &not_flags);
+ if (!cmd_get_params(data, &free_arg, 3, &nick, &mask, &not_flags))
+ return;
user = botuser_find(nick, NULL);
if (user == NULL) user = botuser_add(nick);
botuser_set_mask_notflags(user, mask, botuser_flags2value(not_flags));
- g_free(params);
+ cmd_params_free(free_arg);
}
static void botnet_event_user_pass(BOT_REC *bot, const char *data, const char *sender)
{
USER_REC *user;
- char *params, *nick, *pass;
+ char *nick, *pass;
+ void *free_arg;
- params = cmd_get_params(data, 2, &nick, &pass);
+ if (!cmd_get_params(data, &free_arg, 2, &nick, &pass))
+ return;
user = botuser_find(nick, NULL);
if (user == NULL) user = botuser_add(nick);
botuser_set_password(user, pass);
- g_free(params);
+ cmd_params_free(free_arg);
}
void botnet_users_init(void)
diff --git a/src/irc/bot/botnet.c b/src/irc/bot/botnet.c
index 4f74a867..190481d1 100644
--- a/src/irc/bot/botnet.c
+++ b/src/irc/bot/botnet.c
@@ -508,13 +508,15 @@ static void botnet_destroy(BOTNET_REC *botnet)
static void botnet_event(BOT_REC *bot, const char *data)
{
- char *params, *source, *target, *command, *args, *event;
+ char *source, *target, *command, *args, *event;
+ void *free_arg;
if (!bot->connected)
return;
- params = cmd_get_params(data, 4 | PARAM_FLAG_GETREST,
- &source, &target, &command, &args);
+ if (!cmd_get_params(data, &free_arg, 4 | PARAM_FLAG_GETREST,
+ &source, &target, &command, &args))
+ return;
if (*target == '-' && target[1] == '\0')
target = NULL;
@@ -524,23 +526,25 @@ static void botnet_event(BOT_REC *bot, const char *data)
signal_emit(event, 4, bot, args, source, target);
g_free(event);
- g_free(params);
+ cmd_params_free(free_arg);
}
/* broadcast the signal forward */
static void botnet_event_broadcast(BOT_REC *bot, const char *data)
{
- char *params, *source, *target, *command;
+ char *source, *target, *command;
+ void *free_arg;
if (!bot->connected)
return;
- params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST,
- &source, &target, &command);
+ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST,
+ &source, &target, &command))
+ return;
if (g_strcasecmp(target, bot->botnet->nick) == 0) {
/* message was for us */
- g_free(params);
+ cmd_params_free(free_arg);
return;
}
@@ -552,7 +556,7 @@ static void botnet_event_broadcast(BOT_REC *bot, const char *data)
botnet_send_cmd(bot->botnet, source, target, command);
}
- g_free(params);
+ cmd_params_free(free_arg);
}
static void botnet_event_master(BOT_REC *bot, const char *data, const char *sender)
diff --git a/src/irc/core/bans.c b/src/irc/core/bans.c
index 774587cf..914fad65 100644
--- a/src/irc/core/bans.c
+++ b/src/irc/core/bans.c
@@ -167,14 +167,15 @@ void ban_remove(CHANNEL_REC *channel, const char *bans)
static void command_set_ban(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item, int set)
{
CHANNEL_REC *chanrec;
- char *params, *channel, *nicks;
+ char *channel, *nicks;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected || !irc_server_check(server))
cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST,
- item, &channel, &nicks);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST,
+ item, &channel, &nicks)) return;
if (!ischannel(*channel)) cmd_param_error(CMDERR_NOT_JOINED);
if (*nicks == '\0') {
if (strcmp(data, "*") != 0)
@@ -192,7 +193,7 @@ static void command_set_ban(const char *data, IRC_SERVER_REC *server, WI_IRC_REC
else
ban_remove(chanrec, nicks);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_bantype(const char *data)
diff --git a/src/irc/core/channels-query.c b/src/irc/core/channels-query.c
index 0876f0bd..95ab9ecd 100644
--- a/src/irc/core/channels-query.c
+++ b/src/irc/core/channels-query.c
@@ -181,8 +181,8 @@ static void channel_send_query(IRC_SERVER_REC *server, int query)
chans = rec->queries[query];
- chanstr_commas = gslist_to_string(rec->queries[query], G_STRUCT_OFFSET(CHANNEL_REC, name), ",");
- chanstr_spaces = gslist_to_string(rec->queries[query], G_STRUCT_OFFSET(CHANNEL_REC, name), " ");
+ chanstr_commas = gslistptr_to_string(rec->queries[query], G_STRUCT_OFFSET(CHANNEL_REC, name), ",");
+ chanstr_spaces = gslistptr_to_string(rec->queries[query], G_STRUCT_OFFSET(CHANNEL_REC, name), " ");
chanstr = g_strconcat(chanstr_commas, " ", chanstr_spaces, NULL);
g_free(chanstr_spaces);
diff --git a/src/irc/core/channels.c b/src/irc/core/channels.c
index 6943952e..1048b202 100644
--- a/src/irc/core/channels.c
+++ b/src/irc/core/channels.c
@@ -162,15 +162,17 @@ void channels_join(IRC_SERVER_REC *server, const char *data, int automatic)
SETUP_CHANNEL_REC *schannel;
CHANNEL_REC *chanrec;
GString *outchans, *outkeys;
- char *params, *channels, *keys, *key;
+ char *channels, *keys, *key;
char **chanlist, **keylist, **tmp, **tmpkey, *channel;
+ void *free_arg;
int use_keys;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected || !irc_server_check(server))
cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &channels, &keys);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &channels, &keys))
+ return;
if (*channels == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
chanlist = g_strsplit(channels, ",", -1);
@@ -221,7 +223,7 @@ void channels_join(IRC_SERVER_REC *server, const char *data, int automatic)
g_strfreev(chanlist);
g_strfreev(keylist);
- g_free(params);
+ cmd_params_free(free_arg);
}
void channels_init(void)
diff --git a/src/irc/core/irc-commands.c b/src/irc/core/irc-commands.c
index a344931b..edc0dd7e 100644
--- a/src/irc/core/irc-commands.c
+++ b/src/irc/core/irc-commands.c
@@ -49,27 +49,34 @@ static IRC_SERVER_REC *connect_server(const char *data)
{
IRC_SERVER_CONNECT_REC *conn;
IRC_SERVER_REC *server;
- char *params, *args, *ircnet, *host, *addr, *portstr, *password, *nick;
+ GHashTable *optlist;
+ char *addr, *portstr, *password, *nick, *ircnet, *host;
+ void *free_arg;
g_return_val_if_fail(data != NULL, NULL);
- args = "ircnet host";
- params = cmd_get_params(data, 7 | PARAM_FLAG_MULTIARGS,
- &args, &ircnet, &host, &addr,
- &portstr, &password, &nick);
+ if (!cmd_get_params(data, &free_arg, 4 | PARAM_FLAG_OPTIONS,
+ "connect", &optlist, &addr, &portstr, &password, &nick))
+ return NULL;
if (*addr == '+') addr++;
- if (*addr == '\0') return NULL;
+ if (*addr == '\0') {
+ signal_emit("error command", 1, GINT_TO_POINTER(CMDERR_NOT_ENOUGH_PARAMS));
+ cmd_params_free(free_arg);
+ return NULL;
+ }
if (strcmp(password, "-") == 0)
*password = '\0';
/* connect to server */
conn = irc_server_create_conn(addr, atoi(portstr), password, nick);
- if (*ircnet != '\0') {
+ ircnet = g_hash_table_lookup(optlist, "ircnet");
+ if (ircnet != NULL && *ircnet != '\0') {
g_free_not_null(conn->ircnet);
conn->ircnet = g_strdup(ircnet);
}
- if (*host != '\0') {
+ host = g_hash_table_lookup(optlist, "host");
+ if (host != NULL && *host != '\0') {
IPADDR ip;
if (net_gethostbyname(host, &ip) == 0) {
@@ -80,7 +87,7 @@ static IRC_SERVER_REC *connect_server(const char *data)
}
server = irc_server_connect(conn);
- g_free(params);
+ cmd_params_free(free_arg);
return server;
}
@@ -93,14 +100,16 @@ static void cmd_connect(const char *data)
static void cmd_disconnect(const char *data, IRC_SERVER_REC *server)
{
IRC_SERVER_REC *ircserver;
- char *params, *tag, *msg;
+ char *tag, *msg;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (g_strncasecmp(data, "RECON-", 6) == 0)
return; /* remove reconnection, handle in server-reconnect.c */
- params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &tag, &msg);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &tag, &msg))
+ return;
if (*tag != '\0' && strcmp(tag, "*") != 0)
server = (IRC_SERVER_REC *) server_find_tag(tag);
@@ -120,22 +129,24 @@ static void cmd_disconnect(const char *data, IRC_SERVER_REC *server)
irc_send_cmdv(ircserver, "QUIT :%s", msg);
}
- g_free(params);
+ cmd_params_free(free_arg);
server_disconnect((SERVER_REC *) server);
}
static void cmd_server(const char *data, IRC_SERVER_REC *server)
{
- char *params, *args, *ircnetarg, *hostarg, *addr;
- char *channels, *away_reason, *usermode, *ircnet;
+ GHashTable *optlist;
+ char *addr, *channels, *away_reason, *usermode, *ircnet;
+ void *free_arg;
int no_old_server;
g_return_if_fail(data != NULL);
- args = "ircnet host";
- params = cmd_get_params(data, 4 | PARAM_FLAG_MULTIARGS,
- &args, &ircnetarg, &hostarg, &addr);
+ if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS,
+ "connect", &optlist, &addr))
+ return;
+
if (*addr == '\0' || strcmp(addr, "+") == 0)
cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
@@ -167,7 +178,7 @@ static void cmd_server(const char *data, IRC_SERVER_REC *server)
server->connrec->away_reason = away_reason;
}
g_free_not_null(ircnet);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_quit(const char *data)
@@ -195,12 +206,14 @@ static void cmd_quit(const char *data)
static void cmd_msg(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
- char *params, *target, *msg;
+ char *target, *msg;
+ void *free_arg;
int free_ret;
g_return_if_fail(data != NULL);
- params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &msg))
+ return;
if (*target == '\0' || *msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
if (server == NULL || !server->connected || !irc_server_check(server))
@@ -219,35 +232,39 @@ static void cmd_msg(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
if (free_ret && target != NULL) g_free(target);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_notice(const char *data, IRC_SERVER_REC *server)
{
- char *params, *target, *msg;
+ char *target, *msg;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected || !irc_server_check(server))
cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &msg))
+ return;
if (*target == '\0' || *msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
g_string_sprintf(tmpstr, "NOTICE %s :%s", target, msg);
irc_send_cmd_split(server, tmpstr->str, 2, server->max_msgs_in_cmd);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_ctcp(const char *data, IRC_SERVER_REC *server)
{
- char *params, *target, *ctcpcmd, *ctcpdata;
+ char *target, *ctcpcmd, *ctcpdata;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected || !irc_server_check(server))
cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata);
+ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata))
+ return;
if (*target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
g_strup(ctcpcmd);
@@ -257,61 +274,79 @@ static void cmd_ctcp(const char *data, IRC_SERVER_REC *server)
g_string_sprintf(tmpstr, "PRIVMSG %s :\001%s %s\001", target, ctcpcmd, ctcpdata);
irc_send_cmd_split(server, tmpstr->str, 2, server->max_msgs_in_cmd);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_nctcp(const char *data, IRC_SERVER_REC *server)
{
- char *params, *target, *ctcpcmd, *ctcpdata;
+ char *target, *ctcpcmd, *ctcpdata;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected || !irc_server_check(server))
cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata);
+ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata))
+ return;
if (*target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
g_strup(ctcpcmd);
g_string_sprintf(tmpstr, "NOTICE %s :\001%s %s\001", target, ctcpcmd, ctcpdata);
irc_send_cmd_split(server, tmpstr->str, 2, server->max_msgs_in_cmd);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_join(const char *data, IRC_SERVER_REC *server)
{
- char *params, *args, *channels;
+ GHashTable *optlist;
+ GSList *list;
+ char *channels;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected || !irc_server_check(server))
cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 2 | PARAM_FLAG_OPTARGS | PARAM_FLAG_GETREST, &args, &channels);
+ if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | PARAM_FLAG_UNKNOWN_OPTIONS |
+ PARAM_FLAG_GETREST, "join", &optlist, &channels))
+ return;
- if (stristr(args, "-invite")) {
+ if (g_hash_table_lookup(optlist, "-invite")) {
if (server->last_invite != NULL)
channels_join(server, server->last_invite, FALSE);
} else {
- if (*args != '\0') {
- server = (IRC_SERVER_REC *) server_find_tag(args+1);
- if (server == NULL) cmd_param_error(CMDERR_NOT_CONNECTED);
+ /* -<server tag> */
+ list = hashtable_get_keys(optlist);
+ if (list != NULL) {
+ server = (IRC_SERVER_REC *) server_find_tag(list->data);
+
+ if (server == NULL) {
+ /* unknown option (not server tag) */
+ signal_emit("error command", 2, GINT_TO_POINTER(CMDERR_OPTION_UNKNOWN), list->data);
+ signal_stop();
+ }
+ g_slist_free(list);
}
- channels_join(server, channels, FALSE);
+
+ if (server != NULL) channels_join(server, channels, FALSE);
}
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_part(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
- char *params, *channame, *msg;
CHANNEL_REC *chanrec;
+ char *channame, *msg;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected || !irc_server_check(server))
cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, item, &channame, &msg);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, item, &channame, &msg))
+ return;
if (*channame == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
chanrec = channel_find(server, channame);
@@ -320,19 +355,21 @@ static void cmd_part(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
irc_send_cmdv(server, *msg == '\0' ? "PART %s" : "PART %s :%s",
channame, msg);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_kick(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
- char *params, *channame, *nicks, *reason;
+ char *channame, *nicks, *reason;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected || !irc_server_check(server))
cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 3 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST,
- item, &channame, &nicks, &reason);
+ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST,
+ item, &channame, &nicks, &reason))
+ return;
if (*channame == '\0' || *nicks == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
if (!ischannel(*channame)) cmd_param_error(CMDERR_NOT_JOINED);
@@ -340,36 +377,42 @@ static void cmd_kick(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
g_string_sprintf(tmpstr, "KICK %s %s :%s", channame, nicks, reason);
irc_send_cmd_split(server, tmpstr->str, 3, server->max_kicks_in_cmd);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_topic(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
- char *params, *args, *channame, *topic;
+ GHashTable *optlist;
+ char *channame, *topic;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected || !irc_server_check(server))
cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 3 | PARAM_FLAG_OPTCHAN |
- PARAM_FLAG_OPTARGS | PARAM_FLAG_GETREST,
- item, &args, &channame, &topic);
+ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_OPTCHAN |
+ PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST,
+ item, "topic", &optlist, &channame, &topic))
+ return;
- irc_send_cmdv(server, *topic == '\0' && strstr(args, "-d") == NULL ?
+ irc_send_cmdv(server, *topic == '\0' && g_hash_table_lookup(optlist, "-d") == NULL ?
"TOPIC %s" : "TOPIC %s :%s", channame, topic);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_invite(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
- char *params, *nick, *channame;
+ char *nick, *channame;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected || !irc_server_check(server))
cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 2, &nick, &channame);
+ if (!cmd_get_params(data, &free_arg, 2, &nick, &channame))
+ return;
+
if (*nick == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
if (*channame == '\0' || strcmp(channame, "*") == 0) {
if (!irc_item_channel(item))
@@ -379,24 +422,28 @@ static void cmd_invite(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *ite
}
irc_send_cmdv(server, "INVITE %s %s", nick, channame);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_list(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
- char *params, *args, *str;
+ GHashTable *optlist;
+ char *str;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected || !irc_server_check(server))
cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 2 | PARAM_FLAG_OPTARGS | PARAM_FLAG_GETREST, &args, &str);
+ if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
+ PARAM_FLAG_GETREST, &optlist, &str))
+ return;
- if (*str == '\0' && stristr(args, "-yes") == NULL)
+ if (*str == '\0' && g_hash_table_lookup(optlist, "-yes") == NULL)
cmd_param_error(CMDERR_NOT_GOOD_IDEA);
irc_send_cmdv(server, "LIST %s", str);
- g_free(params);
+ cmd_params_free(free_arg);
/* add default redirection */
server_redirect_default((SERVER_REC *) server, "bogus command list");
@@ -404,13 +451,15 @@ static void cmd_list(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
static void cmd_who(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
- char *params, *channel, *args, *rest;
+ char *channel, *rest;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected || !irc_server_check(server))
cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 3 | PARAM_FLAG_OPTARGS | PARAM_FLAG_GETREST, &args, &channel, &rest);
+ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &channel, &rest))
+ return;
if (strcmp(channel, "*") == 0 || *channel == '\0') {
if (!irc_item_channel(item))
@@ -425,7 +474,7 @@ static void cmd_who(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
irc_send_cmdv(server, *rest == '\0' ? "WHO %s" : "WHO %s %s",
channel, rest);
- g_free(params);
+ cmd_params_free(free_arg);
/* add default redirection */
server_redirect_default((SERVER_REC *) server, "bogus command who");
@@ -473,17 +522,20 @@ static char *get_redirect_nicklist(const char *nicks, int *free)
static void cmd_whois(const char *data, IRC_SERVER_REC *server)
{
- char *params, *qserver, *query;
+ char *qserver, *query;
+ void *free_arg;
int free_nick;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected || !irc_server_check(server))
cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 2, &qserver, &query);
+ if (!cmd_get_params(data, &free_arg, 2, &qserver, &query))
+ return;
+
if (*query == '\0') {
- g_free(params);
- params = cmd_get_params(data, 1, &query);
+ cmd_params_free(free_arg);
+ if (!cmd_get_params(data, &free_arg, 1, &query)) return;
qserver = "";
}
if (*query == '\0') query = server->nick;
@@ -505,7 +557,7 @@ static void cmd_whois(const char *data, IRC_SERVER_REC *server)
"event 311", "whois event", 1,
"event 401", "whois not found", 1, NULL);
if (free_nick) g_free(query);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void event_whois(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr)
@@ -539,14 +591,16 @@ static void event_whowas(const char *data, IRC_SERVER_REC *server, const char *n
static void cmd_whowas(const char *data, IRC_SERVER_REC *server)
{
- char *params, *nicks, *count;
+ char *nicks, *count;
+ void *free_arg;
int free_nick;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected || !irc_server_check(server))
cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 2, &nicks, &count);
+ if (!cmd_get_params(data, &free_arg, 2, &nicks, &count))
+ return;
if (*nicks == '\0') nicks = server->nick;
server->whowas_found = FALSE;
@@ -558,7 +612,7 @@ static void cmd_whowas(const char *data, IRC_SERVER_REC *server)
"event 369", "event 369", 1,
"event 314", "whowas event", 1, NULL);
if (free_nick) g_free(nicks);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_ping(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
@@ -594,20 +648,23 @@ static void server_send_away(IRC_SERVER_REC *server, const char *reason)
static void cmd_away(const char *data, IRC_SERVER_REC *server)
{
- char *params, *args, *reason;
+ GHashTable *optlist;
+ char *reason;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected || !irc_server_check(server))
cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 2 | PARAM_FLAG_OPTARGS | PARAM_FLAG_GETREST, &args, &reason);
+ if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
+ PARAM_FLAG_GETREST, "away", &optlist, &reason)) return;
- if (stristr(args, "-one"))
+ if (g_hash_table_lookup(optlist, "-one") != NULL)
server_send_away(server, reason);
else
g_slist_foreach(servers, (GFunc) server_send_away, reason);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_deop(const char *data, IRC_SERVER_REC *server)
@@ -646,7 +703,8 @@ static void cmd_wall_hash(gpointer key, NICK_REC *nick, GSList **nicks)
static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
- char *params, *channame, *msg, *args;
+ char *channame, *msg, *args;
+ void *free_arg;
CHANNEL_REC *chanrec;
GSList *tmp, *nicks;
@@ -654,7 +712,9 @@ static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
if (server == NULL || !server->connected || !irc_server_check(server))
cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, item, &channame, &msg);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN |
+ PARAM_FLAG_GETREST, item, &channame, &msg))
+ return;
if (*msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
chanrec = channel_find(server, channame);
@@ -677,19 +737,21 @@ static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
g_free(msg);
g_slist_free(nicks);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_cycle(gchar *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
- char *params, *channame, *msg;
CHANNEL_REC *chanrec;
+ char *channame, *msg;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected || !irc_server_check(server))
cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 2 | PARAM_FLAG_OPTCHAN, item, &channame, &msg);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN, item, &channame, &msg))
+ return;
if (*channame == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
chanrec = channel_find(server, channame);
@@ -700,21 +762,23 @@ static void cmd_cycle(gchar *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
irc_send_cmdv(server, chanrec->key == NULL ? "JOIN %s" : "JOIN %s %s",
channame, chanrec->key);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_kickban(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
- char *params, *nick;
+ char *nick;
+ void *free_arg;
g_return_if_fail(data != NULL);
- params = cmd_get_params(data, 1, &nick);
+ if (!cmd_get_params(data, &free_arg, 1, &nick))
+ return;
if (*nick == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
signal_emit("command ban", 3, nick, server, item);
signal_emit("command kick", 3, data, server, item);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void knockout_destroy(IRC_SERVER_REC *server, KNOCKOUT_REC *rec)
@@ -760,7 +824,8 @@ static void cmd_knockout(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *i
{
KNOCKOUT_REC *rec;
CHANNEL_REC *channel;
- char *params, *nick, *reason, *timeoutstr, *str;
+ char *nick, *reason, *timeoutstr, *str;
+ void *free_arg;
int timeleft;
g_return_if_fail(data != NULL);
@@ -771,11 +836,13 @@ static void cmd_knockout(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *i
if (is_numeric(data, ' ')) {
/* first argument is the timeout */
- params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &timeoutstr, &nick, &reason);
+ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &timeoutstr, &nick, &reason))
+ return;
timeleft = atoi(timeoutstr);
} else {
timeleft = 0;
- params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &nick, &reason);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &nick, &reason))
+ return;
}
if (timeleft == 0) timeleft = settings_get_int("knockout_time");
@@ -795,7 +862,7 @@ static void cmd_knockout(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *i
server->knockoutlist = g_slist_append(server->knockoutlist, rec);
- g_free(params);
+ cmd_params_free(free_arg);
}
/* destroy all knockouts in server */
@@ -845,16 +912,18 @@ static void command_1self(const char *data, IRC_SERVER_REC *server)
static void command_2self(const char *data, IRC_SERVER_REC *server)
{
- char *params, *target, *text;
+ char *target, *text;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected || !irc_server_check(server))
cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &text);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &text))
+ return;
if (*target == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
irc_send_cmdv(server, "%s %s :%s", current_command, target, text);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void sig_connected(IRC_SERVER_REC *server)
@@ -942,6 +1011,12 @@ void irc_commands_init(void)
signal_add("whois not found", (SIGNAL_FUNC) sig_whois_not_found);
signal_add("whois event", (SIGNAL_FUNC) event_whois);
signal_add("whowas event", (SIGNAL_FUNC) event_whowas);
+
+ command_set_options("connect", "+ircnet +host");
+ command_set_options("topic", "d");
+ command_set_options("list", "yes");
+ command_set_options("away", "one all");
+ command_set_options("join", "invite");
}
void irc_commands_deinit(void)
diff --git a/src/irc/core/irc-special-vars.c b/src/irc/core/irc-special-vars.c
index 09e0db11..92acd246 100644
--- a/src/irc/core/irc-special-vars.c
+++ b/src/irc/core/irc-special-vars.c
@@ -236,11 +236,13 @@ static void event_privmsg(const char *data, IRC_SERVER_REC *server, const char *
static void cmd_msg(const char *data, IRC_SERVER_REC *server)
{
- char *params, *target, *msg;
+ char *target, *msg;
+ void *free_arg;
g_return_if_fail(data != NULL);
- params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &msg))
+ return;
if (*target != '\0' && *msg != '\0' && !ischannel(*target) && isalpha(*target)) {
g_free_not_null(last_sent_msg);
g_free_not_null(last_sent_msg_body);
@@ -248,7 +250,7 @@ static void cmd_msg(const char *data, IRC_SERVER_REC *server)
last_sent_msg_body = g_strdup(msg);
}
- g_free(params);
+ cmd_params_free(free_arg);
}
static void event_join(const char *data, IRC_SERVER_REC *server, const char *nick, const char *address)
diff --git a/src/irc/core/ircnet-setup.c b/src/irc/core/ircnet-setup.c
index 57cfab1a..b3946e6a 100644
--- a/src/irc/core/ircnet-setup.c
+++ b/src/irc/core/ircnet-setup.c
@@ -154,11 +154,11 @@ static void read_ircnets(void)
static void sig_connected(IRC_SERVER_REC *server)
{
IRCNET_REC *ircnet;
-
+
if (server->connrec->ircnet == NULL) return;
ircnet = ircnet_find(server->connrec->ircnet);
- if (ircnet->autosendcmd)
+ if (ircnet != NULL && ircnet->autosendcmd)
eval_special_string(ircnet->autosendcmd, "", server, NULL);
}
diff --git a/src/irc/core/modes.c b/src/irc/core/modes.c
index 715ad040..fcca2401 100644
--- a/src/irc/core/modes.c
+++ b/src/irc/core/modes.c
@@ -460,7 +460,8 @@ static void cmd_devoice(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *it
static void cmd_mode(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
- char *params, *target, *mode;
+ char *target, *mode;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected || !irc_server_check(server))
@@ -468,9 +469,11 @@ static void cmd_mode(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
if (*data == '+' || *data == '-') {
target = "*";
- params = mode = g_strdup(data); /* cmd_param_error() wants to free params.. */
+ if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_GETREST, &mode))
+ return;
} else {
- params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &mode);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &mode))
+ return;
}
if (strcmp(target, "*") == 0) {
@@ -488,7 +491,7 @@ static void cmd_mode(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
else
irc_send_cmdv(server, "MODE %s %s", target, mode);
- g_free(params);
+ cmd_params_free(free_arg);
}
void modes_init(void)
diff --git a/src/irc/core/netsplit.c b/src/irc/core/netsplit.c
index bfa40c3c..0c394055 100644
--- a/src/irc/core/netsplit.c
+++ b/src/irc/core/netsplit.c
@@ -187,7 +187,8 @@ NICK_REC *netsplit_find_channel(IRC_SERVER_REC *server, const char *nick, const
int quitmsg_is_split(const char *msg)
{
- char *params, *host1, *host2, *p;
+ char *host1, *host2, *p;
+ void *free_arg;
int ok;
g_return_val_if_fail(msg != NULL, FALSE);
@@ -202,8 +203,10 @@ int quitmsg_is_split(const char *msg)
return FALSE;
/* get the two hosts */
+ if (!cmd_get_params(msg, &free_arg, 2 | PARAM_FLAG_NOQUOTES, &host1, &host2))
+ return FALSE;
+
ok = FALSE;
- params = cmd_get_params(msg, 2 | PARAM_FLAG_NOQUOTES, &host1, &host2);
if (g_strcasecmp(host1, host2) != 0) { /* hosts can't be same.. */
/* check that domain length is 2 or 3 */
p = strrchr(host1, '.');
@@ -215,7 +218,7 @@ int quitmsg_is_split(const char *msg)
}
}
}
- g_free(params);
+ cmd_params_free(free_arg);
return ok;
}
diff --git a/src/irc/dcc/dcc-chat.c b/src/irc/dcc/dcc-chat.c
index 44968ce0..afdb9d5b 100644
--- a/src/irc/dcc/dcc-chat.c
+++ b/src/irc/dcc/dcc-chat.c
@@ -59,7 +59,8 @@ DCC_REC *item_get_dcc(void *item)
static void cmd_msg(const char *data)
{
DCC_REC *dcc;
- char *params, *text, *target;
+ char *text, *target;
+ void *free_arg;
g_return_if_fail(text != NULL);
@@ -68,12 +69,13 @@ static void cmd_msg(const char *data)
return;
}
- params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &text);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &text))
+ return;
dcc = dcc_find_item(DCC_TYPE_CHAT, ++target, NULL);
if (dcc != NULL) dcc_chat_send(dcc, text);
- g_free(params);
+ cmd_params_free(free_arg);
signal_stop();
}
@@ -96,9 +98,9 @@ static void cmd_me(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
static void cmd_action(const char *data, IRC_SERVER_REC *server)
{
- char *params, *target, *text;
DCC_REC *dcc;
- char *str;
+ char *target, *text, *str;
+ void *free_arg;
g_return_if_fail(data != NULL);
@@ -107,7 +109,8 @@ static void cmd_action(const char *data, IRC_SERVER_REC *server)
return;
}
- params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &text);
+ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &text))
+ return;
if (*target == '\0' || *text == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
dcc = dcc_find_item(DCC_TYPE_CHAT, target+1, NULL);
@@ -117,25 +120,26 @@ static void cmd_action(const char *data, IRC_SERVER_REC *server)
g_free(str);
}
- g_free(params);
+ cmd_params_free(free_arg);
signal_stop();
}
static void cmd_ctcp(const char *data, IRC_SERVER_REC *server)
{
- char *params, *target, *ctcpcmd, *ctcpdata;
DCC_REC *dcc;
- char *str;
+ char *target, *ctcpcmd, *ctcpdata, *str;
+ void *free_arg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED);
- params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata);
+ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata))
+ return;
if (*target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
if (*target != '=') {
/* handle only DCC CTCPs */
- g_free(params);
+ cmd_params_free(free_arg);
return;
}
@@ -148,7 +152,7 @@ static void cmd_ctcp(const char *data, IRC_SERVER_REC *server)
g_free(str);
}
- g_free(params);
+ cmd_params_free(free_arg);
signal_stop();
}
diff --git a/src/irc/dcc/dcc-files.c b/src/irc/dcc/dcc-files.c
index e2dc732d..9a68813f 100644
--- a/src/irc/dcc/dcc-files.c
+++ b/src/irc/dcc/dcc-files.c
@@ -212,12 +212,14 @@ static void cmd_dcc_get(const char *data)
{
DCC_REC *dcc;
GSList *tmp, *next;
- char *params, *nick, *fname;
+ char *nick, *fname;
+ void *free_arg;
int found;
g_return_if_fail(data != NULL);
- params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &nick, &fname);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &nick, &fname))
+ return;
if (*nick == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
dcc = NULL; found = FALSE;
@@ -235,7 +237,7 @@ static void cmd_dcc_get(const char *data)
if (!found)
signal_emit("dcc error get not found", 1, nick);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void dcc_resume_send(DCC_REC *dcc, int port)
@@ -264,7 +266,8 @@ static void dcc_ctcp_msg(const char *data, IRC_SERVER_REC *server,
const char *sender, const char *sendaddr,
const char *target, DCC_REC *chat)
{
- char *params, *type, *arg, *portstr, *sizestr;
+ char *type, *arg, *portstr, *sizestr;
+ void *free_arg;
unsigned long size;
int port;
DCC_REC *dcc;
@@ -272,8 +275,9 @@ static void dcc_ctcp_msg(const char *data, IRC_SERVER_REC *server,
g_return_if_fail(data != NULL);
g_return_if_fail(sender != NULL);
- params = cmd_get_params(data, 4 | PARAM_FLAG_NOQUOTES,
- &type, &arg, &portstr, &sizestr);
+ if (!cmd_get_params(data, &free_arg, 4 | PARAM_FLAG_NOQUOTES,
+ &type, &arg, &portstr, &sizestr))
+ return;
port = atoi(portstr);
size = atol(sizestr);
@@ -281,7 +285,7 @@ static void dcc_ctcp_msg(const char *data, IRC_SERVER_REC *server,
dcc = dcc_find_by_port(sender, port);
if (dcc == NULL || !is_resume_type(type) ||
!is_resume_ok(type, dcc) || !is_accept_ok(type, dcc)) {
- g_free(params);
+ cmd_params_free(free_arg);
return;
}
@@ -298,7 +302,7 @@ static void dcc_ctcp_msg(const char *data, IRC_SERVER_REC *server,
dcc_get_connect(dcc);
}
- g_free(params);
+ cmd_params_free(free_arg);
}
static void dcc_resume_rec(DCC_REC *dcc)
@@ -331,12 +335,14 @@ static void cmd_dcc_resume(const char *data)
{
DCC_REC *dcc;
GSList *tmp;
- char *params, *nick, *fname;
+ char *nick, *fname;
+ void *free_arg;
int found;
g_return_if_fail(data != NULL);
- params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &nick, &fname);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &nick, &fname))
+ return;
if (*nick == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
dcc = NULL; found = FALSE;
@@ -353,7 +359,7 @@ static void cmd_dcc_resume(const char *data)
if (!found)
signal_emit("dcc error get not found", 1, nick);
- g_free(params);
+ cmd_params_free(free_arg);
}
/* input function: DCC SEND - we're ready to send more data */
@@ -483,7 +489,8 @@ static void dcc_send_init(DCC_REC *dcc)
/* command: DCC SEND */
static void cmd_dcc_send(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
- char *params, *target, *fname, *str, *ptr;
+ char *target, *fname, *str, *ptr;
+ void *free_arg;
char host[MAX_IP_LEN];
int hfile, hlisten, port;
long fsize;
@@ -492,7 +499,8 @@ static void cmd_dcc_send(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *i
g_return_if_fail(data != NULL);
- params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &fname);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &fname))
+ return;
if (*target == '\0' || *fname == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
/* if we're in dcc chat, send the request via it. */
@@ -506,7 +514,7 @@ static void cmd_dcc_send(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *i
if (dcc_find_item(DCC_TYPE_SEND, target, fname)) {
signal_emit("dcc error send exists", 2, target, fname);
- g_free(params);
+ cmd_params_free(free_arg);
return;
}
@@ -525,7 +533,7 @@ static void cmd_dcc_send(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *i
if (hfile == -1) {
signal_emit("dcc error file not found", 2, target, fname);
- g_free(params);
+ cmd_params_free(free_arg);
return;
}
fsize = lseek(hfile, 0, SEEK_END);
@@ -565,7 +573,7 @@ static void cmd_dcc_send(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *i
g_free(str);
g_free(fname);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void read_settings(void)
diff --git a/src/irc/dcc/dcc.c b/src/irc/dcc/dcc.c
index e514c934..75dc5459 100644
--- a/src/irc/dcc/dcc.c
+++ b/src/irc/dcc/dcc.c
@@ -278,7 +278,8 @@ static void dcc_get_address(const char *str, IPADDR *ip)
/* Handle incoming DCC CTCP messages */
static void dcc_ctcp_msg(char *data, IRC_SERVER_REC *server, char *sender, char *sendaddr, char *target, DCC_REC *chat)
{
- char *params, *type, *arg, *addrstr, *portstr, *sizestr, *str;
+ char *type, *arg, *addrstr, *portstr, *sizestr, *str;
+ void *free_arg;
const char *cstr;
DCC_REC *dcc;
gulong size;
@@ -287,8 +288,9 @@ static void dcc_ctcp_msg(char *data, IRC_SERVER_REC *server, char *sender, char
g_return_if_fail(data != NULL);
g_return_if_fail(sender != NULL);
- params = cmd_get_params(data, 5 | PARAM_FLAG_NOQUOTES,
- &type, &arg, &addrstr, &portstr, &sizestr);
+ if (!cmd_get_params(data, &free_arg, 5 | PARAM_FLAG_NOQUOTES,
+ &type, &arg, &addrstr, &portstr, &sizestr))
+ return;
if (sscanf(portstr, "%d", &port) != 1) port = 0;
if (sscanf(sizestr, "%lu", &size) != 1) size = 0;
@@ -349,20 +351,22 @@ static void dcc_ctcp_msg(char *data, IRC_SERVER_REC *server, char *sender, char
break;
}
- g_free(params);
+ cmd_params_free(free_arg);
}
/* Handle incoming DCC CTCP replies */
static void dcc_ctcp_reply(char *data, IRC_SERVER_REC *server, char *sender, char *sendaddr)
{
- char *params, *cmd, *subcmd, *args;
+ char *cmd, *subcmd, *args;
+ void *free_arg;
int type;
DCC_REC *dcc;
g_return_if_fail(data != NULL);
g_return_if_fail(sender != NULL);
- params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &cmd, &subcmd, &args);
+ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &cmd, &subcmd, &args))
+ return;
if (g_strcasecmp(cmd, "REJECT") == 0)
{
@@ -380,7 +384,7 @@ static void dcc_ctcp_reply(char *data, IRC_SERVER_REC *server, char *sender, cha
signal_emit("dcc unknown reply", 3, data, sender, sendaddr);
}
- g_free(params);
+ cmd_params_free(free_arg);
}
static void dcc_reject(DCC_REC *dcc, IRC_SERVER_REC *server)
@@ -409,20 +413,22 @@ static void cmd_dcc_close(char *data, IRC_SERVER_REC *server)
{
DCC_REC *dcc;
GSList *tmp, *next;
- char *params, *type, *nick, *arg;
+ char *type, *nick, *arg;
+ void *free_arg;
gboolean found;
int itype;
g_return_if_fail(data != NULL);
- params = cmd_get_params(data, 3, &type, &nick, &arg);
+ if (!cmd_get_params(data, &free_arg, 3, &type, &nick, &arg))
+ return;
g_strup(type);
itype = dcc_str2type(type);
if (itype == 0)
{
signal_emit("dcc error unknown type", 1, type);
- g_free(params);
+ cmd_params_free(free_arg);
return;
}
@@ -442,7 +448,7 @@ static void cmd_dcc_close(char *data, IRC_SERVER_REC *server)
if (!found)
signal_emit("dcc error close not found", 3, type, nick, arg);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_dcc(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
diff --git a/src/irc/notifylist/notify-commands.c b/src/irc/notifylist/notify-commands.c
index af022dcd..0bef6d23 100644
--- a/src/irc/notifylist/notify-commands.c
+++ b/src/irc/notifylist/notify-commands.c
@@ -30,41 +30,47 @@
static void cmd_notify(gchar *data)
{
- char *params, *mask, *ircnets, *args, *idletime;
+ GHashTable *optlist;
+ char *mask, *ircnets, *idletime;
+ void *free_arg;
int away_check, idle_check_time;
g_return_if_fail(data != NULL);
- args = "@idle";
- params = cmd_get_params(data, 4 | PARAM_FLAG_MULTIARGS | PARAM_FLAG_GETREST, &args, &idletime, &mask, &ircnets);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST,
+ "notify", &optlist, &mask, &ircnets))
+ return;
if (*mask == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
- if (stristr(args, "-idle") == NULL)
+ idletime = g_hash_table_lookup(optlist, "idle");
+ if (idletime == NULL)
idle_check_time = 0;
else {
idle_check_time = is_numeric(idletime, 0) ? (atoi(idletime)*60) :
(settings_get_int("notify_idle_time")*60);
}
- away_check = stristr(args, "-away") != NULL;
+ away_check = g_hash_table_lookup(optlist, "away") != NULL;
notifylist_remove(mask);
notifylist_add(mask, ircnets, away_check, idle_check_time);
- g_free(params);
+ cmd_params_free(free_arg);
}
static void cmd_unnotify(const char *data)
{
- char *params, *mask;
+ char *mask;
+ void *free_arg;
g_return_if_fail(data != NULL);
- params = cmd_get_params(data, 1, &mask);
+ if (!cmd_get_params(data, &free_arg, 1, &mask))
+ return;
if (*mask == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
notifylist_remove(mask);
- g_free(params);
+ cmd_params_free(free_arg);
}
void notifylist_commands_init(void)
@@ -72,6 +78,8 @@ void notifylist_commands_init(void)
settings_add_int("misc", "notify_idle_time", DEFAULT_NOTIFY_IDLE_TIME);
command_bind("notify", NULL, (SIGNAL_FUNC) cmd_notify);
command_bind("unnotify", NULL, (SIGNAL_FUNC) cmd_unnotify);
+
+ command_set_options("notify", "@idle away");
}
void notifylist_commands_deinit(void)