application.
+Wed Nov 6 17:18:13 EET 2002 Pekka Riikonen <priikone@silcnet.org>
+
+ * 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 <priikone@silcnet.org>
* Print notify for server opers when backup router comes
* 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 <priikone@silcnet.org>
* Fixed the INVITE command to not crash Irssi SILC client
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. */
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
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;
};
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,
/* 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
*
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
/* 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");
}