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