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