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