home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dream 52
/
Amiga_Dream_52.iso
/
Linux
/
Divers
/
yagirc-0.51.tar.gz
/
yagirc-0.51.tar
/
yagirc-0.51
/
commands.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-05-11
|
18KB
|
707 lines
/*
commands.c : Functions to all IRC /commands you can use
Copyright (C) 1998 Timo Sirainen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <glib.h>
#include "os.h"
#include "irc.h"
#include "dcc.h"
#include "network.h"
#include "txt.h"
#include "gui.h"
#include "script.h"
#include "params.h"
#include "commands.h"
typedef int (*CALL_FUNC)(char *);
struct CMD_STRUCT
{
char *name;
CALL_FUNC func;
} CMD_STRUCT;
static struct CMD_STRUCT dcc_cmds[] =
{
{ "CHAT", (CALL_FUNC) dcc_chat },
{ "SEND", (CALL_FUNC) dcc_send },
{ "GET", (CALL_FUNC) dcc_get },
{ "CHAT", (CALL_FUNC) dcc_chat },
{ "LIST", (CALL_FUNC) dcc_list },
{ "CLOSE", (CALL_FUNC) dcc_close },
{ NULL, NULL }
};
static char tmp[600];
static char *get_param(char **data)
{
char *pos;
g_return_val_if_fail(data != NULL, NULL);
g_return_val_if_fail(*data != NULL, NULL);
pos = *data;
while (**data != '\0' && **data != ' ') (*data)++;
if (**data == ' ') *(*data)++ = '\0';
return pos;
}
int irccmd_server(char *data)
{
SERVER_REC *serv, *oldserv;
char *ptr;
int port;
GList *tmp;
g_return_val_if_fail(data != NULL, RET_ERR_PARAM);
ptr = strchr(data, ':');
if (ptr == NULL)
port = 6667;
else
{
*ptr = '\0';
if (sscanf(ptr+1, "%d", &port) != 1) port = 6667;
}
if (curwin->defserv == NULL)
oldserv = NULL;
else
{
/* disconnect from old irc server */
oldserv = curwin->defserv;
irc_server_disconnect(curwin->defserv);
}
serv = irc_server_connect(data, port);
if (serv == NULL) return RET_ERROR;
serv->defwin = curwin;
curwin->defserv = serv;
/* put this to default server for all windows with no default servers yet */
for (tmp = g_list_first(winlist); tmp != NULL; tmp = tmp->next)
{
WINDOW_REC *win;
win = (WINDOW_REC *) tmp->data;
if (win->defserv == NULL || win->defserv == oldserv)
win->defserv = curwin->defserv;
}
irc_window_focus(curwin);
return RET_OK;
}
int irccmd_servers(char *data)
{
GList *tmp;
g_return_val_if_fail(data != NULL, RET_ERR_PARAM);
for (tmp = g_list_first(servlist); tmp != NULL; tmp = tmp->next)
{
SERVER_REC *serv;
serv = (SERVER_REC *) tmp->data;
drawtext(curwin, TXT_TYPE_NOTICE, "server %d: %s\n", serv->handle, serv->name);
}
return RET_OK;
}
int irccmd_disconnect(char *data)
{
g_return_val_if_fail(data != NULL, RET_ERR_PARAM);
if (cserver == NULL)
{
/* we're not in any server yet.. */
return RET_NOT_CONNECTED;
}
strcpy(tmp, "QUIT");
if (*data != '\0') sprintf(tmp+4, " :%s", data);
irc_send_cmd(cserver, tmp);
drawtext(curwin, TXT_TYPE_NOTICE, IRCTXT_DISCONNECTED, cserver->name, data);
irc_server_disconnect(cserver);
return RET_OK;
}
int irccmd_quit(char *data)
{
SERVER_REC *old;
g_return_val_if_fail(data != NULL, RET_ERR_PARAM);
/* disconnect from every server */
old = cserver;
while (servlist != NULL)
{
cserver = (SERVER_REC *) servlist->data;
irccmd_disconnect(*data != '\0' ? data : "leaving");
}
cserver = old;
gui_exit();
return RET_OK;
}
int irccmd_quote(char *data)
{
g_return_val_if_fail(data != NULL, RET_ERR_PARAM);
irc_send_cmd(cserver, data);
return RET_OK;
}
int irccmd_join(char *data)
{
SERVER_REC *server;
CHAN_REC *chan;
char *ptr, *next, *key;
g_return_val_if_fail(data != NULL, RET_ERR_PARAM);
if (*data == '\0')
{
#ifdef USE_GUI
if (cserver != NULL)
gui_join_dialog(cserver);
#else
return RET_NOT_ENOUGH_PARAMS;
#endif
}
if (cserver == NULL || !cserver->connected) return RET_NOT_CONNECTED;
for (next = data; next != NULL; data = next)
{
server = cserver;
next = strchr(data, ',');
if (next != NULL) *next++ = '\0';
while (*data == ' ') data++;
if (*data == '\0') break;
if (isdigit(*data))
{
/* server id */
char *digit = data;
while (isdigit(*data)) data++;
if (*data != ' ')
{
/* hm.. I think it was channel anyway.. */
data = digit;
}
else
{
int tag;
*data++ = '\0';
if (sscanf(digit, "%d", &tag) == 1)
{
server = irc_get_server(tag);
if (server == NULL)
{
/* no server has such id.. */
continue;
}
}
}
}
key = strchr(data, ' ');
if (key != NULL)
{
/* channel key */
*key++ = '\0';
}
if (*data != '&' && *data != '#')
{
/* No # or & at start of channel so add # there.. */
ptr = (char *) g_malloc(strlen(data)+2);
sprintf(ptr, "#%s", data);
data = ptr;
}
else
ptr = NULL;
chan = channel_joined(server, data);
if (chan != NULL)
{
/* already joined this channel, set it active.. */
if (curwin->curchan != chan)
{
/* this channel wasn't previously selected in this window */
drawtext(curwin, TXT_TYPE_NOTICE, IRCTXT_TALKING_IN, chan->name);
}
curwin->curchan = chan;
gui_select_channel(curwin, chan);
irc_window_focus(curwin);
if (ptr != NULL) g_free(ptr);
continue;
}
/* Send JOIN command to server */
if (key != NULL)
sprintf(tmp, "JOIN %s %s", data, key);
else
sprintf(tmp, "JOIN %s", data);
irc_send_cmd(server, tmp);
curwin->curchan = (CHAN_REC *) g_malloc(sizeof(CHAN_REC));
memset(curwin->curchan, 0, sizeof(CHAN_REC));
curwin->curchan->name = g_strdup(data);
curwin->curchan->topic = NULL;
curwin->curchan->nicks = NULL;
curwin->curchan->window = curwin;
curwin->curchan->server = server;
curwin->chanlist = g_list_append(curwin->chanlist, curwin->curchan);
gui_channel_join(curwin->curchan, NULL);
if (ptr != NULL) g_free(ptr);
}
return RET_OK;
}
int irccmd_query(char *data)
{
SERVER_REC *server;
CHAN_REC *chan;
g_return_val_if_fail(data != NULL, RET_ERR_PARAM);
if (*data == '\0') irccmd_unquery(""); /* remove current query */
server = cserver;
if (isdigit(*data))
{
/* server id */
char *digit = data;
while (isdigit(*data)) data++;
if (*data != ' ')
{
/* hm.. I think it was channel anyway.. */
data = digit;
}
else
{
int tag;
*data++ = '\0';
if (sscanf(digit, "%d", &tag) == 1)
{
server = irc_get_server(tag);
if (server == NULL)
{
/* no server has such id.. */
return RET_ERROR;
}
}
}
}
chan = channel_joined(server, data);
if (chan != NULL)
{
/* query already existed - change to query window */
if (curwin->curchan != chan)
{
/* this query wasn't previously selected in this window */
drawtext(curwin, TXT_TYPE_NOTICE, IRCTXT_QUERYING, chan->name);
}
curwin->curchan = chan;
irc_window_focus(curwin);
gui_select_channel(curwin, chan);
return RET_OK;
}
curwin->curchan = (CHAN_REC *) g_malloc(sizeof(CHAN_REC));
memset(curwin->curchan, 0, sizeof(CHAN_REC));
curwin->curchan->name = g_strdup(data);
curwin->curchan->nicks = NULL;
curwin->curchan->topic = NULL;
curwin->curchan->window = curwin;
curwin->curchan->server = cserver;
curwin->chanlist = g_list_append(curwin->chanlist, curwin->curchan);
gui_channel_join(curwin->curchan, NULL);
return RET_OK;
}
int irccmd_unquery(char *data)
{
CHAN_REC *chan;
g_return_val_if_fail(data != NULL, RET_ERR_PARAM);
if (*data == '\0')
chan = curwin->curchan; /* remove current query */
else
{
chan = channel_joined(cserver, data);
if (chan == NULL)
{
drawtext(curwin, TXT_TYPE_NOTICE, IRCTXT_NO_QUERY, data);
return RET_ERROR;
}
}
/* remove query */
if (chan == NULL || *chan->name == '#' || *chan->name == '&')
return RET_ERROR;
irc_select_new_channel(curwin);
gui_channel_part(chan, NULL);
return RET_OK;
}
int irccmd_whois(char *data)
{
g_return_val_if_fail(data != NULL, RET_ERR_PARAM);
if (*data == '\0') return RET_NOT_ENOUGH_PARAMS;
sprintf(tmp, "WHOIS %s", data);
irc_send_cmd(cserver, tmp);
return RET_OK;
}
int irccmd_part(char *data)
{
char *channame;
CHAN_REC *chan;
g_return_val_if_fail(data != NULL, RET_ERR_PARAM);
channame = get_param(&data);
if ((*channame == '\0' || strcmp(channame, "*") == 0) && curwin->curchan != NULL)
channame = curwin->curchan->name;
if (*channame == '\0') return RET_NOT_ENOUGH_PARAMS;
chan = channel_joined(cserver, channame);
if (chan == NULL) return RET_ERROR;
sprintf(tmp, "PART %s", channame);
if (data != NULL && *data != '\0')
sprintf(tmp+strlen(tmp), " :%s", data);
irc_send_cmd(cserver, tmp);
return RET_OK;
}
int irccmd_mode(char *data)
{
char *channame;
CHAN_REC *chan;
g_return_val_if_fail(data != NULL, RET_ERR_PARAM);
channame = get_param(&data);
if (strcmp(channame, "*") == 0 && curwin->curchan != NULL)
channame = curwin->curchan->name;
chan = channel_joined(cserver, channame);
if (*data == '\0') return RET_NOT_ENOUGH_PARAMS;
sprintf(tmp, "MODE %s %s", channame, data);
irc_send_cmd(cserver, tmp);
return RET_OK;
}
int irccmd_msg(char *data)
{
CHAN_REC *chan;
char *target;
g_return_val_if_fail(data != NULL, RET_ERR_PARAM);
target = get_param(&data);
if (*target == '\0' || *data == '\0') return RET_NOT_ENOUGH_PARAMS;
chan = channel_joined(cserver, target);
if (*target == '=')
{
/* dcc msg */
DCC_REC *dcc;
dcc = dcc_find_item(DCC_TYPE_CHAT, ++target, NULL);
if (dcc == NULL)
{
drawtext(curwin, TXT_TYPE_DCC, IRCTXT_DCC_CHAT_NOT_FOUND, target);
return RET_ERROR;
}
drawtext(curwin, TXT_TYPE_DEFAULT, "[%5dcc%n(%6%s%n)] %s\n", target, data);
dcc_chat_write(dcc, data);
return RET_OK;
}
if (cserver == NULL) return RET_NOT_CONNECTED;
if (*target == '#' || *target == '&')
{
/* msg to channel */
if (chan != NULL && chan->window->curchan != NULL &&
strcasecmp(chan->window->curchan->name, target) == 0)
drawtext(chan->window, TXT_TYPE_DEFAULT, "<%0%s%n> %s\n", cserver->nick, data);
else
drawtext(curwin, TXT_TYPE_DEFAULT, "<%0%s%n:%2%s%n> %s\n", cserver->nick, target, data);
}
else
{
/* private message */
drawtext(chan == NULL ? curwin : chan->window, TXT_TYPE_DEFAULT,
"[%5msg%n(%6%s%n)]%n %s\n", target, data);
}
sprintf(tmp, "PRIVMSG %s :%s", target, data);
irc_send_cmd(cserver, tmp);
return RET_OK;
}
int irccmd_notice(char *data)
{
CHAN_REC *chan;
char *target;
g_return_val_if_fail(data != NULL, RET_ERR_PARAM);
target = get_param(&data);
if (*target == '\0' || *data == '\0') return RET_NOT_ENOUGH_PARAMS;
chan = channel_joined(cserver, target);
if (cserver == NULL) return RET_NOT_CONNECTED;
drawtext(chan != NULL ? chan->window : curwin, TXT_TYPE_DEFAULT,
"-%4notice%n(%3%s%n)-%n %s\n", target, data);
sprintf(tmp, "NOTICE %s :%s", target, data);
irc_send_cmd(cserver, tmp);
return RET_OK;
}
int irccmd_me(char *data)
{
g_return_val_if_fail(data != NULL, RET_ERR_PARAM);
if (curwin->curchan == NULL) return RET_NOT_JOINED;
drawtext(curwin->curchan->window, TXT_TYPE_DEFAULT, "%7 * %s %8%s\n",
cserver->nick, data);
sprintf(tmp, "PRIVMSG %s :\001ACTION %s\001", curwin->curchan->name, data);
irc_send_cmd(cserver, tmp);
return RET_OK;
}
int irccmd_ctcp(char *data)
{
CHAN_REC *chan;
char *ptr, *target;
g_return_val_if_fail(data != NULL, RET_ERR_PARAM);
target = get_param(&data);
if (*target == '\0' || *target == '\0') return RET_NOT_ENOUGH_PARAMS;
chan = channel_joined(cserver, target);
for (ptr = data; *ptr != '\0' && *ptr != ' '; ptr++)
*ptr = toupper(*ptr);
drawtext(chan == NULL ? curwin : chan->window, TXT_TYPE_DEFAULT,
"[%5ctcp%n(%6%s%n)]%n %s\n", target, data);
sprintf(tmp, "PRIVMSG %s :\001%s\001", target, data);
irc_send_cmd(cserver, tmp);
return RET_OK;
}
int irccmd_dcc(char *data)
{
char *cmd;
int n;
g_return_val_if_fail(data != NULL, RET_ERR_PARAM);
cmd = get_param(&data);
if (*cmd == '\0') return RET_NOT_ENOUGH_PARAMS;
for (n = 0; dcc_cmds[n].name != NULL; n++)
{
if (strcasecmp(dcc_cmds[n].name, cmd) == 0)
return dcc_cmds[n].func(data);
}
drawtext(curwin, TXT_TYPE_DCC, IRCTXT_DCC_UNKNOWN_COMMAND, cmd);
return RET_OK;
}
int irccmd_window(char *data)
{
WINDOW_REC *win;
char *cmd;
g_return_val_if_fail(data != NULL, RET_ERR_PARAM);
cmd = get_param(&data);
if (*cmd == '\0') return RET_NOT_ENOUGH_PARAMS;
while (*data == ' ') data++;
if (strcasecmp(cmd, "NEW") == 0)
{
char *spec;
spec = get_param(&data);
if (*spec == '\0')
win = irc_window_new(cserver, NULL);
else if (strcasecmp(spec, "HIDE") == 0)
win = irc_window_new(cserver, curwin);
}
else if (strcasecmp(cmd, "CLOSE") == 0)
{
irc_window_close(curwin);
}
else if (strcasecmp(cmd, "GOTO") == 0)
{
int num;
if (sscanf(get_param(&data), "%d", &num) == 1 && num > 0)
{
GList *tmp;
tmp = g_list_nth(winlist, num-1);
if (tmp != NULL) gui_window_select((WINDOW_REC *) tmp->data);
}
}
else if (strcasecmp(cmd, "SERVER") == 0)
{
SERVER_REC *serv;
char *ptr;
int port;
if (*data == '\0') return RET_NOT_ENOUGH_PARAMS;
ptr = data;
while (*ptr >= '0' && *ptr <= '9') ptr++;
if (*ptr == '\0' && sscanf(data, "%d", &port) == 1)
{
/* try to change to already connected server */
serv = irc_get_server(port);
if (serv == NULL)
{
/* server not found.. */
drawtext(curwin, TXT_TYPE_NOTICE, IRCTXT_SERVER_NOT_FOUND, port);
}
else
{
/* server selected */
drawtext(curwin, TXT_TYPE_NOTICE, IRCTXT_SERVER_SELECTED,
serv->handle, serv->name);
}
}
else
{
/* connect to server */
ptr = strchr(data, ':');
if (ptr == NULL)
port = 6667;
else
{
*ptr = '\0';
if (sscanf(ptr+1, "%d", &port) != 1) port = 6667;
}
serv = irc_server_connect(data, port);
}
if (serv == NULL) return RET_ERROR;
irc_select_new_server_window(curwin);
serv->defwin = curwin;
curwin->defserv = serv;
irc_window_focus(curwin);
gui_update_statusbar(curwin);
}
else
{
drawtext(curwin, TXT_TYPE_ERROR, IRCTXT_WINDOW_UNKNOWN_CMD, cmd);
return RET_ERROR;
}
return RET_OK;
}
int irccmd_ison(char *data)
{
g_return_val_if_fail(data != NULL, RET_ERR_PARAM);
if (*data == '\0') return RET_NOT_ENOUGH_PARAMS;
if (cserver->ison_reqs > 0)
/* hm.. there's already /ISON going because of notify list check,
sending any /ISON's now would mess up notify list checks.. So,
I don't think it's so bad to ignore it right now? :) maybe message
to user, maybe change and make notify list differently, dunno,
works enough well now .. */
;
else
{
sprintf(tmp, "ISON :%s", data);
irc_send_cmd(cserver, tmp);
}
return RET_OK;
}
int irccmd_load(char *data)
{
#ifdef USE_SCRIPT
return script_load(data);
#else
return RET_OK;
#endif
}
int irccmd_unload(char *data)
{
#ifdef USE_SCRIPT
script_deinit();
#endif
return RET_OK;
}