implemented KICK command
[silc.git] / apps / silc / local_command.c
1 /*
2
3   local_command.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2000 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /*
21  * $Id$
22  * $Log$
23  * Revision 1.6  2001/02/24 15:50:23  priikone
24  *      implemented KICK command
25  *
26  * Revision 1.5  2001/02/19 13:47:30  priikone
27  *      updates.
28  *
29  * Revision 1.4  2001/02/16 00:33:23  priikone
30  *      updates.
31  *
32  * Revision 1.3  2001/02/14 15:31:33  priikone
33  *      Do not allow several server connections.
34  *
35  * Revision 1.2  2001/01/30 21:40:21  priikone
36  *      updates.
37  *
38  * Revision 1.1  2000/09/13 17:47:54  priikone
39  *      Created SILC Client Libary by moving stuff from silc/ directory.
40  *      SILC client library is SILC client without UI. Old UI still exists
41  *      in silc/ directory and uses the new client.
42  *
43  *      Bug fixes and several new functions, structures and functions
44  *      naming changes during the change was made.
45  *
46  */
47
48 #include "clientincludes.h"
49
50 /* Local commands. */
51 SilcClientCommand silc_local_command_list[] =
52 {
53   SILC_CLIENT_LCMD(help, HELP, "HELP", 0, 2),
54   SILC_CLIENT_LCMD(clear, CLEAR, "CLEAR", 0, 1),
55   SILC_CLIENT_LCMD(version, VERSION, "VERSION", 0, 1),
56   SILC_CLIENT_LCMD(server, SERVER, "SERVER", 0, 2),
57   SILC_CLIENT_LCMD(msg, MSG, "MSG", 0, 3),
58   SILC_CLIENT_LCMD(away, AWAY, "AWAY", 0, 2),
59
60   { NULL, 0, NULL, 0, 0 },
61 };
62
63 /* Finds and returns a pointer to the command list. Return NULL if the
64    command is not found. */
65
66 SilcClientCommand *silc_client_local_command_find(const char *name)
67 {
68   SilcClientCommand *cmd;
69
70   for (cmd = silc_local_command_list; cmd->name; cmd++) {
71     if (!strcmp(cmd->name, name))
72       return cmd;
73   }
74
75   return NULL;
76 }
77
78 /* HELP command. This is local command and shows help on SILC */
79
80 SILC_CLIENT_LCMD_FUNC(help)
81 {
82
83 }
84
85 /* CLEAR command. This is local command and clears current output window */
86
87 SILC_CLIENT_LCMD_FUNC(clear)
88 {
89   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
90   SilcClient client = cmd->client;
91   SilcClientInternal app = (SilcClientInternal)client->application;
92
93 #if 0
94   wclear((WINDOW *)app->screen);
95   wrefresh((WINDOW *)app->screen);
96 #endif
97
98   silc_client_command_free(cmd);
99 }
100
101 /* VERSION command. This is local command and shows version of the client */
102
103 SILC_CLIENT_LCMD_FUNC(version)
104 {
105   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
106   SilcClient client = cmd->client;
107   extern char *silc_version;
108   extern char *silc_name;
109   extern char *silc_fullname;
110
111   silc_say(client, cmd->conn,
112            "%s (%s) version %s", silc_name, silc_fullname,
113            silc_version);
114
115   silc_client_command_free(cmd);
116 }
117
118 /* Command MSG. Sends private message to user or list of users. Note that
119    private messages are not really commands, they are message packets,
120    however, on user interface it is convenient to show them as commands
121    as that is the common way of sending private messages (like in IRC). */
122 /* XXX supports only one destination */
123
124 SILC_CLIENT_LCMD_FUNC(msg)
125 {
126   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
127   SilcClientConnection conn = cmd->conn;
128   SilcClient client = cmd->client;
129   SilcClientEntry client_entry = NULL;
130   unsigned int num = 0;
131   char *nickname = NULL, *server = NULL;
132
133   if (!cmd->conn) {
134     silc_say(client, conn,
135              "You are not connected to a server, use /SERVER to connect");
136     goto out;
137   }
138
139   if (cmd->argc < 3) {
140     silc_say(client, conn, "Usage: /MSG <nickname> <message>");
141     goto out;
142   }
143
144   /* Parse the typed nickname. */
145   if (!silc_parse_nickname(cmd->argv[1], &nickname, &server, &num)) {
146     silc_say(client, conn, "Bad nickname");
147     goto out;
148   }
149
150   /* Find client entry */
151   client_entry = silc_idlist_get_client(client, conn, nickname, server, num,
152                                         TRUE);
153   if (!client_entry) {
154     /* Client entry not found, it was requested thus mark this to be
155        pending command. */
156     silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, 0, NULL,
157                                 silc_client_local_command_msg, context);
158     return;
159   }
160
161   /* Display the message for our eyes. */
162   silc_print(client, "-> *%s* %s", cmd->argv[1], cmd->argv[2]);
163
164   /* Send the private message */
165   silc_client_packet_send_private_message(client, conn->sock, client_entry,
166                                           cmd->argv[2], cmd->argv_lens[2],
167                                           TRUE);
168
169  out:
170   silc_client_command_free(cmd);
171 }
172
173
174 /* Command SERVER. Connects to remote SILC server. This is local command. */
175
176 SILC_CLIENT_LCMD_FUNC(server)
177 {
178   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
179   SilcClient client = cmd->client;
180   SilcClientConnection conn = cmd->conn;
181   int i = 0, len, port;
182   char *hostname;
183
184   if (cmd->argc < 2) {
185     /* Show current servers */
186
187     if (!cmd->conn) {
188       silc_say(client, conn, "You are not connected to any server");
189       silc_say(client, conn, "Usage: /SERVER [<server>[:<port>]]");
190       goto out;
191     }
192
193     silc_say(client, conn, "Current server: %s on %d %s", 
194              conn->remote_host, conn->remote_port,
195              conn->remote_info ? conn->remote_info : "");
196     
197     silc_say(client, conn, "Server list:");
198     for (i = 0; i < client->conns_count; i++) {
199       silc_say(client, conn, " [%d] %s on %d %s", i + 1,
200                client->conns[i]->remote_host, 
201                client->conns[i]->remote_port,
202                client->conns[i]->remote_info ? 
203                client->conns[i]->remote_info : "");
204     }
205
206     goto out;
207   }
208
209   /* See if port is included and then extract it */
210   if (strchr(cmd->argv[1], ':')) {
211     len = strcspn(cmd->argv[1], ":");
212     hostname = silc_calloc(len + 1, sizeof(char));
213     memcpy(hostname, cmd->argv[1], len);
214     port = atoi(cmd->argv[1] + 1 + len);
215   } else {
216     hostname = cmd->argv[1];
217     port = 706;
218   }
219
220 #if 0
221   if (conn && conn->remote_host) {
222     if (!strcmp(hostname, conn->remote_host) && port == conn->remote_port) {
223       silc_say(client, conn, "You are already connected to that server");
224       goto out;
225     }
226
227     /* Close connection */
228     cmd->client->ops->disconnect(cmd->client, cmd->conn);
229     silc_client_close_connection(cmd->client, cmd->conn->sock);
230   }
231 #endif
232
233   /* Connect asynchronously to not to block user interface */
234   silc_client_connect_to_server(cmd->client, port, hostname, NULL);
235
236  out:
237   silc_client_command_free(cmd);
238 }
239
240 /* Local command AWAY. Client replies with away message to whomever sends
241    private message to the client if the away message is set. If this is
242    given without arguments the away message is removed. */
243
244 SILC_CLIENT_LCMD_FUNC(away)
245 {
246   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
247   SilcClientConnection conn = cmd->conn;
248   SilcClient client = cmd->client;
249   SilcClientInternal app = (SilcClientInternal)client->application;
250
251   if (!cmd->conn) {
252     silc_say(client, conn,
253              "You are not connected to a server, use /SERVER to connect");
254     goto out;
255   }
256
257   if (cmd->argc == 1) {
258     if (conn->away) {
259       silc_free(conn->away->away);
260       silc_free(conn->away);
261       conn->away = NULL;
262       app->screen->bottom_line->away = FALSE;
263
264       silc_say(client, conn, "Away message removed");
265       silc_screen_print_bottom_line(app->screen, 0);
266     }
267   } else {
268
269     if (conn->away)
270       silc_free(conn->away->away);
271     else
272       conn->away = silc_calloc(1, sizeof(*conn->away));
273     
274     app->screen->bottom_line->away = TRUE;
275     conn->away->away = strdup(cmd->argv[1]);
276
277     silc_say(client, conn, "Away message set: %s", conn->away->away);
278     silc_screen_print_bottom_line(app->screen, 0);
279   }
280
281  out:
282   silc_client_command_free(cmd);
283 }