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