From: Pekka Riikonen Date: Wed, 6 Nov 2002 15:27:56 +0000 (+0000) Subject: Changed the silc_client_command_call to be simpler for X-Git-Tag: silc.client.0.9.8~3 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=0eca6fd991f7259150b000fc75f14fb8963c2720 Changed the silc_client_command_call to be simpler for application. --- diff --git a/CHANGES b/CHANGES index d6324c73..449e8280 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,15 @@ +Wed Nov 6 17:18:13 EET 2002 Pekka Riikonen + + * Fixed manual page installation patch by Ville Räsänen. + USERS help page fix patch by Ville Räsänen + + * Changed the silc_client_command_call interface to make + the command call simpler for the application. The library + now handles the command line parsing, command finding and + execution. Application only needs to call the function + with the command line. Affected files are + lib/silcclient/silcclient.h, command.[ch]. + Mon Nov 4 16:02:59 EET 2002 Pekka Riikonen * Print notify for server opers when backup router comes @@ -9,6 +21,10 @@ Mon Nov 4 16:02:59 EET 2002 Pekka Riikonen * Fixed MOTD command reply sending. Affected file silcd/command.c. + * UTF-8 decode the topic in TOPIC command reply and LIST + command reply in Irssi SILC client. Affected file is + irssi/src/silc/core/client_ops.c. + Sun Nov 3 17:59:15 EET 2002 Pekka Riikonen * Fixed the INVITE command to not crash Irssi SILC client diff --git a/apps/irssi/src/silc/core/silc-servers.c b/apps/irssi/src/silc/core/silc-servers.c index c7270588..f6e0403a 100644 --- a/apps/irssi/src/silc/core/silc-servers.c +++ b/apps/irssi/src/silc/core/silc-servers.c @@ -448,41 +448,13 @@ char *silc_server_get_channels(SILC_SERVER_REC *server) void silc_command_exec(SILC_SERVER_REC *server, const char *command, const char *args) { - SilcUInt32 argc = 0; - unsigned char **argv; - SilcUInt32 *argv_lens, *argv_types; - char *data, *tmpcmd; - SilcClientCommand cmd; - SilcClientCommandContext ctx; - + char *data; g_return_if_fail(server != NULL); - tmpcmd = g_strdup(command); - g_strup(tmpcmd); - cmd = silc_client_command_find(silc_client, tmpcmd); - g_free(tmpcmd); - if (cmd == NULL) - return; - - /* Now parse all arguments */ + /* Call the command */ data = g_strconcat(command, " ", args, NULL); - silc_parse_command_line(data, &argv, &argv_lens, - &argv_types, &argc, cmd->max_args); + silc_client_command_call(silc_client, server->conn, data); g_free(data); - - /* Allocate command context. This and its internals must be free'd - by the command routine receiving it. */ - ctx = silc_client_command_alloc(); - ctx->client = silc_client; - ctx->conn = server->conn; - ctx->command = cmd; - ctx->argc = argc; - ctx->argv = argv; - ctx->argv_lens = argv_lens; - ctx->argv_types = argv_types; - - /* Execute command */ - silc_client_command_call(cmd, ctx); } /* Generic command function to call any SILC command directly. */ diff --git a/lib/silcclient/command.c b/lib/silcclient/command.c index f1a9ace6..66e51786 100644 --- a/lib/silcclient/command.c +++ b/lib/silcclient/command.c @@ -71,24 +71,89 @@ SilcClientCommand silc_client_command_find(SilcClient client, silc_list_start(client->internal->commands); while ((cmd = silc_list_get(client->internal->commands)) != SILC_LIST_END) { - if (cmd->name && !strcmp(cmd->name, name)) + if (cmd->name && !strcasecmp(cmd->name, name)) return cmd; } return NULL; } -/* Calls the command (executes it). Application can call this after - it has allocated the SilcClientCommandContext with the function - silc_client_command_alloc and found the command from the client - library by calling silc_client_command_find. This will execute - the command. */ +/* Executes a command */ -void silc_client_command_call(SilcClientCommand command, - SilcClientCommandContext cmd) +bool silc_client_command_call(SilcClient client, + SilcClientConnection conn, + const char *command_line, ...) { - assert(command); - (*command->command)((void *)cmd, NULL); + va_list va; + SilcUInt32 argc = 0; + unsigned char **argv = NULL; + SilcUInt32 *argv_lens = NULL, *argv_types = NULL; + SilcClientCommand cmd; + SilcClientCommandContext ctx; + char *arg; + + assert(client); + + /* Parse arguments */ + va_start(va, command_line); + if (command_line) { + char *command_name; + + /* Get command name */ + command_name = silc_memdup(command_line, strcspn(command_line, " ")); + if (!command_name) + return FALSE; + + /* Find command by name */ + cmd = silc_client_command_find(client, command_name); + if (!cmd) { + silc_free(command_name); + return FALSE; + } + + /* Parse command line */ + silc_parse_command_line((char *)command_line, &argv, &argv_lens, + &argv_types, &argc, cmd->max_args); + + silc_free(command_name); + } else { + arg = va_arg(va, char *); + if (!arg) + return FALSE; + + /* Find command by name */ + cmd = silc_client_command_find(client, arg); + if (!cmd) + return FALSE; + + while (arg) { + argv = silc_realloc(argv, sizeof(*argv) * (argc + 1)); + argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) * (argc + 1)); + argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1)); + argv[argc] = silc_memdup(arg, strlen(arg)); + argv_lens[argc] = strlen(arg); + argv_types[argc] = argc + 1; + argc++; + arg = va_arg(va, char *); + } + } + + /* Allocate command context. */ + ctx = silc_client_command_alloc(); + ctx->client = client; + ctx->conn = conn; + ctx->command = cmd; + ctx->argc = argc; + ctx->argv = argv; + ctx->argv_lens = argv_lens; + ctx->argv_types = argv_types; + + /* Call the command */ + cmd->command(ctx, NULL); + + va_end(va); + + return TRUE; } /* Add new pending command to be executed when reply to a command has been diff --git a/lib/silcclient/command.h b/lib/silcclient/command.h index 84663109..de06296d 100644 --- a/lib/silcclient/command.h +++ b/lib/silcclient/command.h @@ -36,7 +36,7 @@ struct SilcClientCommandStruct { SilcCommandCb reply; /* Command reply callback */ char *name; /* Name of the command (optional) */ SilcUInt8 max_args; /* Maximum arguments (optional) */ - SilcUInt16 ident; /* Identifier for command (optional) */ + SilcUInt16 ident; /* Identifier for command (optional) */ struct SilcClientCommandStruct *next; }; @@ -97,6 +97,11 @@ do { \ silc_client_command_pending_del(ctx->sock->user_data, cmd, ctx->ident); \ } while(0) +SilcClientCommandContext silc_client_command_alloc(void); +void silc_client_command_free(SilcClientCommandContext ctx); +SilcClientCommandContext silc_client_command_dup(SilcClientCommandContext ctx); +SilcClientCommand silc_client_command_find(SilcClient client, + const char *name); bool silc_client_command_register(SilcClient client, SilcCommand command, const char *name, diff --git a/lib/silcclient/silcclient.h b/lib/silcclient/silcclient.h index 43c1bee9..3a5a4e37 100644 --- a/lib/silcclient/silcclient.h +++ b/lib/silcclient/silcclient.h @@ -1407,92 +1407,45 @@ SilcChannelUser silc_client_on_channel(SilcChannelEntry channel, /* Command management (command.c) */ -/****f* silcclient/SilcClientAPI/silc_client_command_alloc - * - * SYNOPSIS - * - * SilcClientCommandContext silc_client_command_alloc(void); - * - * DESCRIPTION - * - * Allocate Command Context. The context is defined in `command.h' file. - * The context is used by the library commands and applications should use - * it as well. However, application may choose to use some own context - * for its local commands. All library commands, however, must use this - * context. - * - ***/ -SilcClientCommandContext silc_client_command_alloc(void); - -/****f* silcclient/SilcClientAPI/silc_client_command_free - * - * SYNOPSIS - * - * void silc_client_command_free(SilcClientCommandContext ctx); - * - * DESCRIPTION - * - * Free command context and its internals. If the contex was duplicated - * with silc_client_command_dup this may not actually free the data, - * instead it will decrease the reference counter of the context. The - * context will be freed when the reference counter hits zero. - * - ***/ -void silc_client_command_free(SilcClientCommandContext ctx); - -/****f* silcclient/SilcClientAPI/silc_client_command_dup - * - * SYNOPSIS - * - * SilcClientCommandContext - * silc_client_command_dup(SilcClientCommandContext ctx); - * - * DESCRIPTION - * - * Duplicate Command Context by adding reference counter. The context won't - * be free'd untill it hits zero. - * - ***/ -SilcClientCommandContext silc_client_command_dup(SilcClientCommandContext ctx); - -/****f* silcclient/SilcClientAPI/silc_client_command_find +/****f* silcclient/SilcClientAPI/silc_client_command_call * * SYNOPSIS * - * SilcClientCommand silc_client_command_find(SilcClient client, - * const char *name); + * void silc_client_command_call(SilcClient client, + * SilcClientConnection conn, + * const char *command_line, ...); * * DESCRIPTION * - * Finds and returns a pointer to the command list. Return NULL if the - * command is not found. See the `command.[ch]' for the command list. - * Command names are not case-sensitive. + * Calls and executes the command indicated by the `command_name'. + * The `command_line' is a string which includes the command's name and + * its arguments separated with whitespaces (' '). If `command_line' + * is non-NULL then all variable arguments are ignored by default. * - ***/ -SilcClientCommand silc_client_command_find(SilcClient client, - const char *name); - -/****f* silcclient/SilcClientAPI/silc_client_command_call + * If `command_line' is NULL, then the variable arguments define the + * command's nameand its arguments. The variable argument list must + * be terminated with NULL. * - * SYNOPSIS - * - * void silc_client_command_call(SilcClientCommand command); + * Returns FALSE if the command is not known and TRUE after command. + * execution. The "command" client operation is called when the + * command is executed to indicate whether the command executed + * successfully or not. * - * DESCRIPTION + * The "command_reply" client operation will be called when reply is + * received from the server to the command. Application may also use + * the silc_client_command_pending to attach to the command reply. + * The command identifier for silc_client_command_pending function after + * this function call is conn->cmd_ident, which application may use. * - * Calls the command (executes it). Application can call this after - * it has allocated the SilcClientCommandContext with the function - * silc_client_command_alloc and found the command from the client - * library by calling silc_client_command_find. This will execute - * the command. + * EXAMPLE * - * Application can call the command function directly too if it - * wishes to do so. See the command.h for details of the - * SilcClientCommand structure. + * silc_client_command_call(client, NULL, "PING", "silc.silcnet.org", NULL); + * silc_client_command_call(client, "PING silc.silcnet.org"); * ***/ -void silc_client_command_call(SilcClientCommand command, - SilcClientCommandContext cmd); +bool silc_client_command_call(SilcClient client, + SilcClientConnection conn, + const char *command_line, ...); /****f* silcclient/SilcClientAPI/silc_client_command_send * diff --git a/tutorial/mybot/mybot.c b/tutorial/mybot/mybot.c index f6297c44..8e16c897 100644 --- a/tutorial/mybot/mybot.c +++ b/tutorial/mybot/mybot.c @@ -29,7 +29,7 @@ v silc_get_auth_method v - silc_connected -> silc_client_send_command (JOIN) + silc_connected -> silc_client_command_call (JOIN) v silc_command_reply -> silc_send_channel_message ("hello") v @@ -331,13 +331,8 @@ silc_connected(SilcClient client, SilcClientConnection conn, /* Save the connection context */ mybot->conn = conn; - /* Now that we are connected, send the JOIN command to the "mybot" - channel */ - idp = silc_id_payload_encode(conn->local_id, SILC_ID_CLIENT); - silc_client_command_send(client, conn, SILC_COMMAND_JOIN, 0, 2, - 1, "mybot", strlen("mybot"), - 2, idp->data, idp->len); - silc_buffer_free(idp); + /* Now that we are connected, join to mybot channel with JOIN command. */ + silc_client_command_call(client, conn, "JOIN mybot"); }