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