Files
energymech/src/ctcp.c
2018-03-05 23:09:40 +01:00

1042 lines
21 KiB
C

/*
EnergyMech, IRC bot software
Parts Copyright (c) 1997-2004 proton
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.
*/
#define CTCP_C
#include "config.h"
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
int dcc_only_command(char *from)
{
#ifdef REDIRECT
if (!redirect.to)
#endif /* REDIRECT */
if (!CurrentDCC)
{
to_user(from,TEXT_DCC_ONLY,CurrentCmd->name);
return(TRUE);
}
return(FALSE);
}
Client *find_client(const char *nick)
{
Client *client;
if (CurrentDCC && CurrentDCC->user->name == nick)
return(CurrentDCC);
for(client=current->clientlist;client;client=client->next)
{
if (((client->flags & DCC_SEND) == 0) && !Strcasecmp(nick,client->user->name))
return(client);
}
return(NULL);
}
void delete_client(Client *client)
{
Client **pp;
Spy *spy,**pspy;
#ifdef DEBUG
if (client->sock >= 0)
debug("(delete_client) closing {%i}\n",client->sock);
#endif /* DEBUG */
pp = &current->clientlist;
while(*pp)
{
if (*pp == client)
{
*pp = client->next;
break;
}
pp = &(*pp)->next;
}
if (client->user)
{
pspy = &current->spylist;
while(*pspy)
{
spy = *pspy;
/*
* for DCC spy dest we use the exact same pointer as in the userlist
*/
if (spy->dest == client->user->name)
{
*pspy = spy->next;
Free((char**)&spy);
continue;
}
pspy = &(*pspy)->next;
}
send_global(SPYSTR_STATUS,"[%s] %s[%i] has disconnected",
current->nick,client->user->name,client->user->x.x.access);
}
#ifdef DCC_FILE
if (client->fileno >= 0)
close(client->fileno);
#endif /* DCC_FILE */
if (client->sock >= 0)
close(client->sock);
Free((char **)&client);
}
void partyline_broadcast(Client *from, char *format, char *rest)
{
Client *client;
Mech *bot;
for(bot=botlist;bot;bot=bot->next)
{
for(client=bot->clientlist;client;client=client->next)
{
if (0 == (client->flags & (DCC_ACTIVE|DCC_TELNET)))
continue;
if (client == from && client->user->x.x.echo == FALSE)
continue;
to_file(client->sock,format,CurrentNick,rest);
}
}
}
void dcc_banner(Client *client)
{
char tmp[MSGLEN];
client->flags = DCC_ACTIVE;
client->lasttime = now;
sprintf(tmp,"[%s] %s[%i] has connected",
current->nick,client->user->name,(int)client->user->x.x.access);
if ((to_file(client->sock,"[%s] %s\n",time2medium(now),tmp)) < 0)
{
client->flags = DCC_DELETE;
return;
}
send_global(SPYSTR_STATUS,tmp);
if (client->user->x.x.access == OWNERLEVEL)
{
CurrentDCC = client;
Strcpy(tmp,SPYSTR_STATUS);
do_spy(client->user->name,current->nick,tmp,0);
CurrentDCC = NULL;
}
}
#ifdef DCC_FILE
int dcc_sendfile(char *target, char *filename)
{
struct sockaddr_in sai;
Client *client;
int s,f,sz;
char tempfile[strlen(filename)+strlen(DCC_PUBLICFILES)+2]; // strlen(DCC_PUBLICFILES) evaluates at compile time to a constant.
Strcpy(tempfile,DCC_PUBLICFILES);
Strcat(tempfile,filename);
#ifdef DEBUG
debug("(dcc_sendfile) opening %s for transfer\n",tempfile);
#endif /* DEBUG */
if ((f = open(tempfile,O_RDONLY)) < 0)
return -1;
if ((s = SockListener(0)) < 0)
return -1;
sz = sizeof(sai);
if (getsockname(s,(struct sockaddr *)&sai,&sz) < 0)
{
close(s);
return -1;
}
set_mallocdoer(dcc_sendfile);
client = (Client*)Calloc(sizeof(Client) + Strlen2(filename,target)); // target is never NULL
client->fileno = f;
client->sock = s;
client->user = NULL;
client->flags = DCC_WAIT|DCC_ASYNC|DCC_SEND;
client->lasttime = now;
client->whom = Strcpy(client->filename,filename) + 1;
Strcpy(client->whom,target);
client->next = current->clientlist;
current->clientlist = client;
sz = lseek(f,0,SEEK_END);
lseek(f,0,SEEK_SET);
client->fileend = sz;
to_server("PRIVMSG %s :\001DCC SEND %s %u %u %i\001\n",target,
filename,htonl(current->ip.s_addr),ntohs(sai.sin_port),sz);
return(sz);
}
void dcc_pushfile(Client *client, off_t where)
{
char tempdata[16384];
int sz;
sz = (where + 16384) - lseek(client->fileno,0,SEEK_CUR);
sz = read(client->fileno,tempdata,sz);
if (sz < 1)
return;
write(client->sock,tempdata,sz);
}
int dcc_freeslots(int uaccess)
{
Client *client;
int n;
n = (uaccess > 0) ? current->setting[INT_DCCUSER].int_var : 0;
n += current->setting[INT_DCCANON].int_var;
for(client=current->clientlist;client;client=client->next)
{
if (client->flags & (DCC_SEND|DCC_RECV))
n--;
}
return(n);
}
#endif /* DCC_FILE */
void parse_dcc(Client *client)
{
char text[MSGLEN];
char *ptr,*bp;
int s,oc;
if (client->flags & DCC_WAIT)
{
#ifdef DCC_FILE
if (client->flags & DCC_RECV)
{
client->flags = DCC_SEND|DCC_RECV;
return;
}
#endif /* DCC_FILE */
#ifdef DEBUG
#ifdef DCC_FILE
if (client->flags & DCC_SEND)
debug("(parse_dcc) new dcc filetransfer connecting\n");
else
#endif /* DCC_FILE */
debug("(parse_dcc) new user connecting\n");
#endif /* DEBUG */
s = SockAccept(client->sock);
close(client->sock);
client->sock = s;
if (s == -1)
{
client->flags = DCC_DELETE;
return;
}
if ((client->flags & DCC_SEND) == 0)
{
/*
* tell them how much we love them
*/
dcc_banner(client);
}
#ifdef DCC_FILE
else
{
client->flags = DCC_SEND;
client->start = now;
dcc_pushfile(client,0);
}
#endif /* DCC_FILE */
return;
}
/*
* read data from socket
*/
#ifdef DCC_FILE
if (client->flags & DCC_RECV)
{
char bigtemp[4096];
ulong where;
do
{
s = read(client->sock,bigtemp,4096);
if (s > 0)
write(client->fileno,bigtemp,s);
}
while(s > 0);
if ((s < 0) && (errno != EINTR) && (errno != EAGAIN))
client->flags = DCC_DELETE;
where = oc = lseek(client->fileno,0,SEEK_CUR);
where = htonl(where);
write(client->sock,&where,4);
client->lasttime = now;
if (oc == client->fileend)
{
#ifdef DEBUG
debug("(parse_dcc) DCC file recv `%s' completed in %lu seconds (%i bytes)\n",
client->filename,(client->lasttime - client->start),client->fileend);
#endif /* DEBUG */
client->flags = DCC_DELETE;
}
return;
}
if (client->flags & DCC_SEND)
{
ulong where;
client->lasttime = now;
s = client->inputcount;
oc = read(client->sock,(client->sockdata+s),(4-s));
if ((oc < 1) && (errno != EINTR) && (errno != EAGAIN))
{
client->flags = DCC_DELETE;
return;
}
oc += s;
if (oc == 4)
{
where = ((uchar)client->sockdata[0] << 24) |
((uchar)client->sockdata[1] << 16) |
((uchar)client->sockdata[2] << 8) |
(uchar)client->sockdata[3];
client->inputcount = 0;
if (client->fileend == where)
{
#ifdef TCL
tcl_dcc_complete(client,0);
#endif /* TCL */
#ifdef DEBUG
debug("(parse_dcc) dcc_sendfile: end of file\n");
#endif /* DEBUG */
client->flags = DCC_DELETE;
}
else
dcc_pushfile(client,where);
}
else
{
#ifdef DEBUG
debug("(parse_dcc) DCC_SEND partial ack\n");
#endif /* DEBUG */
client->inputcount = oc;
}
return;
}
#endif /* DCC_FILE */
ptr = sockread(client->sock,client->sockdata,text);
oc = errno;
#ifdef TELNET
if (ptr && (client->flags & DCC_TELNETPASS))
{
check_telnet_pass(client,ptr);
}
else
#endif /* TELNET */
if (ptr)
{
/*
* DCC input flood protection
*/
s = now - client->lasttime;
if (s > 10)
{
client->inputcount = strlen(ptr);
}
else
{
client->inputcount += strlen(ptr);
if ((client->inputcount - (s * DCC_INPUT_DECAY)) > DCC_INPUT_LIMIT)
{
client->flags = DCC_DELETE;
return;
}
}
/*
* set up source-destination information for on_msg/on_action
*/
CurrentShit = NULL;
CurrentChan = NULL;
client->lasttime = now;
CurrentDCC = client;
CurrentUser = client->user;
Strcpy(CurrentNick,CurrentUser->name);
if (*ptr == 1)
{
bp = ptr;
chop(&bp);
ptr = get_token(&bp,"\001");
on_action(CurrentUser->name,current->nick,ptr);
}
else
{
on_msg(CurrentUser->name,current->nick,ptr);
}
CurrentDCC = NULL;
/*
* get out of here ASAP, consider dangerous commands such as DIE and DEL (user)
*/
return;
}
switch(oc)
{
case EAGAIN:
case EINTR:
return;
default:
client->flags = DCC_DELETE;
return;
}
}
void process_dcc(void)
{
Client *client;
for(client=current->clientlist;client;client=client->next)
{
if (FD_ISSET(client->sock,&read_fds))
{
parse_dcc(client);
}
else
if ((client->flags & DCC_ASYNC) && (FD_ISSET(client->sock,&write_fds)))
{
#ifdef DEBUG
debug("(process_dcc) chat connected [ASYNC]\n");
#endif /* DEBUG */
dcc_banner(client);
}
else
if ((client->flags & DCC_WAIT) && ((now - client->lasttime) >= WAITTIMEOUT))
{
#ifdef DEBUG
debug("(process_dcc) connection timed out (%s)\n",
(client->flags & (DCC_SEND|DCC_RECV)) ? "file transfer" : client->user->name);
#endif /* DEBUG */
client->flags = DCC_DELETE;
}
#ifdef DCC_FILE
else
if ((client->flags & DCC_SEND) && ((now - client->lasttime) >= DCC_FILETIMEOUT))
{
#ifdef DEBUG
debug("(process_dcc) {%i} DCC %s stalled (%s), closing connection\n",
client->sock,(client->flags & DCC_RECV) ? "RECV" : "SEND",
nullstr(client->filename));
#endif /* DEBUG */
client->flags = DCC_DELETE;
}
#endif /* DCC_FILE */
#ifdef TELNET
else
if ((client->flags & DCC_TELNETPASS) && ((now - client->lasttime) >= TELNET_TIMEOUT))
{
client->flags = DCC_DELETE;
}
#endif /* TELNET */
}
}
void dcc_chat(char *from)
{
struct sockaddr_in sai;
Client *client;
User *user;
int sock,sz;
if ((user = get_authuser(from,NULL)) == NULL)
return;
if (find_client(user->name))
return;
if ((sock = SockListener(0)) < 0)
return;
sz = sizeof(sai);
if (getsockname(sock,(struct sockaddr *)&sai,&sz) < 0)
{
close(sock);
return;
}
set_mallocdoer(dcc_chat);
client = (Client*)Calloc(sizeof(Client));
#ifdef DCC_FILE
client->fileno = -1;
#endif /* DCC_FILE */
client->user = user;
client->sock = sock;
client->flags = DCC_WAIT;
client->lasttime = now;
client->next = current->clientlist;
current->clientlist = client;
to_server("PRIVMSG %s :\001DCC CHAT CHAT %u %u\001\n",
CurrentNick,htonl(current->ip.s_addr),ntohs(sai.sin_port));
}
/*
*
* CTCP things...
*
*/
void ctcp_dcc(char *from, char *to, char *rest)
{
struct in_addr ia;
Client *client;
User *user;
char *addr,*port,ip_addr[20];
ulong longip;
int x;
#ifdef DCC_FILE
char *filename;
int s,f,portnum,filesz;
#endif /* DCC_FILE */
if (!rest || !*rest)
return;
addr = port = chop(&rest);
while(*addr)
{
if (*addr >= 'a' && *addr <= 'z')
*addr = *addr - 0x20;
addr++;
}
x = get_maxaccess(from);
send_spy(SPYSTR_STATUS,"[DCC] :%s[%i]: Requested DCC %s [%s]",CurrentNick,x,port,nullstr(rest));
#ifdef DCC_FILE
if (!Strcasecmp(port,"SEND"))
{
#ifdef DEBUG
debug("(ctcp_dcc) rest: `%s'\n",nullstr(rest));
#endif /* DEBUG */
filename = chop(&rest);
if (!is_safepath(filename))
{
#ifdef DEBUG
debug("(ctcp_dcc) filename `%s' is not safe\n",filename);
#endif /* DEBUG */
return;
}
/*
* check filename against masks in STR_DCCFILES
*/
s = 1;
if ((addr = current->setting[STR_DCCFILES].str_var))
{
char tempmask[strlen(addr)+1];
Strcpy(tempmask,addr);
do
{
port = chop(&addr);
if (matches(port,filename) == 0)
{
s = 0;
break;
}
}
while(port && *port);
}
/*
*
*/
if (s)
return;
/*
* check for free DCC slots (x is maxuserlevel from above)
*/
if (dcc_freeslots(x) < 1)
return;
addr = chop(&rest);
port = chop(&rest);
portnum = a2i(port);
x = errno;
filesz = a2i(rest);
if (errno || x || portnum < 1024 || portnum > 63353 || filesz <= 0)
return;
longip = 0;
while(*addr)
{
longip = (longip * 10) + (*addr - '0');
addr++;
}
ia.s_addr = ntohl(longip);
Strcpy(ip_addr,inet_ntoa(ia));
if (1)
{
char tempname[strlen(filename)+strlen(DCC_PUBLICINCOMING)+1]; // strlen(DCC_PUBLICINCOMING) evaluates to a constant during compile.
Strcpy(Strcpy(tempname,DCC_PUBLICINCOMING),filename);
if ((f = open(tempname,O_RDWR|O_CREAT|O_EXCL,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
return;
if ((s = SockConnect(ip_addr,portnum,FALSE)) < 0)
{
close(f);
return;
}
set_mallocdoer(ctcp_dcc);
client = (Client*)Calloc(sizeof(Client) + Strlen2(filename,from)); // from is never NULL
client->fileno = f;
client->fileend = filesz;
client->sock = s;
client->flags = DCC_WAIT|DCC_SEND|DCC_RECV;
client->lasttime = client->start = now;
client->whom = Strcpy(client->filename,filename) + 1;
Strcpy(client->whom,from);
client->next = current->clientlist;
current->clientlist = client;
}
}
else
#endif /* DCC_FILE */
if (x && (x < BOTLEVEL) && !Strcasecmp(port,"CHAT"))
{
if ((user = get_authuser(from,NULL)) == NULL)
{
to_user(from,"Use \"VERIFY\" to get verified first");
return;
}
if (find_client(user->name))
return;
chop(&rest); /* discard "chat" */
addr = chop(&rest);
port = chop(&rest);
if (!port || !*port)
return;
x = a2i(port);
if (errno || (x < 1024) || (x > 65535))
return;
/*
* quick hack; if someone sends a fake/non-numeric long_ip, this all just fails
* and we couldnt care less. blaha.
*/
longip = 0;
while(*addr)
{
longip = (longip * 10) + (*addr - '0');
addr++;
}
ia.s_addr = ntohl(longip);
Strcpy(ip_addr,inet_ntoa(ia));
#ifdef DEBUG
debug("(ctcp_dcc) %s [%s,%s]\n",from,ip_addr,port);
#endif /* DEBUG */
if ((x = SockConnect(ip_addr,x,FALSE)) < 0)
return;
set_mallocdoer(ctcp_dcc);
client = (Client*)Calloc(sizeof(Client));
#ifdef DCC_FILE
client->fileno = -1;
#endif /* DCC_FILE */
client->sock = x;
client->user = user;
client->flags = DCC_WAIT|DCC_ASYNC;
client->lasttime = now;
client->next = current->clientlist;
current->clientlist = client;
}
}
#ifdef CTCP
void ctcp_finger(char *from, char *to, char *rest)
{
char *reply;
int maxul;
/*
* checking for a spylist first saves a few clocks
*/
if (current->spy & SPYF_STATUS)
{
maxul = get_maxaccess(from);
send_spy(SPYSTR_STATUS,"[CTCP] :%s[%i]: Requested Finger Info",CurrentNick,maxul);
}
if (!current->setting[TOG_CTCP].int_var)
return;
reply = (current->setting[TOG_RF].int_var) ? randstring(VERSIONFILE) : NULL;
to_server("NOTICE %s :\001FINGER %s\001\n",CurrentNick,(reply) ? reply : EXFINGER);
}
void ctcp_ping(char *from, char *to, char *rest)
{
int maxul;
if (!rest || !*rest || (strlen(rest) > 100))
return;
/*
* this kludge saves a few clock cycles
*/
maxul = ASSTLEVEL;
if (current->spylist || !current->setting[TOG_CTCP].int_var)
{
maxul = get_maxaccess(from);
if (current->spy & SPYF_STATUS)
send_spy(SPYSTR_STATUS,"[CTCP] :%s[%i]: Requested Ping Info",CurrentNick,maxul);
}
if (maxul >= ASSTLEVEL)
{
to_server("NOTICE %s :\001PING %s\001\n",CurrentNick,(rest) ? rest : "");
}
}
void ctcp_version(char *from, char *to, char *rest)
{
char *reply;
int maxul;
/*
* checking for a spylist first saves a few clocks
*/
if (current->spy & SPYF_STATUS)
{
maxul = get_maxaccess(from);
send_spy(SPYSTR_STATUS,"[CTCP] :%s[%i]: Requested Version Info",CurrentNick,maxul);
}
if (!current->setting[TOG_CTCP].int_var)
return;
reply = (current->setting[TOG_RV].int_var) ? randstring(VERSIONFILE) : NULL;
to_server("NOTICE %s :\001VERSION %s\001\n",CurrentNick,(reply) ? reply : EXVERSION);
}
#define NEED_SLOT_NO ,0
#define NEED_SLOT_YES ,1
#else /* CTCP */
#define NEED_SLOT_NO /* nothing */
#define NEED_SLOT_YES /* nothing */
#endif /* CTCP */
LS const struct
{
char *name;
void (*func)(char *, char *, char *);
#ifdef CTCP
int need_slot;
#endif /* CTCP */
} ctcp_commands[] =
{
/*
* most common types first
*/
{ "ACTION", on_action NEED_SLOT_NO },
#ifdef CTCP
{ "PING", ctcp_ping NEED_SLOT_YES },
{ "VERSION", ctcp_version NEED_SLOT_YES },
{ "FINGER", ctcp_finger NEED_SLOT_YES },
#endif /* CTCP */
{ "DCC", ctcp_dcc NEED_SLOT_NO },
{ NULL, }};
void on_ctcp(char *from, char *to, char *rest)
{
char *command,*p;
int i,mul;
/*
* some of these stupid CTCP's have leading spaces, bad!
*/
while(*rest == ' ')
rest++;
i = FALSE;
p = command = rest;
for(;*p;p++)
{
if (*p == ' ' && !i)
{
i = TRUE;
*p = 0;
rest = p + 1;
while(*rest == ' ')
rest++;
}
if (*p == 1)
{
*p = 0;
break;
}
}
for(i=0;ctcp_commands[i].name;i++)
{
if (!Strcasecmp(ctcp_commands[i].name,command))
{
#ifdef CTCP
if (ctcp_commands[i].need_slot)
{
for(mul=0;mul<CTCP_SLOTS;mul++)
{
if (ctcp_slot[mul] < now)
{
ctcp_slot[mul] = now + CTCP_TIMEOUT;
break;
}
}
if (mul>=CTCP_SLOTS)
{
#ifdef DEBUG
debug("(on_ctcp) ctcp_slot for %s not found, being flooded?\n",
nullstr(command));
#endif /* DEBUG */
return;
}
}
#endif /* CTCP */
ctcp_commands[i].func(from,to,rest);
return;
}
}
if (current->spy & SPYF_STATUS)
{
mul = get_maxaccess(from);
send_spy(SPYSTR_STATUS,"[CTCP] :%s[%i]: Unknown [%s]",CurrentNick,mul,command);
}
}
/*
*
* commands associated with CTCP and DCC
*
*/
void do_chat(COMMAND_ARGS)
{
User *user;
user = get_authuser(from,NULL);
if (!user)
return;
if (find_client(user->name))
{
to_user(from,"You are already DCC chatting me");
return;
}
dcc_chat(from);
}
#ifdef CTCP
void do_ping_ctcp(COMMAND_ARGS)
{
/*
* on_msg checks: CARGS
*/
char *target;
if ((target = chop(&rest)))
{
if (CurrentCmd->name == C_PING || !Strcasecmp(rest,"PING"))
{
to_server("PRIVMSG %s :\001PING %lu\001\n",target,now);
return;
}
if (*rest)
{
to_server("PRIVMSG %s :\001%s\001\n",target,rest);
return;
}
}
usage(from);
}
#endif /* CTCP */
#ifdef BOTNET
void whom_printbot(char *from, BotInfo *binfo, char *stt)
{
char *us;
int uaccess;
us = "";
if (binfo->nuh)
{
uaccess = get_maxaccess(binfo->nuh);
if (uaccess == BOTLEVEL)
us = "b200";
else
if (uaccess)
sprintf((us = stt),"u%i",uaccess);
}
uaccess = get_authaccess(from,MATCH_ALL);
table_buffer((uaccess >= ASSTLEVEL) ? TEXT_WHOMBOTGUID : TEXT_WHOMBOTLINE,(binfo->nuh) ? nickcpy(NULL,binfo->nuh) : "???",us,
(binfo->server) ? binfo->server : "???",(binfo->version) ? binfo->version : "???",binfo->guid);
}
#endif /* BOTNET */
void do_whom(COMMAND_ARGS)
{
#ifdef BOTNET
BotNet *bn;
BotInfo *binfo;
#endif /* BOTNET */
Server *sp;
char stt[NUHLEN];
Client *client;
Mech *bot;
int m,s;
if (dcc_only_command(from))
return;
for(bot=botlist;bot;bot=bot->next)
{
if (bot->connect == CN_ONLINE)
{
sp = find_server(bot->server);
if (sp)
{
sprintf(stt,"%s:%i",(*sp->realname) ? sp->realname : sp->name,sp->port);
}
else
{
Strcpy(stt,TEXT_NOTINSERVLIST);
}
}
else
{
Strcpy(stt,TEXT_NOTCONNECTED);
}
table_buffer(TEXT_WHOMSELFLINE,bot->nick,(bot == current) ? "(me)" : "b200",stt);
for(client=bot->clientlist;client;client=client->next)
{
m = (now - client->lasttime) / 60;
s = (now - client->lasttime) % 60;
table_buffer(TEXT_WHOMUSERLINE,
#ifdef TELNET
client->user->name,client->user->x.x.access,(client->flags & DCC_TELNET) ? "telnet" : "DCC",m,s);
#else
client->user->name,client->user->x.x.access,"DCC",m,s);
#endif /* TELNET */
}
}
#ifdef BOTNET
for(bn=botnetlist;bn;bn=bn->next)
{
if (bn->status != BN_LINKED)
continue;
for(binfo=bn->botinfo;binfo;binfo=binfo->next)
whom_printbot(from,binfo,stt);
}
#endif /* BOTNET */
table_send(from,3);
}
void do_bye(COMMAND_ARGS)
{
if (CurrentDCC)
{
to_user(from,TEXT_DCC_GOODBYE);
CurrentDCC->flags = DCC_DELETE;
}
}
#ifdef DCC_FILE
void do_send(COMMAND_ARGS)
{
/*
* on_msg checks: CARGS
*/
char *filename,*target;
int sz;
target = chop(&rest);
filename = chop(&rest);
if (!filename)
{
if (CurrentDCC)
{
to_user_q(from,"Unable to send files over DCC connections");
return;
}
filename = target;
target = CurrentNick;
}
if (dcc_freeslots(get_maxaccess(from)) < 1)
{
to_user_q(from,"Unable to send: No free DCC slots");
return;
}
sz = dcc_sendfile(target,filename);
if (sz < 0)
{
to_user_q(from,"Unable to locate file: %s",filename);
return;
}
if (target == CurrentNick)
{
to_user_q(from,"Sending %s (%i bytes)",filename,sz);
}
else
{
to_user_q(from,"Sending %s (%i bytes) to %s",filename,sz,target);
}
}
#endif /* DCC_FILE */