Initial Import

This commit is contained in:
MadCamel
2014-03-08 19:56:21 -05:00
parent 0b366093a7
commit aba69cb20f
221 changed files with 35407 additions and 4 deletions

222
src/Makefile.in Normal file
View File

@@ -0,0 +1,222 @@
#
# EnergyMech, IRC bot software
# Copyright (c) 1997-2009 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.
#
INSTALLNAME = energymech
INSTALLDIR = ..
INSTALLMODE = 0700
LDSCRIPT = @ldscript@
CPROF = @cprof@
LPROF = @lprof@
LIBS = @libflags@
PIPEFLAG = @pipeflag@
GDBFLAG = @gdbflag@
WARNFLAG = @W_FLAGS@
OPTIMIZE = @O_FLAGS@
PYINCLUDE = @PYINCLUDE@
CFLAGS = $(PIPEFLAG) $(GDBFLAG) $(WARNFLAG) $(OPTIMIZE)
LFLAGS = $(PIPEFLAG) $(GDBFLAG)
CC = @CC@
MV = mv -f
RM = rm -f
CHMOD = chmod
INCS = config.h mcmd.h defines.h global.h h.h structs.h text.h
OFILES = alias.o auth.o bounce.o chanban.o channel.o core.o \
ctcp.o debug.o dns.o dynamode.o function.o greet.o help.o irc.o \
kicksay.o main.o net.o net_chan.o note.o notify.o ons.o parse.o \
perl.o prot.o python.o redirect.o reset.o seen.o shit.o socket.o \
spy.o stats.o tcl.o telnet.o toybox.o trivia.o uptime.o \
user.o vars.o web.o @MD5_O@
SRCFILES = alias.c auth.c bounce.c chanban.c channel.c core.c \
ctcp.c debug.c dns.c dynamode.c function.c greet.c help.c irc.c \
kicksay.c main.c net.c net_chan.c note.c notify.c ons.c parse.c \
perl.c prot.c python.c redirect.c reset.c seen.c shit.c socket.c \
spy.c stats.c tcl.c telnet.c toybox.c trivia.c uptime.c \
user.c vars.c web.c
all: $(INSTALLNAME)
mcmd.h: gencmd.c config.h structs.h ;
$(CC) $(LFLAGS) -o gencmd gencmd.c
./gencmd > mcmd.h
install: $(INSTALLNAME)
$(CHMOD) $(INSTALLMODE) $(INSTALLNAME)
$(MV) $(INSTALLNAME) $(INSTALLDIR)
clean: FORCE
$(RM) $(INSTALLNAME) gencmd mcmd.h core $(OFILES)
$(INSTALLNAME): $(OFILES)
$(CC) $(LFLAGS) -o $(INSTALLNAME) $(OFILES) $(LPROF) $(LIBS) $(LDSCRIPT)
@oc@ objcopy -R .note -R .comment $(INSTALLNAME)
@sz@ size $(INSTALLNAME)
mega: $(SRCFILES) $(INCS) usage.h
$(CC) $(CFLAGS) -o $(INSTALLNAME) mega.c $(LPROF) $(LIBS) $(LDSCRIPT) $(PYINCLUDE)
@oc@ objcopy -R .note -R .comment $(INSTALLNAME)
@sz@ size $(INSTALLNAME)
#
# static targets
#
$(INSTALLNAME)-static: $(OFILES)
$(CC) $(LFLAGS) -o $(INSTALLNAME) $(OFILES) $(LPROF) $(LIBS) $(LDSCRIPT) -static
@oc@ objcopy -R .note -R .comment $(INSTALLNAME)
@sz@ size $(INSTALLNAME)
mega-static: $(SRCFILES) $(INCS) usage.h
$(CC) $(CFLAGS) -o $(INSTALLNAME) mega.c $(LPROF) $(LIBS) $(LDSCRIPT) $(PYINCLUDE) -static
@oc@ objcopy -R .note -R .comment $(INSTALLNAME)
@sz@ size $(INSTALLNAME)
#
#
#
alias.o: alias.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
auth.o: auth.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
bounce.o: bounce.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
chanban.o: chanban.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
channel.o: channel.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
core.o: core.c $(INCS) settings.h
$(CC) $(CFLAGS) -c $< $(CPROF)
ctcp.o: ctcp.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
debug.o: debug.c $(INCS) settings.h
$(CC) $(CFLAGS) -c $< $(CPROF) $(PYINCLUDE)
dns.o: dns.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
dynamode.o: dynamode.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
function.o: function.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
greet.o: greet.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
help.o: help.c $(INCS) usage.h
$(CC) $(CFLAGS) -c $< $(CPROF)
irc.o: irc.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
kicksay.o: kicksay.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
main.o: main.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF) $(PYINCLUDE)
net.o: net.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
net_chan.o: net_chan.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
note.o: note.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
notify.o: notify.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
ons.o: ons.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
parse.o: parse.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
perl.o: perl.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
prot.o: prot.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
python.o: python.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF) $(PYINCLUDE)
redirect.o: redirect.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
reset.o: reset.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
seen.o: seen.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
shit.o: shit.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
socket.o: socket.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
spy.o: spy.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
stats.o: stats.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
tcl.o: tcl.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
telnet.o: telnet.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
toybox.o: toybox.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
trivia.o: trivia.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
uptime.o: uptime.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
user.o: user.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
vars.o: vars.c $(INCS) settings.h
$(CC) $(CFLAGS) -c $< $(CPROF)
web.o: web.c $(INCS)
$(CC) $(CFLAGS) -c $< $(CPROF)
md5/md5.o: md5/md5.c $(INCS)
$(CC) $(CFLAGS) -c $< -o $@ -Imd5 $(CPROF)
FORCE:

196
src/alias.c Normal file
View File

@@ -0,0 +1,196 @@
/*
EnergyMech, IRC bot software
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 ALIAS_C
#include "config.h"
#ifdef ALIAS
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
void afmt(char *copy_to, const char *src, const char *input)
{
#define BUFTAIL (tmp+MSGLEN-1) /* avoid buffer overflows */
char tmp[MSGLEN];
const char *np;
char *dest;
int n,t,tu,spc;
dest = tmp;
while(*src)
{
check_fmt:
if (*src == '$')
{
src++;
if (*src == '$')
goto copychar;
tu = t = n = 0;
while(attrtab[(uchar)*src] & NUM)
{
n = (n * 10) + (*(src++) - '0');
}
if (n)
{
if (*src == '-')
{
tu = n;
src++;
while(attrtab[(uchar)*src] & NUM)
{
t = (t * 10) + (*(src++) - '0');
}
}
n--;
spc = 0;
for(np=input;*np;)
{
if (*np == ' ')
{
if (!spc)
n--;
spc = 1;
}
else
{
spc = 0;
if (!n)
break;
}
np++;
}
spc = 0;
while(*np)
{
if (*np == ' ')
{
if (!tu || (t && tu >= t))
goto check_fmt;
if (!spc)
tu++;
spc = 1;
}
else
{
spc = 0;
}
if (dest == BUFTAIL)
goto afmt_escape;
*(dest++) = *(np++);
}
}
goto check_fmt;
}
copychar:
if (dest == BUFTAIL)
goto afmt_escape;
*(dest++) = *(src++);
}
afmt_escape:
*dest = 0;
Strcpy(copy_to,tmp);
}
/*
*
* associated commands
*
*/
void do_alias(COMMAND_ARGS)
{
/*
* on_msg checks: GAXS
*/
Alias *alias;
char *cmd;
if (!*rest)
{
/* list all aliases */
if (!aliaslist)
to_user(from,TEXT_NOALIASES);
else
{
if (dcc_only_command(from))
return;
to_user(from,"\037Alias\037 \037Format\037");
for(alias=aliaslist;alias;alias=alias->next)
{
to_user(from,"%-18s %s",alias->alias,alias->format);
}
}
return;
}
cmd = chop(&rest);
if (!*rest)
{
usage(from); /* usage for CurrentCmd->name */
return;
}
for(alias=aliaslist;alias;alias=alias->next)
{
if (!Strcasecmp(alias->alias,cmd))
{
Free(&alias->format);
set_mallocdoer(do_alias);
alias->format = Strdup(rest);
to_user(from,"Replaced alias: %s --> %s",cmd,rest);
return;
}
}
set_mallocdoer(do_alias);
alias = (Alias*)Calloc(sizeof(Alias)+strlen(cmd));
Strcpy(alias->alias,cmd);
set_mallocdoer(do_alias);
alias->format = Strdup(rest);
alias->next = aliaslist;
aliaslist = alias;
to_user(from,"Added alias: %s --> %s",cmd,rest);
}
void do_unalias(COMMAND_ARGS)
{
/*
* on_msg checks: GAXS + CARGS
*/
Alias *alias,**ap;
for(ap=&aliaslist;*ap;ap=&(*ap)->next)
{
if (!Strcasecmp(rest,(*ap)->alias))
{
alias = *ap;
*ap = alias->next;
to_user(from,"Removed alias: %s (--> %s)",alias->alias,alias->format);
Free(&alias->format);
Free((void*)&alias);
return;
}
}
to_user(from,"Couldnt find matching alias");
}
#endif /* ALIAS */

449
src/auth.c Normal file
View File

@@ -0,0 +1,449 @@
/*
EnergyMech, IRC bot software
Copyright (c) 2001-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 AUTH_C
#include "config.h"
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
#ifndef MD5CRYPT
/*
* simple password encryption
*/
char pctab[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuwvxuz0123456789+-";
#define CIPHER(a1,a2,a3,a4,b1,b2,b3,b4) \
{ \
a2 = a2 ^ a1; \
b2 = b2 ^ b1; \
a3 = a2 ^ a1; \
b3 = b2 ^ b1; \
b3 >>= 2; \
b3 |= ((a3 & 3) << 30); \
a3 >>= 2; \
a2 = a3 ^ a2; \
b2 = b3 ^ b2; \
a4 = ~a4 ^ a2; \
b4 = -b4 ^ b2; \
a2 = a4 ^ ~a2; \
b2 = b4 ^ -b2; \
b1 >>= 1; \
b1 |= ((a1 & 1) << 31); \
a1 >>= 1; \
}
char *cipher(char *arg)
{
static char res[40];
ulong B1a,B2a,B3a,B4a;
ulong B1b,B2b,B3b,B4b;
uchar *ptr;
ulong R1;
int i;
if (!arg || !*arg)
return(NULL);
B1a = B2a = B3a = B4a = 0;
B1b = B2b = B3b = B4b = 0;
ptr = arg;
while(*ptr)
{
R1 = *ptr;
for(i=0;i<8;i++)
{
if (R1 & 1)
{
B1a |= 0x80008000;
B1b |= 0x80008000;
}
R1 >>= 1;
CIPHER(B1a,B2a,B3a,B4a,B1b,B2b,B3b,B4b);
}
ptr++;
}
while((B1a) || (B1b))
{
CIPHER(B1a,B2a,B3a,B4a,B1b,B2b,B3b,B4b);
}
for(i=0;i<10;i++)
{
res[i] = pctab[(B4b & 0x3f)];
B4b >>= 6;
B4b |= ((B4a & 0x3f) << 26);
B4a >>= 6;
}
res[i] = 0;
return(res);
}
char *makepass(char *plain)
{
return(cipher(plain));
}
int passmatch(char *plain, char *encoded)
{
return(!Strcmp(cipher(plain),encoded));
}
#else /* MD5CRYPT */
/*
* use MD5 to hash passwords
*/
char *CRYPT_FUNC(const char *, const char *);
char *makepass(char *plain)
{
char salt[8];
sprintf(salt,"$1$%04x",(rand() >> 16));
return(CRYPT_FUNC(plain,salt));
}
int passmatch(char *plain, char *encoded)
{
char *enc;
if (matches("$1$????$*",encoded))
return(FALSE);
enc = CRYPT_FUNC(plain,encoded);
return(!Strcmp(enc,encoded));
}
#endif /* MD5CRYPT */
/*
*
*/
void delete_auth(char *userhost)
{
Auth *auth,**pp;
pp = &current->authlist;
while(*pp)
{
if (!Strcasecmp(userhost,(*pp)->nuh))
{
auth = *pp;
*pp = auth->next;
Free((char**)&auth);
/*
* dont return yet, there might be more auths
*/
continue;
}
pp = &(*pp)->next;
}
}
void remove_auth(Auth *auth)
{
Auth **pp;
pp = &current->authlist;
while(*pp)
{
if (*pp == auth)
{
*pp = auth->next;
Free((char**)&auth);
/*
* when removing a DCC/telnet auth the connection should also be removed
*/
return;
}
pp = &(*pp)->next;
}
}
/*
* register nick-changes in auths
*/
void change_authnick(char *nuh, char *newnuh)
{
Auth *auth,*oldauth,**pp;
char *n1,*n2;
pp = &current->authlist;
while(*pp)
{
auth = *pp;
if (!nickcmp(nuh,auth->nuh))
{
for(n1=nuh;*n1 != '!';n1++);
for(n2=newnuh;*n2 != '!';n2++);
if ((n1 - nuh) >= (n2 - newnuh))
{
#ifdef DEBUG
debug("(change_authnick) auth->nuh = `%s'; was `%s' (Strcpy) (L1 = %i, L2 = %i)\n",
newnuh,nuh,(int)(n1 - nuh),(int)(n2 - newnuh));
#endif /* DEBUG */
Strcpy(auth->nuh,newnuh);
}
else
{
#ifdef DEBUG
debug("(change_authnick) auth->nuh = `%s'; was `%s' (re-alloc)\n",newnuh,nuh);
#endif /* DEBUG */
/*
* de-link the old auth record
*/
oldauth = auth;
*pp = auth->next;
set_mallocdoer(change_authnick);
auth = (Auth*)Calloc(sizeof(Auth) + strlen(newnuh));
auth->user = oldauth->user;
auth->active = now;
auth->next = current->authlist;
current->authlist = auth;
Strcpy(auth->nuh,newnuh);
Free((char**)&oldauth);
}
return;
}
pp = &(*pp)->next;
}
}
LS User *au_user;
LS char *au_userhost;
LS char *au_channel;
LS int au_access;
__attr(CORE_SEG, __regparm (1) )
void aucheck(User *user)
{
Strp *ump;
if (au_channel)
{
for(ump=user->chan;ump;ump=ump->next)
{
if (*ump->p == '*' || !Strcasecmp(au_channel,ump->p))
break;
}
if (!ump)
return;
}
for(ump=user->mask;ump;ump=ump->next)
{
if (!matches(ump->p,au_userhost))
{
if (au_access < user->x.x.access)
{
au_access = user->x.x.access;
au_user = user;
}
return;
}
}
}
User *get_authuser(char *userhost, char *channel)
{
User *user;
Auth *auth;
au_user = NULL;
au_userhost = userhost;
au_channel = channel;
au_access = 0;
/*
* people who are authenticated
*/
for(auth=current->authlist;auth;auth=auth->next)
{
if (au_access < auth->user->x.x.access)
{
if (!Strcasecmp(userhost,auth->nuh))
{
aucheck(auth->user);
}
}
}
if (current->setting[TOG_ENFPASS].int_var)
return(au_user);
/*
* people who dont need a password
*/
for(user=current->userlist;user;user=user->next)
{
if (!user->pass && (au_access < user->x.x.access))
{
aucheck(user);
}
}
return(au_user);
}
int get_authaccess(char *userhost, char *channel)
{
User *user;
Strp *ump;
if (userhost == CoreUser.name)
return(100);
if (CurrentDCC && CurrentDCC->user->name == userhost)
{
user = CurrentDCC->user;
if (!channel)
return(user->x.x.access);
for(ump=user->chan;ump;ump=ump->next)
{
if (*ump->p == '*' || !Strcasecmp(ump->p,channel))
return(user->x.x.access);
}
return(0);
}
if (is_bot(userhost))
return(BOTLEVEL);
get_authuser(userhost,channel);
return(au_access);
}
int make_auth(const char *userhost, const User *user)
{
Auth *auth;
Chan *chan;
ChanUser *cu;
for(auth=current->authlist;auth;auth=auth->next)
{
if ((auth->user == user) && !Strcasecmp(auth->nuh,userhost))
return(TRUE);
}
#ifdef DEBUG
debug("(make_auth) %s = %s\n",userhost,user->name);
#endif /* DEBUG */
/*
* there is no matching auth for this user, we add one
*/
set_mallocdoer(make_auth);
auth = (Auth*)Calloc(sizeof(Auth) + strlen(userhost));
auth->user = (User*)user;
auth->active = now;
Strcpy(auth->nuh,userhost);
auth->next = current->authlist;
current->authlist = auth;
for(chan=current->chanlist;chan;chan=chan->next)
{
if (!chan->bot_is_op)
continue;
if (!chan->setting[TOG_AOP].int_var)
continue;
if ((cu = find_chanuser(chan,userhost)) == NULL)
continue;
if (cu->user && cu->user->x.x.aop)
{
send_mode(chan,120,QM_CHANUSER,'+','o',(void*)cu);
}
}
return(FALSE);
}
/*
*
* authentication commands
*
*/
/*
* Usage: VERIFY <password>
*/
void do_auth(COMMAND_ARGS)
{
#ifdef BOTNET
char *checksum;
#endif /* BOTNET */
Strp *ump;
User *user;
char *pass;
int hostmatch;
if ((pass = chop(&rest)) == NULL)
return;
/*
* chop chop
*/
if (strlen(pass) > MAXPASSCHARS)
pass[MAXPASSCHARS] = 0;
hostmatch = FALSE;
/*
* find a matching password
*/
for(user=current->userlist;user;user=user->next)
{
for(ump=user->mask;ump;ump=ump->next)
{
if (!matches(ump->p,from))
{
if (user->pass && passmatch(pass,user->pass))
goto listcheck;
hostmatch = TRUE;
}
}
}
/*
* if there was a matching host, they get a message...
*/
if (hostmatch)
to_user(from,TEXT_PASS_INCORRECT);
return;
listcheck:
#ifdef BOTNET
checksum = "";
if (user->pass)
{
sprintf(gsockdata,"%s %s %s",from,user->name,user->pass);
checksum = makepass(gsockdata);
}
botnet_relay(NULL,"PA%s %s %s\n",user->name,from,checksum);
#endif /* BOTNET */
if (make_auth(from,user))
{
to_user(from,"You have already been authorized");
return;
}
to_user(from,"You are now officially immortal");
}

396
src/bounce.c Normal file
View File

@@ -0,0 +1,396 @@
/*
EnergyMech, IRC bot software
Copyright (c) 2001-2005 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 BOUNCE_C
#include "config.h"
#ifdef BOUNCE
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
#define INTERNAL_NICK "bounce"
#define INTERNAL_SOURCE ":bounce!bounce@bounce"
#define TEXT_ASK_HANDLE INTERNAL_SOURCE " PRIVMSG %s :" TEXT_ENTERNICKNAME "\n"
#define TEXT_ASK_PASSWORD INTERNAL_SOURCE " PRIVMSG %s :" TEXT_ENTERPASSWORD "\n"
#define TEXT_ASK_SERVER INTERNAL_SOURCE " PRIVMSG %s :Which server would you like to connect to?\n"
#define TEXT_USING_VHOST INTERNAL_SOURCE " PRIVMSG %s :Using virtual host %s\n"
#define TEXT_NOW_CONNECTING INTERNAL_SOURCE " PRIVMSG %s :Now connecting to %s:%i ...\n"
#define BNC_LOGIN 0
#define BNC_ASK_HANDLE 1
#define BNC_ASK_PASSWORD 2
#define BNC_ASK_SERVER 3
#define BNC_CONNECTING 4
#define BNC_ACTIVE 5
#define BNC_DEAD 6
#ifdef IDWRAP
#define USE_VHOST 2
#else /* not IDWRAP */
#define USE_VHOST TRUE
#endif /* IDWRAP */
void bounce_parse(ircLink *irc, char *message)
{
Mech fakebot;
User *user;
char *cmd,*server,*aport,*virtual;
int iport;
if (irc->status == BNC_LOGIN)
{
cmd = chop(&message);
if (!Strcasecmp(cmd,"USER"))
{
if (irc->userLine)
return;
set_mallocdoer(bounce_parse);
irc->userLine = Strdup(message);
}
else
if (!Strcasecmp(cmd,"NICK"))
{
if (irc->nickLine)
return;
set_mallocdoer(bounce_parse);
irc->nickLine = Strdup(message);
if ((cmd = chop(&message)) == NULL)
{
irc->status = BNC_DEAD;
return;
}
set_mallocdoer(bounce_parse);
irc->nick = Strdup(cmd);
}
if (irc->userLine && irc->nickLine)
{
to_file(irc->usersock,TEXT_ASK_HANDLE,irc->nick);
irc->active = now;
++irc->status;
}
return;
}
/* "PRIVMSG bounce :<handle>" */
/* "PRIVMSG bounce :<password>" */
/* "PRIVMSG bounce :<server> [port [virtual]]" */
server = chop(&message);
cmd = chop(&message);
if (!cmd || Strcasecmp(server,"PRIVMSG") || nickcmp(cmd,INTERNAL_NICK)
|| (*message != ':'))
{
irc->status = BNC_DEAD;
return;
}
message++;
if (irc->status == BNC_ASK_HANDLE)
{
for(current=botlist;current;current=current->next)
{
if ((user = find_handle(message)))
{
set_mallocdoer(bounce_parse);
irc->handle = Strdup(user->name);
break;
}
}
to_file(irc->usersock,TEXT_ASK_PASSWORD,irc->nick);
++irc->status;
/*
* dont bomb out even if the username is invalid
* guessing of valid usernames would be possible otherwise
*/
}
else
if (irc->status == BNC_ASK_PASSWORD)
{
irc->status = BNC_DEAD;
for(current=botlist;current;current=current->next)
{
if (irc->handle && (user = find_handle(irc->handle)))
{
if (user->x.x.bounce && user->pass
&& passmatch(message,user->pass))
{
to_file(irc->usersock,TEXT_ASK_SERVER,irc->nick);
irc->status = BNC_ASK_SERVER;
irc->active = now;
return;
}
}
}
}
else
if (irc->status == BNC_ASK_SERVER)
{
server = chop(&message);
aport = chop(&message);
virtual = chop(&message);
irc->status = BNC_DEAD;
if (!server)
return;
iport = 6667;
if (aport)
{
iport = a2i(aport);
if (errno || (iport < 1) || (iport > 65536))
return;
}
current = &fakebot;
current->vhost_type = 0;
current->setting[STR_VIRTUAL].str_var = virtual; /* may be NULL, is OK */
#ifdef WINGATE
current->setting[STR_WINGATE].str_var = NULL;
#endif /* WINGATE */
#ifdef IDWRAP
current->identfile = NULL;
current->setting[STR_IDENT].str_var = irc->handle;
#endif /* IDWRAP */
if (virtual)
{
to_file(irc->usersock,TEXT_USING_VHOST,irc->nick,virtual);
}
to_file(irc->usersock,TEXT_NOW_CONNECTING,irc->nick,server,iport);
if ((irc->servsock = SockConnect(server,iport,USE_VHOST)) >= 0)
{
irc->status = BNC_CONNECTING;
irc->active = now + 60; /* 120 second timeout */
#ifdef IDWRAP
irc->idfile = current->identfile;
#endif /* IDWRAP */
}
}
}
#ifdef IDWRAP
void bounce_cleanup(void)
{
ircLink *irc;
for(irc=bnclist;irc;irc=irc->next)
{
if (irc->idfile)
unlink(irc->idfile);
}
}
#endif /* IDWRAP */
void new_port_bounce(const struct Setting *no_op)
{
if (bounce_sock != -1)
close(bounce_sock);
bounce_sock = -1;
}
void select_bounce(void)
{
ircLink *irc;
if ((bounce_sock == -1) && (bounce_port > 0))
{
bounce_sock = SockListener(bounce_port);
#ifdef DEBUG
if (bounce_sock >= 0)
{
debug("(select_bounce) {%i} irc proxy socket is active (%i)\n",
bounce_sock,bounce_port);
}
#endif /* DEBUG */
}
if (bounce_sock != -1)
{
chkhigh(bounce_sock);
FD_SET(bounce_sock,&read_fds);
}
for(irc=bnclist;irc;irc=irc->next)
{
if (irc->servsock != -1)
{
chkhigh(irc->servsock);
if (irc->status == BNC_CONNECTING)
FD_SET(irc->servsock,&write_fds);
else
FD_SET(irc->servsock,&read_fds);
}
/*
* dont read data from client when connecting to server
*/
if (irc->status != BNC_CONNECTING)
{
chkhigh(irc->usersock);
FD_SET(irc->usersock,&read_fds);
}
}
}
void process_bounce(void)
{
char message[MSGLEN];
ircLink *irc,**pp;
char *p;
int s;
if ((bounce_sock != -1) && FD_ISSET(bounce_sock,&read_fds))
{
if ((s = SockAccept(bounce_sock)) >= 0)
{
set_mallocdoer(process_bounce);
irc = (ircLink*)Calloc(sizeof(ircLink)); /* sets all to zero */
irc->next = bnclist;
bnclist = irc;
irc->active = now;
irc->usersock = s;
--irc->servsock; /* == -1 */
}
}
for(irc=bnclist;irc;irc=irc->next)
{
/*
* client socket has data to read
*/
if (FD_ISSET(irc->usersock,&read_fds))
{
while((p = sockread(irc->usersock,irc->usermem,message)))
{
if (irc->status == BNC_ACTIVE)
{
if (to_file(irc->servsock,FMT_PLAINLINE,message) < 0)
/* fall into switch() with a valid errno */
break;
}
else
{
bounce_parse(irc,message);
}
}
switch(errno)
{
default:
irc->status = BNC_DEAD;
case EAGAIN:
case EINTR:
break;
}
}
if (irc->servsock < 0)
continue;
/*
* server socket just got connected
*/
if (FD_ISSET(irc->servsock,&write_fds))
{
#ifdef DEBUG
debug("(process_bounce) {%i} servsock connected\n",irc->servsock);
#endif /* DEBUG */
irc->status = BNC_ACTIVE;
irc->active = now;
to_file(irc->servsock,"USER %s\n",irc->userLine);
if (to_file(irc->servsock,"NICK %s\n",irc->nickLine) < 0)
{
/*
* write error of some kind, dump both client and server
*/
irc->status = BNC_DEAD;
}
Free((char**)&irc->userLine);
Free((char**)&irc->nickLine);
}
/*
* server socket has data to read
*/
if (FD_ISSET(irc->servsock,&read_fds))
{
irc->active = now;
while((p = sockread(irc->servsock,irc->servmem,message)))
{
if (to_file(irc->usersock,FMT_PLAINLINE,message) < 0)
/* fall into switch() with a valid errno */
break;
}
switch(errno)
{
default:
irc->status = BNC_DEAD;
case EAGAIN:
case EINTR:
break;
}
}
}
/*
* clean out dead and time outed sockets
*/
pp = &bnclist;
while((irc = *pp))
{
if (irc->status == BNC_DEAD || ((irc->status != BNC_ACTIVE) && ((now - irc->active) > 60)))
{
#ifdef DEBUG
debug("(process_bounce) {%i} {%i} BNC_DEAD or timeout, removing...\n",irc->usersock,irc->servsock);
#endif /* DEBUG */
*pp = irc->next;
if (irc->servsock >= 0)
close(irc->servsock);
if (irc->usersock >= 0)
close(irc->usersock);
Free((char**)&irc->userLine);
Free((char**)&irc->nickLine);
Free((char**)&irc->nick);
Free((char**)&irc->handle);
#ifdef IDWRAP
if (irc->idfile)
{
unlink(irc->idfile);
Free((char**)&irc->idfile);
}
#endif /* IDWRAP */
Free((char**)&irc);
continue;
}
pp = &irc->next;
}
}
#endif /* BOUNCE */

161
src/chanban.c Normal file
View File

@@ -0,0 +1,161 @@
/*
EnergyMech, IRC bot software
Copyright (c) 2009 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 CHANBAN_C
#include "config.h"
#ifdef CHANBAN
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
/*
if the chanban setting is on, make a whois for all that join #mychannel
if #bannedchannel is in their list of channels, kickban them with appropriate message
check people randomly, if their whois is old and sendq is empty, do a new whois on them
never kickban people on the same channel as the bot
TODO: never kickban authenticated people
*/
/*
* called from main doit() loop
* current is not set
*/
void process_chanbans(void)
{
Strp *sp,**pp;
Chan *anychan;
ChanUser *cu,*selcu;
for (current=botlist;current;current=current->next)
{
if (current->lastchanban > (now - 10))
{
#ifdef DEBUG
debug("(process_chanbans) skipping %s (%i), (lastchanban (%lu) > now - 10 (%lu)\n",
current->nick,current->guid,current->lastchanban,(now - 10));
#endif /* DEBUG */
continue;
}
if (current->sendq) // only do chanbans on empty queue
{
#ifdef DEBUG
debug("(process_chanbans) skipping %s (%i), sendq not empty\n",current->nick,current->guid);
#endif /* DEBUG */
continue;
}
selcu = NULL;
for(anychan=current->chanlist;anychan;anychan=anychan->next)
{
if (anychan->modelist || anychan->kicklist) // only do chanbans on empty queue
goto has_queue;
if (anychan->setting[TOG_CHANBAN].int_var && anychan->bot_is_op)
{
for(cu=anychan->users;cu;cu=cu->next)
{
if (cu->user)
{
if (!selcu || cu->lastwhois < selcu->lastwhois)
{
selcu = cu;
}
}
}
}
}
if (selcu && selcu->lastwhois < (now-30))
{
selcu->flags &= ~CU_CHANBAN;
selcu->lastwhois = now;
current->lastchanban = now;
pp = &current->sendq;
while(*pp)
pp = &(*pp)->next;
set_mallocdoer(process_chanbans);
*pp = sp = (Strp*)Calloc(sizeof(Strp) + 6 + strlen(selcu->nick));
sprintf(sp->p,"WHOIS %s",selcu->nick);
/* Calloc sets to zero sp->next = NULL; */
}
has_queue:
;
}
}
void chanban_action(char *nick, char *channel, Shit *shit)
{
ChanUser *cu;
char *nuh;
// the channel is shitted and the user is on it...
// 1, make sure the bot isnt on the channel
// 2, kb the user on all channels where the shit is active and i am op
// check all current channels
for(CurrentChan=current->chanlist;CurrentChan;CurrentChan=CurrentChan->next)
{
if (!Strcasecmp(channel,CurrentChan->name)) // if the bot is on the channel, skip it
{
#ifdef DEBUG
debug("(chanban_action) skipping %s: bot is on channel\n",channel);
#endif /* DEBUG */
return;
}
// is the shit for this channel?
if (!Strcasecmp(shit->chan,CurrentChan->name))
{
// if chanban is turned on && if bot is op (pretty pointless otherwise)
if (CurrentChan->setting[TOG_CHANBAN].int_var && CurrentChan->bot_is_op)
{
#ifdef DEBUG
debug("(chanban_action) %s: Tog is on, I am op\n",CurrentChan->name);
#endif /* DEBUG */
cu = find_chanuser(CurrentChan,nick);
if (!(cu->flags & CU_CHANBAN))
// dont kickban the same user multiple times from the same channel
{
nuh = get_nuh(cu); // clobbers nuh_buf
#ifdef DEBUG
debug("(chanban_action) slapping %s on %s for being on %s (mask %s): %s\n",
nick,CurrentChan->name,channel,shit->mask,shit->reason);
#endif /* DEBUG */
cu->flags |= CU_CHANBAN;
format_uh(nuh,1); // returns mask in 'nuh' buffer (nuh_buf)
send_mode(CurrentChan,90,QM_RAWMODE,'+','b',(void*)nuh);
send_kick(CurrentChan,nick,"%s (%s)",shit->reason,channel); // clobbers gsockdata
}
}
}
}
}
/*
*
* commands
*
*/
#endif /* CHANBAN */

1105
src/channel.c Normal file

File diff suppressed because it is too large Load Diff

552
src/config.h.in Normal file
View File

@@ -0,0 +1,552 @@
/*
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.
*/
#ifndef CONFIG_H
#define CONFIG_H
/*
* DEBUG: extreme amounts of debug code, needed if you want to use the -d commandline switch
*/
@DEF_DEBUG@
/*
* BOTNET: support for connecting bots to eachother in a botnet
*/
@DEF_BOTNET@
/*
* TELNET: connecting to the partyline via telnet
*/
@DEF_TELNET@
#define TELNET_TIMEOUT 60 /* 60 seconds to enter password */
/*
* ALIAS: create aliases for commands
*/
@DEF_ALIAS@
#define MAXALIASRECURSE 20
/*
* Support for SEEN command, undefined by default
* because it consumes a lardass amount of memory
*/
@DEF_SEEN@
/*
* sessions support (mech.session)
*/
@DEF_SESSION@
/*
* Support to alter commandlevels on the fly. undefine
* for static command levels (as defined in gencmd.c)
*/
@DEF_DYNCMD@
/*
* NEWBIE: support for some newbie spanking routines
*/
@DEF_NEWBIE@
/*
* WINGATE: support for proxy connections through wingates
*/
@DEF_WINGATE@
/*
* MD5CRYPT: support use of MD5 to hash passwords
*/
@DEF_MD5@
/*
* Standard CTCP replies (PING, FINGER, VERSION), and commands (CTCP, PING).
* DCC CHAT and the CHAT command still works even if this is undefined.
*/
@DEF_CTCP@
#define CTCP_SLOTS 6 /* how many slots we have to send out CTCP replies */
#define CTCP_TIMEOUT 60 /* how long before a used slot expires and can be used again */
/*
*
*/
@DEF_DCCFILE@
#define DCC_PUBLICFILES "public/"
#define DCC_PUBLICINCOMING DCC_PUBLICFILES "incoming/"
#define DCC_FILETIMEOUT 90
/*
* UPTIME: send uptime packets to uptime.energymech.net
*/
@DEF_UPTIME@
/*
* REDIRECT: send command output from certain commands to a different target
*/
@DEF_REDIRECT@
/*
* GREET: greet known users when they join a channel
*/
@DEF_GREET@
/*
* PERL: scripting using the perl language (may not be supported on all hosts)
*/
@DEF_PERL@
/*
* TCL: scripting using the TCL language (may not be supported on all hosts)
*/
@DEF_TCL@
/*
* PYTHON: scripting using the Python language (may not be supported on all hosts)
*/
@DEF_PYTHON@
/*
* DYNAMODE: dynamic updating of the +l channel user limit
*/
@DEF_DYNAMODE@
/*
* WEB: serving documents via HTTP
*/
@DEF_WEB@
/*
* NOTE: enable commands to leave notes for users to read at a later time
*/
@DEF_NOTE@
/*
* NOTIFY: notify list with filtering and online logging
*/
@DEF_NOTIFY@
/*
* IDWRAP: support for idwrap ident spoofing
*/
@DEF_IDWRAP@
#define IDWRAP_PATH @IDWRAP_PATH@
/*
* TRIVIA: support for playing trivia game
*/
@DEF_TRIVIA@
/*
* TOYBOX: various amusing commands
*/
@DEF_TOYBOX@
/*
* BOUNCE: support for `standalone' irc proxy
*/
@DEF_BOUNCE@
/*
* STATS: channel statistics
*/
@DEF_STATS@
/*
* RAWDNS: support for asynchronous hostname lookups
*/
@DEF_RAWDNS@
/*
* IRCD_EXTENSIONS: support some special features of new ircds
*/
@DEF_IRCD_EXT@
#ifdef IRCD_EXTENSIONS
@DEF_CHANBAN@
#else
#undef CHANBAN
#endif /* IRCD_EXTENSIONS */
/*
* FASTNICK: faster nick regain if the nick is seen when released
* Enables code that is potentially dangerous if an attacker aquires
* the nick that the bot wants
*/
#undef FASTNICK
/*
* NEWUSER_SPAM: notify new users when they are added.
* Spamming added users with their access levels, etc.
* (it only spams when a nick is specified for ADD)
*/
#define NEWUSER_SPAM
/*
* assume that sockets have default options
*/
#define ASSUME_SOCKOPTS
/*
* very dangerous features that allow execution of commands on the shell
* dont define this unless you know exactly what you're doing
*/
#undef PLEASE_HACK_MY_SHELL
/*
* define SCRIPTING if either PERL, TCL or PYTHON is enabled
*/
#if defined(PERL) || defined(TCL) || defined(PYTHON)
#define SCRIPTING
#endif
/*
*
*/
@DEF_CRYPT_FUNCTION@
@CRYPT_HAS_MD5@
@CRYPT_HAS_DES@
/*
* Easier to include ALL header files here and
* then include only *this* file elsewhere.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <termios.h>
#include <signal.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
/*
* stuff under here shouldnt be changed
* unless you really know what you're doing
*/
#define str_bold(x) "\002" x "\002"
#define str_underline(x) "\037" x "\037"
#define COMMENT_CHAR ';'
#define COMMENT_STRCHR ";"
#define BOTDIR ""
#define MECHBASENAME "mech"
#define RANDDIR "messages/"
#define HELPDIR "help/"
#define CFGFILE BOTDIR MECHBASENAME ".conf"
#define PIDFILE BOTDIR MECHBASENAME ".pid"
#define MSGFILE BOTDIR MECHBASENAME ".msg"
#define SESSIONFILE BOTDIR MECHBASENAME ".session"
#define TRIVIASCOREFILE BOTDIR MECHBASENAME ".trivscore"
#define AWAYFILE RANDDIR "away.txt"
#define NICKSFILE RANDDIR "nick.txt"
#define RANDKICKSFILE RANDDIR "kick.txt"
#define RANDTOPICSFILE RANDDIR "say.txt"
#define RANDSAYFILE RANDDIR "say.txt"
#define RANDINSULTFILE RANDDIR "insult.txt"
#define RANDPICKUPFILE RANDDIR "pickup.txt"
#define RAND8BALLFILE RANDDIR "8ball.txt"
#define SIGNOFFSFILE RANDDIR "signoff.txt"
#define VERSIONFILE RANDDIR "version.txt"
#define DEFAULT_IRC_PORT 6667
#define DEFAULTSHITLEVEL 2
#define DEFAULTSHITLENGTH 30 /* in days */
#define EXVERSION "EnergyMech 3"
#define EXFINGER EXVERSION
#define AWAYFORM "AWAY :%s (since %s)\n"
#define KILLSOCKTIMEOUT 30
#define WAITTIMEOUT 30
#define NICKFLOODTIME 120 /* 240 second window for floods ( 240 / 2 = 120 ) */
#define PINGSENDINTERVAL 210
#define RESETINTERVAL 90
#define SRSIZE 200
#define MRSIZE 200
#define DCC_INPUT_LIMIT 2000
#define DCC_INPUT_DECAY 200 /* 2000 (limit) / 200 (per second) = 10 seconds */
#define LINKTIME 120
#define AUTOLINK_DELAY 240 /* should be greater than link timeout ... */
#define REJOIN_DELAY 8 /* seconds between each channel joined */
#define NEEDOP_DELAY 10 /* seconds between each neeop request */
#define SEEN_TIME 14 /* how long in DAYS to keep track of a record? */
#define JOINLEVEL 70 /* affects invites */
#define ASSTLEVEL 80
#define OWNERLEVEL 100
#define BOTLEVEL 200
#define DEFAULT_KS_LEVEL 1
#define MAX_KS_LEVEL 3
#define MAXPROTLEVEL 4
#define SELFPROTLEVEL 1 /* protlevel for the bot itself */
#define PASSLEN 20
#define PASSBUF PASSLEN+1
#define NAMELEN 79
#define NAMEBUF NAMELEN+1
#define MINPASSCHARS 4
#define MAXPASSCHARS 50
#define MAXHOSTLEN 64
#define NUHLEN 128
#define MSGLEN 512
#define MAXLEN 800
#define LASTCMDSIZE 20
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define NEWFILEMODE 0644
#define SECUREFILEMODE 0600 /* files that might contain priviliged information
(eg, plaintext passwords in the debug log) */
/*
* Defines for commandlist parsing
*/
#define DCC 0x00100 /* requires DCC */
#define CC 0x00200 /* requires commandchar */
#define PASS 0x00400 /* requires password / authentication */
#define CARGS 0x00800 /* requires args */
#define NOPUB 0x01000 /* ignore in channel (for password commands) */
#define NOCMD 0x02000 /* not allowed to be executed thru CMD */
#define GAXS 0x04000 /* check global access */
#define CAXS 0x08000 /* check channel access */
#define REDIR 0x10000 /* may be redirected */
#define LBUF 0x20000 /* should be linebuffered to server */
#define CBANG 0x40000 /* command may be prefixed with a bang (!) */
#define ACCHAN 0x80000 /* needs an active channel */
#define CLEVEL 0x000ff
/*
* integer only version of RANDOM()
*/
#define RANDOM(min,max) (min + (rand() / (RAND_MAX / (max - min + 1))))
/* unaligned memory access */
@UNALIGNED_MEM@
/* 32bit machines */
@PTSIZE_DEFINE32@
/* 64bit machines */
@PTSIZE_DEFINE64@
/*
* How to make things non-portable:
*/
#ifdef PTSIZE_32BIT
#define mx_ptr unsigned int
#define mx_pfmt "%.8x"
#endif
#ifdef PTSIZE_64BIT
#define mx_ptr long long
#define mx_pfmt "%.16Lx"
#endif
/*
* String of compile-time options:
*/
#define OPT_COMMA ""
#define OPT_COREONLY 1
#ifdef MAIN_C
#ifdef LIBRARY
static
#endif
const char __mx_opts[] = ""
#ifdef ALIAS
OPT_COMMA "alias"
#undef OPT_COMMA
#define OPT_COMMA ", "
#undef OPT_COREONLY
#endif /* ALIAS */
#ifdef BOUNCE
OPT_COMMA "bounce"
#undef OPT_COMMA
#define OPT_COMMA ", "
#undef OPT_COREONLY
#endif /* BOUNCE */
#ifdef CHANBAN
OPT_COMMA "chanban"
#undef OPT_COMMA
#define OPT_COMMA ", "
#undef OPT_COREONLY
#endif /* CHANBAN */
#ifdef DEBUG
OPT_COMMA "debug"
#undef OPT_COMMA
#define OPT_COMMA ", "
#undef OPT_COREONLY
#endif /* DEBUG */
#ifdef DYNCMD
OPT_COMMA "dyn"
#undef OPT_COMMA
#define OPT_COMMA ", "
#undef OPT_COREONLY
#endif /* DYNCMD */
#ifdef MD5CRYPT
OPT_COMMA "md5"
#undef OPT_COMMA
#define OPT_COMMA ", "
#undef OPT_COREONLY
#endif /* MD5CRYPT */
#ifdef BOTNET
OPT_COMMA "net"
#undef OPT_COMMA
#define OPT_COMMA ", "
#undef OPT_COREONLY
#endif /* BOTNET */
#ifdef NEWBIE
OPT_COMMA "newbie"
#undef OPT_COMMA
#define OPT_COMMA ", "
#undef OPT_COREONLY
#endif /* NEWBIE */
#ifdef PYTHON
OPT_COMMA "python"
#undef OPT_COMMA
#define OPT_COMMA ", "
#undef OPT_COREONLY
#endif /* PYTHON */
#ifdef RAWDNS
OPT_COMMA "rawdns"
#undef OPT_COMMA
#define OPT_COMMA ", "
#undef OPT_COREONLY
#endif /* RAWDNS */
#ifdef SEEN
OPT_COMMA "seen"
#undef OPT_COMMA
#define OPT_COMMA ", "
#undef OPT_COREONLY
#endif /* SEEN */
#ifdef SESSION
OPT_COMMA "session"
#undef OPT_COMMA
#define OPT_COMMA ", "
#undef OPT_COREONLY
#endif /* SESSION */
#ifdef TCL
OPT_COMMA "tcl"
#undef OPT_COMMA
#define OPT_COMMA ", "
#undef OPT_COREONLY
#endif /* TCL */
#ifdef TELNET
OPT_COMMA "telnet"
#undef OPT_COMMA
#define OPT_COMMA ", "
#undef OPT_COREONLY
#endif /* TELNET */
#ifdef WINGATES
OPT_COMMA "wingate"
#undef OPT_COMMA
#define OPT_COMMA ", "
#undef OPT_COREONLY
#endif /* WINGATES */
#ifdef OPT_COREONLY
"(core only)"
#endif /* OPT_COREONLY */
;
/*
* end of the option ID string
*/
#else /* MAIN_C */
extern char __mx_opts[];
#endif /* MAIN_C */
#ifndef ulong
#define ulong unsigned long
#endif
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef INT_MAX
#define INT_MAX ((int)(((unsigned int)-3) >> 1))
#endif
#define TIME_MAX 2147483647
/*
* why are you looking here?
*/
#undef I_HAVE_A_LEGITIMATE_NEED_FOR_MORE_THAN_4_BOTS
#endif /* CONFIG_H */

1681
src/core.c Normal file

File diff suppressed because it is too large Load Diff

1041
src/ctcp.c Normal file

File diff suppressed because it is too large Load Diff

1337
src/debug.c Normal file

File diff suppressed because it is too large Load Diff

468
src/defines.h Normal file
View File

@@ -0,0 +1,468 @@
/*
EnergyMech, IRC bot software
Parts Copyright (c) 1997-2009 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.
*/
#ifndef DEFINES_H
#define DEFINES_H 1
/*
* dont export too many symbols...
*/
#ifdef LIBRARY
#define LS static
#else /* not LIBRARY */
#define LS /* nothing */
#endif /* LIBRARY */
/*
* Channel Crap
*/
#define CHAN_ANY 0
#define CHAN_ACTIVE 1
#define ANY_CHANNEL NULL
#define GLOBAL_CHANNEL MATCH_ALL
#define COLLECT_TYPE 1
#define REJOIN_TYPE 2
#define CYCLE_TYPE 4
#define ADD_MODE 1
#define SUB_MODE 2
#define MODE_FORCE 3
#define MODE_PRIVATE 0x0004
#define MODE_SECRET 0x0008
#define MODE_MODERATED 0x0010
#define MODE_TOPICLIMIT 0x0020
#define MODE_INVITEONLY 0x0040
#define MODE_NOPRIVMSGS 0x0080
#define MODE_KEY 0x0100
#define MODE_BAN 0x0200
#define MODE_LIMIT 0x0400
#define MODE_FLAGS 0x07ff
#define CU_VOICE 0x0001
#define CU_CHANOP 0x0002
#define CU_VOICETMP 0x0004
#define CU_NEEDOP 0x0008
#define CU_MODES 0x00ff
#define CU_DEOPPED 0x0100
#define CU_KICKED 0x0200
#define CU_BANNED 0x0400
#define CU_MASSTMP 0x0800
#define CU_KSWARN 0x1000
#define CU_CHANBAN 0x2000
#define SHIT_NOOP 0 // do nothing
#define SHIT_CHANOP 1 // not allowed to be chanop
#define SHIT_KB 2 // simple kick and ban
#define SHIT_PERMABAN 3 // permanent ban, re-ban if unbanned
#define SHIT_CHANBAN 4
#define MAXSHITLEVEL 4
#define MAXSHITLEVELSTRING "4"
#define MAXSHITLEVELCHAR '4'
/*
* channel modequeues
*/
#define QM_RAWMODE 0
#define QM_CHANUSER 1
#define QM_PRI_LOW 100
/*
* Bitfield for short_tv being set to 1 or 30 seconds
*/
#define TV_TELNET_NICK 0x0002
#define TV_UCACHE 0x0004
#define TV_SERVCONNECT 0x0008
#define TV_LINEBUF 0x0010
#define TV_BOTNET 0x0020
#define TV_REJOIN 0x0040
#define TV_TRIVIA 0x0080
/* Misc Crap: */
#define EXTRA_CHAR(q) q==1?"":"s"
#define SPLIT 1
/* Parse Stuff */
#define PA_END 1 /* b00000001 */ /* mask for `end' bit */
#define PA_WHOIS 2 /* b00000010 */
#define PA_LUSERS 4 /* b00000100 */
#define PA_STATS 8 /* b00001000 */
#define PA_USERHOST 16 /* b00010000 */
#define PA_DNS 32 /* b00100000 */ /* for resolving hosts */
#define PA_TYPE 62 /* b00111110 */ /* mask for type bits */
/* DCC Crap: */
#define DCC_SEND 0x0001
#define DCC_RECV 0x0002
#define DCC_WAIT 0x0010
#define DCC_ASYNC 0x0020
#define DCC_ACTIVE 0x0040
#define DCC_TELNET 0x0080
#define DCC_TELNETPASS 0x0100
#define DCC_DELETE 0x0200
/*
* format_uh()
*/
#define FUH_USERHOST 1
#define FUH_HOST 2
/* Type of Variable: */
#define INT_VAR 0x01
#define STR_VAR 0x02
#define TOG_VAR 0x04
#define GLOBAL_VAR 0x08
#define PROC_VAR 0x10
#define CHR_VAR (0x20 | INT_VAR)
#define ANY_VAR 0xff
#define INT_GLOBAL INT_VAR|GLOBAL_VAR
#define TOG_GLOBAL TOG_VAR|GLOBAL_VAR
#define TOG_PROC TOG_VAR|PROC_VAR|GLOBAL_VAR
#define INT_PROC INT_VAR|PROC_VAR|GLOBAL_VAR
#define STR_PROC STR_VAR|PROC_VAR|GLOBAL_VAR
#define CHR_PROC CHR_VAR|PROC_VAR|GLOBAL_VAR
#define STR_GLOBAL STR_VAR|GLOBAL_VAR
#define CHR_GLOBAL CHR_VAR|GLOBAL_VAR
#define IsInt(x) (VarName[x].type & INT_VAR)
#define IsStr(x) (VarName[x].type & STR_VAR)
#define IsTog(x) (VarName[x].type & TOG_VAR)
#define IsNum(x) (VarName[x].type & (INT_VAR|TOG_VAR))
#define IsChar(x) ((VarName[x].type & CHR_VAR) == CHR_VAR)
#define IsProc(x) (VarName[x].type & PROC_VAR)
/*
* see settings.h for the actual setting struct
*/
enum {
/*
* channel settings
*/
TOG_ABK,
TOG_AOP,
INT_AUB,
INT_AVOICE,
#ifdef CHANBAN
TOG_CHANBAN,
#endif /* CHANBAN */
INT_CKL,
TOG_CTL,
#ifdef DYNAMODE
STR_DYNLIMIT,
#endif /* DYNAMODE */
TOG_ENFM,
STR_ENFMODES,
INT_FL,
INT_FPL,
INT_IKT,
TOG_KS,
INT_MAL,
INT_MBL,
INT_MDL,
INT_MKL,
INT_MPL,
INT_NCL,
INT_PROT,
TOG_PUB,
TOG_RK,
TOG_SD,
TOG_SHIT,
TOG_SO,
#ifdef STATS
STR_STATS,
#endif /* STATS */
TOG_TOP,
/*
* global settings
* Note: first global setting (now: INT_AAWAY) is used below ...
*/
INT_AAWAY,
STR_ALTNICK,
#ifdef BOTNET
TOG_AUTOLINK,
#endif /* BOTNET */
#ifdef BOUNCE
INT_BNCPORT,
#endif /* BOUNCE */
TOG_CC,
CHR_CMDCHAR,
#ifdef CTCP
TOG_CTCP,
#endif /* CTCP */
INT_CTIMEOUT,
#ifdef DCC_FILE
INT_DCCANON,
STR_DCCFILES,
INT_DCCUSER,
#endif /* DCC_FILE */
TOG_ENFPASS,
STR_IDENT,
STR_IRCNAME,
#ifdef NOTIFY
INT_ISONDELAY,
#endif /* NOTIFY */
#ifdef BOTNET
STR_LINKPASS,
INT_LINKPORT,
#endif /* BOTNET */
INT_MODES,
#ifdef BOTNET
TOG_NETUSERS,
#endif /* BOTNET */
TOG_NOIDLE,
#ifdef NOTIFY
STR_NOTIFYFILE,
#endif /* NOTIFY */
TOG_ONOTICE,
#ifdef TRIVIA
CHR_QCHAR,
INT_QDELAY,
STR_QFILE,
#endif /* TRIVIA */
#ifdef CTCP
TOG_RF,
TOG_RV,
#endif /* CTCP */
#ifdef SEEN
STR_SEENFILE,
#endif /* SEEN */
STR_SERVERGROUP,
TOG_SPY,
STR_UMODES,
#ifdef UPTIME
STR_UPHOST,
STR_UPNICK,
INT_UPPORT,
#endif /* UPTIME */
STR_USERFILE,
STR_VIRTUAL,
#ifdef WEB
INT_WEBPORT,
#endif /* WEB */
#ifdef WINGATE
STR_WINGATE,
INT_WINGPORT,
#endif /* WINGATE */
__NULL_VAR__,
SIZE_VARS
};
/*
* why would channel structs contain global vars?
* they shouldnt! and now they dont! :)
*/
#define CHANSET_SIZE INT_AAWAY
/*
* For botlinks
*/
#ifdef BOTNET
/* BotNet->status */
#define BN_UNKNOWN 0
#define BN_DEAD 1
#define BN_LINKSOCK 2
#define BN_CONNECT 3
#define BN_BANNERSENT 4
#define BN_WAITAUTH 5
#define BN_WAITLINK 6
#define BN_LINKED 7
#define BNAUTH_PLAINTEXT 0
#define BNAUTH_DES 1
#define BNAUTH_MD5 2
#endif /* BOTNET */
/* for connect status */
#define CN_NOSOCK 0
#define CN_DNSLOOKUP 1
#define CN_TRYING 2
#define CN_CONNECTED 3
#define CN_ONLINE 4
#define CN_DISCONNECT 5
#define CN_BOTDIE 6
#define CN_NEXTSERV 7
#define CN_WINGATEWAIT 8
#define CN_SPINNING 9 /* after exhausting serverlist */
/* DCC Kill flags (BYE command) */
#define DCC_NULL 0
#define DCC_COMMAND 1
#define DCC_KILL 2
/* VHOST types */
#define VH_ZERO 0
#define VH_IPALIAS (1 << 1)
#define VH_IPALIAS_FAIL (1 << 2)
#define VH_IPALIAS_BOTH (VH_IPALIAS|VH_IPALIAS_FAIL)
#define VH_WINGATE (1 << 3)
#define VH_WINGATE_FAIL (1 << 4)
#define VH_WINGATE_BOTH (VH_WINGATE|VH_WINGATE_FAIL)
/* server error types */
#define SP_NULL 0
#define SP_NOAUTH 1
#define SP_KLINED 2
#define SP_FULLCLASS 3
#define SP_TIMEOUT 4
#define SP_ERRCONN 5
#define SP_DIFFPORT 6
#define SP_NO_DNS 7
#define SP_THROTTLED 8
/* find_channel() */
#define CH_ACTIVE 0x1
#define CH_OLD 0x2
#define CH_ANY 0x3
/* check_mass() */
#define CHK_CAPS 0
#define CHK_PUB 1
#define CHK_PUBLIC CHK_PUB
#define CHK_DEOP 2
#define CHK_BAN 3
#define CHK_KICK 4
/*
* seen selector types
*/
#define SEEN_PARTED 0
#define SEEN_QUIT 1
#define SEEN_NEWNICK 2
#define SEEN_KICKED 3
/*
* spying types, source and target types are mixed
*/
#define SPY_FILE 1
#define SPY_DCC 2
#define SPY_CHANNEL 3
#define SPY_STATUS 4
#define SPY_MESSAGE 5
#define SPY_RAWIRC 6
#define SPY_BOTNET 7
#define SPYF_ANY 1
#define SPYF_CHANNEL (1 << SPY_CHANNEL)
#define SPYF_STATUS (1 << SPY_STATUS)
#define SPYF_MESSAGE (1 << SPY_MESSAGE)
#define SPYF_RAWIRC (1 << SPY_RAWIRC)
#define SPYF_BOTNET (1 << SPY_BOTNET)
/*
* notify defines
*/
#define NF_OFFLINE 0
#define NF_WHOIS 1
#define NF_MASKONLINE 2 /* anything above NF_MASKONLINE is "online" */
#define NF_NOMATCH 3
/*
* uptime defines
*/
#define UPTIME_ENERGYMECH 1 /* http://www.energymech.net */
#define UPTIME_EGGDROP 2 /* http://www.eggheads.org */
#define UPTIME_MINIMECH 3 /* http://www.energymech.net */
#define UPTIME_WINMECH 4 /* http://www.energymech.net */
#define UPTIME_RACBOT 5 /* http://www.racbot.org */
#define UPTIME_MIRC 6 /* http://www.mirc.com */
#define UPTIME_HAL9000 7 /* http://www.2010.org */
#define UPTIME_ANABOT 8 /* http://www.sirklabs.hu/ana-liza/ */
#define UPTIME_ANGELBOT 9 /* unknown */
#define UPTIME_FIRECLAW 10 /* http://www.fireclaw.org */
#define UPTIME_GARNAX 11 /* http://garnax.mircx.com */
#define UPTIME_WINEGGDROP 12 /* http://www.eggheads.org */
#define UPTIME_SUPYBOT 14 /* http://supybot.sourceforge.net */
#define UPTIME_GENERICDEATH 5000 /* generic death */
#define UPTIME_SIGSEGV 5001
#define UPTIME_SIGBUS 5002
#define UPTIME_SIGTERM 5003
#define UPTIME_SIGINT 5004
#define UPTIMEHOST "uptime.energymech.net"
#ifdef __CYGWIN__
#define UPTIME_BOTTYPE UPTIME_WINMECH
#else
#define UPTIME_BOTTYPE UPTIME_ENERGYMECH
#endif /* __CYGWIN__ */
/*
* scripting hooks
*/
#define HOOK_PARSE 0
#define HOOK_TIMER 1
#define HOOK_COMMAND 2
#define HOOK_BOTNET 3
#define HOOK_DCC_COMPLETE 4
#define HOOK_DNS 5
/*
*
*/
#define IRCX_WALLCHOPS 1
#define IRCX_WALLVOICES 2
#define IRCX_IMODE 4
#define IRCX_EMODE 8
/*
* stats.c
*/
#define CSTAT_PARTIAL 1
/*
* dns.c
*/
#define MAX_NAMESERVERS 4
/*
* redirect.c
*/
#define R_NOTICE 0
#define R_PRIVMSG 1
#define R_FILE 2
#define R_BOTNET 3
#endif /* DEFINES_H */

939
src/dns.c Normal file
View File

@@ -0,0 +1,939 @@
/*
EnergyMech, IRC bot software
Copyright (c) 1997-2009 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 DNS_C
#include "config.h"
#ifdef RAWDNS
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
#define unpack_ushort(x) (((x)[0] << 8) | ((x)[1]))
#define unpack_ulong(x) (((x)[0] << 24) | ((x)[1] << 16) | ((x)[2] << 8) | ((x)[3]))
typedef struct dnsType
{
ushort type;
ushort class;
} dnsType;
typedef struct dnsRType
{
ushort type; /* &0 */
ushort class; /* &2 */
ulong ttl; /* &4 */
ushort rdlength; /* &8 */
} dnsRType;
#define DNS_QUERY 1
#define DNS_TYPE_A 1
#define DNS_CLASS_IN 1
#define DNS_TYPE_NS 2
#define DNS_TYPE_CNAME 5
#define QUERY_FLAGS 128
#define MAX_QUESTIONS 16
LS int dnssock = -1;
LS int dnsserver = 0;
#ifdef DEBUG
char *type_textlist[] =
{
NULL,
"A",
"NS",
"MD",
"MF",
"CNAME",
"SOA",
"MB",
"MG",
"MR",
"NULL",
"WKS",
"PTR",
"HINFO",
"MINFO",
"MX",
"TXT",
};
#endif /* DEBUG */
void init_rawdns(void)
{
struct sockaddr_in sai;
if ((dnssock = socket(AF_INET,SOCK_DGRAM,0)) < 0)
return;
memset(&sai,0,sizeof(sai));
sai.sin_addr.s_addr = INADDR_ANY;
sai.sin_family = AF_INET;
if (bind(dnssock,(struct sockaddr*)&sai,sizeof(sai)) < 0)
{
close(dnssock);
dnssock = -1;
return;
}
SockFlags(dnssock);
#ifdef DEBUG
debug("(init_rawdns) {%i} dnssock is active\n",dnssock);
#endif /* DEBUG */
}
struct in_addr dnsroot_lookup(const char *hostname)
{
dnsAuthority *da;
struct in_addr ip;
for(da=dnsroot;da;da=da->next)
{
if (!Strcasecmp(hostname,da->hostname))
{
#ifdef DEBUG
debug("(dnsroot_lookup) %s = %s\n",hostname,inet_ntoa(da->ip));
#endif /* DEBUG */
return(da->ip);
}
}
ip.s_addr = -1;
return(ip);
}
const char *get_dns_token(const char *src, const char *packet, char *dst, int sz)
{
const char *endsrc = NULL;
ushort offptr;
int tsz;
int dot = 0;
for(;;dot=1)
{
tsz = (uchar)*(src++);
if ((tsz & 0xC0) == 0xC0)
{
offptr = (tsz & 0x3f) << 8;
offptr |= *src;
if ((packet + offptr) > (packet + sz))
return(src+1);
if (!endsrc)
endsrc = src + 1;
src = packet + offptr;
tsz = *(src++);
}
if (tsz == 0)
break;
if (dot)
*(dst++) = '.';
while(tsz)
{
tsz--;
*(dst++) = *(src++);
}
}
*dst = 0;
return((endsrc) ? endsrc : src);
}
int make_query(char *packet, const char *hostname)
{
char *size,*dst;
/*
* make a packet
*/
packet[0] = rand() >> 24;
packet[1] = rand() >> 24;
packet[2] = 1; // RD, recursion desired flag
packet[3] = 0;
((ulong*)packet)[1] = htonl(0x10000);
((ulong*)packet)[2] = 0;
size = packet + 12;
dst = size + 1;
while(*hostname)
{
if ((*dst = *hostname) == '.')
{
*size = (dst - size - 1);
size = dst;
}
hostname++;
dst++;
}
*size = (dst - size - 1);
dst[0] = 0;
dst[1] = 0;
dst[2] = 1;
dst[3] = 0;
dst[4] = 1;
return(dst - packet + 5);
}
#ifndef UNALIGNED_MEM
struct in_addr temp_ip_data;
struct in_addr *get_stored_ip(const char *ipdata)
{
memcpy((char *)&temp_ip_data,ipdata,4);
return(&temp_ip_data);
}
#else
#define get_stored_ip(x) ((struct in_addr *)x)
#endif /* UNALIGNED_MEM */
/*
*
*/
#ifdef SCRIPTING
void dns_hook(char *host, char * resolved)
{
Hook *hook;
Mech *backbot;
backbot = current;
for(hook=hooklist;hook;hook=hook->next)
{
if (hook->flags == HOOK_DNS && !Strcasecmp(host,hook->type.host))
{
for(current=botlist;current;current=current->next)
{
if (hook->guid == 0 || hook->guid == current->guid)
{
hook->func(hook->type.host,resolved,hook);
}
}
}
}
current = backbot;
}
#endif /* SCRIPTING */
void parse_query(int psz, dnsQuery *query)
{
struct sockaddr_in sai;
char packet[512];
Mech *backupbot;
struct in_addr *ip;
dnsList *dns;
const char *src,*rtyp;
char token[64],token2[64];
int sz,n;
src = (const char*)query;
#ifdef DEBUG
for(n=0;n<16;n++)
token[n] = (ntohs(query->flags) & (1<<n)) ? '1' : '0';
token[16] = 0;
n = ntohs(query->flags);
debug("(parse_query) %i: flags = %i { %s %i %s%s%s%s%s }\n",
sz,n,token,
(n&15), // result code
(n&32768) ? "QR 1 (Answer) ":"QR 0 (Question) ",
(n&1024) ? "AA ":"",
(n&512) ? "TC ":"",
(n&256)? "RD ":"",
(n&128)? "RA ":"");
#endif /* DEBUG */
src += 12;
for(dns=dnslist;dns;dns=dns->next)
{
if (dns->id == ntohs(query->qid))
break;
}
if (!dns)
return;
n = ntohs(query->questions);
while(n--)
{
/* skip QNAME */
src = get_dns_token(src,(const char *)query,token,psz);
/* skip (ushort)QTYPE and (ushort)QCLASS */
src += 4;
}
n = ntohs(query->answers);
while(n)
{
src = get_dns_token(src,(const char*)query,token,psz);
rtyp = src;
src += 10;
#ifdef DEBUG
debug("(parse_query) %i: answer = %s\n",dns->id,token);
#endif /* DEBUG */
if ((unpack_ushort(&rtyp[0]) == DNS_TYPE_CNAME) &&
(unpack_ushort(&rtyp[2]) == DNS_CLASS_IN))
{
get_dns_token(src,(const char *)query,token2,psz);
#ifdef DEBUG
debug("(parse_query) %i: cname: %s = %s\n",dns->id,token,token2);
#endif /* DEBUG */
if (dns->cname)
Free((char**)&dns->cname);
dns->when = now + 30;
set_mallocdoer(parse_query);
dns->cname = Strdup(token2);
}
if ((unpack_ushort(&rtyp[0]) == DNS_TYPE_A) &&
(unpack_ushort(&rtyp[2]) == DNS_CLASS_IN) &&
(unpack_ushort(&rtyp[8]) == 4))
{
ip = get_stored_ip(src);
if (dns->auth && !Strcasecmp(dns->auth->hostname,token))
{
dns->auth->ip.s_addr = ip->s_addr;
dns->when = now + 60;
#ifdef DEBUG
debug("(parse_query) a auth: %s = %s\n",token,inet_ntoa(*ip));
#endif /* DEBUG */
}
else
if (!Strcasecmp(dns->host,token) || (dns->cname && !Strcasecmp(dns->cname,token)))
{
dns->ip.s_addr = ip->s_addr;
dns->when = now + 3600;
#ifdef DEBUG
debug("(parse_query) a: %s = %s\n",token,inet_ntoa(*ip));
#endif /* DEBUG */
/* a final dns anwer was received */
backupbot = current;
for(current=botlist;current;current=current->next)
{
send_pa(PA_DNS|PA_END,token,"Resolved: %s (%s)",token,inet_ntoa(*ip));
}
#ifdef SCRIPTING
dns_hook(token,inet_ntoa(*ip));
#endif /* SCRIPTING */
current = backupbot;
return;
}
}
src += unpack_ushort(&rtyp[8]);
n--;
}
n = ntohs(query->authorities);
sz = (n > 1) ? RANDOM(1,n) : 1;
#ifdef DEBUG
if (n)
debug("(parse_query) auth: select %i count %i\n",sz,n);
#endif /* DEBUG */
while(n)
{
src = get_dns_token(src,(const char*)query,token,psz);
rtyp = src;
src += 10;
if ((unpack_ushort(&rtyp[0]) == DNS_TYPE_NS) &&
(unpack_ushort(&rtyp[2]) == DNS_CLASS_IN))
{
dnsAuthority *da;
get_dns_token(src,(const char *)query,token2,psz);
if (sz == n)
{
if (dns->auth == NULL)
{
set_mallocdoer(parse_query);
da = dns->auth = (dnsAuthority*)Calloc(sizeof(dnsAuthority) + strlen(token2));
/* Calloc sets to zero da->ip.s_addr = 0; */
Strcpy(da->hostname,token2);
}
else
if (dns->findauth == 1)
{
dns->findauth = 2;
if (dns->auth2)
Free((char**)&dns->auth2);
set_mallocdoer(parse_query);
da = dns->auth2 = (dnsAuthority*)Calloc(sizeof(dnsAuthority) + strlen(token2));
/* Calloc sets to zero da->ip.s_addr = 0; */
Strcpy(da->hostname,token2);
#ifdef DEBUG
debug("(parse_query) 2nd auth set: %s\n",token2);
#endif /* DEBUG */
}
}
#ifdef DEBUG
debug("(parse_query) authorities: %s = %s%s\n",token,token2,(sz==n) ? MATCH_ALL : "");
#endif /* DEBUG */
}
#ifdef DEBUG
else
{
debug("(parse_query) DNS TYPE %s(%i), CLASS %i, size %i\n",
type_textlist[unpack_ushort(&rtyp[0])],unpack_ushort(&rtyp[0]),
unpack_ushort(&rtyp[2]),unpack_ushort(&rtyp[8]));
}
#endif /* DEBUG */
src += unpack_ushort(&rtyp[8]);
n--;
}
if (dns->findauth >= 1)
dns->findauth = 1;
n = ntohs(query->resources);
while(n)
{
src = get_dns_token(src,(const char*)query,token,psz);
rtyp = src;
src += 10;
if ( (unpack_ushort(&rtyp[0]) == DNS_TYPE_A) &&
(unpack_ushort(&rtyp[2]) == DNS_CLASS_IN) &&
(unpack_ushort(&rtyp[8]) == 4))
{
ip = get_stored_ip(src);
if (dns->auth && !Strcasecmp(dns->auth->hostname,token))
dns->auth->ip.s_addr = ip->s_addr;
if (dns->auth2 && !Strcasecmp(dns->auth2->hostname,token))
dns->auth2->ip.s_addr = ip->s_addr;
#ifdef DEBUG
debug("(parse_query) resources: %s = %s\n",token,inet_ntoa(*ip));
#endif /* DEBUG */
}
src += unpack_ushort(&rtyp[8]);
n--;
}
if (dns->auth && dns->auth->ip.s_addr == 0)
{
sai.sin_addr = dnsroot_lookup(dns->auth->hostname);
if (sai.sin_addr.s_addr != -1)
dns->auth->ip.s_addr = sai.sin_addr.s_addr;
}
if (dns->auth2 && dns->auth2->ip.s_addr == 0)
{
sai.sin_addr = dnsroot_lookup(dns->auth2->hostname);
if (sai.sin_addr.s_addr != -1)
dns->auth2->ip.s_addr = sai.sin_addr.s_addr;
}
if (dns->auth && dns->auth->ip.s_addr && dns->auth2)
{
Free((char**)&dns->auth2);
dns->findauth = 0;
}
#ifdef DEBUG
debug("> dns->when %lu\n",dns->when);
debug("> dns->ip %s\n",inet_ntoa(dns->ip));
debug("> dns->auth %s : %s (%i)\n",(dns->auth) ? dns->auth->hostname : NULLSTR,
(dns->auth) ? inet_ntoa(dns->auth->ip) : "-",(dns->auth) ? dns->auth->count : 0);
debug("> dns->auth2 %s : %s (%i)\n",(dns->auth2) ? dns->auth2->hostname : NULLSTR,
(dns->auth2) ? inet_ntoa(dns->auth2->ip) : "-",(dns->auth2) ? dns->auth2->count : 0);
debug("> dns->findauth %i\n",dns->findauth);
debug("> dns->id %i\n",dns->id);
debug("> dns->cname %s\n",nullstr(dns->cname));
debug("> dns->host %s\n",dns->host);
#endif /* DEBUG */
src = NULL;
if (dns->auth2)
{
if (dns->auth2->ip.s_addr && dns->auth)
{
src = dns->auth->hostname;
sai.sin_addr.s_addr = dns->auth2->ip.s_addr;
}
else
{
src = dns->auth2->hostname;
sai.sin_addr.s_addr = (ia_ns[dnsserver].s_addr == 0) ? ia_default.s_addr : ia_ns[dnsserver].s_addr;
if (++dns->auth->count >= MAX_QUESTIONS)
{
#ifdef DEBUG
debug("(parse_query) dns->auth->count >= 32, starting over\n");
#endif /* DEBUG */
/* too many questions about who the authorative dns server is, start from scratch */
Free((char**)&dns->auth);
Free((char**)&dns->auth2);
dns->findauth = 0;
src = (dns->cname) ? dns->cname : dns->host;
}
}
}
else
if (dns->auth)
{
if (dns->auth->ip.s_addr)
{
/*
* we know the IP of the authorative NS to ask
*/
src = (dns->cname) ? dns->cname : dns->host;
sai.sin_addr.s_addr = dns->auth->ip.s_addr;
}
else
{
/*
* have to dig up the IP of the NS to ask
*/
dns->findauth = 1;
src = dns->auth->hostname;
sai.sin_addr.s_addr = (ia_ns[dnsserver].s_addr == 0) ? ia_default.s_addr : ia_ns[dnsserver].s_addr;
if (++dns->auth->count >= MAX_QUESTIONS)
{
#ifdef DEBUG
debug("(parse_query) dns->auth->count >= 32, starting over\n");
#endif /* DEBUG */
/* too many questions about who the authorative dns server is, start from scratch */
Free((char**)&dns->auth);
Free((char**)&dns->auth2);
dns->findauth = 0;
src = (dns->cname) ? dns->cname : dns->host;
}
}
}
if (src)
{
dns->id = rand();
#ifdef DEBUG
debug("(parse_query) %i: asking %s who is `%s'\n",dns->id,inet_ntoa(sai.sin_addr),src);
#endif /* DEBUG */
sz = make_query(packet,src);
dns->when = now + 60;
sai.sin_family = AF_INET;
sai.sin_port = htons(53);
((dnsQuery*)packet)->qid = htons(dns->id);
if (sendto(dnssock,packet,sz,0,(struct sockaddr*)&sai,sizeof(sai)) < 0)
{
close(dnssock);
dnssock = -1;
}
}
if (dns->auth && dns->auth->ip.s_addr)
Free((char**)&dns->auth);
if (dns->auth2 && dns->auth2->ip.s_addr)
Free((char**)&dns->auth2);
if (src == NULL && dns->ip.s_addr == 0 && dns->cname && dns->host && dns->auth == NULL && dns->auth2 == NULL)
{
dns->id = rand();
sai.sin_addr.s_addr = (ia_ns[dnsserver].s_addr == 0) ? ia_default.s_addr : ia_ns[dnsserver].s_addr;
#ifdef DEBUG
debug("(parse_query) %i: asking %s who is `%s' (CNAME question)\n",dns->id,inet_ntoa(sai.sin_addr),dns->cname);
#endif /* DEBUG */
sz = make_query(packet,dns->cname);
dns->when = now + 60;
sai.sin_family = AF_INET;
sai.sin_port = htons(53);
((dnsQuery*)packet)->qid = htons(dns->id);
if (sendto(dnssock,packet,sz,0,(struct sockaddr*)&sai,sizeof(sai)) < 0)
{
close(dnssock);
dnssock = -1;
}
}
}
void rawdns(const char *hostname)
{
struct sockaddr_in sai;
dnsQuery *query;
dnsList *item;
char packet[512];
int sz;
if (dnssock == -1)
init_rawdns();
if (dnssock == -1)
return;
sz = make_query(packet,hostname);
query = (dnsQuery*)packet;
set_mallocdoer(rawdns);
item = (dnsList*)Calloc(sizeof(dnsList) + strlen(hostname));
Strcpy(item->host,hostname);
item->id = ntohs(query->qid);
item->when = now + 30;
item->next = dnslist;
dnslist = item;
/*
* send the packet
*/
sai.sin_family = AF_INET;
sai.sin_port = htons(53);
sai.sin_addr.s_addr = (ia_ns[dnsserver].s_addr == 0) ? ia_default.s_addr : ia_ns[dnsserver].s_addr;
#ifdef DEBUG
debug("(rawdns) questions %s: %s\n",inet_ntoa(sai.sin_addr),item->host);
#endif /* DEBUG */
dnsserver++;
if (ia_ns[dnsserver].s_addr == 0)
dnsserver = 0;
if (sendto(dnssock,packet,sz,0,(struct sockaddr*)&sai,sizeof(sai)) < 0)
{
close(dnssock);
dnssock = -1;
}
}
void select_rawdns(void)
{
dnsList *dns,**pdns;
if (dnssock != -1)
{
chkhigh(dnssock);
FD_SET(dnssock,&read_fds);
}
restart:
pdns = &dnslist;
while(*pdns)
{
if ((*pdns)->when < now)
{
dns = *pdns;
if (dns->cname)
Free((char**)&dns->cname);
if (dns->auth)
Free((char**)&dns->auth);
if (dns->auth2)
Free((char**)&dns->auth2);
#ifdef DEBUG
debug("(select_rawdns) removing %s qid %i\n",dns->host,dns->id);
#endif /* DEBUG */
for(current=botlist;current;current=current->next)
{
send_pa(PA_DNS|PA_END,dns->host,"Unable to resolve %s",dns->host);
}
#ifdef SCRIPTING
dns_hook(dns->host,"~");
#endif /* SCRIPTING */
*pdns = dns->next;
Free((char**)&dns);
goto restart;
}
pdns = &(*pdns)->next;
}
}
void process_rawdns(void)
{
struct sockaddr_in sai;
char packet[512];
int sz,n;
if (dnssock == -1)
return;
if (FD_ISSET(dnssock,&read_fds))
{
sz = sizeof(sai);
n = recvfrom(dnssock,packet,512,0,(struct sockaddr*)&sai,&sz);
if (n < sizeof(dnsQuery))
return;
#ifdef DEBUG
debug("(process_rawdns) packet from: %s (%i bytes)\n",inet_ntoa(sai.sin_addr),n);
#endif /* DEBUG */
parse_query(n,(dnsQuery*)packet);
}
}
char *poll_rawdns(char *hostname)
{
dnsList *dns;
for(dns=dnslist;dns;dns=dns->next)
{
if (dns->ip.s_addr && !Strcasecmp(dns->host,hostname))
{
#ifdef DEBUG
debug("(poll_rawdns) a: %s ==> %s\n",hostname,inet_ntoa(dns->ip));
#endif /* DEBUG */
return(inet_ntoa(dns->ip));
}
}
return(NULL);
}
LS int backup_debug;
int read_dnsroot(char *line)
{
struct in_addr ia;
dnsAuthority *da;
char *name,*a,*ip,*src;
name = chop(&line);
a = chop(&line); /* TTL is optional */
if (a && Strcmp(a,"A"))
a = chop(&line);
ip = chop(&line);
if (a && !Strcmp(a,"A") && ip && inet_aton(ip,&ia) != 0)
{
/* remove trailing dot */
for(src=name;*src;)
{
if (*src == '.' && *(src+1) == 0)
*src = 0;
else
src++;
}
set_mallocdoer(read_dnsroot);
da = (dnsAuthority*)Calloc(sizeof(dnsAuthority) + strlen(name));
Strcpy(da->hostname,name);
da->ip.s_addr = ia.s_addr;
da->next = dnsroot;
dnsroot = da;
#ifdef DEBUG
dodebug = backup_debug;
debug("(read_dnsroot) stored root IP: %s = %s\n",name,ip);
dodebug = 0;
#endif /* DEBUG */
}
return(FALSE);
}
/*
* find the IP quickly
*/
ulong rawdns_get_ip(const char *host)
{
ulong ip;
if ((ip = inet_addr(host)) == INADDR_NONE)
{
}
#ifdef DEBUG
debug("(rawdns_get_ip) %s -> %s\n",host,inet_ntoa(*((struct in_addr*)&ip)));
#endif /* DEBUG */
return(ip);
}
/*
*
* commands related to DNS
*
*/
void do_dnsroot(COMMAND_ARGS)
{
int in;
if ((in = open(rest,O_RDONLY)) >= 0)
{
#ifdef SESSION
Strp *p;
p = (Strp*)Calloc(strlen(rest)+1);
p->next = dnsrootfiles;
Strcpy(p->p,rest);
dnsrootfiles = p;
#endif /* SESSION */
#ifdef DEBUG
backup_debug = dodebug;
dodebug = 0;
#endif /* DEBUG*/
readline(in,&read_dnsroot); /* readline closes in */
#ifdef DEBUG
dodebug = backup_debug;
#endif /* DEBUG */
}
}
void do_dnsserver(COMMAND_ARGS)
{
/*
* on_msg checks: GAXS
*/
struct in_addr ia;
char *p,c,tempservers[MAX_NAMESERVERS*16+3];
/* (xxx.yyy.zzz.www + 1 space * MAX_NAMESERVERS) + 1 terminator char + 2 chars bold font */
int i;
if (!*rest)
{
*(p = tempservers) = 0;
for(i=0;i<MAX_NAMESERVERS;i++)
{
if (ia_ns[i].s_addr > 0)
{
if (i == dnsserver)
{
sprintf(p,"\037%s\037 ",inet_ntoa(ia_ns[i]));
p = STREND(p);
}
else
{
p = Strcpy(p,inet_ntoa(ia_ns[i]));
*(p++) = ' ';
*p = 0;
}
}
}
if (*tempservers == 0)
Strcpy(tempservers,"\037127.0.0.1\037");
to_user(from,"Current DNS Servers: %s",tempservers);
return;
}
c = *(rest++);
if ((ia.s_addr = inet_addr(rest)) == INADDR_NONE)
c = 0;
switch(c)
{
case '+':
for(i=0;i<MAX_NAMESERVERS;i++)
{
if (ia_ns[i].s_addr == 0)
{
ia_ns[i].s_addr = ia.s_addr;
to_user(from,"DNS Server added: %s",rest);
return;
}
}
to_user(from,"No free DNS Server slots found, remove one before adding new servers");
return;
case '-':
for(i=0;i<MAX_NAMESERVERS;i++)
{
if (ia_ns[i].s_addr == ia.s_addr || ia.s_addr == 0)
{
ia_ns[i].s_addr = 0;
}
}
for(i=1;i<MAX_NAMESERVERS;i++)
{
if (ia_ns[i-1].s_addr == 0)
{
ia_ns[i-1].s_addr = ia_ns[i].s_addr;
ia_ns[i].s_addr = 0;
}
}
dnsserver = 0;
if (ia.s_addr > 0)
to_user(from,"DNS Server removed: %s",rest);
else
to_user(from,"All known DNS Servers removed.");
return;
default:
usage(from);
}
}
/*
* resolve the dns of a user/host
* usage: DNS <nick|host>
*/
void do_dns(COMMAND_ARGS)
{
/*
* on_msg checks: CARGS and GAXS
*/
char *host,*res,*src,*dst,*dot;
ulong ip;
/* to date, all hostnames contain atleast one dot */
if ((STRCHR(rest,'.')))
{
host = rest;
}
else
{
/* no dots, try to find it as a nick */
/* searches all channels and nicks, clobbers get_nuh */
if ((host = find_nuh(rest)) == NULL)
{
to_user(from,"Unable to resolve %s: unknown nick/host",rest);
return;
}
while(*host && *host != '@')
host++;
if (*host == '@')
host++;
#ifdef DEBUG
debug("(do_dns) %s is on host %s\n",rest,host);
#endif /* DEBUG */
}
if ((ip = inet_addr(host)) != INADDR_NONE)
{
/* flip an IP backwards to resolve hostname */
// a11.b22.c33.d44
// d44.c33.b22.a11.in-addr.arpa
dst = gsockdata;
flipstep:
src = host;
dot = NULL;
while(*src)
{
if (*src == '.')
dot = src;
src++;
}
if (dot)
{
*dot++ = 0; // safe to modify buffer?
while(*dot)
*dst++ = *dot++;
*dst++ = '.';
goto flipstep;
}
Strcpy(Strcpy(dst,host),".in-addr.arpa");
#ifdef DEBUG
debug("(do_dns) host flipped to %s\n",gsockdata);
#endif /* DEBUG */
host = gsockdata;
}
/* check if its in cache now */
if ((res = poll_rawdns(host)))
{
//Resolved: irc.dal.net (194.68.45.50)
send_pa(PA_DNS|PA_END,NULL,"Resolved: %s (%s)",host,res);
return;
}
make_ireq(PA_DNS,from,host);
rawdns(host);
}
#endif /* RAWDNS */

88
src/dynamode.c Normal file
View File

@@ -0,0 +1,88 @@
/*
EnergyMech, IRC bot software
Copyright (c) 2001-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 DYNAMODE_C
#include "config.h"
#ifdef DYNAMODE
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
void check_dynamode(Chan *chan)
{
ChanUser *cu;
char tempconf[strlen(chan->setting[STR_DYNLIMIT].str_var)+2];
char ascnum[11];
char *src,*num,*end;
int n = 0,wind,v[3];
/*
* parse `delay:window:minwin'
*/
end = Strcpy(tempconf,chan->setting[STR_DYNLIMIT].str_var);
num = src = tempconf;
for(;(src<=end) && (n<3);src++)
{
if (*src == 0 || *src == ':')
{
*src = 0;
v[n] = a2i(num);
if (errno)
{
v[0] = 90; /* delay */
v[1] = 10; /* window */
v[2] = 4; /* minwin */
break;
}
num = src+1;
n++;
}
}
v[0] = (v[0] < 20) ? 20 : (v[0] > 600) ? 600 : v[0];
if ((now - chan->lastlimit) < v[0])
return;
v[1] = (v[1] < 5) ? 5 : (v[1] > 50) ? 50 : v[1];
v[2] = (v[2] < 1) ? 1 : (v[2] > 50) ? 50 : v[2];
chan->lastlimit = now;
n = 0;
for(cu=chan->users;cu;cu=cu->next)
n++;
wind = n / v[1];
if (wind < v[2])
wind = v[2];
wind += n;
n = wind - chan->limit;
if (!chan->limitmode || (n < -2) || (n > 1))
{
sprintf(ascnum,"%i",wind);
send_mode(chan,160,QM_RAWMODE,'+','l',ascnum);
}
}
#endif /* DYNAMODE */

1096
src/function.c Normal file

File diff suppressed because it is too large Load Diff

433
src/gencmd.c Normal file
View File

@@ -0,0 +1,433 @@
/*
EnergyMech, IRC bot software
Copyright (c) 1997-2009 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 GENCMD_C
#include "config.h"
#include "structs.h"
/*
These are defined in config.h
DCC 0x00100 requires DCC
CC 0x00200 requires commandchar
PASS 0x00400 requires password / authentication
CARGS 0x00800 requires args
NOPUB 0x01000 ignore in channel (for password commands)
NOCMD 0x02000 not allowed to be executed thru CMD
GAXS 0x04000 check global access
CAXS 0x08000 check channel access
REDIR 0x10000 may be redirected
LBUF 0x20000 can be linebuffered to server
CBANG 0x40000 command may be prefixed with a bang (!)
ACCHAN 0x80000 needs an active channel
CLEVEL 0x000ff
*/
#define CCPW CC|PASS
struct
{
int pass;
char *name;
char *func;
ulong flags;
char *cmdarg;
} pre_mcmd[] =
{
/*
* public access commands
*/
{ 0, "VERIFY", "do_auth", 0 | NOPUB },
#ifdef TOYBOX
{ 0, "8BALL", "do_8ball", 0 | CBANG },
#endif /* TOYBOX */
/*
* Level 10
*/
{ 0, "ACCESS", "do_access", 10 | CCPW },
{ 0, "BYE", "do_bye", 10 | CC },
{ 0, "CHAT", "do_chat", 10 | CCPW | NOCMD },
#ifdef RAWDNS
{ 0, "DNS", "do_dns", 10 | CCPW | GAXS | CARGS },
#endif /* RAWDNS */
{ 0, "DOWN", "do_opdeopme", 10 | CC | CAXS },
{ 0, "ECHO", "do_echo", 10 | CCPW | CARGS },
{ 0, "HELP", "do_help", 10 | CCPW | REDIR | LBUF },
{ 0, "PASSWD", "do_passwd", 10 | PASS | NOPUB | CARGS },
#ifdef DCC_FILE
{ 0, "SEND", "do_send", 10 | CC | NOCMD | CBANG | CARGS },
#endif /* DCC_FILE */
{ 0, "USAGE", "do_usage", 10 | CCPW | REDIR | CARGS },
/*
* Level 20
*/
{ 0, "ONTIME", "do_upontime", 20 | CCPW , "Ontime: %s" },
{ 0, "UPTIME", "do_upontime", 20 | CCPW , "Uptime: %s" },
{ 0, "VER", "do_version", 20 | CCPW },
{ 0, "WHOM", "do_whom", 20 | CCPW | REDIR | LBUF },
#ifdef SEEN
{ 0, "SEEN", "do_seen", 20 | CCPW | CBANG },
#endif /* SEEN */
/*
* Level 40
*/
{ 0, "BAN", "do_kickban", 40 | CCPW | CAXS | CARGS | ACCHAN , "\\x00ban\\0bann" },
{ 0, "BANLIST", "do_banlist", 40 | CCPW | CAXS | DCC | REDIR | LBUF | ACCHAN },
{ 0, "CCHAN", "do_cchan", 40 | CCPW }, /* global_access ? */
{ 0, "CSERV", "do_cserv", 40 | CCPW },
{ 0, "CHANNELS", "do_channels", 40 | CCPW | DCC },
{ 0, "DEOP", "do_opvoice", 40 | CCPW | CAXS | CARGS , "o-" },
{ 0, "ESAY", "do_esay", 40 | CCPW | CAXS | CARGS },
{ 0, "IDLE", "do_idle", 40 | CCPW | CARGS },
{ 0, "INVITE", "do_invite", 40 | CCPW | CAXS | ACCHAN },
{ 0, "KB", "do_kickban", 40 | CCPW | CAXS | CARGS | ACCHAN , "\\x04kickban\\0kickbann" },
{ 0, "KICK", "do_kickban", 40 | CCPW | CAXS | CARGS | ACCHAN , "\\x07kick\\0kick" },
{ 0, "LUSERS", "do_irclusers", 40 | CCPW | DCC | REDIR | LBUF },
{ 0, "ME", "do_sayme", 40 | CCPW | CARGS },
{ 0, "MODE", "do_mode", 40 | CCPW | CARGS },
{ 0, "NAMES", "do_names", 40 | CCPW },
{ 0, "OP", "do_opvoice", 40 | CCPW | CAXS , "o+" },
{ 0, "SAY", "do_sayme", 40 | CCPW | CARGS },
{ 0, "SCREW", "do_kickban", 40 | CCPW | CAXS | CARGS | ACCHAN , "\\x02screwban\\0screwbann" },
{ 0, "SET", "do_set", 40 | CCPW },
{ 0, "SITEBAN", "do_kickban", 40 | CCPW | CAXS | CARGS | ACCHAN , "\\x01siteban\\0sitebann" },
{ 0, "SITEKB", "do_kickban", 40 | CCPW | CAXS | CARGS | ACCHAN , "\\x05sitekickban\\0sitekickbann" },
{ 0, "TIME", "do_time", 40 | CCPW },
{ 0, "TOPIC", "do_topic", 40 | CCPW | CAXS | CARGS | ACCHAN },
{ 0, "UNBAN", "do_unban", 40 | CCPW | CAXS },
{ 0, "UNVOICE", "do_opvoice", 40 | CCPW | CAXS | CARGS , "v-" },
{ 0, "UP", "do_opdeopme", 40 | CCPW | CAXS },
{ 0, "USER", "do_user", 40 | CCPW | CARGS },
{ 0, "USERHOST", "do_ircwhois", 40 | CCPW | CARGS },
{ 0, "VOICE", "do_opvoice", 40 | CCPW | CAXS , "v+" },
{ 0, "WALL", "do_wall", 40 | CCPW | CAXS | CARGS | ACCHAN },
{ 0, "WHO", "do_showusers", 40 | CCPW | CAXS | DCC },
{ 0, "WHOIS", "do_ircwhois", 40 | CCPW | CARGS | DCC | REDIR | LBUF },
#ifdef NOTE
{ 0, "NOTE", "do_note", 40 | CCPW | CARGS },
{ 0, "READ", "do_read", 40 | CCPW },
#endif /* NOTE */
#ifdef STATS
{ 0, "INFO", "do_info", 40 | CCPW | CAXS | DCC },
#endif /* STATS */
/*
* Level 50
*/
{ 0, "QSHIT", "do_shit", 50 | CCPW | CARGS },
{ 0, "RSHIT", "do_rshit", 50 | CCPW | CARGS },
{ 0, "SHIT", "do_shit", 50 | CCPW | CARGS },
{ 0, "SHITLIST", "do_shitlist", 50 | CCPW | DCC | REDIR | LBUF },
#ifdef GREET
{ 0, "GREET", "do_greet", 50 | CCPW | CARGS },
#endif /* GREET */
#ifdef TOYBOX
{ 0, "INSULT", "do_random_msg", 50 | CCPW , RANDINSULTFILE },
{ 0, "PICKUP", "do_random_msg", 50 | CCPW , RANDPICKUPFILE },
{ 0, "RSAY", "do_random_msg", 50 | CCPW , RANDSAYFILE },
{ 0, "RT", "do_randtopic", 50 | CCPW | CAXS | ACCHAN },
#endif /* TOYBOX */
#ifdef TRIVIA
{ 0, "TRIVIA", "do_trivia", 50 | CCPW | CAXS | CARGS | CBANG },
#endif /* TRIVIA */
/*
* Level 60
*/
{ 0, "SHOWIDLE", "do_showidle", 60 | CCPW | CAXS | DCC | ACCHAN },
{ 0, "USERLIST", "do_userlist", 60 | CCPW | DCC },
#ifdef CTCP
{ 0, "CTCP", "do_ping_ctcp", 60 | CCPW | CARGS },
{ 0, "PING", "do_ping_ctcp", 60 | CCPW | CARGS },
#endif /* CTCP */
/*
* Level 70 == JOINLEVEL
*/
{ 0, "CYCLE", "do_cycle", 70 | CCPW | CAXS | ACCHAN },
{ 0, "FORGET", "do_forget", 70 | CCPW | CARGS },
{ 0, "JOIN", "do_join", 70 | CCPW | CARGS },
{ 0, "KS", "do_kicksay", 70 | CCPW | REDIR | LBUF },
{ 0, "PART", "do_part", 70 | CCPW | CAXS | ACCHAN },
{ 0, "RKS", "do_rkicksay", 70 | CCPW | CARGS },
{ 0, "SETPASS", "do_setpass", 70 | CCPW | NOPUB | CARGS },
#ifdef NOTIFY
{ 0, "NOTIFY", "do_notify", 70 | CCPW | DCC | GAXS | REDIR | LBUF },
#endif /* NOTIFY */
/*
* Level 80 == ASSTLEVEL
*/
{ 0, "AWAY", "do_away", 80 | CCPW | GAXS },
#if defined(BOTNET) && defined(REDIRECT)
{ 0, "CMD", "do_cmd", 80 | CCPW | CARGS },
#endif /* BOTNET && REDIRECT */
{ 0, "LAST", "do_last", 80 | CCPW | DCC },
{ 0, "LOAD", "do_load", 80 | CCPW | GAXS },
{ 0, "MSG", "do_msg", 80 | CCPW | CARGS },
{ 0, "NEXTSERVER", "do_server", 80 | CCPW | GAXS },
{ 0, "SAVE", "do_save", 80 | CCPW | GAXS },
{ 0, "SERVER", "do_server", 80 | CCPW | GAXS | REDIR | LBUF },
{ 0, "SERVERGROUP", "do_servergroup", 80 | CCPW | GAXS | REDIR | LBUF },
{ 0, "STATS", "do_ircstats", 80 | CCPW | DCC | CARGS },
#ifdef ALIAS
{ 0, "ALIAS", "do_alias", 80 | CCPW | GAXS },
{ 0, "UNALIAS", "do_unalias", 80 | CCPW | GAXS | CARGS },
#endif /* ALIAS */
#ifdef TOYBOX
{ 0, "BIGSAY", "do_bigsay", 80 | CCPW | CAXS | CARGS },
#endif /* TOYBOX */
/*
* Level 90
*/
{ 0, "CLEARSHIT", "do_clearshit", 90 | CCPW | GAXS },
{ 0, "DO", "do_do", 90 | CCPW | GAXS | CARGS },
{ 0, "NICK", "do_nick", 90 | CCPW | GAXS | CARGS },
{ 0, "RSPY", "do_rspy", 90 | CCPW | CARGS },
{ 0, "SPY", "do_spy", 90 | CCPW },
#ifdef BOTNET
{ 0, "LINK", "do_link", 90 | CCPW | GAXS },
#endif /* BOTNET */
#ifdef DYNCMD
{ 0, "CHACCESS", "do_chaccess", 90 | CCPW | GAXS | CARGS },
#endif /* DYNCMD */
#ifdef UPTIME
{ 0, "UPSEND", "do_upsend", 90 | CCPW | GAXS },
#endif /* UPTIME */
/*
* Level 100
*/
#ifdef RAWDNS
{ 0, "DNSSERVER", "do_dnsserver", 100 | CCPW | GAXS },
{ 0, "DNSROOT", "do_dnsroot", 100 | CCPW | GAXS | CARGS },
#endif /* RAWDNS */
{ 0, "CORE", "do_core", 100 | CCPW | DCC },
{ 0, "DIE", "do_die", 100 | CCPW | GAXS },
{ 0, "RESET", "do_reset", 100 | CCPW | GAXS | NOCMD },
{ 0, "SHUTDOWN", "do_shutdown", 100 | CCPW | GAXS | NOPUB | NOCMD },
#ifdef DEBUG
{ 0, "DEBUG", "do_debug", 100 | CCPW | GAXS },
#endif /* DEBUG */
#ifdef PYTHON
#ifdef PLEASE_HACK_MY_SHELL
{ 0, "PYTHON", "do_python", 100 | CCPW | GAXS | CARGS },
#endif /* PLEASE_HACK_MY_SHELL */
{ 0, "PYTHONSCRIPT", "do_pythonscript", 100 | CCPW | GAXS | CARGS },
#endif /* PYTHON */
#ifdef TCL
#ifdef PLEASE_HACK_MY_SHELL
{ 0, "TCL", "do_tcl", 100 | CCPW | GAXS | CARGS },
#endif /* PLEASE_HACK_MY_SHELL */
{ 0, "TCLSCRIPT", "do_tcl", 100 | CCPW | GAXS | CARGS },
#endif /* TCL */
/*---*/
{ 0, NULL, NULL, 0 },
};
#define __define_strng 4
#define __define_print 3
#define __struct_acces 2
#define __struct_print 1
int main(int argc, char **argv)
{
FILE *of;
usercombo combo;
char tmp[100];
char *pt,*tabs;
int i,j,wh;
int pass;
int ct;
int sl;
OnMsg v;
pass = __define_strng;
ct = 0;
printf("/""* This file is automatically generated from gencmd.c *""/\n");
printf("#ifndef MCMD_H\n#define MCMD_H 1\n\n");
while(pass)
{
if (pass == __struct_print)
{
printf("LS const OnMsg mcmd[] =\n{\n");
}
if (pass == __struct_acces)
{
printf("LS OnMsg_access acmd[] = \n{\n");
}
for(i=0;pre_mcmd[i].name;i++)
{
pt = 0;
wh = 0;
for(j=0;pre_mcmd[j].name;j++)
{
if (pre_mcmd[j].pass != pass)
{
pt = pre_mcmd[j].name;
wh = j;
break;
}
}
for(j=0;pre_mcmd[j].name;j++)
{
if ((pre_mcmd[j].pass != pass) && (strcmp(pt,pre_mcmd[j].name) > 0))
{
pt = pre_mcmd[j].name;
wh = j;
}
}
if (pass == __define_strng)
{
//printf("#define S_%s%s\t\"%s\"\n",pt,((strlen(pt) + 2) < 8) ? "\t" : "",pt);
}
if (pass == __define_print)
{
//printf("#define C_%s%s\tmcmd[%i].name\n",pt,((strlen(pt) + 2) < 8) ? "\t" : "",ct);
printf("BEG const char C_%s[]%s\tMDEF(\"%s\");\n",pt,((strlen(pt) + 3) < 8) ? "\t" : "",pt);
ct++;
}
if (pass == __struct_acces)
{
printf("\t%i,\t/""* %s *""/\n",
pre_mcmd[wh].flags & CLEVEL,
pt);
}
if (pass == __struct_print)
{
memset(&v,0,sizeof(v));
v.defaultaccess = pre_mcmd[wh].flags & CLEVEL;
/* + defaultaccess */
v.dcc = (pre_mcmd[wh].flags & DCC) ? 1 : 0;
v.cc = (pre_mcmd[wh].flags & CC) ? 1 : 0;
v.pass = (pre_mcmd[wh].flags & PASS) ? 1 : 0;
v.args = (pre_mcmd[wh].flags & CARGS) ? 1 : 0;
v.nopub = (pre_mcmd[wh].flags & NOPUB) ? 1 : 0;
v.nocmd = (pre_mcmd[wh].flags & NOCMD) ? 1 : 0;
v.gaxs = (pre_mcmd[wh].flags & GAXS) ? 1 : 0;
v.caxs = (pre_mcmd[wh].flags & CAXS) ? 1 : 0;
v.redir = (pre_mcmd[wh].flags & REDIR) ? 1 : 0;
v.lbuf = (pre_mcmd[wh].flags & LBUF) ? 1 : 0;
v.cbang = (pre_mcmd[wh].flags & CBANG) ? 1 : 0;
v.acchan = (pre_mcmd[wh].flags & ACCHAN) ? 1 : 0;
sprintf(tmp,"%3i,%2i,%2i,%2i,%2i,%2i,%2i,%2i,%2i,%2i,%2i,%2i,%2i",
v.defaultaccess,
v.dcc,
v.cc,
v.pass,
v.args,
v.nopub,
v.nocmd,
v.gaxs,
v.caxs,
v.redir,
v.lbuf,
v.cbang,
v.acchan
);
sl = strlen(pre_mcmd[wh].func) + 1;
tabs = "\t\t\t";
sl = (sl & ~7) / 8;
tabs += sl;
printf( (pre_mcmd[wh].cmdarg) ? "{ C_%s,%s\t%s,%s%s\t, \"%s\"\t},\n" : "{ C_%s,%s\t%s,%s%s\t},\n",
pt,
((strlen(pt) + 5) < 8) ? "\t" : "",
pre_mcmd[wh].func,
tabs,
tmp,
pre_mcmd[wh].cmdarg
);
}
pre_mcmd[wh].pass = pass;
}
if (pass == __define_strng)
{
/* nothing */
}
if (pass == __define_print)
{
printf("\n#ifdef MAIN_C\n\n");
}
if (pass == __struct_print)
{
printf("{ NULL, }};\n\n");
}
if (pass == __struct_acces)
{
printf("};\n\n");
}
pass--;
}
printf("#define LOCALHOST_ULONG %lu\n",inet_addr("127.1"));
printf("#else /""* MAIN_C *""/\n\n");
printf("extern OnMsg mcmd[];\n");
printf("extern OnMsg_access acmd[];\n\n");
printf("#endif /""* MAIN_C *""/\n\n");
printf("#endif /""* MCMD_H *""/\n\n");
unlink("usercombo.h");
of = fopen("usercombo.h","w");
fprintf(of,"/""* This file is automatically generated from gencmd.c *""/\n");
#ifdef BOTNET
combo.comboflags = 0; combo.x.noshare = 1;
fprintf(of,"#define COMBO_NOSHARE\t0x%x\n",combo.comboflags);
combo.comboflags = 0; combo.x.readonly = 1;
fprintf(of,"#define COMBO_READONLY\t0x%x\n",combo.comboflags);
#endif /* BOTNET */
#ifdef GREET
combo.comboflags = 0; combo.x.greetfile = 1;
fprintf(of,"#define COMBO_GREETFILE\t0x%x\n",combo.comboflags);
combo.comboflags = 0; combo.x.randline = 1;
fprintf(of,"#define COMBO_RANDLINE\t0x%x\n",combo.comboflags);
#endif /* GREET */
#ifdef BOUNCE
combo.comboflags = 0; combo.x.bounce = 1;
fprintf(of,"#define COMBO_BOUNCE\t0x%x\n",combo.comboflags);
#endif /* BOUNCE */
combo.comboflags = 0; combo.x.echo = 1;
fprintf(of,"#define COMBO_ECHO\t0x%x\n",combo.comboflags);
combo.comboflags = 0; combo.x.aop = 1;
fprintf(of,"#define COMBO_AOP\t0x%x\n",combo.comboflags);
combo.comboflags = 0; combo.x.avoice = 1;
fprintf(of,"#define COMBO_AVOICE\t0x%x\n",combo.comboflags);
fclose(of);
return(0);
}

450
src/global.h Normal file
View File

@@ -0,0 +1,450 @@
/*
EnergyMech, IRC bot software
Copyright (c) 1997-2009 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.
*/
#ifndef GLOBAL_H
#define GLOBAL_H 1
#ifdef MAIN_C
#define MDEF(x) = x
#define BEG LS
#else /* MAIN_C */
#define MDEF(x)
#define BEG extern
#endif /* MAIN_C */
/*
*
*/
#define DEFAULTCMDCHAR '-'
#define MECHUSERLOGIN "v3.energymech.net"
BEG const char VERSION[] MDEF("3.0.99p3");
BEG const char SRCDATE[] MDEF("July 24th, 2009");
#ifdef __CYGWIN__
BEG const char BOTCLASS[] MDEF("WinMech");
#else /* ! CYGWIN */
BEG const char BOTCLASS[] MDEF("EnergyMech");
#endif /* CYGWIN */
BEG const char BOTLOGIN[] MDEF("emech");
BEG const char NULLSTR[] MDEF("<NULL>");
BEG const char ERR_CHAN[] MDEF("I'm not on %s");
BEG const char ERR_FILEOPEN[] MDEF("Couldn't open the file %s");
BEG const char ERR_INIT[] MDEF("init: Warning:");
BEG const char ERR_NICK[] MDEF("Invalid nickname: %s");
BEG const char ERR_NOCHANNELS[] MDEF("I'm not active on any channels");
BEG const char ERR_NOTOPPED[] MDEF("I'm not opped on %s");
BEG const char ERR_UNKNOWN_COMMAND[] MDEF("Squeeze me?");
BEG const char __SPYSTR_RAWIRC[] MDEF("rawirc");
BEG const char __SPYSTR_MESSAGE[] MDEF("message");
BEG const char __SPYSTR_STATUS[] MDEF("status");
BEG const char __SPYSTR_BOTNET[] MDEF("botnet");
#define SPYSTR_RAWIRC (char*)__SPYSTR_RAWIRC
#define SPYSTR_MESSAGE (char*)__SPYSTR_MESSAGE
#define SPYSTR_STATUS (char*)__SPYSTR_STATUS
#define SPYSTR_BOTNET (char*)__SPYSTR_BOTNET
BEG const char STR_MECHRESET[] MDEF("MECHRESET=");
BEG Mech *botlist MDEF(NULL);
BEG Mech *current;
BEG char *executable;
BEG char *configfile MDEF(CFGFILE);
BEG char *mechresetenv MDEF(NULL);
BEG time_t uptime MDEF(0);
BEG int do_exec MDEF(FALSE); /* call mech_exec on mechexit */
BEG int makecore MDEF(FALSE);
BEG int respawn MDEF(0);
BEG int sigmaster MDEF(0);
BEG int ctimeout MDEF(30); /* proc var */
BEG ino_t parent_inode;
BEG KillSock *killsocks MDEF(NULL);
BEG Server *serverlist MDEF(NULL);
BEG ServerGroup *servergrouplist MDEF(NULL);
BEG ServerGroup *currentservergroup MDEF(NULL);
BEG int servergroupid MDEF(0);
BEG int serverident MDEF(1);
BEG char CurrentNick[NUHLEN];
BEG Client *CurrentDCC MDEF(NULL);
BEG Chan *CurrentChan MDEF(NULL);
BEG User *CurrentUser MDEF(NULL);
BEG Shit *CurrentShit MDEF(NULL);
BEG const OnMsg *CurrentCmd MDEF(NULL);
BEG User *cfgUser MDEF(NULL);
BEG User __internal_users[2];
#define CoreUser (__internal_users[0])
#define LocalBot (__internal_users[1])
/*
* generic output buffer, can be used as buffer in any `leaf' function
* (functions that do not call any other non-trivial functions)
*/
BEG char gsockdata[MAXLEN];
BEG char nick_buf[MAXHOSTLEN];
BEG char nuh_buf[NUHLEN];
/*
* select() stuff.
*/
BEG fd_set read_fds;
BEG fd_set write_fds;
BEG int hisock;
BEG int short_tv;
/*
* current UNIX timestamp
*/
BEG time_t now;
/*
* defined features
*/
#ifdef ALIAS
BEG Alias *aliaslist MDEF(NULL);
#endif /* ALIAS */
#ifdef UPTIME
BEG char *defaultuptimehost MDEF("uptime.energymech.net");
#endif /* UPTIME */
#ifdef BOTNET
BEG const char UNKNOWNATUNKNOWN[] MDEF("unknown@unknown");
#define UNKNOWN (&UNKNOWNATUNKNOWN[8])
BEG BotNet *botnetlist MDEF(NULL);
BEG NetCfg *netcfglist MDEF(NULL);
BEG char *linkpass MDEF(NULL); /* proc var */
BEG int linkport MDEF(0); /* proc var */
BEG int autolink MDEF(0); /* proc var */
BEG time_t last_autolink MDEF(0);
BEG NetCfg *autolink_cfg MDEF(NULL);
BEG int global_tick MDEF(0);
#endif /* BOTNET */
#ifdef BOUNCE
BEG ircLink *bnclist MDEF(NULL);
BEG int bounce_sock MDEF(-1);
BEG int bounce_port MDEF(0); /* proc var */
#endif /* BOUNCE */
#ifdef CTCP
BEG time_t ctcp_slot[CTCP_SLOTS];
#endif /* CTCP */
#ifdef DEBUG
BEG char debugbuf[MAXLEN];
BEG char *debugfile MDEF(NULL);
BEG int dodebug MDEF(FALSE);
BEG int debug_fd MDEF(-1);
BEG int debug_on_exit MDEF(FALSE);
BEG aMEA *mrrec;
BEG void *mallocdoer;
#endif /* DEBUG */
#ifdef NOTE
BEG Note *notelist MDEF(NULL);
#endif /* NOTE */
#ifdef SCRIPTING
BEG Hook *hooklist MDEF(NULL);
#endif /* SCRIPTING */
#ifdef REDIRECT
LS struct
{
char *to;
int method;
#ifdef BOTNET
int guid;
#endif /* BOTNET */
} redirect;
#endif /* REDIRECT */
#ifdef SEEN
BEG char *seenfile MDEF(NULL); /* proc var */
BEG Seen *seenlist MDEF(NULL);
#endif /* SEEN */
#ifdef TRIVIA
BEG int triv_qdelay MDEF(30); /* proc var */
BEG char *triv_qfile MDEF(NULL); /* proc var */
BEG char triv_qchar MDEF('*'); /* proc var */
BEG TrivScore *scorelist MDEF(NULL);
#endif /* TRIVIA */
#ifdef UPTIME
BEG int uptimeport MDEF(9969); /* proc var */
BEG char *uptimehost MDEF(NULL); /* proc var */
BEG char *uptimenick MDEF(NULL); /* proc var */
BEG int uptimesock;
BEG ulong uptimeip MDEF((ulong)-1);
BEG ulong uptimecookie;
BEG ulong uptimeregnr MDEF(0);
BEG time_t uptimelast MDEF(0);
#endif /* UPTIME */
#ifdef WEB
BEG int websock MDEF(-1);
BEG int webport MDEF(0);
#endif /* WEB */
#ifdef RAWDNS
BEG dnsList *dnslist MDEF(NULL);
BEG dnsAuthority *dnsroot MDEF(NULL);
BEG struct in_addr ia_ns[MAX_NAMESERVERS];
BEG struct in_addr ia_default;
#ifdef SESSION
BEG Strp *dnsrootfiles MDEF(NULL);
#endif /* SESSION */
#endif /* RAWDNS */
#ifndef I_HAVE_A_LEGITIMATE_NEED_FOR_MORE_THAN_4_BOTS
BEG int spawning_lamer MDEF(0);
#endif /* I_HAVE_A_LEGITIMATE_NEED_FOR_MORE_THAN_4_BOTS */
/*
* attrtab defines
*/
#define NUM 0x01
#define NICK 0x02
#define FIRST 0x04
#define CRLF 0x08
#define FNICK (NICK|FIRST)
#define NNICK (NICK|NUM)
#ifdef MAIN_C
/*
* tolowertab blatantly ripped from ircu2.9.32
*/
LS const uchar tolowertab[256] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
' ', '!', '"', '#', '$', '%', '&', 0x27,
'(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', ':', ';', '<', '=', '>', '?',
'@', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', '{', '|', '}', '~', '_',
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', '{', '|', '}', '~', 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
/*
* be wary, this is not a normal upper-to-lower table...
*/
LS const uchar nickcmptab[256] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
' ', 0x00, '"', '#', '$', '%', '&', 0x27, /* <-- observe! the '!' changed to 0x00 */
'(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', ':', ';', '<', '=', '>', '?',
'@', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', '{', '|', '}', '~', '_',
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', '{', '|', '}', '~', 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
LS const uchar attrtab[256] =
{
0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 - 0x07 */
0, 0, CRLF, 0, 0, CRLF, 0, 0, /* 0x08 - 0x0F */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x17 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x18 - 0x1F */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x27 */
0, 0, 0, 0, 0, NICK, 0, 0, /* 0x28 - 0x2F */
NNICK, NNICK, NNICK, NNICK, NNICK, NNICK, NNICK, NNICK, /* 0x30 - 0x37 */
NNICK, NNICK, 0, 0, 0, 0, 0, 0, /* 0x38 - 0x3F */
0, FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, /* 0x40 - 0x47 */
FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, /* 0x48 - 0x4F */
FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, /* 0x50 - 0x57 */
FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, /* 0x58 - 0x5F */
FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, /* 0x60 - 0x67 */
FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, /* 0x68 - 0x6F */
FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, /* 0x70 - 0x77 */
FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, 0, 0, /* 0x78 - 0x7F */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x87 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x88 - 0x8F */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x97 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x98 - 0x9F */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 - 0xA7 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xA8 - 0xAF */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0 - 0xB7 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xB8 - 0xBF */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 - 0xC7 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xC8 - 0xCF */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 - 0xD7 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xD8 - 0xDF */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0 - 0xE7 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xE8 - 0xEF */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0 - 0xF7 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xF8 - 0xFF */
};
/*
* user struct for the core client
*/
LS const Strp CMA =
{
NULL,
"*"
};
/*
* client struct for the core client
*/
LS ShortClient CoreClient =
{
NULL, /* next */
(User*)&CoreUser, /* user */
-1, /* socket */
0, /* flags */
0, /* inputcount */
0 /* lasttime */
};
LS ShortChan CoreChan =
{
NULL,
NULL
};
typedef struct coreServerGroup
{
ServerGroup *next;
int servergroup;
char name[8];
} coreServerGroup;
LS coreServerGroup defaultServerGroup =
{
NULL, /* next */
0, /* servergroup */
"default" /* name */
};
#else /* MAIN_C */
extern const uchar tolowertab[];
extern const uchar nickcmptab[];
extern const uchar attrtab[];
extern const User xxCoreUser;
extern const User xxLocalBot;
extern ShortClient CoreClient;
extern ShortChan CoreChan;
extern ServerGroup defaultServerGroup;
#endif /* MAIN_C */
#endif /* GLOBAL_H */

164
src/greet.c Normal file
View File

@@ -0,0 +1,164 @@
/*
EnergyMech, IRC bot software
Copyright (c) 1997-2009 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 GREET_C
#include "config.h"
#ifdef GREET
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
/*
* woo.. no args? we use CurrentChan, CurrentNick and CurrentUser.
*/
void greet(void)
{
Strp *sp,**pp;
char linebuf[MSGLEN],readbuf[MSGLEN];
char *str;
int fd,sz;
pp = &current->sendq;
while(*pp)
pp = &(*pp)->next;
if (CurrentUser->x.x.greetfile)
{
if ((fd = open(CurrentUser->greet,O_RDONLY)) < 0)
return;
sz = sizeof(Strp) + 9 + strlen(CurrentNick);
memset(readbuf,0,sizeof(readbuf));
while(TRUE)
{
str = sockread(fd,readbuf,linebuf);
if (str)
{
*pp = sp = (Strp*)Calloc(sz + strlen(str));
/* Calloc sets to zero sp->next = NULL; */
pp = &sp->next;
sprintf(sp->p,"NOTICE %s :%s",CurrentNick,str);
}
else
if (errno != EAGAIN)
break;
}
close(fd);
}
else
if (CurrentUser->x.x.randline)
{
if ((str = randstring(CurrentUser->greet)))
goto single_line;
return;
}
else
{
str = CurrentUser->greet;
single_line:
*pp = sp = (Strp*)Calloc(sizeof(Strp) + 13 + Strlen(CurrentChan->name,CurrentNick,str,NULL));
sprintf(sp->p,"PRIVMSG %s :[%s] %s",CurrentChan->name,CurrentNick,str);
/* Calloc sets to zero sp->next = NULL; */
}
}
/*
*
* commands tied to the greeting feature
*
*/
void do_greet(COMMAND_ARGS)
{
/*
* on_msg checks: CARGS
*/
User *user;
char *handle;
int isfile;
if ((handle = chop(&rest)) == NULL)
goto usage;
if ((user = find_handle(handle)) == NULL)
{
to_user(from,TEXT_UNKNOWNUSER,handle);
return;
}
if (!usercanmodify(from,user))
{
to_user(from,TEXT_USEROWNSYOU,user->name);
return;
}
isfile = FALSE;
if (*rest == '@' || *rest == '%')
{
isfile = *rest;
rest++;
while(*rest == ' ')
rest++;
}
if (*rest)
{
if (isfile)
{
if (!is_safepath(rest))
goto usage;
}
user->x.x.greetfile = (isfile == '@') ? TRUE : FALSE;
user->x.x.randline = (isfile == '%') ? TRUE : FALSE;
set_mallocdoer(do_greet);
user->greet = Strdup(rest);
to_user(from,"greeting for user %s has been set to: %s%s",user->name,user->greet,
(isfile == '@') ? " (file)" : ((isfile == '%') ? " (random line from file)" : ""));
current->ul_save++;
}
else
if (isfile)
{
goto usage;
}
else
if (user->greet)
{
Free((char**)&user->greet);
to_user(from,"greeting for user %s has been removed",user->name);
current->ul_save++;
}
return;
usage:
usage(from); /* usage for CurrentCmd->name */
}
#endif /* GREET */

783
src/h.h Normal file
View File

@@ -0,0 +1,783 @@
/*
EnergyMech, IRC bot software
Copyright (c) 1997-2009 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.
*/
#ifndef H_H
#define H_H 1
#define ischannel(x) (*x == '#')
#define nullstr(x) (x) ? x : NULLSTR
#define nullbuf(x) (x && *x) ? x : NULLSTR
#define chkhigh(x) if (x > hisock) { hisock = x; }
#define COMMAND_ARGS char *from, char *to, char *rest, int cmdaccess
#define STRCHR strchr
#define STREND(x) STRCHR(x,0)
/*
* some default code for socket flags
*/
#ifdef ASSUME_SOCKOPTS
#define unset_closeonexec(x) fcntl(x,F_SETFD,0);
#else /* ASSUME_SOCKOPTS */
#define unset_closeonexec(x) fcntl(x,F_SETFD,(~FD_CLOEXEC) & fcntl(x,F_GETFD));
#endif /* ASSUME_SOCKOPTS */
/*
* Dont try this at home kids...
*/
#ifdef __ELF__
#define __sect(x) __section__ (x)
#else
#define __sect(x) /* nothing */
#endif
#ifdef __GNUC__
#define __vattr(x) __attribute__ (( x ))
#define __page(x) __attribute__ (( __sect(x) ))
#define __attr(x,y) __attribute__ (( __sect(x), y ))
#define __att2(x,y,z) __attribute__ (( __sect(x), y, z ))
#else
#define __vattr(x) /* nothing */
#define __page(x) /* nothing */
#define __attr(x,y) /* nothing */
#define __att2(x,y,z) /* nothing */
#endif
#if !defined(__profiling__) && defined(__i386__)
# define __regparm(x) regparm (x)
#else
# define __regparm(x)
#endif
#define CORE_SEG ".text.a"
#define CFG1_SEG ".text.b"
#define CMD1_SEG ".text.c"
#define INIT_SEG ".text.d"
#define RARE_SEG ".text.e"
#define DBUG_SEG ".text.f"
#ifdef DEBUG
#define set_mallocdoer(x) mallocdoer = x;
#define mechexit(x,y) \
{ \
if (debug_on_exit) \
wrap_debug(); \
if (do_exec) \
mech_exec(); \
y(x); \
}
#else /* not DEBUG */
#define set_mallocdoer(x)
#define mechexit(x,y) \
{ \
if (do_exec) \
mech_exec(); \
y(x); \
}
#endif /* DEBUG */
LS Chan *find_channel_ac(char *) __attr(CORE_SEG, __regparm (1) );
LS Chan *find_channel_ny(char *) __attr(CORE_SEG, __regparm (1) );
LS ChanUser *find_chanuser(Chan *, const char *) __attr(CORE_SEG, __regparm (2) );
LS Client *find_client(const char *) __page(CORE_SEG);
LS Mech *add_bot(int, char *) __page(CORE_SEG);
LS KickSay *find_kicksay(char *, char *) __page(CORE_SEG);
LS Server *add_server(char *, int, char *) __page(CFG1_SEG);
LS Server *find_server(int) __page(CORE_SEG);
LS ServerGroup *getservergroupid(int) __page(CMD1_SEG);
LS Shit *add_shit(char *, char *, char *, char *, int, int) __page(CMD1_SEG);
LS Shit *find_shit(const char *, const char *) __page(CORE_SEG);
LS Shit *get_shituser(char *, char *) __page(CORE_SEG);
LS User *add_user(char *, char *, int) __page(CFG1_SEG);
LS User *find_handle(char *) __page(CORE_SEG);
LS User *get_authuser(char *, char *) __page(CORE_SEG);
LS User *get_user(const char *, const char *) __page(CORE_SEG);
LS int get_authaccess(char *, char *) __page(CORE_SEG);
LS int get_protaction(Chan *, char *) __page(CORE_SEG);
LS int get_shitaction(const char *, const char *) __page(CORE_SEG);
LS int get_useraccess(char *, char *) __page(CORE_SEG);
LS int get_maxaccess(const char *) __page(CORE_SEG);
LS int Strcasecmp(const char *, const char *) __att2(CORE_SEG, const, __regparm (2) );
LS int Strcmp(const char *, const char *) __att2(CORE_SEG, const, __regparm (2) );
LS char *Strcat(char *, const char *) __attr(CORE_SEG, __regparm (2) );
LS char *Strchr(const char *, int) __att2(CORE_SEG, const, __regparm (2) );
LS char *Strcpy(char *, const char *) __attr(CORE_SEG, __regparm (2) );
LS char *Strdup(char *) __page(CORE_SEG);
LS void Strncpy(char *, const char *, int) __attr(CORE_SEG, __regparm (3) );
LS char *chop(char **) __attr(CORE_SEG, __regparm (1) );
LS int get_number(const char *) __page(CORE_SEG);
LS int nickcmp(const char *, const char *) __att2(CORE_SEG, const, __regparm (2) );
LS char *nickcpy(char *, const char *) __attr(CORE_SEG, __regparm (2) );
LS char *cipher(char *) __page(CMD1_SEG);
LS char *cluster(char *) __page(CMD1_SEG);
LS char *find_nuh(char *) __page(CORE_SEG);
LS char *format_uh(char *, int) __page(CMD1_SEG);
LS char *get_channel(char *, char **) __attr(CMD1_SEG, __regparm (2) );
LS char *get_channel2(char *, char **) __page(CMD1_SEG);
LS char *get_nuh(ChanUser *) __page(CORE_SEG);
LS char *get_token(char **, const char *) __page(CORE_SEG);
LS char *getuh(char *) __page(CORE_SEG);
LS char *idle2str(time_t, int) __page(CORE_SEG);
LS char *makepass(char *) __page(CMD1_SEG);
LS char *nick2uh(char *, char *) __page(CMD1_SEG);
LS char *randstring(char *) __page(CORE_SEG);
LS char *sockread(int, char *, char *) __page(CORE_SEG);
LS char *logtime(time_t) __page(CORE_SEG);
LS void table_buffer(const char *, ...) __attr(CMD1_SEG, format (printf, 1, 2) );
LS void table_send(const char *, const int) __attr(CMD1_SEG, __regparm (2) );
LS char *time2away(time_t) __page(CORE_SEG);
LS char *time2medium(time_t) __page(CORE_SEG);
LS char *time2small(time_t) __page(CMD1_SEG);
LS char *time2str(time_t) __page(CMD1_SEG);
LS char *tolowercat(char *dest, const char *src) __attr(CMD1_SEG, __regparm (2) );
/*
* socket.c
*/
LS ulong get_ip(const char *) __page(CORE_SEG);
LS int SockAccept(int) __page(CORE_SEG);
LS int SockConnect(char *, int, int) __page(CORE_SEG);
LS void SockFlags(int) __page(CORE_SEG);
LS int SockListener(int) __page(CORE_SEG);
LS int SockOpts(void) __page(CORE_SEG);
LS int capslevel(char *) __page(CORE_SEG);
LS int check_mass(Chan *, ChanUser *, int) __page(CORE_SEG);
LS int compile_timer(HookTimer *, char *) __page(CORE_SEG); /* SCRIPTING */
LS int conf_callback(char *) __page(INIT_SEG); /* INIT */
LS int do_help_callback(char *) __page(CMD1_SEG);
LS int find_setting(char *) __page(CMD1_SEG);
LS int is_bot(const char *) __page(CORE_SEG);
LS int is_nick(const char *) __page(CORE_SEG);
LS int killsock(int) __page(CORE_SEG);
LS int access_needed(char *) __page(CMD1_SEG);
LS int mode_effect(Chan *, qMode *) __page(CORE_SEG);
LS int passmatch(char *, char *) __page(CMD1_SEG);
LS int randstring_count(char *) __page(CORE_SEG);
LS int randstring_getline(char *) __page(CORE_SEG);
LS int read_seenlist(void) __page(CFG1_SEG);
LS int read_seenlist_callback(char *) __page(CFG1_SEG);
LS int read_userlist(char *) __page(CFG1_SEG);
LS int read_userlist_callback(char *) __page(CFG1_SEG);
LS int reverse_mode(char *, Chan *, int, int) __page(CORE_SEG);
LS int to_file(int, const char *, ...) __attr(CORE_SEG, format (printf, 2, 3) );
LS int try_server(Server *, char *) __page(CORE_SEG);
LS int usercanmodify(const char *, const User *) __attr(CORE_SEG, __regparm (2) );
LS int write_seenlist(void) __page(CORE_SEG);
LS int write_session(void) __page(CORE_SEG);
LS int write_userlist(char *) __page(CORE_SEG);
LS void var_resolve_host(const struct Setting *) __page(CFG1_SEG);
LS ulong stringhash(char *) __page(CORE_SEG);
/*
* function.c
*/
LS void *Calloc(int) __attr(CORE_SEG, __regparm (1) );
LS void Free(char **) __attr(CORE_SEG, __regparm (1) );
LS int Strlen(const char *, ...) __page(CORE_SEG);
LS int Strlen2(const char *, const char *) __attr(CORE_SEG, __regparm (2) );
LS int matches(const char *, const char *) __att2(CORE_SEG, const, __regparm (2) );
LS int num_matches(const char *, const char *) __att2(CORE_SEG, const, __regparm (2) );
LS int a2i(char *) __attr(CORE_SEG, __regparm (1) );
LS int is_safepath(const char *) __page(CORE_SEG);
LS void afmt(char *, const char *, const char *) __page(CMD1_SEG);
LS void aucheck(User *) __attr(CORE_SEG, __regparm (1) );
LS void change_authnick(char *, char *) __page(CORE_SEG);
LS void change_pass(User *, char *) __page(CMD1_SEG);
LS void chan_modestr(Chan *, char *) __page(CMD1_SEG);
LS void channel_massmode(Chan *, char *, int, char, char) __page(CMD1_SEG);
LS void channel_massunban(Chan *, char *, time_t) __page(CMD1_SEG);
LS void check_idlekick(void) __page(CORE_SEG);
LS void check_kicksay(Chan *, ChanUser *, char *) __page(CORE_SEG);
LS void check_shit(void) __page(CORE_SEG);
LS void common_public(Chan *, char *, char *, char *) __page(CORE_SEG);
LS void connect_to_server(void) __page(CORE_SEG);
LS void copy_vars(UniVar *, UniVar *) __page(CMD1_SEG);
LS void ctcp_dcc(char *, char *, char *) __page(CORE_SEG);
LS void cycle_channel(Chan *) __page(CORE_SEG);
LS void dcc_banner(Client *) __page(CORE_SEG);
LS void dcc_chat(char *) __page(CMD1_SEG);
LS int dcc_only_command(char *) __page(CMD1_SEG);
LS void debug(char *, ...) __attr(CORE_SEG, format (printf, 1, 2) );
LS void delete_auth(char *) __page(RARE_SEG); /* rare */
LS void delete_ban(Chan *, char *) __page(CORE_SEG);
LS void delete_modemask(Chan *, char *, int) __page(CORE_SEG);
LS void delete_client(Client *) __page(CORE_SEG);
LS void delete_vars(UniVar *, int) __page(CMD1_SEG);
LS void deop_ban(Chan *, ChanUser *, char *) __page(CMD1_SEG);
LS void deop_screwban(Chan *, ChanUser *) __page(CMD1_SEG);
LS void deop_siteban(Chan *, ChanUser *) __page(CMD1_SEG);
/*
* user.c
*/
LS void cfg_chan(char *) __page(CFG1_SEG);
LS void cfg_greet(char *) __page(CFG1_SEG);
LS void cfg_mask(char *) __page(CFG1_SEG);
LS void cfg_note(char *) __page(CFG1_SEG);
LS void cfg_opt(char *) __page(CFG1_SEG);
LS void cfg_pass(char *) __page(CFG1_SEG);
LS void cfg_shit(char *) __page(CFG1_SEG);
LS void cfg_user(char *) __page(CFG1_SEG);
void mirror_user(User *) __page(CORE_SEG);
void mirror_userlist(void) __page(CORE_SEG);
LS void addtouser(Strp **, const char *) __attr(CORE_SEG, __regparm (2) );
LS int remfromuser(Strp **, const char *) __attr(CORE_SEG, __regparm (2) );
/*
* commands
*/
LS void do_8ball(COMMAND_ARGS) __page(CMD1_SEG); /* TOYBOX */
LS void do_access(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_alias(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_auth(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_away(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_banlist(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_bigsay(COMMAND_ARGS) __page(CMD1_SEG); /* TOYBOX */
LS void do_bye(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_cchan(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_chaccess(COMMAND_ARGS) __page(CMD1_SEG); /* DYNCMDACCESS */
LS void do_channels(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_chat(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_clearshit(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_cmd(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_core(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_cserv(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_cycle(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_debug(COMMAND_ARGS) __page(DBUG_SEG); /* DEBUG */
LS void do_die(COMMAND_ARGS) __page(RARE_SEG); /* rare */
LS void do_do(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_echo(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_esay(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_forget(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_greet(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_help(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_idle(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_invite(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_irclusers(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_ircstats(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_ircuserhost(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_ircwhois(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_join(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_kick(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_kickban(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_kicksay(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_last(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_link(COMMAND_ARGS) __page(CMD1_SEG); /* BOTNET */
LS void do_load(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_mode(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_msg(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_names(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_nick(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_note(COMMAND_ARGS) __page(CMD1_SEG); /* NOTE */
LS void do_notify(COMMAND_ARGS) __page(CMD1_SEG); /* NOTIFY */
LS void do_opdeopme(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_opvoice(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_part(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_passwd(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_ping_ctcp(COMMAND_ARGS) __page(CMD1_SEG); /* CTCP */
LS void do_random_msg(COMMAND_ARGS) __page(CMD1_SEG); /* TOYBOX */
LS void do_randtopic(COMMAND_ARGS) __page(CMD1_SEG); /* TOYBOX */
LS void do_read(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_reset(COMMAND_ARGS) __page(RARE_SEG); /* rare */
LS void do_rkicksay(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_rshit(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_rspy(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_save(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_sayme(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_seen(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_server(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_servergroup(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_set(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_setpass(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_shit(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_shitlist(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_showidle(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_showusers(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_shutdown(COMMAND_ARGS) __page(RARE_SEG); /* rare */
LS void do_siteban(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_spy(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_time(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_topic(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_trivia(COMMAND_ARGS) __page(CMD1_SEG); /* TRIVIA */
LS void do_unalias(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_unban(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_upsend(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_upontime(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_usage(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_user(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_userlist(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_version(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_wall(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_whom(COMMAND_ARGS) __page(CMD1_SEG);
/*
* end of commands
*/
LS void fix_config_line(char *) __attr(CORE_SEG, __regparm (1) );
LS void greet(void) __page(CMD1_SEG);
LS void join_channel(char *, char *) __page(CORE_SEG);
LS void kill_all_bots(char *) __attr(RARE_SEG, __noreturn__ ); /* rare */
LS int make_auth(const char *, const User *) __page(CORE_SEG);
LS Ban *make_ban(Ban **, char *, char *, time_t) __page(CORE_SEG);
LS void make_chanuser(char *, char *) __attr(CORE_SEG, __regparm (2) );
LS void make_ireq(int, char *, char *) __page(CMD1_SEG);
LS void mass_action(Chan *, ChanUser *) __page(CORE_SEG);
LS void mech_exec(void) __attr(RARE_SEG, __noreturn__ ); /* rare */
LS void on_action(char *, char *, char *) __page(CORE_SEG);
LS void on_ctcp(char *, char *, char *) __page(CORE_SEG);
LS void on_join(Chan *, char *) __page(CORE_SEG);
LS void on_kick(char *, char *) __page(CORE_SEG);
LS void on_mode(char *, char *, char *) __page(CORE_SEG);
LS void on_msg(char *, char *, char *) __page(CORE_SEG);
LS void on_nick(char *, char *) __page(CORE_SEG);
LS void parse_213(char *, char *) __page(CMD1_SEG); /* stats C */
LS void parse_219(char *, char *) __page(CMD1_SEG); /* end of stats */
LS void parse_251(char *, char *) __page(CORE_SEG);
LS void parse_252(char *, char *) __page(CORE_SEG);
LS void parse_253(char *, char *) __page(CORE_SEG);
LS void parse_254(char *, char *) __page(CORE_SEG);
LS void parse_255(char *, char *) __page(CORE_SEG);
LS void parse_301(char *, char *) __page(CORE_SEG);
LS void parse_311(char *, char *) __page(CORE_SEG);
LS void parse_312(char *, char *) __page(CORE_SEG);
LS void parse_313(char *, char *) __page(CORE_SEG);
LS void parse_315(char *, char *) __page(CORE_SEG);
LS void parse_317(char *, char *) __page(CORE_SEG);
LS void parse_318(char *, char *) __page(CORE_SEG);
LS void parse_319(char *, char *) __page(CORE_SEG);
LS void parse_324(char *, char *) __page(CORE_SEG);
LS void parse_352(char *, char *) __page(CORE_SEG);
LS void parse_367(char *, char *) __page(CORE_SEG);
LS void parse_376(char *, char *) __page(CORE_SEG);
LS void parse_401(char *, char *) __page(CMD1_SEG); /* no such nick/channel */
LS void parse_433(char *, char *) __page(CORE_SEG);
LS void parse_451(char *, char *) __page(CORE_SEG);
LS void parse_471(char *, char *) __page(CORE_SEG);
LS void parse_473(char *, char *) __page(CORE_SEG);
LS void parse_dcc(Client *) __page(CORE_SEG);
LS void parse_error(char *, char *) __page(CORE_SEG);
LS void parse_invite(char *, char *) __page(CMD1_SEG);
LS void parse_join(char *, char *) __page(CORE_SEG);
LS void parse_mode(char *, char *) __page(CORE_SEG);
LS void parse_notice(char *, char *) __page(CORE_SEG);
LS void parse_part(char *, char *) __page(CORE_SEG);
LS void parse_ping(char *, char *) __page(CORE_SEG);
LS void parse_privmsg(char *, char *) __page(CORE_SEG);
LS void parse_quit(char *, char *) __page(CORE_SEG);
LS void parse_topic(char *, char *) __page(CMD1_SEG);
LS void parse_wallops(char *, char *) __page(CORE_SEG);
LS void parse_server_input(void) __page(CORE_SEG);
LS void parseline(char *) __page(CORE_SEG);
LS void partyline_broadcast(Client *, char *, char *) __page(CORE_SEG);
LS void print_help(char *, char *, int) __page(CMD1_SEG);
LS void process_dcc(void) __page(CORE_SEG);
LS void prot_action(Chan *, char *, ChanUser *, char *, ChanUser *) __page(CORE_SEG);
LS void purge_banlist(Chan *) __page(CORE_SEG);
LS void purge_chanusers(Chan *) __page(CORE_SEG);
LS void purge_shitlist(void) __page(RARE_SEG); /* rare */
LS void purge_kicklist(void) __page(RARE_SEG); /* rare */
LS void push_kicks(Chan *) __page(CORE_SEG);
LS void push_modes(Chan *, int) __page(CORE_SEG);
LS void readcfgfile(void) __page(INIT_SEG); /* INIT */
LS void readline(int s, int (*callback)(char *)) __page(CORE_SEG);
LS void register_with_server(void) __page(CORE_SEG);
LS void remove_auth(Auth *) __page(CORE_SEG);
LS void remove_chan(Chan *) __page(CORE_SEG);
LS void remove_chanuser(Chan *, char *) __attr(CORE_SEG, __regparm (2) );
LS void remove_kicksay(KickSay *) __page(CMD1_SEG);
LS void remove_ks(KillSock *) __page(CORE_SEG);
LS void remove_shit(Shit *) __page(CMD1_SEG);
LS void remove_user(User *) __page(CMD1_SEG);
LS void reset_userlink(User *, User *) __page(CMD1_SEG);
LS void reverse_topic(Chan *, char *, char *) __page(CORE_SEG);
LS void screwban_format(char *) __page(CMD1_SEG);
LS void send_global(const char *, const char *, ...) __attr(CORE_SEG, format (printf, 2, 3) );
LS void send_kick(Chan *, const char *, const char *, ...) __attr(CORE_SEG, format (printf, 3, 4) );
LS void send_mode(Chan *, int, int, char, char, void *) __page(CORE_SEG);
LS void send_pa(int, const char *, const char *, ...) __page(CORE_SEG);
LS void send_spy(const char *, const char *, ...) __attr(CORE_SEG, format (printf, 2, 3) );
LS void send_uptime(int) __page(CORE_SEG);
LS void set_binarydefault(UniVar *) __page(CFG1_SEG);
LS void set_str_varc(Chan *, int, char *) __page(CFG1_SEG);
LS void setbotnick(Mech *, char *) __page(CORE_SEG);
LS void shit_action(Chan *, ChanUser *) __page(CORE_SEG);
LS void signoff(char *, char *) __page(RARE_SEG); /* rare */
LS void spy_typecount(Mech *) __page(CMD1_SEG);
LS void to_server(char *, ...) __attr(CORE_SEG, format (printf, 1, 2) );
LS void to_user(const char *, const char *, ...) __attr(CORE_SEG, format (printf, 2, 3) );
LS void to_user_q(const char *, const char *, ...) __attr(CORE_SEG, format (printf, 2, 3) );
LS void unchop(char *, char *) __attr(CORE_SEG, __regparm (2) );
LS void unmode_chanuser(Chan *, ChanUser *) __page(CORE_SEG);
LS void update(SequenceTime *) __page(CORE_SEG);
LS void update_modes(Chan *) __page(CORE_SEG);
LS void usage(char *) __attr(CMD1_SEG, __regparm (1) );
LS void usage_command(char *, const char *) __page(CMD1_SEG);
LS void user_sync(void) __page(CFG1_SEG);
LS void whom_printbot(char *, BotInfo *, char *) __page(CMD1_SEG);
/*
* signals
*/
LS int sig_hup_callback(char *) __page(RARE_SEG);
LS void do_sighup(void) __page(CMD1_SEG);
LS void do_sigint(void) __page(RARE_SEG);
LS void do_sigusr1(void) __page(CMD1_SEG);
LS void sig_alrm(int) __page(RARE_SEG);
LS void sig_child(int) __page(RARE_SEG);
LS void sig_bus(int) __page(CMD1_SEG);
LS void sig_hup(int) __page(RARE_SEG);
LS void sig_int(int) __page(RARE_SEG);
LS void sig_pipe(int) __page(CORE_SEG);
LS void sig_segv(int) __page(RARE_SEG);
LS void sig_term(int) __page(RARE_SEG);
LS void sig_usr1(int) __page(CMD1_SEG);
LS void sig_usr2(int) __page(DBUG_SEG); /* DEBUG */
LS void sig_suicide() __attr(RARE_SEG, __noreturn__);
/*
* BOTNET prototypes
*/
#ifdef BOTNET
LS BotInfo *make_botinfo(int, int, char *, char *, char *) __page(CORE_SEG);
LS ChanUser *find_chanbot(Chan *, char *) __page(CORE_SEG);
LS Mech *get_netbot(void) __page(CORE_SEG);
LS NetCfg *find_netcfg(int) __page(CORE_SEG);
LS int connect_to_bot(NetCfg *cfg) __page(CORE_SEG);
LS void basicAuth(BotNet *, char *) __page(CORE_SEG);
LS void basicAuthOK(BotNet *, char *) __page(CORE_SEG);
LS void basicBanner(BotNet *, char *) __page(CORE_SEG);
LS void basicLink(BotNet *, char *) __page(CORE_SEG);
LS void basicQuit(BotNet *, char *) __page(CORE_SEG);
LS void netchanNeedop(BotNet *, char *) __page(CORE_SEG);
LS void partyAuth(BotNet *, char *) __page(CORE_SEG);
LS void partyCommand(BotNet *, char *) __page(CORE_SEG);
LS void partyMessage(BotNet *, char *) __page(CORE_SEG);
LS void ushareDelete(BotNet *, char *) __page(CMD1_SEG);
LS void ushareTick(BotNet *, char *) __page(CORE_SEG);
LS void ushareUser(BotNet *, char *) __page(CORE_SEG);
LS void botnet_binfo_relay(BotNet *, BotInfo *) __attr(CORE_SEG, __regparm (2) );
LS void botnet_binfo_tofile(int, BotInfo *) __attr(CORE_SEG, __regparm (2) );
LS void botnet_deaduplink(BotNet *) __page(CORE_SEG);
LS void botnet_dumplinklist(BotNet *) __page(CORE_SEG);
LS void botnet_newsock(void) __page(CORE_SEG);
LS void botnet_parse(BotNet *, char *) __page(CORE_SEG);
LS void botnet_refreshbotinfo(void) __page(CORE_SEG);
LS void botnet_relay(BotNet *, char *, ...) __page(CORE_SEG);
LS void check_botinfo(BotInfo *, const char *) __page(CORE_SEG);
LS void check_botjoin(Chan *, ChanUser *) __page(CORE_SEG);
LS void select_botnet(void) __page(CORE_SEG);
LS void process_botnet(void) __page(CORE_SEG);
LS void reset_linkable(int) __page(CORE_SEG);
#endif /* BOTNET */
/*
* bounce baby bounce!
*/
#ifdef BOUNCE
LS void new_port_bounce(const struct Setting *) __page(RARE_SEG);
LS void bounce_cleanup(void) __page(RARE_SEG); /* rare */
LS void bounce_parse(ircLink *, char *) __page(CORE_SEG);
LS void process_bounce(void) __page(CORE_SEG);
LS void select_bounce(void) __page(CORE_SEG);
#endif /* BOUNCE */
/*
*
*/
#ifdef CHANBAN
LS void do_chanban(COMMAND_ARGS) __page(CMD1_SEG);
LS void process_chanbans(void) __page(CORE_SEG);
#endif /* CHANBAN */
/*
*
*/
#ifdef CTCP
LS void ctcp_finger(char *, char *, char *) __page(CORE_SEG);
LS void ctcp_ping(char *, char *, char *) __page(CORE_SEG);
LS void ctcp_version(char *, char *, char *) __page(CORE_SEG);
#endif /* CTCP */
/*
*
*/
#ifdef DEBUG
LS char *atime(time_t) __page(DBUG_SEG);
LS const char *proc_lookup(void *, int) __page(DBUG_SEG);
LS const char *strdef(const DEFstruct *, int) __page(DBUG_SEG);
LS void run_debug(void) __page(DBUG_SEG);
LS int wrap_debug(void) __page(DBUG_SEG);
LS void debug_botinfo(BotInfo *) __page(DBUG_SEG);
LS void debug_botnet(void) __page(DBUG_SEG);
LS void debug_core(void) __page(DBUG_SEG);
LS void debug_memory(void) __page(DBUG_SEG);
LS void debug_server(Server *, char *) __page(DBUG_SEG);
LS void debug_settings(UniVar *, int) __page(DBUG_SEG);
LS void memreset(void) __page(DBUG_SEG);
LS void memtouch(void *) __page(DBUG_SEG);
LS char *ulong2bin(int, ulong) __page(DBUG_SEG);
#endif /* DEBUG */
#ifdef DCC_FILE
LS int dcc_sendfile(char *, char *) __page(CMD1_SEG);
LS void do_send(COMMAND_ARGS) __page(CMD1_SEG);
#endif /* DCC_FILE */
/*
*
*/
#ifdef DYNAMODE
LS void check_dynamode(Chan *) __page(CORE_SEG);
#endif /* DYNAMODE */
/*
*
*/
#ifdef IDWRAP
LS void unlink_identfile(void) __page(CORE_SEG);
#endif /* IDWRAP */
/*
*
*/
#ifdef NOTE
LS int catch_note(char *, char *, char *) __page(CMD1_SEG);
#endif /* NOTE */
/*
*
*/
#ifdef NOTIFY
LS int mask_check(Notify *, char *) __page(CORE_SEG);
LS int notify_callback(char *) __page(CMD1_SEG);
LS int notifylog_callback(char *) __page(CFG1_SEG);
LS int read_notify(char *) __page(CFG1_SEG);
LS void catch_ison(char *) __page(CORE_SEG);
LS void catch_whois(char *, char *, char *) __page(CORE_SEG);
LS void nfshow_brief(Notify *) __page(CMD1_SEG);
LS void nfshow_full(Notify *) __page(CMD1_SEG);
LS void parse_303(char *, char *) __page(CORE_SEG);
LS void purge_notify(void) __page(CFG1_SEG);
LS void read_notifylog(void) __page(CFG1_SEG);
LS void send_ison(void) __page(CORE_SEG);
LS void write_notifylog(void) __page(CORE_SEG);
#endif /* NOTIFY */
/*
* Python
*/
#ifdef PYTHON
#if defined(DEBUG_C) || defined(MAIN_C) || defined(PYTHON_C)
LS void do_python(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_pythonscript(COMMAND_ARGS) __page(CMD1_SEG);
LS int python_parse_jump(char *, char *, Hook *) __page(CORE_SEG);
LS int python_timer_jump(Hook *) __page(CORE_SEG);
LS void python_dcc_complete(Client *, int) __page(CORE_SEG);
LS PyObject *python_hook(PyObject *, PyObject *, PyObject *) __page(CMD1_SEG);
LS PyObject *python_unhook(PyObject *, PyObject *, PyObject *) __page(CMD1_SEG);
LS PyObject *python_to_server(PyObject *, PyObject *, PyObject *) __page(CORE_SEG);
LS PyObject *python_to_file(PyObject *, PyObject *, PyObject *) __page(CORE_SEG);
LS PyObject *python_userlevel(PyObject *, PyObject *, PyObject *) __page(CORE_SEG);
LS PyObject *python_debug(PyObject *, PyObject *) __page(DBUG_SEG);
LS void init_python(void) __page(CFG1_SEG);
LS void free_python(void) __page(CFG1_SEG);
#endif /* defined */
#endif /* PYTHON */
/*
*
*/
#ifdef RAWDNS
LS void do_dns(COMMAND_ARGS) __page(CMD1_SEG);
LS void init_rawdns(void) __page(INIT_SEG); /* INIT */
LS void process_rawdns(void) __page(CORE_SEG);
LS void rawdns(const char *) __page(CORE_SEG);
LS void select_rawdns(void) __page(CORE_SEG);
LS char *poll_rawdns(char *) __page(CORE_SEG);
LS void parse_query(int, dnsQuery *) __page(CORE_SEG);
LS void do_dnsserver(COMMAND_ARGS) __page(CMD1_SEG);
LS void do_dnsroot(COMMAND_ARGS) __page(CMD1_SEG);
LS int read_dnsroot(char *) __page(CFG1_SEG);
LS ulong rawdns_get_ip(const char *) __page(CORE_SEG);
#endif /* RAWDNS */
/*
* fun with pipes (aka, REDIRECTS)
*/
#ifdef REDIRECT
LS int begin_redirect(char *, char *) __page(CORE_SEG);
LS void send_redirect(char *) __page(CMD1_SEG);
LS void end_redirect(void) __page(CORE_SEG);
#endif /* REDIRECT */
/*
* RESET recover is not a defined feature?
*/
LS char *recover_client(char *) __page(INIT_SEG); /* INIT */
LS char *recover_debug(char *) __page(INIT_SEG); /* INIT */
LS char *recover_server(char *) __page(INIT_SEG); /* INIT */
LS void recover_reset(void) __page(INIT_SEG); /* INIT */
/*
*
*/
#ifdef SEEN
LS void make_seen(char *, char *, char *, char *, time_t, int) __page(CORE_SEG); /* SEEN */
#endif /* SEEN */
/*
*
*/
#ifdef STATS
LS void stats_loghour(Chan *, char *, int) __page(CORE_SEG);
LS void stats_plusminususer(Chan *, int) __page(CORE_SEG);
LS void do_info(COMMAND_ARGS) __page(CMD1_SEG);
#endif /* STATS */
/*
* Scripts-R-Us
*/
#ifdef TCL
LS void do_tcl(COMMAND_ARGS) __page(CMD1_SEG); /* TCL + PLEASE_HACK_MY_SHELL */
LS char *tcl_var_read() __page(CORE_SEG);
LS char *tcl_var_write() __page(CORE_SEG);
LS int tcl_parse_jump() __page(CORE_SEG);
LS int tcl_timer_jump() __page(CORE_SEG);
LS void tcl_dcc_complete(Client *, int) __page(CORE_SEG);
LS int tcl_hook() __page(CMD1_SEG);
LS int tcl_unhook() __page(CMD1_SEG);
LS int tcl_to_server() __page(CORE_SEG);
LS int tcl_to_file() __page(CORE_SEG);
LS int tcl_userlevel() __page(CORE_SEG);
LS int tcl_debug() __page(DBUG_SEG);
LS void init_tcl(void) __page(CFG1_SEG);
#endif /* TCL */
#ifdef TELNET
int check_telnet(int, char *) __page(CMD1_SEG);
void check_telnet_pass(Client *, char *) __page(CMD1_SEG);
#endif /* TELNET */
#ifdef TOYBOX
LS int read_bigcharset(char *) __page(CMD1_SEG);
LS int read_bigcharset_callback(char *) __page(CMD1_SEG);
#endif /* TOYBOX */
#ifdef TRIVIA
LS char *random_question(char *) __page(CORE_SEG);
LS int trivia_score_callback(char *) __page(CMD1_SEG);
LS void hint_one(void) __page(CMD1_SEG);
LS void hint_three(void) __page(CMD1_SEG);
LS void hint_two(void) __page(CMD1_SEG);
LS void read_triviascore(void) __page(CMD1_SEG);
LS void trivia_check(Chan *, char *) __page(CORE_SEG);
LS void trivia_cleanup(void) __page(CORE_SEG);
LS void trivia_no_answer(void) __page(CORE_SEG);
LS void trivia_question(void) __page(CORE_SEG);
LS void trivia_tick(void) __page(CORE_SEG);
LS void trivia_week_toppers(void) __page(CORE_SEG);
LS void write_triviascore(void) __page(CMD1_SEG);
#endif /* TRIVIA */
/*
* UPTIME prototypes
*/
#ifdef UPTIME
LS void init_uptime(void) __page(INIT_SEG); /* INIT */
LS void process_uptime(void) __page(CORE_SEG);
LS void uptime_death(int) __page(RARE_SEG); /* rare */
#endif /* UPTIME */
/*
* WEB prototypes
*/
#ifdef WEB
LS char *webread(int, char *, char *) __page(CORE_SEG);
LS void eml_fmt(WebSock *, char *) __page(CORE_SEG);
LS void select_web(void) __page(CORE_SEG);
LS void parse(WebSock *, char *) __page(CORE_SEG);
LS void process_web(void) __page(CORE_SEG);
LS void web_404(WebSock *, char *) __page(CORE_SEG);
LS void web_raw(WebSock *, char *) __page(CORE_SEG);
LS void web_botstatus(WebSock *, char *) __page(CORE_SEG);
LS void web_debug(WebSock *, char *) __page(DBUG_SEG);
#endif /* WEB */
#endif /* H_H */

262
src/help.c Normal file
View File

@@ -0,0 +1,262 @@
/*
EnergyMech, IRC bot software
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 HELP_C
#include "config.h"
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
#include "usage.h"
void print_help(char *from, char *line, int len)
{
char *lp;
int tl;
tl = TRUE;
if ((strlen(line) + len) > 70)
{
lp = line;
while(*lp)
{
if (*lp == '\037')
tl = !tl;
if (tl)
*lp = tolowertab[(uchar)*lp];
lp++;
}
to_user(from,FMT_PLAIN,line);
*line = 0;
}
}
int do_help_callback(char *line)
{
#ifdef DEBUG
debug("(do_help_callback) `%s'\n",line);
#endif /* DEBUG */
table_buffer(FMT_PLAIN,line);
return(FALSE);
}
void do_help(COMMAND_ARGS)
{
char line[MSGLEN];
char *pt;
int i,level,axs;
int cur,nxt,count,ci,tl;
int in;
if (dcc_only_command(from))
return;
axs = get_maxaccess(from);
if (!*rest)
{
cur = -1;
*line = 0;
help_loop:
count = 0;
nxt = OWNERLEVEL;
for(i=0;mcmd[i].name;i++)
{
tl = acmd[i];
if ((tl < nxt) && (tl > cur))
nxt = tl;
if (tl != cur)
continue;
if (count == 0)
sprintf(line,"\037Level %3i\037: ",cur);
count++;
}
if (!count)
{
cur = nxt;
goto help_loop;
}
ci = count;
for(i=0;mcmd[i].name;i++)
{
tl = acmd[i];
if (tl != cur)
continue;
if (ci != count)
Strcat(line,", ");
print_help(from,line,strlen(mcmd[i].name));
if (*line == 0)
Strcpy(line," ");
Strcat(line,(char*)mcmd[i].name);
count--;
}
print_help(from,line,500);
if ((cur != OWNERLEVEL) && (nxt <= axs))
cur = nxt;
else
return;
goto help_loop;
}
level = a2i(rest);
if (!errno)
{
if ((level > axs) || (level < 0))
level = axs;
to_user(from,"\037Commands available at Level %i:\037",level);
*line = 0;
ci = 0;
for(i=0;mcmd[i].name;i++)
{
if (acmd[i] <= level)
{
if (ci != 0)
Strcat(line,", ");
ci++;
print_help(from,line,strlen(mcmd[i].name));
Strcat(line,(char*)mcmd[i].name);
}
}
if (ci)
print_help(from,line,58);
else
to_user(from,TEXT_NONE);
return;
}
if (STRCHR(rest,'*'))
{
line[0] = 0;
ci = 0;
to_user(from,"\037Commands that match query %s\037:",rest);
for(i=0;mcmd[i].name;i++)
{
if ((!matches(rest,(char*)mcmd[i].name)) && (acmd[i] <= axs))
{
if (ci != 0)
Strcat(line,", ");
ci++;
print_help(from,line,strlen(mcmd[i].name));
Strcat(line,(char*)mcmd[i].name);
}
}
if (ci)
print_help(from,line,500);
else
to_user(from,TEXT_NONE);
return;
}
/*
* We dont want to show help for "../../../../../../etc/passwd"
*/
if (!is_safepath(rest))
return;
pt = Strcpy(line,HELPDIR);
for(i=0;(rest[i]);i++)
{
if (rest[i] >= 'a' && rest[i] <= 'z')
*pt = rest[i] - 0x20;
else
*pt = rest[i];
pt++;
}
*pt = 0;
#ifdef DEBUG
debug("(do_help) help file check: %s\n",line);
#endif /* DEBUG */
if ((in = open(line,O_RDONLY)) < 0)
{
to_user(from,"No help found for \"%s\"",rest);
return;
}
#ifdef DEBUG
debug("(do_help) helpfile for = '%s'\n",rest);
#endif /* DEBUG */
table_buffer("\037Help on %s\037",rest);
level = access_needed(rest);
if (level > 200)
table_buffer("Level needed: Command disabled");
else
if (level > 0)
table_buffer("Level needed: %i",level);
for(i=0;ulist[i].command;i++)
{
if (!Strcasecmp(rest,ulist[i].command))
{
pt = (ulist[i].usage) ? ulist[i].usage : "";
table_buffer("Usage: %s %s",ulist[i].command,pt);
break;
}
}
readline(in,&do_help_callback); /* readline closes in */
table_send(from,0);
}
void usage_command(char *to, const char *arg)
{
char *pt;
int i;
for(i=0;ulist[i].command;i++)
{
if (!Strcasecmp(arg,ulist[i].command))
{
pt = ulist[i].usage;
to_user_q(to,(pt) ? "Usage: %s %s" : "Usage: %s",ulist[i].command,pt);
return;
}
}
to_user(to,"Usage: (missing)");
}
__attr(CMD1_SEG,__regparm(1))
void usage(char *to)
{
CurrentChan = NULL;
usage_command(to,CurrentCmd->name);
}
void do_usage(COMMAND_ARGS)
{
/*
* on_msg checks: CARGS
*/
char *cmd;
int i;
cmd = chop(&rest);
for(i=0;mcmd[i].name;i++)
{
if (!Strcasecmp(cmd,mcmd[i].name))
{
usage_command(from,mcmd[i].name);
return;
}
}
to_user_q(from,"Unknown command: %s",cmd);
}

137
src/irc.c Normal file
View File

@@ -0,0 +1,137 @@
/*
EnergyMech, IRC bot software
Parts Copyright (c) 1997-2009 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 IRC_C
#include "config.h"
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
/*
* nick can be NULL
*/
void make_ireq(int t, char *from, char *nick)
{
IReq *ir;
char *pt;
set_mallocdoer(make_ireq);
ir = (IReq*)Calloc(sizeof(IReq) + Strlen2(from,nick));
ir->t = t;
ir->when = now;
pt = Strcat(ir->from,from) + 1;
if (nick)
{
ir->nick = pt;
Strcpy(ir->nick,nick);
}
ir->next = current->parselist;
current->parselist = ir;
}
void send_pa(int type, const char *nick, const char *format, ...)
{
char text[MAXLEN];
va_list vargs;
IReq *ir,**pp;
int pr,end;
pr = 0;
end = type & PA_END;
type = type & PA_TYPE;
for(pp=&current->parselist;(ir = *pp);)
{
#ifdef RAWDNS
if (ir->t == PA_DNS && !Strcasecmp(nick,ir->nick))
{
#ifdef DEBUG
debug("(send_pa) PA_DNS %s\n",ir->nick);
ir->nick = (char *)nick;
#endif /* DEBUG */
}
#endif /* RAWDNS */
if (ir->t == type && (!nick || !nickcmp(nick,ir->nick)))
{
if (format)
{
if (!pr++)
{
va_start(vargs,format);
vsprintf(text,format,vargs);
va_end(vargs);
}
to_user(ir->from,FMT_PLAIN,text);
}
if (end)
{
*pp = ir->next;
Free((char**)&ir);
continue;
}
}
pp=&ir->next;
}
}
/*
*
* commands that parse irc replies
*
*/
void do_irclusers(COMMAND_ARGS)
{
to_server("LUSERS\n");
make_ireq(PA_LUSERS,from,NULL);
}
void do_ircstats(COMMAND_ARGS)
{
/*
* on_msg checks: DCC + CARGS
*/
char *line,*serv;
line = chop(&rest);
serv = chop(&rest);
to_server((serv) ? "STATS %s %s\n" : "STATS %s\n",line,serv);
make_ireq(PA_STATS,from,NULL);
}
void do_ircwhois(COMMAND_ARGS)
{
/*
* on_msg checks: CARGS
*/
char *nick;
nick = chop(&rest);
to_server("WHOIS %s\n",nick);
make_ireq((CurrentCmd->name == C_WHOIS) ? PA_WHOIS : PA_USERHOST,from,nick);
}

265
src/kicksay.c Normal file
View File

@@ -0,0 +1,265 @@
/*
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 KICKSAY_C
#include "config.h"
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
KickSay *find_kicksay(char *text, char *channel)
{
KickSay *kick,*save;
int num,best;
save = NULL;
best = 0;
for(kick=current->kicklist;kick;kick=kick->next)
{
if (!channel || *kick->chan == '*' || !Strcasecmp(channel,kick->chan))
{
num = num_matches(kick->mask,text);
if (num > best)
{
best = num;
save = kick;
}
}
}
return(save);
}
void check_kicksay(Chan *chan, ChanUser *doer, char *text)
{
KickSay *kick,*save;
char *mask;
int action;
save = NULL;
action = -1;
for(kick=current->kicklist;kick;kick=kick->next)
{
if (*kick->chan == '*' || !Strcasecmp(chan->name,kick->chan))
{
if (!matches(kick->mask,text))
{
if (kick->action > action)
{
action = kick->action;
save = kick;
}
}
}
}
if (save)
{
if (!action)
{
if (doer->flags & CU_KSWARN)
action = 1;
if (!(doer->flags & CU_KSWARN))
{
doer->flags |= CU_KSWARN;
to_server("NOTICE %s :%s\n",doer->nick,save->reason);
}
}
if (action > 1)
{
mask = format_uh(get_nuh(doer),FUH_USERHOST);
if (action > 2)
{
add_shit("Auto KS",chan->name,mask,save->reason,2,now+3600);
}
if (!(doer->flags & CU_BANNED))
{
doer->flags |= CU_BANNED;
send_mode(chan,90,QM_RAWMODE,'+','b',mask);
}
}
if (action && !(doer->flags & CU_KICKED))
{
doer->flags |= CU_KICKED;
send_kick(chan,CurrentNick,FMT_PLAIN,save->reason);
}
}
}
void remove_kicksay(KickSay *kick)
{
KickSay **pp;
pp = &current->kicklist;
while(*pp)
{
if (*pp == kick)
{
*pp = kick->next;
Free((char**)&kick);
return;
}
pp = &(*pp)->next;
}
}
void purge_kicklist(void)
{
while(current->kicklist)
remove_kicksay(current->kicklist);
}
/*
*
* kicksay commands
*
*/
#ifdef NEWBIE
char *ks_actions[MAX_KS_LEVEL+1] = { "warn (0)","kick (1)","kickban (2)","autoshit (3)" };
#else
char *ks_actions[MAX_KS_LEVEL+1] = { "warn","kick","kickban","autoshit" };
#endif /* NEWBIE */
void do_kicksay(COMMAND_ARGS)
{
/*
* on_msg checks: CARGS
*/
KickSay *kick;
char *channel,*mask;
int inum;
channel = chop(&rest);
if (!channel)
{
if (!current->kicklist)
{
to_user(from,"Kicksay list is empty");
return;
}
if (dcc_only_command(from))
return;
table_buffer("\037channel\037\t\037action\037\t\037string\037\t\037kick reason\037");
for(kick=current->kicklist;kick;kick=kick->next)
{
table_buffer("%s\t%s\t%s\t%s",kick->chan,ks_actions[kick->action],kick->mask,kick->reason);
}
table_send(from,2);
return;
}
if (ischannel(channel) || *channel == '*')
{
if (get_useraccess(from,channel) < cmdaccess)
return;
inum = DEFAULT_KS_LEVEL;
if (*rest != '"')
{
inum = a2i(chop(&rest));
if (errno || inum < 0 || inum > MAX_KS_LEVEL)
return;
}
mask = get_token(&rest,"\"");
if (!mask || !*mask)
goto usage;
/*
* check for previously existing kicks
*/
if ((kick = find_kicksay(mask,channel)) != NULL)
{
to_user(from,"I'm already kicking on \"%s\"",kick->mask);
return;
}
/*
* dig out the reason (the rest)
*/
while(rest && *rest == ' ')
rest++;
if (!*rest)
goto usage;
/*
* add it to the list
*/
set_mallocdoer(do_kicksay);
kick = (KickSay*)Calloc(sizeof(KickSay) + Strlen(channel,mask,rest,NULL));
kick->next = current->kicklist;
current->kicklist = kick;
kick->action = inum;
if (!matches("\\*?*\\*",mask))
kick->chan = Strcpy(kick->mask,mask) + 1;
else
{
kick->mask[0] = '*';
Strcpy(kick->mask+1,mask);
kick->chan = Strcat(kick->mask,MATCH_ALL) + 1;
}
kick->reason = Strcpy(kick->chan,channel) + 1;
Strcpy(kick->reason,rest);
to_user(from,"Now kicking on \"%s\" on %s",mask,channel);
current->ul_save++;
return;
}
usage:
usage(from); /* usage for CurrentCmd->name */
}
void do_rkicksay(COMMAND_ARGS)
{
/*
* on_msg checks: CARGS
*/
KickSay *kick;
char *channel;
channel = chop(&rest); /* cant be NULL (CARGS) */
if (!ischannel(channel) && *channel != '*')
goto usage;
if (!*rest)
goto usage;
if (!(kick = find_kicksay(rest,channel)))
{
to_user(from,"I'm not kicking on that");
return;
}
to_user(from,"No longer kicking on %s",kick->mask);
remove_kicksay(kick);
current->ul_save++;
return;
usage:
usage(from); /* usage for CurrentCmd->name */
}

105
src/ld/mech.ldscript Normal file
View File

@@ -0,0 +1,105 @@
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(_start)
SEARCH_DIR(/lib);
SEARCH_DIR(/usr/lib);
SEARCH_DIR(/usr/local/lib);
SECTIONS
{
. = 0x08048000 + SIZEOF_HEADERS;
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) }
.rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) }
.rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) }
.rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) }
.rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
.rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.bss : { *(.rel.bss) }
.rela.bss : { *(.rela.bss) }
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
.init : { *(.init) } =0x9090
.plt : { *(.plt) }
.text :
{
*(.text)
*(.text.d) /* INIT */
*(.text.e) /* RARE */
*(.text.c) /* CMD1 */
*(.text.a) /* CORE */
*(.text.f) /* DBUG */
*(.text.b) /* CFG1 */
*(.stub)
*(.gnu.warning)
*(.gnu.linkonce.t*)
} =0x9090
_etext = .;
PROVIDE (etext = .);
.fini : { *(.fini) } =0x9090
.rodata : { *(.rodata) *(.gnu.linkonce.r*) }
.rodata1 : { *(.rodata1) }
. = ALIGN(0x1000) + (. & (0x1000 - 1));
.data :
{
*(.data)
*(.gnu.linkonce.d*)
CONSTRUCTORS
}
.data1 : { *(.data1) }
.ctors : { *(.ctors) }
.dtors : { *(.dtors) }
.got : { *(.got.plt) *(.got) }
.dynamic : { *(.dynamic) }
.sdata : { *(.sdata) }
_edata = .;
PROVIDE (edata = .);
__bss_start = .;
.sbss : { *(.sbss) *(.scommon) }
.bss :
{
*(.dynbss)
*(.bss)
*(COMMON)
}
. = ALIGN(32 / 8);
_end = . ;
PROVIDE (end = .);
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
}

1039
src/main.c Normal file

File diff suppressed because it is too large Load Diff

400
src/md5/md5.c Normal file
View File

@@ -0,0 +1,400 @@
/* md5.c */
/*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
*
* To compute the message digest of a chunk of bytes, declare an
* MD5Context structure, pass it to MD5Init, call MD5Update as
* needed on buffers full of bytes, and then call MD5Final, which
* will fill a supplied 16-byte array with the digest.
*/
#ifndef MD5_CRYPT_C
#define MD5_CRYPT_C
#include <string.h> /* for memcpy() */
#include "md5.h"
#ifndef HIGHFIRST
#define byteReverse(buf, len) /* Nothing */
#else
void byteReverse(unsigned char *buf, unsigned longs);
#ifndef ASM_MD5
/*
* Note: this code is harmless on little-endian machines.
*/
void
byteReverse(unsigned char *buf, unsigned longs)
{
uint32 t;
do {
t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
((unsigned) buf[1] << 8 | buf[0]);
*(uint32 *) buf = t;
buf += 4;
} while (--longs);
}
#endif
#endif
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
void
MD5Init(struct MD5Context *ctx)
{
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
ctx->bits[0] = 0;
ctx->bits[1] = 0;
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
void
MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
{
uint32 t;
/* Update bitcount */
t = ctx->bits[0];
if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
ctx->bits[1]++; /* Carry from low to high */
ctx->bits[1] += len >> 29;
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
if (t) {
unsigned char *p = (unsigned char *) ctx->in + t;
t = 64 - t;
if (len < t) {
memcpy(p, buf, len);
return;
}
memcpy(p, buf, t);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32 *) ctx->in);
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
while (len >= 64) {
memcpy(ctx->in, buf, 64);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32 *) ctx->in);
buf += 64;
len -= 64;
}
/* Handle any remaining bytes of data. */
memcpy(ctx->in, buf, len);
}
/*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
void
MD5Final(unsigned char digest[16], struct MD5Context *ctx)
{
unsigned count;
unsigned char *p;
/* Compute number of bytes mod 64 */
count = (ctx->bits[0] >> 3) & 0x3F;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = ctx->in + count;
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Pad out to 56 mod 64 */
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, count);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32 *) ctx->in);
/* Now fill the next block with 56 bytes */
memset(ctx->in, 0, 56);
} else {
/* Pad block to 56 bytes */
memset(p, 0, count - 8);
}
byteReverse(ctx->in, 14);
/* Append length in bits and transform */
((uint32 *) ctx->in)[14] = ctx->bits[0];
((uint32 *) ctx->in)[15] = ctx->bits[1];
MD5Transform(ctx->buf, (uint32 *) ctx->in);
byteReverse((unsigned char *) ctx->buf, 4);
memcpy(digest, ctx->buf, 16);
memset((char *) ctx, 0, sizeof(ctx)); /* In case it's sensitive */
}
#ifndef ASM_MD5
/* The four core functions - F1 is optimized somewhat */
/* #define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
void
MD5Transform(uint32 buf[4], uint32 const in[16])
{
register uint32 a, b, c, d;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
#endif
/* md5crypt.c */
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*/
/*
* Ported from FreeBSD to Linux, only minimal changes. --marekm
*/
static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static void
to64(char *s, unsigned long v, int n)
{
while (--n >= 0) {
*s++ = itoa64[v&0x3f];
v >>= 6;
}
}
/*
* UNIX password
*
* Use MD5 for what it is best at...
*/
char *md5_crypt(const char *pw, const char *salt)
{
static char *magic = "$1$"; /*
* This string is magic for
* this algorithm. Having
* it this way, we can get
* get better later on
*/
static char passwd[120], *p;
static const char *sp,*ep;
unsigned char final[16];
int sl,pl,i,j;
MD5_CTX ctx,ctx1;
unsigned long l;
/* Refine the Salt first */
sp = salt;
/* If it starts with the magic string, then skip that */
if(!strncmp(sp,magic,strlen(magic)))
sp += strlen(magic);
/* It stops at the first '$', max 8 chars */
for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++)
continue;
/* get the length of the true salt */
sl = ep - sp;
MD5Init(&ctx);
/* The password first, since that is what is most unknown */
MD5Update(&ctx,pw,strlen(pw));
/* Then our magic string */
MD5Update(&ctx,magic,strlen(magic));
/* Then the raw salt */
MD5Update(&ctx,sp,sl);
/* Then just as many characters of the MD5(pw,salt,pw) */
MD5Init(&ctx1);
MD5Update(&ctx1,pw,strlen(pw));
MD5Update(&ctx1,sp,sl);
MD5Update(&ctx1,pw,strlen(pw));
MD5Final(final,&ctx1);
for(pl = strlen(pw); pl > 0; pl -= 16)
MD5Update(&ctx,final,pl>16 ? 16 : pl);
/* Don't leave anything around in vm they could use. */
memset(final,0,sizeof final);
/* Then something really weird... */
for (j=0,i = strlen(pw); i ; i >>= 1)
if(i&1)
MD5Update(&ctx, final+j, 1);
else
MD5Update(&ctx, pw+j, 1);
/* Now make the output string */
strcpy(passwd,magic);
strncat(passwd,sp,sl);
strcat(passwd,"$");
MD5Final(final,&ctx);
/*
* and now, just to make sure things don't run too fast
* On a 60 Mhz Pentium this takes 34 msec, so you would
* need 30 seconds to build a 1000 entry dictionary...
*/
for(i=0;i<1000;i++) {
MD5Init(&ctx1);
if(i & 1)
MD5Update(&ctx1,pw,strlen(pw));
else
MD5Update(&ctx1,final,16);
if(i % 3)
MD5Update(&ctx1,sp,sl);
if(i % 7)
MD5Update(&ctx1,pw,strlen(pw));
if(i & 1)
MD5Update(&ctx1,final,16);
else
MD5Update(&ctx1,pw,strlen(pw));
MD5Final(final,&ctx1);
}
p = passwd + strlen(passwd);
l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4;
l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4;
l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4;
l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4;
l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4;
l = final[11] ; to64(p,l,2); p += 2;
*p = '\0';
/* Don't leave anything around in vm they could use. */
memset(final,0,sizeof final);
return passwd;
}
#endif /* MD5_CRYPT_C */

27
src/md5/md5.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef MD5_H
#define MD5_H
#ifdef __alpha
typedef unsigned int uint32;
#else
typedef unsigned long uint32;
#endif
struct MD5Context {
uint32 buf[4];
uint32 bits[2];
unsigned char in[64];
};
void MD5Init(struct MD5Context *context);
void MD5Update(struct MD5Context *context, unsigned char const *buf,
unsigned len);
void MD5Final(unsigned char digest[16], struct MD5Context *context);
void MD5Transform(uint32 buf[4], uint32 const in[16]);
/*
* This is needed to make RSAREF happy on some MS-DOS compilers.
*/
typedef struct MD5Context MD5_CTX;
#endif /* !MD5_H */

53
src/mega.c Normal file
View File

@@ -0,0 +1,53 @@
#define MAIN_C
#include "config.h"
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
#undef MAIN_C
#define VARS_C
#include "settings.h"
#undef VARS_C
#include "alias.c"
#include "auth.c"
#include "bounce.c"
#include "chanban.c"
#include "channel.c"
#include "core.c"
#include "ctcp.c"
#include "debug.c"
#include "dns.c"
#include "dynamode.c"
#include "function.c"
#include "greet.c"
#include "help.c"
#include "irc.c"
#include "kicksay.c"
#include "main.c"
#include "net.c"
#include "net_chan.c"
#include "note.c"
#include "notify.c"
#include "ons.c"
#include "parse.c"
#include "perl.c"
#include "prot.c"
#include "python.c"
#include "redirect.c"
#include "reset.c"
#include "seen.c"
#include "shit.c"
#include "socket.c"
#include "spy.c"
#include "stats.c"
#include "tcl.c"
#include "telnet.c"
#include "toybox.c"
#include "trivia.c"
#include "uptime.c"
#include "user.c"
#include "vars.c"
#include "web.c"

1585
src/net.c Normal file

File diff suppressed because it is too large Load Diff

144
src/net_chan.c Normal file
View File

@@ -0,0 +1,144 @@
/*
EnergyMech, IRC bot software
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 NET_C
#include "config.h"
#ifdef BOTNET
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
ChanUser *find_chanbot(Chan *chan, char *nick)
{
ChanUser *cu;
if (chan->cacheuser && !nickcmp(nick,chan->cacheuser->nick)
&& chan->cacheuser->user && chan->cacheuser->user->x.x.access == BOTLEVEL)
return(chan->cacheuser);
for(cu=chan->users;cu;cu=cu->next)
{
if (cu->user && cu->user->x.x.access == BOTLEVEL)
{
if (!nickcmp(nick,cu->nick))
return(chan->cacheuser = cu);
}
}
return(NULL);
}
void check_botjoin(Chan *chan, ChanUser *cu)
{
BotNet *bn;
BotInfo *binfo;
#ifdef DEBUG
debug("(check_botjoin) chan = %s; cu = %s!%s\n",chan->name,cu->nick,cu->userhost);
#endif /* DEBUG */
for(bn=botnetlist;bn;bn=bn->next)
{
if (bn->status != BN_LINKED)
continue;
for(binfo=bn->botinfo;binfo;binfo=binfo->next)
{
if (!nickcmp(cu->nick,binfo->nuh) &&
!Strcasecmp(cu->userhost,getuh(binfo->nuh)))
{
if ((cu = find_chanbot(chan,binfo->nuh)) == NULL)
return;
cu->flags |= CU_NEEDOP;
send_mode(chan,50,QM_CHANUSER,'+','o',(void*)cu);
#ifdef DEBUG
debug("(check_botjoin) CU_NEEDOP set, mode pushed\n");
#endif /* DEBUG */
return;
}
}
}
}
void check_botinfo(BotInfo *binfo, const char *channel)
{
Chan *chan;
ChanUser *cu;
Mech *backup;
char *userhost;
userhost = getuh(binfo->nuh);
backup = current;
for(current=botlist;current;current=current->next)
{
for(chan=current->chanlist;chan;chan=chan->next)
{
if (channel && Strcasecmp(channel,chan->name))
continue;
if ((cu = find_chanbot(chan,binfo->nuh)) == NULL)
continue;
if (!Strcasecmp(cu->userhost,userhost))
{
cu->flags |= CU_NEEDOP;
send_mode(chan,50,QM_CHANUSER,'+','o',(void*)cu);
}
}
}
current = backup;
}
/*
*
* protocol routines
*
*/
void netchanNeedop(BotNet *source, char *rest)
{
BotNet *bn;
BotInfo *binfo;
char *channel;
int guid;
guid = a2i(chop(&rest));
channel = chop(&rest);
if (errno || guid < 1 || !channel)
return;
botnet_relay(source,"CO%i %s\n",guid,channel);
for(bn=botnetlist;bn;bn=bn->next)
{
if (bn->status != BN_LINKED)
continue;
for(binfo=bn->botinfo;binfo;binfo=binfo->next)
{
if (binfo->guid == guid)
check_botinfo(binfo,channel);
}
}
}
#endif /* BOTNET */

215
src/note.c Normal file
View File

@@ -0,0 +1,215 @@
/*
EnergyMech, IRC bot software
Copyright (c) 2001-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 NOTE_C
#include "config.h"
#ifdef NOTE
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
int catch_note(char *from, char *to, char *rest)
{
User *u;
Note *n,**pp;
Strp *sp,**np;
#ifdef DEBUG
debug("(catch_note) from = %s, to = %s, rest = %s\n",from,to,rest);
#endif /* DEBUG */
pp = &notelist;
while(*pp)
{
n = *pp;
#ifdef DEBUG
debug("(catch_note) n->from = %s, n->to = %s\n",n->from,n->to);
#endif /* DEBUG */
if (!Strcasecmp(from,n->from) && !Strcasecmp(to,n->to))
{
#ifdef DEBUG
debug("(catch_note) note to user = %s\n",n->user);
#endif /* DEBUG */
if (!Strcasecmp(rest,"."))
{
to_user(from,"Note for %s has been saved",n->user);
*pp = n->next;
Free((char**)&n);
return(TRUE);
}
if (!(u = find_handle(n->user)))
return(TRUE);
np = &u->note;
while(*np)
np = &(*np)->next;
set_mallocdoer(catch_note);
*np = sp = (Strp*)Calloc(sizeof(Strp) + strlen(rest));
/* Calloc sets to zero sp->next = NULL; */
Strcpy(sp->p,rest);
return(TRUE);
}
if ((now - n->start) > 120)
{
*pp = n->next;
Free((char**)&n);
return(TRUE);
}
pp = &(*pp)->next;
}
return(FALSE);
}
/*
*
*
*
*/
void do_note(COMMAND_ARGS)
{
User *u;
Note *n;
Strp *sp,**np;
char header[MSGLEN];
/*
* no-args is handled in on_msg()
*/
if (!(u = find_handle(rest)))
{
to_user(from,TEXT_UNKNOWNUSER,rest);
return;
}
to_user(from,"Enter your note for %s, end with \".\" on a line by itself",
u->name);
set_mallocdoer(do_note);
n = Calloc(sizeof(Note) + Strlen(from,to,u->name,NULL));
n->start = now;
n->next = notelist;
notelist = n;
/*
* custom Strcat makes it sooooo easy
*/
n->to = Strcat(n->from,from) + 1;
n->user = Strcat(n->to,to) + 1;
Strcpy(n->user,rest);
/*
* add a note header
*/
sprintf(header,"\001%s %s",from,time2str(now));
np = &u->note;
while(*np)
np = &(*np)->next;
set_mallocdoer(do_note);
*np = sp = (Strp*)Calloc(sizeof(Strp) + strlen(header));
/* Calloc sets to zero sp->next = NULL; */
Strcpy(sp->p,header);
}
void do_read(COMMAND_ARGS)
{
Strp *sp,**pp;
User *user;
char *opt,*sender;
int which,n,sz;
if (CurrentDCC)
user = CurrentUser;
else
if ((user = get_authuser(from,ANY_CHANNEL)) == NULL)
return;
sz = n = 0;
for(sp=user->note;sp;sp=sp->next)
{
if (*sp->p == 1)
n++;
else
sz += strlen(sp->p);
}
if (rest && (opt = chop(&rest)))
{
which = a2i(opt);
if (errno || !which)
goto read_usage;
if (which < -n || which > n)
{
to_user(from,"invalid message number");
return;
}
n = 0;
pp = &user->note;
while(*pp)
{
sp = *pp;
if (*sp->p == 1)
n++;
if (which == n)
{
opt = sp->p + 1;
sender = chop(&opt);
to_user(from,"From: %s on %s",sender,opt);
opt[-1] = ' ';
to_user(from," ");
sp = sp->next;
while(sp && *sp->p != 1)
{
to_user(from,FMT_PLAIN,sp->p);
sp = sp->next;
}
to_user(from," ");
return;
}
else
if (which == -n)
{
while(TRUE)
{
*pp = sp->next;
Free((char**)&sp);
sp = *pp;
if (!sp || *sp->p == 1)
break;
}
to_user(from,"message number %i has been deleted",-which);
return;
}
}
}
to_user(from,(n) ? "you have %i message%s (%i bytes)" : "you have no messages",n,(n == 1) ? "" : "s",sz);
return;
read_usage:
usage(from); /* usage for CurrentCmd->name */
}
#endif /* NOTE */

755
src/notify.c Normal file
View File

@@ -0,0 +1,755 @@
/*
EnergyMech, IRC bot software
Copyright (c) 2001-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 NOTIFY_C
#include "config.h"
#ifdef NOTIFY
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#define CHOOSE_NUMBER 25
#define CHOOSE_MOVETO (CHOOSE_NUMBER - 2)
#define LOGFILENAMEFMT "notify-guid%i.log"
#define LOGFILENAMEBUF 32 /* need to recalculate this if LOGFILENAMEFMT is changed */
LS Notify **endoflist;
LS int lock_ison = FALSE;
void purge_notify(void)
{
Notify *nf;
nfLog *nlog;
/*
* empty the notifylist
*/
while(current->notifylist)
{
nf = current->notifylist;
current->notifylist = nf->next;
while(nf->log)
{
nlog = nf->log;
nf->log = nlog->next;
Free((char**)&nlog);
}
Free((char**)&nf);
}
}
int mask_check(Notify *nf, char *userhost)
{
char *mask,*rest;
int ret;
/*
* no mask (NULL)
*/
if (!nf->mask)
return(NF_MASKONLINE);
ret = NF_NOMATCH;
if (nf->endofmask)
{
/*
* multiple masks separated by spaces
*/
mask = rest = nf->mask;
chop(&rest);
}
else
{
/*
* single mask
*/
if (!matches(nf->mask,userhost))
ret = NF_MASKONLINE;
return(ret);
}
while(mask)
{
if (!matches(mask,userhost))
{
ret = NF_MASKONLINE;
break;
}
mask = chop(&rest);
}
if (nf->endofmask)
{
/*
* undo the chop()'s
*/
for(mask=nf->mask;mask<nf->endofmask;mask++)
{
if (*mask == 0)
*mask = ' ';
}
}
return(ret);
}
void send_ison(void)
{
Notify *nf,*chosen[CHOOSE_NUMBER];
char isonmsg[MSGLEN];
char *p,*src;
int i,x,period;
/*
* dont send nicks to ISON too often
*/
period = current->setting[INT_ISONDELAY].int_var;
x = now - current->lastnotify;
if ((x < period) || (lock_ison && (x < 600)))
return;
current->lastnotify = now;
/*
* the nature of the code makes it so that the first NULL is
* pushed further down the list as more entries are added,
* so no need to blank the whole list
*/
chosen[0] = NULL;
/*
* select the oldest (CHOOSE_NUMBER) nicks for an update
*/
for(nf=current->notifylist;nf;nf=nf->next)
{
for(i=0;i<CHOOSE_NUMBER;i++)
{
if (!chosen[i] || (chosen[i]->checked > nf->checked))
{
for(x=CHOOSE_MOVETO;x>=i;x--)
chosen[x+1] = chosen[x];
chosen[i] = nf;
break;
}
}
}
if (chosen[0])
{
p = isonmsg;
for(i=0;i<CHOOSE_NUMBER;i++)
{
/*
* drop out once the end-of-chosen-list NULL is found
*/
if (!chosen[i])
break;
chosen[i]->checked = 1;
src = chosen[i]->nick;
if (i) *(p++) = ' ';
while((*p = *(src++))) p++;
}
to_server("ISON :%s\n",isonmsg);
lock_ison = TRUE;
}
}
void catch_ison(char *rest)
{
Notify *nf;
char whoismsg[MSGLEN];
char *nick,*dst;
lock_ison = FALSE;
*whoismsg = 0;
dst = whoismsg;
while((nick = chop(&rest)))
{
for(nf=current->notifylist;nf;nf=nf->next)
{
if (!nickcmp(nf->nick,nick))
{
nf->checked = now;
/*
* /whois user to get user@host + realname
*/
if (nf->status == NF_OFFLINE)
{
if (*whoismsg) *(dst++) = ',';
*dst = 0;
dst = Strcat(dst,nf->nick);
nf->status = NF_WHOIS;
}
}
}
}
if (*whoismsg)
to_server("WHOIS %s\n",whoismsg);
for(nf=current->notifylist;nf;nf=nf->next)
{
if (nf->checked == 1)
{
nf->checked = now;
if (nf->status >= NF_WHOIS)
{
/*
* close the log entry for this online period
*/
if (nf->log && nf->log->signon && !nf->log->signoff)
nf->log->signoff = now;
/*
* announce that the user is offline if its a mask match
*/
if (nf->status == NF_MASKONLINE)
send_spy(SPYSTR_STATUS,"Notify: %s is offline",nf->nick);
nf->status = NF_OFFLINE;
}
}
}
}
void catch_whois(char *nick, char *userhost, char *realname)
{
Notify *nf;
nfLog *nlog;
if (!realname || !*realname)
realname = "unknown";
for(nf=current->notifylist;nf;nf=nf->next)
{
if ((nf->status == NF_WHOIS) && !nickcmp(nf->nick,nick))
{
/*
* put in a new log entry
*/
set_mallocdoer(catch_whois);
nlog = (nfLog*)Calloc(sizeof(nfLog) + Strlen2(userhost,realname));
nlog->signon = now;
nlog->next = nf->log;
nf->log = nlog;
nlog->realname = Strcat(nlog->userhost,userhost) + 1;
Strcpy(nlog->realname,realname);
/*
* if there is a mask, we need a match to announce the online status
*/
nf->status = mask_check(nf,userhost);
if (nf->status == NF_MASKONLINE)
send_spy(SPYSTR_STATUS,"Notify: %s (%s) is online",nf->nick,userhost);
return;
}
}
}
/*
*
* saving and loading notify information
*
*/
int notifylog_callback(char *rest)
{
Notify *nf;
nfLog *nlog,**pp;
time_t on,off;
char *nick,*userhost;
if (*rest == COMMENT_CHAR)
return(FALSE);
nick = chop(&rest);
on = a2i(chop(&rest));
if (errno)
return(FALSE);
off = a2i(chop(&rest));
if (errno)
return(FALSE);
userhost = chop(&rest);
if (rest && *rest == ':')
rest++;
if (!*rest)
return(FALSE);
for(nf=current->notifylist;nf;nf=nf->next)
{
if (!nickcmp(nick,nf->nick))
{
pp = &nf->log;
while(*pp)
{
if ((*pp)->signon < on)
break;
pp = &(*pp)->next;
}
set_mallocdoer(notifylog_callback);
nlog = (nfLog*)Calloc(sizeof(nfLog) + Strlen2(userhost,rest));
nlog->signon = on;
nlog->signoff = off;
nlog->next = *pp;
*pp = nlog;
nlog->realname = Strcat(nlog->userhost,userhost) + 1;
Strcpy(nlog->realname,rest);
break;
}
}
return(FALSE);
}
void read_notifylog(void)
{
char fname[LOGFILENAMEBUF];
int fd;
#ifdef DEBUG
int dd;
#endif /* DEBUG */
sprintf(fname,LOGFILENAMEFMT,current->guid);
if ((fd = open(fname,O_RDONLY)) < 0)
return;
#ifdef DEBUG
dd = dodebug;
dodebug = FALSE;
#endif /* DEBUG */
readline(fd,&notifylog_callback); /* readline closes fd */
#ifdef DEBUG
dodebug = dd;
#endif /* DEBUG */
}
void write_notifylog(void)
{
Notify *nf;
nfLog *nlog;
char fname[LOGFILENAMEBUF];
int fd;
#ifdef DEBUG
int dd;
#endif /* DEBUG */
sprintf(fname,LOGFILENAMEFMT,current->guid);
if ((fd = open(fname,O_WRONLY|O_CREAT|O_TRUNC,NEWFILEMODE)) < 0)
return;
#ifdef DEBUG
dd = dodebug;
dodebug = FALSE;
#endif /* DEBUG */
for(nf=current->notifylist;nf;nf=nf->next)
{
to_file(fd,COMMENT_STRCHR "\n" COMMENT_STRCHR " Nick: %s\n",nf->nick);
if (nf->info)
to_file(fd,COMMENT_STRCHR " Note: %s\n",nf->info);
if (nf->mask)
to_file(fd,COMMENT_STRCHR " Mask: %s\n",nf->mask);
to_file(fd,COMMENT_STRCHR "\n");
for(nlog=nf->log;nlog;nlog=nlog->next)
{
to_file(fd,"%s %lu %lu %s :%s\n",nf->nick,nlog->signon,
(nlog->signoff) ? nlog->signoff : now,
nlog->userhost,nlog->realname);
}
}
close(fd);
#ifdef DEBUG
dodebug = dd;
#endif /* DEBUG */
}
int notify_callback(char *rest)
{
Notify *nf;
char *nick;
char *src,*dst;
char *lspace;
errno = EINVAL;
if (!rest || *rest == COMMENT_CHAR)
return(FALSE);
fix_config_line(rest);
if ((nick = chop(&rest)) == NULL)
return(FALSE);
#ifdef DEBUG
debug("(notify_callback) parsing %s `%s'\n",nick,nullstr(rest));
#endif /* DEBUG */
lspace = rest - 1;
src = dst = rest;
while(*src)
{
if (*src == ' ')
{
if (!lspace)
{
lspace = dst;
*(dst++) = *src;
}
src++;
}
else
if (*src == ':' && lspace)
{
*lspace = 0;
break;
}
else
{
lspace = NULL;
*(dst++) = *(src++);
}
}
if (*src == ':')
*(src++) = 0;
if (!*src)
src = NULL;
#ifdef DEBUG
debug("(notify_callback) creating struct\n");
#endif /* DEBUG */
/*
* nick = nick
* rest = mask(s) or *rest == 0
* src = description or NULL
*/
set_mallocdoer(notify_callback);
nf = (Notify*)Calloc(sizeof(Notify) + Strlen(nick,rest,src,NULL));
dst = Strcat(nf->nick,nick);
if (*rest)
{
nf->mask = dst + 1;
dst = Strcat(nf->mask,rest);
if (STRCHR(nf->mask,' '))
nf->endofmask = dst;
}
if (src)
{
nf->info = dst + 1;
Strcpy(nf->info,src);
}
/* put it at the end of notifylist */
*endoflist = nf;
endoflist = &nf->next;
errno = 0;
return(FALSE);
}
int read_notify(char *filename)
{
int fd;
if (!filename)
return(FALSE);
if ((fd = open(filename,O_RDONLY)) < 0)
return(FALSE);
/*
* save online logs
*/
if (current->notifylist)
write_notifylog();
/*
* delete the whole list
*/
purge_notify();
endoflist = &current->notifylist;
readline(fd,&notify_callback); /* readline closes fd */
/*
* read back online logs
*/
read_notifylog();
return(TRUE);
}
/*
*
* commands...
*
*/
#define NF_OPTIONS 7
LS const char notify_opt[NF_OPTIONS][10] =
{
"-ALL",
"-NOMATCH",
"-RELOAD",
"-FULL",
"-SEEN",
};
#define NFF_ALL 1
#define NFF_NOMATCH 2
#define NFF_RELOAD 4
#define NFF_FULL 8
#define NFF_SEEN 16
LS char *nf_from;
LS int nf_header;
void nfshow_brief(Notify *nf)
{
time_t when;
char mem[40];
char *s;
int d,h,m;
if (nf->status == NF_NOMATCH)
s = " nickname in use";
else
if (nf->status >= NF_WHOIS)
s = " online now";
else
if (nf->log && nf->log->signoff)
{
s = mem;
when = now - nf->log->signoff;
d = when / 86400;
h = (when -= d * 86400) / 3600;
m = (when -= h * 3600) / 60;
sprintf(mem,"%2i day%1s %02i:%02i ago",d,EXTRA_CHAR(d),h,m);
}
else
s = " never seen";
if (!nf_header)
to_user(nf_from,"\037nick\037 \037last seen\037 \037note\037");
to_user(nf_from,(nf->info) ? "%-9s %-22s %s" : "%-9s %s",
nf->nick,s,nf->info);
nf_header++;
}
void nfshow_full(Notify *nf)
{
char mem[MSGLEN];
nfLog *nlog;
char *s,*opt;
if (nf_header)
to_user(nf_from," ");
to_user(nf_from,(nf->status == NF_MASKONLINE) ? "Nick: \037%s\037" : "Nick: %s",nf->nick);
if (nf->info)
to_user(nf_from,"Note: %s",nf->info);
if (nf->mask)
to_user(nf_from,"Mask: %s",nf->mask);
if (nf->log)
{
to_user(nf_from,"Online history:");
for(nlog=nf->log;nlog;nlog=nlog->next)
{
opt = mem;
s = time2away(nlog->signon);
if (s[1] == ':')
*(opt++) = ' ';
*opt = 0;
opt = Strcat(opt,s);
while(opt < (mem+18))
*(opt++) = ' ';
*opt = 0;
opt = Strcat(opt," -- ");
if (nlog->signoff)
{
s = time2away(nlog->signoff);
if (s[1] == ':')
*(opt++) = ' ';
*opt = 0;
}
else
{
s = " online now";
}
opt = Strcat(opt,s);
while(opt < (mem+41))
*(opt++) = ' ';
*opt = 0;
s = (nlog->realname) ? "%s: %s (%s)" : "%s: %s";
to_user(nf_from,s,mem,nlog->userhost,nlog->realname);
}
}
nf_header++;
}
void sub_notifynick(char *from, char *rest)
{
Notify *nf,**pp;
char *nick;
int i;
nick = chop(&rest);
if (!nick)
{
usage(from);
return;
}
i = 0;
pp = &current->notifylist;
while(*pp)
{
nf = *pp;
if (!nickcmp(nick,nf->nick))
{
*pp = nf->next;
Free((char**)&nf);
i++;
}
else
{
pp = &nf->next;
}
}
if (!i)
to_user(from,"Nick not found: %s",nick);
else
to_user(from,"Nick removed from notify: %s",nick);
}
void do_notify(COMMAND_ARGS)
{
char message[MSGLEN];
Notify *nf;
nfLog *nlog;
char *opt;
int n,flags;
nf_from = from;
flags = nf_header = 0;
*message = 0;
if (*rest)
{
while((opt = chop(&rest)))
{
if (!Strcmp(opt,"+"))
{
endoflist = &current->notifylist;
while(*endoflist)
endoflist = &(*endoflist)->next;
notify_callback(rest);
return;
}
if (!Strcmp(opt,"-"))
{
sub_notifynick(from,rest);
return;
}
for(n=0;n<NF_OPTIONS;n++)
{
if (!Strcasecmp(notify_opt[n],opt))
{
flags |= (1 << n);
break;
}
}
if (n>=NF_OPTIONS)
{
for(nf=current->notifylist;nf;nf=nf->next)
{
if (!nickcmp(opt,nf->nick))
{
if (flags & NFF_FULL)
nfshow_full(nf);
else
nfshow_brief(nf);
break;
}
}
if (!nf)
{
if (*message)
Strcat(message,", ");
Strcat(message,opt);
}
nf_header++;
}
}
}
if (*message)
{
#ifdef DEBUG
debug("(do_notify) dumping errnames\n");
#endif /* DEBUG */
to_user(from,"User%s not found: %s",(STRCHR(message,',')) ? "s" : "",message);
}
if (nf_header)
return;
if (flags & NFF_RELOAD)
{
opt = current->setting[STR_NOTIFYFILE].str_var;
if (opt && read_notify(opt))
{
flags = get_useraccess(from,"");
send_spy(SPYSTR_STATUS,"Notify: %s reloaded by %s[%i]",
opt,CurrentNick,flags);
to_user(from,"notify list read from file %s",opt);
}
else
{
to_user(from,"notify list could not be read from file %s",nullstr(opt));
}
return;
}
for(nf=current->notifylist;nf;nf=nf->next)
{
if ((nf->status == NF_MASKONLINE) || (flags & NFF_ALL) || ((flags & NFF_NOMATCH) && (nf->status == NF_NOMATCH)))
goto show_it;
if ((flags & NFF_SEEN) && nf->log)
{
for(nlog=nf->log;nlog;nlog=nlog->next)
{
if (mask_check(nf,nlog->userhost) == NF_MASKONLINE)
goto show_it;
}
}
continue;
show_it:
if (flags & NFF_FULL)
nfshow_full(nf);
else
nfshow_brief(nf);
}
if (!nf_header)
{
to_user(from,"no notify users are online");
}
}
#endif /* NOTIFY */

1163
src/ons.c Normal file

File diff suppressed because it is too large Load Diff

1497
src/parse.c Normal file

File diff suppressed because it is too large Load Diff

184
src/perl.c Normal file
View File

@@ -0,0 +1,184 @@
/*
EnergyMech, IRC bot software
Copyright (c) 2001-2009 proton
Copyright (c) 2001 MadCamel
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 PERL_C
#include "config.h"
#ifdef PERL
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "perl.h"
PerlInterpreter *energymech_perl = NULL;
/*
* parse_jump() translates from C to perl
*/
int perl_parse_jump(char *from, char *rest, Hook *hook)
{
dSP; /* Declare a local stack pointer */
char *args[3];
#ifdef DEBUG
debug("(perl_parse_jump) %s %s %s\n",
nullstr(hook->self),nullstr(from),nullstr(rest));
#endif /* DEBUG */
args[0] = (*from && from) ? from : ""; /* Nulls are a no-no */
args[1] = rest;
args[2] = NULL;
/* Call_argv returns the # of args returned from perl */
if (call_argv(Hook->self, G_EVAL|G_SCALAR, args) < 1)
return(0);
SPAGAIN; /* Rehash stack, it's probably been clobbered */
return(POPi); /* Pop an int */
}
/*
* accept 2 arguments
* char *name = name of the IRC input to hook (PRIVMSG, NOTICE, PING, JOIN, PART, etc..)
* char *subroutine = name of the function that should be called in the script for each of the
* hooked input lines (coming from parseline())
*
* this function should be made directly callable from the script as "parse_hook" or similar
*/
/* Don't ask! You don't want to know! */
XS(XS_perl_parse_hook)
{
Hook *hook;
char *name, *sub;
int c;
dXSARGS; items = 0;
/*
* translate *name and *sub from perl variables to C strings
* SvPV(ST(0)) returns a string(char) pointer to the first arg.
* but I don't know if it's safe to point directly in to perl
* space like that.
*/
if ((name = strdup(SvPV(ST(0), i)))) == NULL)
XSRETURN_EMPTY;
if ((sub = strdup(SvPV(ST(0), i)))) == NULL)
{
free(name);
XSRETURN_EMPTY;
}
/*
* make a Hook struct and link it into the parse hook list
*/
set_mallocdoer(perl_parse_hook);
hook = (Hook*)Calloc(sizeof(Hook) + Strlen2(name,sub));
hook->func = perl_parse_jump;
hook->next = hooklist;
hooklist = hook;
hook->command = Strcpy(hook->self,sub) + 1;
Strcpy(hook->command,name);
free(name);
free(sub);
/*
* return successful status to script
* I don't know how to return a number so I return the sub name.
*/
XST_mPV(0, sub);
XSRETURN(1);
}
void init_perl(void)
{
energymech_perl = perl_alloc();
perl_construct(energymech_perl);
/*
* make parse_hook() callable from scripts
*/
newXS("mech::parse_hook", XS_perl_parse_hook, "mech");
}
void do_perl(COMMAND_ARGS)
{
/*
* call init_perl() if the perl interpreter isnt initialized yet
*/
/*
* call the perl interpreter with the content of *rest
*/
/*
* be verbose about success or fail to the user
*/
}
void do_perlscript(COMMAND_ARGS)
{
char *args[2];
dSP;
/*
* call init_perl() if the perl interpreter isnt initialized yet
*/
/*
* chop(&rest) for name of script filename and load it into the perl interpreter
*/
args[0] = "";
args[1] = chop(&rest);
/* FIXME: Trap parse errors */
perl_parse(energymech_perl, NULL, 1, argv, (char **)NULL);
/* Call sub named Init, what should contain
* mech::perl_parse_hook("PRIVMSG", "yoink_privmsg");
* Note to self: Wouldn't it be better to pass subs by
* Reference(perl ver of pointer) instead of name?
* How the fsck do i do that?!
*/
call_pv("Init", G_EVAL|G_NOARGS);
if(SvTRUE(ERRSV))
{
STRLEN n_a;
to_user(from, "perl script %s failed to init: %s",
argv[1], SvPV(ERRSV, n_a));
}
/*
* be verbose about success or fail to the user
*/
}
#endif /* PERL */

610
src/prot.c Normal file
View File

@@ -0,0 +1,610 @@
/*
EnergyMech, IRC bot software
Parts Copyright (c) 1997-2009 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 PROTECTION_C
#include "config.h"
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
/*
*
* kicking and screaming
*
*/
void send_kick(Chan *chan, const char *nick, const char *format, ...)
{
qKick *new,**pp;
va_list vargs;
/*
* gsockdata safe to use since we're a `tail' function
*/
va_start(vargs,format);
vsprintf(gsockdata,format,vargs);
va_end(vargs);
pp = &chan->kicklist;
while(*pp)
pp = &(*pp)->next;
set_mallocdoer(send_kick);
*pp = new = (qKick*)Calloc(sizeof(qKick) + Strlen2(nick,gsockdata));
/* Calloc sets to zero new->next = NULL; */
new->reason = Strcpy(new->nick,nick) + 1;
Strcpy(new->reason,gsockdata);
}
void push_kicks(Chan *chan)
{
qKick *kick;
int n;
n = (current->sendq_time - now);
while(n < 6)
{
if ((kick = chan->kicklist) == NULL)
return;
chan->kicklist = kick->next;
to_server("KICK %s %s :%s\n",chan->name,kick->nick,kick->reason);
Free((char**)&kick);
n += 2;
}
}
void unmode_chanuser(Chan *chan, ChanUser *cu)
{
qMode *mode,**pp;
pp = &chan->modelist;
while(*pp)
{
mode = *pp;
if ((mode->type == QM_CHANUSER) && (mode->data == (void*)cu))
{
*pp = mode->next;
Free((char**)&mode);
/*
* there might be more modes associated with this chanuser
*/
continue;
}
pp = &mode->next;
}
}
void send_mode(Chan *chan, int pri, int type, char plusminus, char modeflag, void *data)
{
qMode *mode,**pp;
#ifdef NO_DEBUG
debug("(send_mode) chan = %s; pri = %i; type = %i; plusminus = %c; modeflag = %c; data = "mx_pfmt"\n",
chan->name,pri,type,plusminus,modeflag,(mx_ptr)data);
#endif /* DEBUG */
/*
* make minusmodes always one priority lower than plusmodes
*/
if (plusminus == '-')
pri |= 1;
pp = &chan->modelist;
while(*pp)
{
mode = *pp;
if (mode->pri == pri)
{
/*
* check for duplicate
*/
if ((mode->type == type) && (mode->plusminus == plusminus) &&
(mode->modeflag == modeflag) && (mode->data == data))
return;
}
if (mode->pri > pri)
break;
pp = &mode->next;
}
set_mallocdoer(send_mode);
mode = (qMode*)Calloc(sizeof(qMode));
mode->next = *pp;
*pp = mode;
mode->pri = pri;
mode->type = type;
mode->plusminus = plusminus;
mode->modeflag = modeflag;
switch(type)
{
case QM_CHANUSER:
mode->data = data;
break;
default:
if (data)
{
set_mallocdoer(send_mode);
mode->data = (void*)Strdup((char*)data);
}
else
{
mode->data = NULL;
}
}
}
int mode_effect(Chan *chan, qMode *mode)
{
ChanUser *cu;
int f;
if (mode->type == QM_CHANUSER)
{
cu = (ChanUser*)mode->data;
f = 0;
switch(mode->modeflag)
{
case 'o':
f = (cu->flags & CU_CHANOP) ? '+' : '-';
break;
case 'v':
f = (cu->flags & CU_VOICE) ? '+' : '-';
break;
}
if (f && f == mode->plusminus)
return(FALSE);
}
return(TRUE);
}
void push_modes(Chan *chan, int lowpri)
{
qMode *mode;
char flaglist[32],parmlist[MSGLEN];
char *dstflag,*dstparm,*srcparm,lastmode;
int n,maxmodes;
n = (current->sendq_time - now);
loop:
maxmodes = current->setting[INT_MODES].int_var;
lastmode = 0;
dstflag = flaglist;
dstparm = parmlist;
while((mode = chan->modelist))
{
/*
* if the line has already been partially filled,
* then its ok to fill up "empty slots" with non-priority modes.
*/
if (lowpri && !lastmode && (mode->pri >= QM_PRI_LOW))
return;
chan->modelist = mode->next;
if (mode_effect(chan,mode))
{
switch(mode->type)
{
case QM_CHANUSER:
srcparm = ((ChanUser*)mode->data)->nick;
break;
default:
srcparm = (char*)mode->data;
}
if (mode->plusminus != lastmode)
*(dstflag++) = lastmode = mode->plusminus;
*(dstflag++) = mode->modeflag;
if (srcparm)
{
*(dstparm++) = ' ';
dstparm = Strcpy(dstparm,srcparm);
}
maxmodes--;
}
#ifdef NO_DEBUG
else
{
debug("(push_modes) ineffectual mode: %c%c %s\n",mode->plusminus,mode->modeflag,
(mode->type == QM_CHANUSER) ? ((ChanUser*)mode->data)->nick : (char*)mode->data);
}
#endif /* DEBUG */
if (mode->type != QM_CHANUSER)
Free((char**)&mode->data);
Free((char**)&mode);
if (!maxmodes)
break;
}
if (!lastmode)
return;
*dstflag = 0;
*dstparm = 0;
/*
* the missing space is not a bug.
*/
to_server("MODE %s %s%s\n",chan->name,flaglist,parmlist);
n += 2;
if (lowpri && n < lowpri)
goto loop;
}
void update_modes(Chan *chan)
{
ChanUser *cu;
for(cu=chan->users;cu;cu=cu->next)
{
if (
(chan->setting[TOG_AOP].int_var && cu->user && cu->user->x.x.aop) ||
((cu->flags & (CU_CHANOP|CU_NEEDOP)) == CU_NEEDOP)
)
{
#ifdef NO_DEBUG
debug("(update_modes) pushing: MODE %s +o %s!%s\n",
chan->name,cu->nick,cu->userhost);
#endif /* DEBUG */
send_mode(chan,50,QM_CHANUSER,'+','o',(void*)cu);
}
}
}
/*
* check_mass() takes no action, it only touches the abuse counters
* and timers, TRUE is returned if the limit is reached
*/
int check_mass(Chan *chan, ChanUser *doer, int type)
{
time_t *when;
int *num,limit;
/*
* must handle servers ...
*/
if (!doer)
return(FALSE);
if (doer->user && doer->user->x.x.access >= ASSTLEVEL)
return(FALSE);
if ((type == INT_CKL || type == INT_FL) && (doer->flags & CU_CHANOP))
return(FALSE);
limit = chan->setting[type].int_var;
switch(type)
{
/*
* two things we dont want channel users to do
*/
//case CHK_CAPS:
case INT_CKL:
num = &doer->capsnum;
break;
//case CHK_PUB:
case INT_FL:
num = &doer->floodnum;
break;
/*
* three things we dont want channel ops to do
*/
//case CHK_DEOP:
case INT_MDL:
num = &doer->deopnum;
break;
//case CHK_BAN:
case INT_MBL:
num = &doer->bannum;
break;
default:
/* case CHK_KICK: */
/* case INT_MKL: */
num = &doer->kicknum;
break;
}
when = (time_t*)&num[1];
if ((now - *when) > 10)
{
*when = now;
*num = 0;
}
++(*num);
if (*num >= limit && limit)
return(TRUE);
return(FALSE);
}
void mass_action(Chan *chan, ChanUser *doer)
{
int mpl;
if ((mpl = chan->setting[INT_MPL].int_var) == 0)
return;
if (mpl >= 2)
{
if (0 == (doer->flags & CU_DEOPPED) || 0 == (doer->flags & CU_BANNED))
{
deop_ban(chan,doer,NULL);
doer->flags |= CU_DEOPPED|CU_BANNED;
}
}
if (0 == (doer->flags & CU_KICKED))
{
send_kick(chan,CurrentNick,KICK_MASSMODES);
doer->flags |= CU_KICKED;
}
}
void prot_action(Chan *chan, char *from, ChanUser *doer, char *target, ChanUser *victim)
{
int maxprot,uprot;
/*
* cant do anything to a user that isnt on the channel
* doer is normally supplied, but not always
*/
if (!doer)
{
if ((doer = find_chanuser(chan,from)) == NULL)
return;
}
/*
* No protective measures for doers with high access
*/
if (doer->user && doer->user->x.x.access >= ASSTLEVEL)
return;
maxprot = chan->setting[INT_PROT].int_var;
if (victim)
uprot = (victim->user) ? victim->user->x.x.prot : 0;
else
{
uprot = get_protaction(chan,target);
}
if ((uprot >= 4) && (!(doer->flags & CU_BANNED)))
{
doer->flags |= CU_BANNED|CU_DEOPPED;
deop_ban(chan,doer,NULL);
}
if ((uprot >= 3) && (!(doer->flags & CU_KICKED)))
{
doer->flags |= CU_KICKED;
send_kick(chan,doer->nick,"\002%s is Protected\002",(target) ? target : get_nuh(victim));
}
/*
* with (uprot == 2) our ONLY action is to deop the guilty party
*/
if ((uprot == 2) && (!(doer->flags & CU_DEOPPED)))
{
doer->flags |= CU_DEOPPED;
send_mode(chan,50,QM_CHANUSER,'-','o',(void*)doer);
}
}
/*
*
* mode commands
*
*/
void do_opdeopme(COMMAND_ARGS)
{
/*
* on_msg checks CAXS
*/
Chan *chan;
ChanUser *cu;
if ((chan = CurrentChan) && chan->bot_is_op)
{
if ((cu = find_chanuser(chan,from)))
{
send_mode(chan,80,QM_CHANUSER,
(CurrentCmd->name == C_DOWN) ? '-' : '+','o',cu);
}
}
}
void do_opvoice(COMMAND_ARGS)
{
/*
* on_msg checks CAXS + CARGS
*/
Chan *chan;
char *m;
if ((chan = CurrentChan) && chan->bot_is_op)
{
/* rest can only be NULL on OP/VOICE commands,
DEOP/UNVOICE commands require arguments (CARGS) */
if (!*rest)
rest = CurrentNick;
m = CurrentCmd->cmdarg;
#ifdef DEBUG
debug("(do_opvoice) Chan '%s', sign %c, mode %c, rest '%s'\n",chan->name,m[1],m[0],rest);
#endif /* DEBUG */
channel_massmode(chan,rest,MODE_FORCE,m[1],m[0]);
}
}
void do_kickban(COMMAND_ARGS)
{
/*
* on_msg checks CAXS + CARGS + ACCHAN
*/
Chan *chan;
ChanUser *victim;
const char *m;
char *nick,*nuh;
uchar c;
int uaccess;
nick = chop(&rest);
chan = CurrentChan;
/*
* is the bot opped on that channel?
*/
if (!chan->bot_is_op)
return;
if ((victim = find_chanuser(chan,nick)) == NULL)
return;
if (*rest == 0)
{
if ((rest = randstring(RANDKICKSFILE)) == NULL)
rest = KICK_DEFAULT;
}
m = CurrentCmd->cmdarg;
c = *(m++);
uaccess = get_authaccess(from,to);
if (victim->user && victim->user->x.x.access > uaccess)
{
nuh = get_nuh(victim);
send_kick(chan,CurrentNick,"%s attempt of %s",m,nuh);
return;
}
if (c & 0x4)
send_kick(chan,nick,FMT_PLAIN,rest);
switch(c & 0x3)
{
case 0:
deop_ban(chan,victim,NULL);
break;
case 1:
deop_siteban(chan,victim);
break;
case 2:
deop_screwban(chan,victim);
break;
}
m = STREND(m)+1;
to_user(from,"%s %sed on %s",nick,m,to);
}
void do_unban(COMMAND_ARGS)
{
/*
* on_msg checks: CAXS
*/
Ban *ban;
Chan *chan;
char *nick,*nuh;
nick = (rest) ? chop(&rest) : NULL;
if (((chan = find_channel_ac(to)) == NULL) || !chan->bot_is_op)
return;
if (nick && STRCHR(nick,'*'))
{
channel_massunban(chan,nick,0);
return;
}
if (!nick)
{
to_user(from,"You have been unbanned on %s",to);
nuh = from;
}
else
{
if ((nuh = nick2uh(from,nick)) == NULL)
return;
to_user(from,"%s unbanned on %s",nuh,to);
}
for(ban=chan->banlist;ban;ban=ban->next)
{
if (!matches(ban->banstring,nuh))
{
send_mode(chan,90,QM_RAWMODE,'-','b',(void*)ban->banstring);
}
}
}
void do_banlist(COMMAND_ARGS)
{
/*
* on_msg checks CAXS
*/
Ban *ban;
Chan *chan = CurrentChan;
#ifdef IRCD_EXTENSIONS
char *s;
if (chan->banlist)
{
table_buffer(str_underline("channel") "\t" str_underline("type") "\t" str_underline("mask") "\t" str_underline("set by"));
for(ban=chan->banlist;ban;ban=ban->next)
{
#ifdef NEWBIE
if (ban->imode)
s = "invitelist";
else
if (ban->emode)
s = "ban exception";
else
s = "ban";
#else /* NEWBIE */
if (ban->imode)
s = "I";
else
if (ban->emode)
s = "e";
else
s = "b";
#endif /* NEWBIE */
table_buffer("%s\t%s\t%s\t%s",to,s,ban->banstring,ban->bannedby);
}
table_send(from,2);
}
else
to_user(from,"There are no active bans/exceptions on %s",to);
#else /* IRCD_EXTENSIONS */
if (chan->banlist)
{
table_buffer(str_underline("channel") "\t\037ban mask\037\t\037set by\037");
for(ban=chan->banlist;ban;ban=ban->next)
table_buffer("%s\t%s\t%s",to,ban->banstring,ban->bannedby);
table_send(from,2);
}
else
to_user(from,"There are no active bans on %s",to);
#endif /* IRCD_EXTENSIONS */
}

973
src/python.c Normal file
View File

@@ -0,0 +1,973 @@
/*
EnergyMech, IRC bot software
Copyright (c) 2009 Nemesis128 <stnsls@gmail.com>
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.
*/
/* Python scripting backend for Energymech
by Nemesis128 <stnsls@gmail.com>
*/
#define PYTHON_C
#include "config.h"
#ifdef PYTHON
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
#define PYVAR_guid 0
#define PYVAR_currentnick 1
#define PYVAR_botnick 2
#define PYVAR_wantnick 3
#define PYVAR_userhost 4
#define PYVAR_server 5
#define PYVAR_nextserver 6
#define PYVAR_currentchan 7
#if PY_MAJOR_VERSION >= 3
char *python_unicode2char(PyUnicodeObject *obj)
{ /* try to get a valid char* from PyUnicode object.
returned str must be free'd afterwards. */
int sz = PyUnicode_GET_SIZE(obj);
wchar_t *wcs = (wchar_t*) malloc(sizeof(wchar_t) * sz);
PyUnicode_AsWideChar(obj, wcs, sz);
char *cs = (char*) malloc(sizeof(char) * (sz + 1));
wcstombs(cs, wcs, sz);
cs[sz] = '\0';
free(wcs);
return cs;
}
#endif /* Py3k */
static PyObject *python_error; /* emech exception object */
static PyObject *python_getvar(PyObject *self, PyObject *args)
{ /* get some global var */
#ifdef DEBUG
if (!current)
{
PyErr_SetString(python_error, "(python_getvar) No current bot?!");
return NULL;
}
#endif /* DEBUG */
int vartype;
if (!PyArg_ParseTuple(args, "i", &vartype))
return NULL;
switch (vartype)
{
case PYVAR_guid:
return Py_BuildValue("i", current ? current->guid : -1);
case PYVAR_currentnick:
return Py_BuildValue("s", CurrentNick);
case PYVAR_botnick:
return Py_BuildValue("s", current && current->nick ? current->nick : "");
case PYVAR_wantnick:
return Py_BuildValue("s", current && current->wantnick ? current->wantnick : "");
case PYVAR_userhost:
return Py_BuildValue("s", current && current->userhost ? current->userhost : "");
case PYVAR_server:
return Py_BuildValue("i", current && current->server ? current->server : -1);
case PYVAR_nextserver:
return Py_BuildValue("i", current && current->nextserver ? current->nextserver : -1);
case PYVAR_currentchan:
return Py_BuildValue("s", current && current->activechan ? current->activechan->name : "");
default:
PyErr_SetString(python_error, "(python_getvar) invalid var");
return NULL;
}
}
/* From channel.c */
static PyObject *python_is_chanuser(PyObject *self, PyObject *args, PyObject *keywds)
/* Return True if $nick is on $chan, else False */
{
char *chan, *nick;
static char *kwlist[] = {"chan", "nick", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "ss", kwlist, &chan, &nick))
return NULL;
Chan *ch = (Chan*) find_channel(chan, CHAN_ANY);
if (!ch) Py_RETURN_FALSE;
ChanUser *cu = find_chanuser(ch, nick);
if (!cu) Py_RETURN_FALSE;
Py_RETURN_TRUE;
}
#if 0
static PyObject *python_do_join(PyObject *self, PyObject *args, PyObject *keywds)
/* Join a channel */
{
char *from, *to="", *rest;
int cmdaccess = 100;
static char *kwlist[] = {"from", "rest", "cmdaccess", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "ss|i", kwlist,
&from, &rest, &cmdaccess))
return NULL;
do_join(from, to, rest, cmdaccess);
Py_RETURN_NONE;
}
static PyObject *python_do_part(PyObject *self, PyObject *args, PyObject *keywds)
/* Part a channel */
{
char *from, *to, *rest="";
int cmdaccess = 100;
static char *kwlist[] = {"from", "to", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "ss", kwlist, &from, &to))
return NULL;
do_part(from, to, rest, cmdaccess);
Py_RETURN_NONE;
}
static PyObject *python_do_cycle(PyObject *self, PyObject *args, PyObject *keywds)
/* Cycle a channel */
{
char *from, *to, *rest="";
int cmdaccess = 100;
static char *kwlist[] = {"from", "to", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "ss", kwlist, &from, &to))
return NULL;
do_cycle(from, to, rest, cmdaccess);
Py_RETURN_NONE;
}
static PyObject *python_do_wall(PyObject *self, PyObject *args, PyObject *keywds)
/* Wall */
{
char *from, *to, *rest;
int cmdaccess = 100;
static char *kwlist[] = {"from", "to", "rest", "cmdaccess", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "sss|i", kwlist,
&from, &to, &rest, &cmdaccess))
return NULL;
do_wall(from, to, rest, cmdaccess);
Py_RETURN_NONE;
}
static PyObject *python_do_mode(PyObject *self, PyObject *args, PyObject *keywds)
/* Mode */
{
char *from, *to, *rest;
int cmdaccess = 100;
static char *kwlist[] = {"from", "to", "rest", "cmdaccess", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "sss|i", kwlist,
&from, &to, &rest, &cmdaccess))
return NULL;
do_mode(from, to, rest, cmdaccess);
Py_RETURN_NONE;
}
static PyObject *python_do_invite(PyObject *self, PyObject *args, PyObject *keywds)
/* Invite */
{
char *from, *to, *rest;
int cmdaccess = 100;
static char *kwlist[] = {"from", "to", "rest", "cmdaccess", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "sss|i", kwlist,
&from, &to, &rest, &cmdaccess))
return NULL;
do_invite(from, to, rest, cmdaccess);
Py_RETURN_NONE;
}
static PyObject *python_do_sayme(PyObject *self, PyObject *args, PyObject *keywds)
/* Say /me */
{
char *from, *to, *rest;
int cmdaccess = 100;
static char *kwlist[] = {"from", "to", "rest", "cmdaccess", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "sss|i", kwlist,
&from, &to, &rest, &cmdaccess))
return NULL;
do_sayme(from, to, rest, cmdaccess);
Py_RETURN_NONE;
}
static PyObject *python_do_topic(PyObject *self, PyObject *args, PyObject *keywds)
/* Set topic */
{
char *from, *to, *rest;
int cmdaccess = 100;
static char *kwlist[] = {"from", "to", "rest", "cmdaccess", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "sss|i", kwlist,
&from, &to, &rest, &cmdaccess))
return NULL;
do_topic(from, to, rest, cmdaccess);
Py_RETURN_NONE;
}
static PyObject *python_do_idle(PyObject *self, PyObject *args, PyObject *keywds)
/* Check idle time */
{
char *from, *to, *rest;
int cmdaccess = 100;
static char *kwlist[] = {"from", "to", "rest", "cmdaccess", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "sss|i", kwlist,
&from, &to, &rest, &cmdaccess))
return NULL;
do_idle(from, to, rest, cmdaccess);
Py_RETURN_NONE;
}
#endif /* 0 */
static PyObject *python_find_nuh(PyObject *self, PyObject *args, PyObject *keywds)
/* Find nuh */
{
char *nick, *nuh;
static char *kwlist[] = {"nick", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "s", kwlist, &nick))
return NULL;
nuh = find_nuh(nick);
if (nuh == NULL) Py_RETURN_NONE;
else return Py_BuildValue("s", nuh);
}
/* From core.c */
#if 0
static PyObject *python_do_die(PyObject *self, PyObject *args, PyObject *keywds)
{
char *from="", *to="", *rest="";
int cmdaccess=0;
static char *kwlist[] = {"from", "rest", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|s", kwlist, &from, &rest))
return NULL;
do_die(from, to, rest, cmdaccess);
Py_RETURN_NONE;
}
static PyObject *python_do_shutdown(PyObject *self, PyObject *args, PyObject *keywds)
{
char *from="", *to="", *rest="";
int cmdaccess=0;
static char *kwlist[] = {"from", "rest", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|s", kwlist, &from, &rest))
return NULL;
do_shutdown(from, to, rest, cmdaccess);
Py_RETURN_NONE;
}
static PyObject *python_do_server(PyObject *self, PyObject *args, PyObject *keywds)
/* Connect server */
{
char *from, *to, *rest;
int cmdaccess = 100;
static char *kwlist[] = {"from", "to", "rest", "cmdaccess", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "sss|i", kwlist,
&from, &to, &rest, &cmdaccess))
return NULL;
do_server(from, to, rest, cmdaccess);
Py_RETURN_NONE;
}
#endif /* 0 */
PyObject *python_hook(PyObject *self, PyObject *args, PyObject *keywds)
{
Hook *hook;
HookTimer hooktimer;
PyObject *cb, *funcname;
char *type, *command, *cbname;
int guid = 0, mode, sz1, sz2;
static char *kwlist[] = {"type", "command", "callback", "guid", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "ssO|i", kwlist,
&type, &command, &cb, &guid))
return NULL;
/* check callback function */
if (!PyFunction_Check(cb))
{
PyErr_SetString(python_error, "(python_hook) callback is not a function");
return NULL;
}
funcname = PyObject_GetAttrString(cb, "__name__"); /* new ref */
if (!funcname)
{
PyErr_SetString(python_error, "(python_hook) cant get function name");
return NULL;
}
#if PY_MAJOR_VERSION >= 3
cbname = python_unicode2char((PyUnicodeObject*) funcname);
#else
cbname = PyString_AsString(funcname); /* not a copy! */
#endif /* Py3k */
mode = strlen(type);
sz1 = strlen(command);
sz2 = strlen(cbname);
if (!mode || !sz1 || !sz2)
{
Py_DECREF(funcname);
#if PY_MAJOR_VERSION >= 3
free(cbname);
#endif /* Py3k */
PyErr_SetString(python_error, "(python_hook) invalid params");
return NULL;
}
if (!Strcasecmp(type, "command"))
mode = HOOK_COMMAND;
else
if (!Strcasecmp(type, "dcc_complete"))
mode = HOOK_DCC_COMPLETE;
else
if (!Strcasecmp(type, "parse"))
mode = HOOK_PARSE;
else
if (!Strcasecmp(type, "timer"))
{
if (compile_timer(&hooktimer, command) < 0)
{
Py_DECREF(funcname);
#if PY_MAJOR_VERSION >= 3
free(cbname);
#endif /* Py3k */
PyErr_SetString(python_error, "(python_hook) cant compile timer");
return NULL;
}
mode = HOOK_TIMER;
sz1 = sizeof(HookTimer);
}
else
{
Py_DECREF(funcname);
#if PY_MAJOR_VERSION >= 3
free(cbname);
#endif /* Py3k */
PyErr_SetString(python_error, "(python_hook) invalid hook type");
return NULL;
}
set_mallocdoer(python_hook);
hook = (Hook*) Calloc(sizeof(Hook) + sz1 + sz2);
hook->guid = guid;
hook->flags = mode;
hook->next = hooklist;
hooklist = hook;
hook->type.any = (void*) (Strcpy(hook->self, cbname) + 1);
switch(mode)
{
case HOOK_COMMAND:
case HOOK_PARSE:
Strcpy(hook->type.command, command);
hook->func = python_parse_jump;
break;
default:
/* case HOOK_TIMER: */
memcpy(hook->type.timer, &hooktimer, sizeof(HookTimer));
hook->func = python_timer_jump;
break;
}
#ifdef DEBUG
debug("(python_hook) hooked %s `%s' --> %s\n",
nullstr(type), nullstr(command), nullstr(cbname));
#endif /* DEBUG */
Py_DECREF(funcname);
#if PY_MAJOR_VERSION >= 3
free(cbname);
#endif /* Py3k */
Py_RETURN_NONE;
}
PyObject *python_unhook(PyObject *self, PyObject *args, PyObject *keywds)
{
return Py_BuildValue("i", 1);
}
int python_parse_jump(char *from, char *rest, Hook *hook)
{
int i;
PyObject *mainmod, *cb, *res;
#ifdef DEBUG
debug("(python_parse_jump) %s %s %s\n",
nullstr(hook->self), nullstr(from), nullstr(rest));
#endif /* DEBUG */
if (from)
nickcpy(CurrentNick, from);
else
*CurrentNick = 0;
/* get callback object */
mainmod = PyImport_AddModule("__main__");
if (!mainmod)
{
#ifdef DEBUG
debug("(python_parse_jump) cant get main module\n");
#endif /* DEBUG */
return 0; /* python exception has been set */
}
cb = PyDict_GetItemString(PyModule_GetDict(mainmod), hook->self);
if (!PyFunction_Check(cb))
{
#ifdef DEBUG
debug("(python_parse_jump) invalid callback function\n");
#endif /* DEBUG */
return 0;
}
/* call our function */
res = PyObject_CallFunction(cb, "ss", from, rest); /* new ref */
#if PY_MAJOR_VERSION >= 3
i = PyLong_AsLong(res);
#else
i = PyInt_AS_LONG(res);
#endif /* Py3k */
#ifdef DEBUG
debug("(python_parse_jump) result = %d\n", i);
#endif
Py_DECREF(res);
return i;
}
int python_timer_jump(Hook *hook)
{
return 0;
}
#ifdef DCC_FILE
void python_dcc_complete(Client *client, int cps)
{
PyObject *mainmod = NULL, *cb, *res;
Hook *hook;
for (hook = hooklist; hook; hook = hook->next)
{
if (hook->flags == HOOK_DCC_COMPLETE &&
hook->guid && current && hook->guid == current->guid)
{
/* get callback object */
if (!mainmod)
mainmod = PyImport_AddModule("__main__");
if (!mainmod)
{
#ifdef DEBUG
debug("(python_dcc_complete) cant get main module\n");
#endif /* DEBUG */
return; /* python exception has been set */
}
cb = PyDict_GetItemString(PyModule_GetDict(mainmod), hook->self);
if (!PyFunction_Check(cb))
{
#ifdef DEBUG
debug("(python_dcc_complete) invalid callback function\n");
#endif /* DEBUG */
return;
}
/* call our function */
res = PyObject_CallFunction(cb, "ssi",
client->whom, client->filename, cps); /* new ref */
#ifdef DEBUG
#if PY_MAJOR_VERSION >= 3
debug("(python_dcc_complete) result = %d\n", PyLong_AsLong(res));
#else
debug("(python_dcc_complete) result = %d\n", PyInt_AS_LONG(res));
#endif /* Py3k */
#endif /* DEBUG */
Py_DECREF(res);
}
}
}
#endif /* DCC_FILE */
PyObject *python_userlevel(PyObject *self, PyObject *args, PyObject *keywds)
{
#ifdef DEBUG
if (!current)
{
PyErr_SetString(python_error, "(python_userlevel) No current bot?!");
return NULL;
}
#endif /* DEBUG */
char *nuh, *chan;
int n;
static char *kwlist[] = {"nuh", "chan", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|s", kwlist, &nuh, &chan))
return NULL;
n = get_useraccess(nuh, chan);
return Py_BuildValue("i", n);
}
PyObject *python_to_server(PyObject *self, PyObject *args, PyObject *keywds)
{
#ifdef DEBUG
if (!current)
{
PyErr_SetString(python_error, "(python_to_server) No current bot?!");
return NULL;
}
#endif /* DEBUG */
Strp *sp, **pp;
char *line;
int sendqmax = -1, n, sz;
static char *kwlist[] = {"line", "sendqmax", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|i", kwlist, &line, &sendqmax))
return NULL;
#ifdef DEBUG
debug("(python_to_server) max = %i; line = %s\n", sendqmax, line);
#endif /* DEBUG */
sz = strlen(line);
if (sendqmax >= 0)
{
n = 0;
pp = &current->sendq;
while (*pp)
{
n++;
pp = &(*pp)->next;
}
if (sendqmax && n >= sendqmax) n = -n;
else
if (sz)
{
*pp = sp = (Strp*) Calloc(sizeof(Strp) + sz);
/* Calloc sets to zero sp->next = NULL; */
Strcpy(sp->p, line);
}
}
else
{
if ((n = write(current->sock, line, sz)) < 0)
{
#ifdef DEBUG
debug("(python_to_server) {%i} errno = %i\n", current->sock, errno);
#endif /* DEBUG */
close(current->sock);
current->sock = -1;
current->connect = CN_NOSOCK;
PyErr_SetString(python_error, "Socket error");
return NULL;
}
current->sendq_time += 2;
}
return Py_BuildValue("i", n);
}
PyObject *python_to_file(PyObject *self, PyObject *args, PyObject *keywds)
{
int fd, r;
char *txt;
static char *kwlist[] = {"fd", "text", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "is", kwlist, &fd, &txt))
return NULL;
r = write(fd, txt, strlen(txt));
return Py_BuildValue("i", r);
}
#ifdef DCC_FILE
static PyObject *python_dcc_sendfile(PyObject *self, PyObject *args, PyObject *keywds)
{
char *filename, *target;
int sz;
static char *kwlist[] = {"file", "target", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "ss", kwlist, &filename, &target))
return NULL;
if ((sz = dcc_sendfile(target, filename)) < 0)
{
PyErr_SetString(python_error, "(python_dcc_sendfile) error!");
return NULL;
}
return Py_BuildValue("i", sz);
}
#endif /* DCC_FILE */
#ifdef DEBUG
PyObject *python_debug(PyObject *self, PyObject *args)
{
PyObject *o;
if (!PyArg_ParseTuple(args, "O", &o))
return NULL;
o = PyObject_Repr(o);
if (!o)
{
debug("(python_debug) object has no __repr__ method\n");
Py_RETURN_NONE;
}
#if PY_MAJOR_VERSION >= 3
char *cs;
cs = python_unicode2char((PyUnicodeObject*) o);
debug("(python_debug) %s\n", cs);
free(cs);
#else
debug("(python_debug) %s\n", PyString_AsString(o));
#endif /* Py3k */
Py_RETURN_NONE;
}
#endif /* DEBUG */
#ifdef RAWDNS
int python_dns_jump(char *host, char *resolved, Hook *hook)
{
PyObject *mainmod, *cb, *res;
int i = 0;
#ifdef DEBUG
debug("(python_dns_jump) %s %s %s\n",
nullstr(hook->self), nullstr(host), nullstr(resolved));
#endif /* DEBUG */
/* get callback object */
mainmod = PyImport_AddModule("__main__");
if (!mainmod)
{
#ifdef DEBUG
debug("(python_dns_jump) cant get main module\n");
#endif /* DEBUG */
return 0; /* python exception has been set */
}
cb = PyDict_GetItemString(PyModule_GetDict(mainmod), hook->self);
if (!PyFunction_Check(cb))
{
#ifdef DEBUG
debug("(python_dns_jump) invalid callback function\n");
#endif /* DEBUG */
return 0;
}
/* call our function */
res = PyObject_CallFunction(cb, "ss", host, resolved); /* new ref */
#if PY_MAJOR_VERSION >= 3
i = PyLong_AsLong(res);
#else
i = PyInt_AS_LONG(res);
#endif /* Py3k */
#ifdef DEBUG
debug("(python_dns_jump) result = %d\n", i);
#endif /* DEBUG */
Py_DECREF(res);
return i;
}
static PyObject *python_dns(PyObject *self, PyObject *args, PyObject *keywds)
{
PyObject *cb, *funcname;
Hook *hook;
char *host, *cbname;
static char *kwlist[] = {"host", "callback", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "sO", kwlist, host, cb))
return NULL;
/* check callback function */
if (!PyFunction_Check(cb))
{
PyErr_SetString(python_error, "(python_dns) callback is not a function");
return NULL;
}
funcname = PyObject_GetAttrString(cb, "__name__"); /* new ref */
if (!funcname)
{
PyErr_SetString(python_error, "(python_dns) cant get function name");
return NULL;
}
#if PY_MAJOR_VERSION >= 3
cbname = python_unicode2char((PyUnicodeObject*) funcname);
#else
cbname = PyString_AsString(funcname); /* not a copy! */
#endif /* Py3k */
#ifdef DEBUG
debug("(python_dns) resolving: %s (callback %s)\n", host, cbname);
#endif /* DEBUG */
set_mallocdoer(python_dns);
hook = (Hook*)Calloc(sizeof(Hook) + strlen(host));
hook->guid = (current) ? current->guid : 0;
hook->flags = HOOK_DNS;
hook->next = hooklist;
hooklist = hook;
hook->type.host = Strcpy(hook->self, cbname) + 1;
Strcpy(hook->type.host, host);
hook->func = python_dns_jump;
rawdns(host);
#if PY_MAJOR_VERSION >= 3
free(cbname);
#endif /* Py3k */
Py_DECREF(funcname);
Py_RETURN_NONE;
}
#endif /* RAWDNS */
static PyObject *python_execute(PyObject *self, PyObject *args)
{
PyObject *cmd, *from, *to, *rest;
char *c_cmd, *c_from, *c_to, *c_rest;
int cmdaccess, i;
void (*found)(char*,char*,char*,int) = NULL;
if (!PyArg_ParseTuple(args, "OOOOi", &cmd, &from, &to, &rest, &cmdaccess))
return NULL;
/* check for 4 strings */
#if PY_MAJOR_VERSION >= 3
if (!PyUnicode_CheckExact(cmd)
|| !(PyUnicode_CheckExact(from))/* || Py_None == from)*/
|| !PyUnicode_CheckExact(to)
|| !PyUnicode_CheckExact(rest))
#else
if (!PyString_CheckExact(cmd)
|| !(PyString_CheckExact(from))/* || Py_None == from)*/
|| !PyString_CheckExact(to)
|| !PyString_CheckExact(rest))
#endif /* Py3k */
{
PyErr_SetString(python_error, "(python_execute) invalid arguments");
return NULL;
}
/* extract vars */
#if PY_MAJOR_VERSION >= 3
c_cmd = python_unicode2char((PyUnicodeObject*) cmd);
if (from != Py_None) c_from = python_unicode2char((PyUnicodeObject*) from);
c_to = python_unicode2char((PyUnicodeObject*) to);
c_rest = python_unicode2char((PyUnicodeObject*) rest);
#else
c_cmd = PyString_AsString(cmd); /* not a copy */
if (from != Py_None) c_from = PyString_AsString(from);
c_to = PyString_AsString(to);
c_rest = PyString_AsString(rest);
#endif /* Py3k */
/*
if (from == Py_None)
{
from = LocalBot..;
}*/
/* check command exists */
for (i = 0; mcmd[i].name; ++i)
{
if (!Strcmp(mcmd[i].name, c_cmd))
{
found = mcmd[i].func;
break;
}
}
if (!found)
{
#ifdef DEBUG
debug("(python_execute) squeeze me (%s) !?!\n", c_cmd);
#endif /* DEBUG */
#if PY_MAJOR_VERSION >= 3
free(c_cmd); if (from != Py_None) free(c_from); free(c_to); free(c_rest);
#endif /* Py3k */
Py_RETURN_NONE;
}
#ifdef DEBUG
debug("(python_execute) (%s) (%s) (%s) (%s) (%d)\n", c_cmd, c_from, c_to, c_rest, cmdaccess);
#endif /* DEBUG */
(*found)(c_from, c_to, c_rest, cmdaccess);
#if PY_MAJOR_VERSION >= 3
free(c_cmd); if (from != Py_None) free(c_from); free(c_to); free(c_rest);
#endif /* Py3k */
Py_RETURN_NONE;
}
static struct PyMethodDef pythonMethods[] =
{
{"getvar", (PyCFunction) python_getvar, METH_VARARGS, "Get variable"},
{"userlevel", (PyCFunction) python_userlevel, METH_VARARGS|METH_KEYWORDS, "User level"},
/* From channel.c */
{"is_chanuser", (PyCFunction) python_is_chanuser, METH_VARARGS|METH_KEYWORDS, "Check nick is in channel"},
#if 0
{"join", (PyCFunction) python_do_join, METH_VARARGS|METH_KEYWORDS, "Join a channel"},
{"part", (PyCFunction) python_do_part, METH_VARARGS|METH_KEYWORDS, "Part a channel"},
{"cycle", (PyCFunction) python_do_cycle, METH_VARARGS|METH_KEYWORDS, "Cycle a channel"},
{"wall", (PyCFunction) python_do_wall, METH_VARARGS|METH_KEYWORDS, "Do wall"},
{"mode", (PyCFunction) python_do_mode, METH_VARARGS|METH_KEYWORDS, "Do mode"},
{"invite", (PyCFunction) python_do_invite, METH_VARARGS|METH_KEYWORDS, "Do invite"},
{"sayme", (PyCFunction) python_do_sayme, METH_VARARGS|METH_KEYWORDS, "Do sayme"},
{"topic", (PyCFunction) python_do_topic, METH_VARARGS|METH_KEYWORDS, "Do topic"},
{"idle", (PyCFunction) python_do_idle, METH_VARARGS|METH_KEYWORDS, "Do idle"},
#endif /* 0 */
{"find_nuh", (PyCFunction) python_find_nuh, METH_VARARGS|METH_KEYWORDS, "Find nuh"},
/* From core.c */
#if 0
{"die", (PyCFunction) python_do_die, METH_VARARGS|METH_KEYWORDS, "Die"},
{"shutdown", (PyCFunction) python_do_shutdown, METH_VARARGS|METH_KEYWORDS, "Shutdown"},
{"server", (PyCFunction) python_do_server, METH_VARARGS|METH_KEYWORDS, "Connect server"},
#endif /* 0 */
/* Scripting stuff */
{"hook", (PyCFunction) python_hook, METH_VARARGS|METH_KEYWORDS, "Create hook"},
{"unhook", (PyCFunction) python_unhook, METH_VARARGS|METH_KEYWORDS, "Destroy hook"},
#ifdef DCC_FILE
{"dcc_sendfile", (PyCFunction) python_dcc_sendfile, METH_VARARGS|METH_KEYWORDS, "DCC send file"},
#endif /* DCC_FILE */
{"to_server", (PyCFunction) python_to_server, METH_VARARGS|METH_KEYWORDS, "Write line to server"},
{"to_file", (PyCFunction) python_to_file, METH_VARARGS|METH_KEYWORDS, "Write text to file"},
#ifdef DEBUG
{"debug", (PyCFunction) python_debug, METH_VARARGS, "Emech debug"},
#endif /* DEBUG */
#ifdef RAWDNS
{"dns", (PyCFunction) python_dns, METH_VARARGS|METH_KEYWORDS, "DNS"},
#endif /* RAWDNS */
{"execute", (PyCFunction) python_execute, METH_VARARGS, "Execute internal command"},
{NULL, NULL, 0, NULL} /* sentinel */
};
#if PY_MAJOR_VERSION >= 3
struct PyModuleDef pythonModule =
{
PyModuleDef_HEAD_INIT,
"emech", /* module name */
"EnergyMech", /* module docstring */
-1, /* size of per-interpreter state of the module,
or -1 if the module keeps state in global variables. */
pythonMethods
};
#endif /* Py3k */
PyMODINIT_FUNC pythonInit(void)
{
PyObject *m;
#if PY_MAJOR_VERSION == 3
if ((m = PyModule_Create(&pythonModule)) == NULL)
return NULL;
#else
m = Py_InitModule4("emech", pythonMethods,
"EnergyMech", (PyObject*) NULL, PYTHON_API_VERSION);
#endif /* Py3k */
python_error = PyErr_NewException("emech.Error", NULL, NULL);
Py_INCREF(python_error);
PyModule_AddObject(m, "Error", python_error);
#ifdef DEBUG
PyModule_AddIntConstant(m, "define_debug", 1);
#else
PyModule_AddIntConstant(m, "define_debug", 0);
#endif /* DEBUG */
PyModule_AddStringConstant(m, "HOOK_COMMAND", "command");
PyModule_AddStringConstant(m, "HOOK_PARSE", "parse");
PyModule_AddStringConstant(m, "HOOK_TIMER", "timer");
PyModule_AddStringConstant(m, "DCC_COMPLETE", "dcc_complete");
PyModule_AddIntConstant(m, "OK", 0);
PyModule_AddIntConstant(m, "ERROR", 1);
PyModule_AddIntConstant(m, "GUID", PYVAR_guid);
PyModule_AddIntConstant(m, "CURRENTNICK", PYVAR_currentnick);
PyModule_AddIntConstant(m, "BOTNICK", PYVAR_botnick);
PyModule_AddIntConstant(m, "WANTNICK", PYVAR_wantnick);
PyModule_AddIntConstant(m, "USERHOST", PYVAR_userhost);
PyModule_AddIntConstant(m, "SERVER", PYVAR_server);
PyModule_AddIntConstant(m, "NEXTSERVER", PYVAR_nextserver);
PyModule_AddIntConstant(m, "CURRENTCHAN", PYVAR_currentchan);
PyModule_AddStringConstant(m, "VERSION", (char *)VERSION);
PyModule_AddStringConstant(m, "SRCDATE", (char *)SRCDATE);
PyModule_AddStringConstant(m, "BOTCLASS", (char *)BOTCLASS);
if (PyErr_Occurred())
{
PyErr_Print();
Py_FatalError("Cant initialize module emech!");
}
#if PY_MAJOR_VERSION >= 3
return m;
#endif /* Py3k */
}
void init_python(void)
{
if (Py_IsInitialized()) return;
PyImport_AppendInittab((char*) "emech", pythonInit);
#if PY_MAJOR_VERSION >= 3
Py_SetProgramName(L"energymech");
wchar_t *argv2[] = {L""};
#else
Py_SetProgramName("energymech");
char *argv2[] = {""};
#endif /* Py3k */
Py_Initialize();
PySys_SetArgv(1, argv2);
}
#ifdef PLEASE_HACK_MY_SHELL
void do_python(COMMAND_ARGS)
{
init_python();
int res = PyRun_SimpleString(rest);
to_user(from, "python command %s", (res == 0) ? "executed ok" : "failed");
}
#endif /* PLEASE_HACK_MY_SHELL */
void do_pythonscript(COMMAND_ARGS)
{
init_python();
FILE *f = fopen(rest, "r");
if (f == NULL)
{
to_user(from, "python script %s not existing or unreadable", rest);
return;
}
int res = PyRun_SimpleFileEx(f, rest, 1);
to_user(from,"python script %s", (res == 0) ? "loaded ok" : "failed to load");
}
void free_python(void)
{
if (Py_IsInitialized()) Py_Finalize();
}
#endif /* PYTHON */

167
src/redirect.c Normal file
View File

@@ -0,0 +1,167 @@
/*
EnergyMech, IRC bot software
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 REDIRECT_C
#include "config.h"
#ifdef REDIRECT
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
int begin_redirect(char *from, char *args)
{
char *pt,*nick;
if (!args)
return(0);
pt = STRCHR(args,'>');
if (pt)
{
*pt = 0;
nick = pt+1;
pt--;
while((pt > args) && (*pt == ' '))
{
*pt = 0;
pt--;
}
while(*nick == ' ')
nick++;
if (*nick)
{
#ifdef DEBUG
debug("(begin_redirect) from %s --> %s\n",from,nick);
#endif /* DEBUG */
if (ischannel(nick))
{
if (find_channel_ac(nick))
{
redirect.to = Strdup(nick);
redirect.method = R_PRIVMSG;
return(0);
}
else
{
to_user(from,ERR_CHAN,nick);
return(-1);
}
}
if (*nick == '>')
{
nick++;
while(*nick == ' ')
nick++;
if (!*nick)
{
to_user(from,"Missing name for redirect.");
return(-1);
}
if (!is_safepath(nick))
{
to_user(from,"Bad filename.");
return(-1);
}
redirect.to = Strdup(nick);
redirect.method = R_FILE;
return(0);
}
if ((pt = find_nuh(nick)))
{
redirect.to = Strdup(nick);
redirect.method = R_NOTICE;
return(0);
}
else
{
to_user(from,TEXT_UNKNOWNUSER,nick);
return(-1);
}
}
else
{
to_user(from,"Bad redirect");
return(-1);
}
}
return(0);
}
void send_redirect(char *message)
{
Strp *new,**pp;
char *fmt;
int fd;
if (!redirect.to)
return;
switch(redirect.method)
{
case R_FILE:
if ((fd = open(redirect.to,O_WRONLY|O_CREAT|O_APPEND,NEWFILEMODE)) < 0)
return;
fmt = Strcat(message,"\n");
write(fd,message,(fmt-message));
close(fd);
return;
#ifdef BOTNET
case R_BOTNET:
{
char tempdata[MAXLEN];
Mech *backup;
/* PM<targetguid> <targetuserhost> <source> <message> */
sprintf(tempdata,"%i %s %s %s",redirect.guid,redirect.to,current->nick,message);
backup = current;
partyMessage(NULL,tempdata);
current = backup;
}
return;
#endif /* BOTNET */
case R_NOTICE:
fmt = "NOTICE %s :%s";
break;
/* case R_PRIVMSG: */
default:
fmt = "PRIVMSG %s :%s";
break;
}
pp = &current->sendq;
while(*pp)
pp = &(*pp)->next;
*pp = new = (Strp*)Calloc(sizeof(Strp) + Strlen(message,fmt,redirect.to,NULL));
/* Calloc sets to zero new->next = NULL; */
sprintf(new->p,fmt,redirect.to,message);
}
void end_redirect(void)
{
if (redirect.to)
Free((char**)&redirect.to);
}
#endif /* REDIRECT */

430
src/reset.c Normal file
View File

@@ -0,0 +1,430 @@
/*
EnergyMech, IRC bot software
Copyright (c) 1997-2008 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 RESET_C
#include "config.h"
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#ifdef TELNET
LS int client_type = DCC_ACTIVE;
#endif /* TELNET */
char *recover_client(char *env)
{
struct sockaddr_in sai;
Client *client;
User *user;
char *p,*handle;
int guid,fd,sz;
guid = fd = 0;
p = env;
/*
* get the guid number
*/
while(*p >= '0' && *p <= '9')
{
guid = (guid * 10) + (*p - '0');
p++;
}
if (*p != ':')
return(env);
p++;
/*
* get the fd number
*/
while(*p >= '0' && *p <= '9')
{
fd = (fd * 10) + (*p - '0');
p++;
}
if (*p != ':')
return(env);
p++;
handle = p;
while(*p)
{
if (*p == ' ' || *p == 0)
break;
p++;
}
if (p == handle)
return(env);
if (*p == ' ')
*(p++) = 0;
#ifdef DEBUG
debug("(recover_client) guid = %i; fd = %i; handle = %s\n",guid,fd,handle);
#endif /* DEBUG */
/*
* check that it's an inet stream socket
*/
sz = sizeof(sai);
if (getsockname(fd,(struct sockaddr*)&sai,&sz) < 0)
{
close(fd);
return(p);
}
for(current=botlist;current;current=current->next)
{
if (current->guid == guid)
{
for(user=current->userlist;user;user=user->next)
{
if (!Strcasecmp(user->name,handle))
goto found_user;
}
break;
}
}
close(fd);
return(p);
found_user:
if (to_file(fd,"[%s] [%s] %s[%i] has connected (reset recover)\n",
time2medium(now),current->wantnick,handle,user->x.x.access) < 0)
{
close(fd);
return(p);
}
set_mallocdoer(recover_client);
client = (Client*)Calloc(sizeof(Client));
client->user = user;
client->sock = fd;
#ifdef TELNET
client->flags = client_type;
#else
client->flags = DCC_ACTIVE;
#endif /* TELNET */
client->lasttime = now;
client->next = current->clientlist;
current->clientlist = client;
if (user->x.x.access == OWNERLEVEL)
{
CurrentDCC = client;
Strcpy(client->sockdata,"status");
do_spy(user->name,current->wantnick,client->sockdata,0);
*client->sockdata = 0;
CurrentDCC = NULL;
}
#ifdef DEBUG
debug("(recover_client) client socket recovered\n");
#endif /* DEBUG */
return(p);
}
#ifdef DEBUG
char *recover_debug(char *env)
{
struct stat s;
char *p;
debug_fd = 0;
p = env;
/*
* get the fd number
*/
while(*p >= '0' && *p <= '9')
{
debug_fd = (debug_fd * 10) + (*p - '0');
p++;
}
if (*p != ' ' && *p != 0)
return(env);
if (fstat(debug_fd,&s) < 0)
{
dodebug = FALSE;
close(debug_fd);
debug_fd = -1;
}
else
{
dodebug = TRUE;
debug("(recover_debug) debug fd recovered\n");
CoreClient.sock = debug_fd;
}
return(p);
}
#endif /* DEBUG */
char *recover_server(char *env)
{
struct sockaddr_in sai;
char *p;
int guid,fd,sz;
#ifdef IRCD_EXTENSIONS
int ircx = 0;
#endif /* IRCD_EXTENSIONS */
guid = fd = 0;
p = env;
/*
* get the guid number
*/
while(*p >= '0' && *p <= '9')
{
guid = (guid * 10) + (*p - '0');
p++;
}
if (*p != ':')
return(env);
p++;
/*
* get the fd number
*/
while(*p >= '0' && *p <= '9')
{
fd = (fd * 10) + (*p - '0');
p++;
}
#ifndef IRCD_EXTENSIONS
if (*p != ' ' && *p != 0)
return(env);
#endif /* ! IRCD_EXTENSIONS */
#ifdef IRCD_EXTENSIONS
if (*p == ':' && *(p+1) == 'X')
{
p += 2;
/*
* get the ircx flags number
*/
while(*p >= '0' && *p <= '9')
{
ircx = (ircx * 10) + (*p - '0');
p++;
}
if (*p != ' ' && *p != 0)
return(env);
}
else
if (*p != ' ' && *p != 0)
return(env);
#ifdef DEBUG
debug("(recover_server) guid = %i; fd = %i, ircx = %i\n",guid,fd,ircx);
#endif /* DEBUG */
#else /* IRCD_EXTENSIONS */
#ifdef DEBUG
debug("(recover_server) guid = %i; fd = %i\n",guid,fd);
#endif /* DEBUG */
#endif /* IRCD_EXTENSIONS */
sz = sizeof(sai);
if (getsockname(fd,(struct sockaddr*)&sai,&sz) < 0)
{
close(fd);
return(p);
}
for(current=botlist;current;current=current->next)
{
if (current->guid == guid)
{
current->reset = 1;
current->sock = fd;
current->connect = CN_ONLINE;
current->ontime = now;
#ifdef IRCD_EXTENSIONS
current->ircx_flags = ircx;
#endif /* IRCD_EXTENSIONS */
#ifdef DEBUG
debug("(recover_server) {%i} server socket recovered\n",fd);
#endif /* DEBUG */
to_file(fd,"LUSERS\n");
break;
}
}
return(p);
}
#ifdef IRCD_EXTENSIONS
/*
#define IRCX_WALLCHOPS 1
#define IRCX_WALLVOICES 2
#define IRCX_IMODE 4
#define IRCX_EMODE 8
*/
#endif /* IRCD_EXTENSIONS */
void recover_reset(void)
{
char *env = mechresetenv;
mechresetenv = NULL;
while(*env)
{
switch(*env)
{
case 'c':
#ifdef TELNET
client_type = DCC_ACTIVE;
#endif /* TELNET */
env = recover_client(env+1);
break;
#ifdef DEBUG
case 'd':
env = recover_debug(env+1);
break;
#endif /* DEBUG */
#ifdef TELNET
case 't':
client_type = DCC_TELNET;
env = recover_client(env+1);
break;
#endif /* TELNET */
case 'f':
env = recover_server(env+1);
break;
default:
env++;
}
}
}
/*
*
* commands
*
*/
void do_reset(COMMAND_ARGS)
{
Client *client;
Mech *backup;
char env[MSGLEN];
char *p;
int n,sz;
if (current->userlist && current->ul_save)
{
p = current->setting[STR_USERFILE].str_var;
write_userlist(p);
}
#ifdef SESSION
write_session();
#endif /* SESSION */
#ifdef SEEN
if (seenfile)
write_seenlist();
#endif /* SEEN */
#ifdef TRIVIA
write_triviascore();
#endif /* TRIVIA */
#ifdef NOTIFY
if (current->notifylist)
write_notifylog();
#endif /* NOTIFY */
*env = 0;
p = Strcat(env,STR_MECHRESET);
n = 0;
#ifdef DEBUG
/*
* debug stuff
*/
if (dodebug && (debug_fd >= 0))
{
sprintf(p,"d%i",debug_fd);
p = STREND(p);
n++;
}
#endif /* DEBUG */
/*
* Save server connections
*/
for(backup=botlist;backup;backup=backup->next)
{
if ((backup->connect == CN_ONLINE) && ((MSGLEN - (p - env)) > 25))
{
unset_closeonexec(backup->sock);
if (n)
*(p++) = ' ';
#ifdef IRCD_EXTENSIONS
sprintf(p,"f%i:%i:X%i",backup->guid,backup->sock,backup->ircx_flags);
#else /* IRCD_EXTENSIONS */
sprintf(p,"f%i:%i",backup->guid,backup->sock);
#endif /* IRCD_EXTENSIONS */
p = STREND(p);
n++;
}
for(client=backup->clientlist;client;client=client->next)
{
#ifdef TELNET
if ((client->flags & (DCC_ACTIVE|DCC_TELNET)) == 0)
continue;
#else
if (client->flags != DCC_ACTIVE)
continue;
#endif /* TELNET */
sz = strlen(client->user->name) + 26;
if ((MSGLEN - (p - env)) > sz)
{
unset_closeonexec(client->sock);
if (n)
*(p++) = ' ';
#ifdef TELNET
sprintf(p,(client->flags & DCC_TELNET) ? "t%i:%i:%s" : "c%i:%i:%s",
backup->guid,client->sock,client->user->name);
#else
sprintf(p,"c%i:%i:%s",backup->guid,client->sock,client->user->name);
#endif /* TELNET */
p = STREND(p);
n++;
}
}
}
#ifdef DEBUG
debug("(do_reset) %s [%i]\n",env,(int)(p - env));
#endif /* DEBUG */
mechresetenv = (n) ? env : NULL;
do_exec = TRUE;
mech_exec();
/* NOT REACHED */
}

313
src/seen.c Normal file
View File

@@ -0,0 +1,313 @@
/*
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 SEEN_C
#include "config.h"
#ifdef SEEN
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
int write_seenlist(void)
{
Seen *seen;
int f;
#ifdef DEBUG
int dodeb;
#endif /* DEBUG */
if (!seenfile)
return(FALSE);
if ((f = open(seenfile,O_WRONLY|O_CREAT|O_TRUNC,NEWFILEMODE)) < 0)
return(FALSE);
#ifdef DEBUG
dodeb = dodebug;
dodebug = FALSE;
#endif /* DEBUG */
for(seen=seenlist;seen;seen=seen->next)
{
if ((seen->when - now) > (86400 * SEEN_TIME))
continue;
else
{
if (seen->t != 0)
{
to_file(f,"%s %s %lu %i %s %s\n",
seen->nick,seen->userhost,
seen->when,seen->t,
(seen->pa) ? seen->pa : "",
(seen->pb) ? seen->pb : "");
}
}
}
close(f);
#ifdef DEBUG
dodebug = dodeb;
#endif /* DEBUG */
return(TRUE);
}
int read_seenlist_callback(char *rest)
{
char *nick,*uh,*pa,*pb;
time_t when;
int t;
nick = chop(&rest);
uh = chop(&rest);
when = a2i(chop(&rest)); /* seen time, a2i handles NULL */
if (errno)
return(FALSE);
t = a2i(chop(&rest)); /* seen type, a2i handles NULL */
if (errno)
return(FALSE);
pa = chop(&rest);
pb = rest;
if ((now - when) < (SEEN_TIME * 86400))
{
/* if (pa && !*pa)
pa = NULL; chop() doesnt return empty strings */
if (!*pb)
pb = NULL;
make_seen(nick,uh,pa,pb,when,t);
}
return(FALSE);
}
int read_seenlist(void)
{
Seen *seen;
int in;
#ifdef DEBUG
int dodeb;
#endif /* DEBUG */
if (!seenfile || ((in = open(seenfile,O_RDONLY)) < 0))
return(FALSE);
#ifdef DEBUG
dodeb = dodebug;
dodebug = FALSE;
#endif /* DEBUG */
while((seen = seenlist))
{
seenlist = seen->next;
Free((char**)&seen);
}
readline(in,&read_seenlist_callback); /* readline closes in */
#ifdef DEBUG
dodebug = dodeb;
#endif /* DEBUG */
return(TRUE);
}
void make_seen(char *nick, char *userhost, char *pa, char *pb, time_t when, int t)
{
Seen *seen,**pp;
char *pt;
uchar c1;
int i;
for(pt=userhost;*pt;pt++)
{
if (*pt == '!')
{
userhost = pt + 1;
break;
}
}
c1 = nickcmptab[(uchar)(*nick)];
pt = nick + 1;
pp = &seenlist;
step_one:
if (*pp)
{
if (c1 > nickcmptab[(uchar)(*(*pp)->nick)])
{
pp = &(*pp)->next;
goto step_one;
}
}
step_two:
if (*pp)
{
if (c1 == nickcmptab[(uchar)(*(*pp)->nick)])
{
i = nickcmp(pt,(*pp)->nick+1);
if (i > 0)
{
pp = &(*pp)->next;
goto step_two;
}
if (!i)
{
seen = *pp;
*pp = seen->next;
Free((char**)&seen);
}
}
}
/*
* dont fuck with this code unless you really know what you're doing
* pa might be NULL, but then pb is NULL also; pb might be NULL
* any NULL terminates the Strlen() check
*/
set_mallocdoer(make_seen);
seen = (Seen*)Calloc(sizeof(Seen) + Strlen(nick,userhost,pa,pb,NULL));
seen->next = *pp;
*pp = seen;
seen->when = when;
seen->t = t;
/* Calloc sets to zero seen->pa = seen->pb = NULL; */
seen->userhost = Strcpy(seen->nick,nick) + 1;
pt = Strcpy(seen->userhost,userhost) + 1;
if (pa)
{
seen->pa = pt;
pt = Strcpy(seen->pa,pa) + 1;
if (pb)
{
seen->pb = pt;
Strcpy(seen->pb,pb);
}
}
}
/*
*
* commands for seen features
*
*/
void do_seen(COMMAND_ARGS)
{
Seen *seen;
char ago[35]; /* enought for "36500 days, 23 hours and 59 minutes" (100 years) */
char *chan,*fmt,*n,*u,*c1,*c2,*c3;
time_t when;
int d,h,m,mul;
chan = get_channel(to,&rest);
mul = get_maxaccess(from);
if (!*rest)
{
if (mul) to_user_q(from,"Who do you want me look for?");
return;
}
n = chop(&rest);
if (!is_nick(n))
{
if (mul) to_user_q(from,ERR_NICK,n);
return;
}
if (!nickcmp(n,current->nick))
{
fmt = "%s is me you dweeb!";
}
else
if (!nickcmp(n,from))
{
fmt = "Trying to find yourself %s?";
}
else
{
for(seen=seenlist;seen;seen=seen->next)
{
if (!Strcasecmp(n,seen->nick))
break;
}
if (!seen)
{
fmt = "I have no memory of %s";
}
else
{
when = now - seen->when;
d = when / 86400;
h = (when -= d * 86400) / 3600;
m = (when -= h * 3600) / 60;
*ago = 0;
c2 = ago;
if (d)
{
sprintf(c2,"%i day%s, ",d,EXTRA_CHAR(d));
}
if (h || d)
{
sprintf(ago,"%s%i hour%s and ",ago,h,EXTRA_CHAR(h));
}
sprintf(ago,"%s%i minute%s",ago,m,EXTRA_CHAR(m));
n = seen->nick;
u = seen->userhost;
c1 = seen->pa;
c2 = ago;
switch(seen->t)
{
case SEEN_PARTED:
fmt = "%s (%s) parted from %s, %s ago";
break;
case SEEN_QUIT:
fmt = "%s (%s) signed off with message \"%s\", %s ago";
break;
case SEEN_NEWNICK:
fmt = "%s (%s) changed nicks to %s, %s ago";
break;
case SEEN_KICKED:
c2 = seen->pb;
c3 = ago;
fmt = "%s (%s) was kicked by %s with message \"%s\", %s ago";
}
}
}
to_user_q(from,fmt,n,u,c1,c2,c3);
}
#endif /* SEEN */

153
src/settings.h Normal file
View File

@@ -0,0 +1,153 @@
/*
EnergyMech, IRC bot software
Copyright (c) 2001-2009 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.
*/
#ifndef SETTINGS_H
#define SETTINGS_H 1
#ifdef VARS_C
#define DEFAULTCMDCHAR '-'
#define ZERO 0
#define INTCAST(x) (void*)((int)x)
#define CHARCAST (void*)((int)DEFAULTCMDCHAR)
LS const Setting VarName[SIZE_VARS] =
{
/*
* all channel settings in the beginning
*/
/* TYPE UACCES MIN DEFAULT NAME MAX */
{ TOG_VAR, 40, 0, ZERO, "ABK", 1 },
{ TOG_VAR, 40, 0, ZERO, "AOP", 1 }, /* autoop enable */
{ INT_VAR, 40, 0, ZERO, "AUB", 86400 },
{ INT_VAR, 40, 0, INTCAST(1), "AVOICE", 2 },
#ifdef CHANBAN
{ TOG_VAR, 40, 0, ZERO, "CHANBAN", 1, }, /* chanban enable */
#endif /* CHANBAN */
{ INT_VAR, 40, 0, ZERO, "CKL", 20 },
{ TOG_VAR, 40, 0, ZERO, "CTL", 1 },
#ifdef DYNAMODE
{ STR_VAR, 40, 0, NULL, "DYNLIMIT", 1 }, /* settings for dynamode: `delay:window:minwin' */
#endif /* DYNAMODE */
{ TOG_VAR, 40, 0, ZERO, "ENFM", 1 },
{ STR_VAR, 40, 0, NULL, "ENFMODES" }, /* modes to enforce, +ENFM to enable */
{ INT_VAR, 40, 0, INTCAST(6), "FL", 20 }, /* number of lines that counts as a text flood */
{ INT_VAR, 40, 0, ZERO, "FPL", 2 },
{ INT_VAR, 40, 0, INTCAST(0), "IKT", 40320 }, /* idle-kick: minutes of idle-time (max 4 weeks) */
{ TOG_VAR, 40, 0, ZERO, "KS", 1 }, /* kicksay enable */
{ INT_VAR, 40, 0, INTCAST(90), "MAL", 200 },
{ INT_VAR, 40, 2, INTCAST(7), "MBL", 20 },
{ INT_VAR, 40, 2, INTCAST(7), "MDL", 20 },
{ INT_VAR, 40, 2, INTCAST(7), "MKL", 20 },
{ INT_VAR, 40, 0, INTCAST(1), "MPL", 2 }, /* mass action levels: 0=off, 1=kick, 2=kickban */
{ INT_VAR, 40, 2, INTCAST(20), "NCL", 20 },
{ INT_VAR, 40, 0, INTCAST(4), "PROT", 4 }, /* max enforced protection level */
{ TOG_VAR, 40, 0, INTCAST(1), "PUB", 1 }, /* public commands */
{ TOG_VAR, 40, 0, ZERO, "RK", 1 }, /* revenge kick enable */
{ TOG_VAR, 40, 0, ZERO, "SD", 1 }, /* server-op deop enable */
{ TOG_VAR, 40, 0, INTCAST(1), "SHIT", 1 }, /* shitlist enable */
{ TOG_VAR, 40, 0, ZERO, "SO", 1 }, /* safe-op enable */
#ifdef STATS
{ STR_VAR, 80, 0, NULL, "STATS" }, /* statistics log file */
#endif /* STATS */
{ TOG_VAR, 40, 0, ZERO, "TOP", 1 },
/*
* all global variables
*/
/* TYPE UACCES MIN DEFAULT NAME MAX */
{ INT_GLOBAL, 40, 0, ZERO, "AAWAY", 1440 }, /* set auto-away after ___ minutes */
{ STR_GLOBAL, 90, 0, NULL, "ALTNICK" }, /* alternative nick */
#ifdef BOTNET
{ TOG_PROC, 90, 0, (&autolink), "AUTOLINK", 1 }, /* establish links automagically */
#endif /* BOTNET */
#ifdef BOUNCE
{ INT_PROC, 100, 0, (&bounce_port), "BNCPORT", 65535, (&new_port_bounce) }, /* irc proxy port to listen on */
#endif /* BOUNCE */
{ TOG_GLOBAL, 90, 0, INTCAST(1), "CC", 1 }, /* require command char */
{ CHR_GLOBAL, 90, 1, CHARCAST, "CMDCHAR", 255 }, /* command char */
#ifdef CTCP
{ TOG_GLOBAL, 90, 0, INTCAST(1), "CTCP", 1 }, /* ctcp replies enable */
#endif /* CTCP */
{ INT_PROC, 100, 10, (&ctimeout), "CTIMEOUT", 3600 }, /* how long to wait between connect attempts */
#ifdef DCC_FILE
{ INT_GLOBAL, 80, 0, ZERO, "DCCANON", 100 }, /* anonymous (non user) DCC slots */
{ STR_GLOBAL, 80, 0, NULL, "DCCFILES" }, /* string with space separated masks for auto-accepted filenames */
{ INT_GLOBAL, 80, 0, INTCAST(4), "DCCUSER", 100 }, /* user DCC slots */
#endif /* DCC_FILE */
{ TOG_GLOBAL, 80, 0, ZERO, "ENFPASS", 1 }, /* disallow users with no passwords */
{ STR_GLOBAL, 90, 0, NULL, "IDENT" }, /* register with this in the `user' field */
{ STR_GLOBAL, 90, 0, NULL, "IRCNAME" }, /* register with this in the `real name' field */
#ifdef NOTIFY
{ INT_GLOBAL, 80, 10, INTCAST(30), "ISONDELAY", 600 }, /* seconds between each ISON */
#endif /* NOTIFY */
#ifdef BOTNET
{ STR_PROC, 90, 0, (&linkpass), "LINKPASS" }, /* local process linkpass */
{ INT_PROC, 100, 0, (&linkport), "LINKPORT", 65535 }, /* listen on <linkport> for botnet connections */
#endif /* BOTNET */
{ INT_GLOBAL, 80, 1, INTCAST(3), "MODES", 20 }, /* max number of channel modes to send */
#ifdef BOTNET
{ TOG_GLOBAL, 90, 0, INTCAST(1), "NETUSERS", 1 }, /* this bot accepts shared users (on by default) */
#endif /* BOTNET */
{ TOG_GLOBAL, 80, 0, ZERO, "NOIDLE", 1 }, /* dont idle */
#ifdef NOTIFY
{ STR_GLOBAL, 80, 0, NULL, "NOTIFYFILE" }, /* read notify settings from <notifyfile> */
#endif /* NOTIFY */
{ TOG_GLOBAL, 90, 0, ZERO, "ONOTICE", 1 }, /* ircd has /notice @#channel */
#ifdef TRIVIA
{ CHR_PROC, 80, 0, (&triv_qchar), "QCHAR" }, /* use <qchar> as mask char when displaying answer */
{ INT_PROC, 80, 1, (&triv_qdelay), "QDELAY", 3600 }, /* seconds between each question */
{ STR_PROC, 80, 0, (&triv_qfile), "QFILE" }, /* load questions from <qfile> */
#endif /* TRIVIA */
#ifdef CTCP
{ TOG_GLOBAL, 80, 0, ZERO, "RF", 1 }, /* random ctcp finger reply */
{ TOG_GLOBAL, 80, 0, ZERO, "RV", 1 }, /* random ctcp version reply */
#endif /* CTCP */
#ifdef SEEN
{ STR_PROC, 90, 0, (&seenfile), "SEENFILE" }, /* load/save seen database from <seenfile> */
#endif /* SEEN */
{ STR_GLOBAL, 80, 0, NULL, "SERVERGROUP" }, /* connect bot to a certain group of servers */
{ TOG_GLOBAL, 90, 0, ZERO, "SPY", 1 }, /* send info about executed commands to status channel */
{ STR_GLOBAL, 90, 0, NULL, "UMODES" }, /* send these modes on connect */
#ifdef UPTIME
{ STR_PROC, 100, 0, (&uptimehost), "UPHOST" }, /* send uptime packets to <uphost> */
{ STR_PROC, 100, 0, (&uptimenick), "UPNICK" }, /* send <upnick> as identifier instead of bots nick */
{ INT_PROC, 100, 0, (&uptimeport), "UPPORT", 65535 }, /* send packets to port <upport> */
#endif /* UPTIME */
{ STR_GLOBAL, 90, 0, NULL, "USERFILE" }, /* what file to load/save userlist from/to */
{ STR_GLOBAL, 90, 0, NULL, "VIRTUAL", 0, (&var_resolve_host) }, /* visual host */
#ifdef WEB
{ INT_PROC, 100, 0, (&webport), "WEBPORT", 65535 }, /* httpd should listen on... */
#endif /* WEB */
#ifdef WINGATE
{ STR_GLOBAL, 90, 0, NULL, "WINGATE", 0, (&var_resolve_host) }, /* wingate hostname */
{ INT_GLOBAL, 90, 0, ZERO, "WINGPORT", 65535 }, /* wingate port */
#endif /* WINGATE */
{ 0, }};
#undef ZERO
#undef INTCAST
#undef CHARCAST
#else /* VARS_C */
extern const Setting VarName[];
#endif /* VARS_C */
#endif /* SETTINGS_H */

401
src/shit.c Normal file
View File

@@ -0,0 +1,401 @@
/*
EnergyMech, IRC bot software
Parts Copyright (c) 1997-2009 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 SHITLIST_C
#include "config.h"
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
/*
*
* shitlist enforcing
*
*/
void shit_action(Chan *chan, ChanUser *cu)
{
Shit *shit;
char *nick,*fromnick;
char *userhost;
if (!chan->setting[TOG_SHIT].int_var || !chan->bot_is_op || cu->user)
return;
userhost = get_nuh(cu);
if ((cu->shit = find_shit(userhost,chan->name)) == NULL)
return;
shit = cu->shit;
if (shit->action == SHIT_KB || shit->action == SHIT_PERMABAN)
{
nick = cu->nick;
send_mode(chan,85,QM_CHANUSER,'-','o',cu);
send_mode(chan,90,QM_RAWMODE,'+','b',shit->mask);
fromnick = nickcpy(NULL,shit->from);
send_kick(chan,nick,"%s %s: %s",time2small(shit->time),fromnick,
(shit->reason) ? shit->reason : "GET THE HELL OUT!!!");
return;
}
else
/*
* shitlevel 1: not allowed to be chanop
*/
if (shit->action == SHIT_CHANOP)
{
send_mode(chan,160,QM_CHANUSER,'-','o',(void*)cu);
}
}
void check_shit(void)
{
ChanUser *cu;
Chan *chan;
for(chan=current->chanlist;chan;chan=chan->next)
{
for(cu=chan->users;cu;cu=cu->next)
{
shit_action(chan,cu);
}
}
}
/*
*
* shitlist management. adding, deleting, clearing, searching, ...
*
*/
void remove_shit(Shit *shit)
{
Chan *chan;
ChanUser *cu;
Shit **pp;
#ifdef DEBUG
debug("(remove_shit) removing shit %s on channel %s (Level 4)\n",shit->mask,shit->chan,shit->action);
#endif /* DEBUG */
pp = &current->shitlist;
while(*pp)
{
if (*pp == shit)
{
/*
* remove links to this shit record from the chanuserlist
*/
for(chan=current->chanlist;chan;chan=chan->next)
{
for(cu=chan->users;cu;cu=cu->next)
{
if (cu->shit == shit)
cu->shit = NULL;
}
}
*pp = shit->next;
Free((char**)&shit);
current->ul_save++;
return;
}
pp = &(*pp)->next;
}
}
void purge_shitlist(void)
{
while(current->shitlist)
remove_shit(current->shitlist);
}
Shit *add_shit(char *from, char *chan, char *mask, char *reason, int axs, int expire)
{
Shit *shit;
set_mallocdoer(add_shit);
shit = (Shit*)Calloc(sizeof(Shit) + Strlen(from,chan,mask,reason,NULL));
shit->action = axs;
shit->time = now;
shit->expire = expire;
shit->next = current->shitlist;
current->shitlist = shit;
shit->chan = Strcpy(shit->mask,mask) + 1;
shit->from = Strcpy(shit->chan,chan) + 1;
shit->reason = Strcpy(shit->from,from) + 1;
Strcpy(shit->reason,reason);
current->ul_save++;
return(shit);
}
Shit *find_shit(const char *userhost, const char *channel)
{
Shit *shit,*save;
int num,best;
if (!userhost)
return(NULL);
save = NULL;
best = 0;
for(shit=current->shitlist;shit;shit=shit->next)
{
if (!channel || !Strcasecmp(channel,shit->chan) ||
(*shit->chan == '*') || (*channel == '*'))
{
num = num_matches(shit->mask,userhost);
if (num > best)
{
best = num;
save = shit;
}
}
}
if (save && save->expire < now)
{
remove_shit(save);
save = NULL;
}
return(save);
}
Shit *get_shituser(char *userhost, char *channel)
{
ChanUser *cu;
Chan *chan;
Shit *shit;
char *p;
#ifdef DEBUG
debug("(get_shituser) userhost = '%s', channel = '%s'\n",
nullstr(userhost),nullstr(channel));
#endif /* DEBUG */
/*
* save us a few million function calls if the shitlist is empty
*/
if (!current->shitlist)
return(NULL);
if (!nickcmp(current->nick,userhost))
return(NULL);
for(chan=current->chanlist;chan;chan=chan->next)
{
for(cu=chan->users;cu;cu=cu->next)
{
p = get_nuh(cu);
if (matches(userhost,p))
continue;
if ((shit = find_shit(p,channel)) != NULL)
return(shit);
}
}
return(NULL);
}
int get_shitaction(const char *userhost, const char *chan)
{
Shit *shit;
if ((shit = find_shit(userhost,chan)))
return(shit->action);
return(0);
}
/*
*
* commands related to shitlist
*
*/
/*
* SHIT <channel|*> <nick|mask> <action> [expire] <reason>
*/
void do_shit(COMMAND_ARGS)
{
/*
* on_msg checks CARGS
*/
char *channel,*nick,*nuh;
int shitlevel,days,uaccess,shitaccess;
if (CurrentCmd->name == C_QSHIT)
{
channel = MATCH_ALL;
}
else
{
channel = chop(&rest);
if (!ischannel(channel) && *channel != '*')
{
usage:
usage(from); /* usage for CurrentCmd->name */
return;
}
}
if ((uaccess = get_useraccess(from,channel)) < cmdaccess)
return;
if ((nick = chop(&rest)) == NULL)
goto usage;
if (CurrentCmd->name == C_QSHIT)
{
shitlevel = DEFAULTSHITLEVEL;
days = 86400 * DEFAULTSHITLENGTH;
if (*rest == 0)
rest = TEXT_DEFAULTSHIT;
}
else
{
shitlevel = a2i(chop(&rest));
if (errno)
goto usage;
if (shitlevel < 1 || shitlevel > MAXSHITLEVEL)
{
to_user(from,"Valid levels are from 1 thru " MAXSHITLEVELSTRING);
return;
}
/*
* option: expire in XXX days
*/
days = 86400 * 30;
if (*rest >= '1' && *rest <= '9')
{
days = 86400 * a2i(chop(&rest));
if (errno)
goto usage;
}
if (*rest == 0)
goto usage;
}
#ifdef CHANBAN
if (shitlevel == SHIT_CHANBAN)
{
nuh = nick;
}
else
#endif /* CHANBAN */
{
if ((nuh = nick2uh(from,nick)) == NULL)
return;
if (find_shit(nuh,channel))
{
to_user(from,TEXT_ALREADYSHITTED,nuh);
return;
}
if (uaccess != OWNERLEVEL)
{
shitaccess = get_useraccess(nuh,channel);
if (shitaccess > uaccess)
{
to_user(from,TEXT_SHITLOWACCESS,nuh);
return;
}
}
format_uh(nuh,FUH_USERHOST);
}
#ifdef DEBUG
debug("(do_shit) adding %s to %s (Level %i)\n",nuh,channel,shitlevel);
#endif /* DEBUG */
add_shit(from,channel,nuh,rest,shitlevel,now + days);
to_user(from,TEXT_HASSHITTED,nuh,channel);
to_user(from,TEXT_SHITEXPIRES,time2str(now + days));
check_shit();
}
void do_rshit(COMMAND_ARGS)
{
/*
* on_msg checks: CARGS
*/
Shit *shit;
char *chan,*nick,*nuh;
int uaccess;
chan = chop(&rest);
if (!chan || !*chan || (!ischannel(chan) && *chan != '*'))
{
usage(from); /* usage for CurrentCmd->name */
return;
}
if ((uaccess = get_useraccess(from,chan)) < cmdaccess)
return;
if ((nick = chop(&rest)) == NULL)
{
to_user(from,"No nick or userhost specified");
return;
}
if ((nuh = nick2uh(from,nick)) == NULL)
return;
if ((shit = find_shit(nuh,chan)) == NULL)
{
to_user(from,"%s is not in my shit list on that channel",nuh);
return;
}
if ((get_useraccess(shit->from,chan)) > uaccess)
{
to_user(from,"The person who did this shitlist has a higher level than you");
return;
}
remove_shit(shit);
to_user(from,"User %s is no longer being shitted on %s",nuh,chan);
}
char *shit_actions[MAXSHITLEVEL+1] = { "nothing (0)", "no op/voice (1)", "kickban (2)", "permaban (3)", "chanban (4)" };
void do_shitlist(COMMAND_ARGS)
{
Shit *shit;
table_buffer("\037channel\037\t\037mask\037\t\037action\037\t\037set by\037\t\037reason\037\t\037expires\037");
for(shit=current->shitlist;shit;shit=shit->next)
{
table_buffer("%s\t%s\t%s\t%s\t%s\t%s",shit->chan,shit->mask,shit_actions[shit->action],
nickcpy(NULL,shit->from),shit->reason,time2away(shit->expire));
}
table_send(from,2);
}
void do_clearshit(COMMAND_ARGS)
{
purge_shitlist();
to_user(from,TEXT_CLEAREDSHITLIST);
}

674
src/socket.c Normal file
View File

@@ -0,0 +1,674 @@
/*
EnergyMech, IRC bot software
Parts Copyright (c) 1997-2009 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 SOCKET_C
#include "config.h"
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#ifndef RAWDNS
/*
* only include this hack if rawdns isnt compiled in
*/
ulong get_ip(const char *host)
{
struct hostent *he;
ulong ip;
if ((ip = inet_addr(host)) == INADDR_NONE)
{
if ((he = gethostbyname(host)) == NULL)
{
#ifdef DEBUG
debug("(get_ip) unable to resolve %s\n",host);
#endif /* DEBUG */
return(-1);
}
ip = (ulong)((struct in_addr*)he->h_addr)->s_addr;
}
#ifdef DEBUG
debug("(get_ip) %s -> %s\n",host,inet_ntoa(*((struct in_addr*)&ip)));
#endif /* DEBUG */
return(ip);
}
#endif /* ! RAWDNS */
/*
* some default code for socket flags
*/
void SockFlags(int fd)
{
#ifdef ASSUME_SOCKOPTS
fcntl(fd,F_SETFL,O_NONBLOCK|O_RDWR);
fcntl(fd,F_SETFD,FD_CLOEXEC);
#else /* not ASSUME_SOCKOPTS */
fcntl(fd,F_SETFL,O_NONBLOCK | fcntl(fd,F_GETFL));
fcntl(fd,F_SETFD,FD_CLOEXEC | fcntl(fd,F_GETFD));
#endif /* ASSUME_SOCKOPTS */
}
int SockOpts(void)
{
struct { int onoff; int linger; } parm;
int s;
if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0)
return(-1);
parm.onoff = parm.linger = 0;
setsockopt(s,SOL_SOCKET,SO_LINGER,(char*)&parm,sizeof(parm));
parm.onoff++;
setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(char*)&parm.onoff,sizeof(int));
SockFlags(s);
return(s);
}
int SockListener(int port)
{
struct sockaddr_in sai;
int s;
if ((s = SockOpts()) < 0)
return(-1);
memset((char*)&sai,0,sizeof(sai));
sai.sin_family = AF_INET;
sai.sin_addr.s_addr = INADDR_ANY;
sai.sin_port = htons(port);
if ((bind(s,(struct sockaddr*)&sai,sizeof(sai)) < 0) || (listen(s,1) < 0))
{
close(s);
return(-1);
}
return(s);
}
#ifdef RAWDNS
#define get_ip rawdns_get_ip
#endif /* RAWDNS */
int SockConnect(char *host, int port, int use_vhost)
{
struct sockaddr_in sai;
int s;
#ifdef IDWRAP
char *id,identfile[64];
int t = FALSE;
#endif /* IDWRAP */
#ifdef DEBUG
debug("(SockConnect) %s %i%s\n",nullstr(host),port,(use_vhost) ? " [VHOST]" : "");
#endif /* DEBUG */
if ((s = SockOpts()) < 0)
return(-1);
memset((char*)&sai,0,sizeof(sai));
sai.sin_family = AF_INET;
/*
* special case, BOUNCE feature may call SockConnect()
* to create the IDWRAP symlink, using special use_vhost value == 2
*/
#if defined(BOUNCE) && defined(IDWRAP)
if ((use_vhost == TRUE)
#else /* not ... */
if (use_vhost
#endif /* ... */
&& ((current->vhost_type & VH_IPALIAS_FAIL) == 0)
&& current->setting[STR_VIRTUAL].str_var)
{
current->vhost_type |= VH_IPALIAS_BOTH;
if ((sai.sin_addr.s_addr = get_ip(current->setting[STR_VIRTUAL].str_var)) != -1)
{
if (bind(s,(struct sockaddr *)&sai,sizeof(sai)) >= 0)
{
current->vhost_type &= ~(VH_IPALIAS_FAIL|VH_WINGATE);
#ifdef WINGATE
use_vhost++;
#endif /* WINGATE */
#ifdef IDWRAP
t = TRUE;
#endif /* IDWRAP */
#ifdef DEBUG
debug("(SockConnect) IP Alias virtual host bound OK\n");
#endif /* DEBUG */
}
}
}
#ifdef IDWRAP
/*
* do a blank bind to get a port number
*/
if (!t)
{
sai.sin_addr.s_addr = INADDR_ANY;
bind(s,(struct sockaddr *)&sai,sizeof(sai));
}
#endif /* IDWRAP */
memset((char*)&sai,0,sizeof(sai));
sai.sin_family = AF_INET;
#ifdef WINGATE
/*
* bouncer connects (WinGate, ...)
*/
if ((use_vhost == TRUE) && ((current->vhost_type & VH_WINGATE_FAIL) == 0)
&& current->setting[STR_WINGATE].str_var)
{
#ifdef DEBUG
debug("(SockConnect) Trying wingate @ %s:%i\n",
current->setting[STR_WINGATE].str_var,
current->setting[INT_WINGPORT].int_var);
#endif /* DEBUG */
current->vhost_type |= VH_WINGATE_BOTH;
sai.sin_port = htons(current->setting[INT_WINGPORT].int_var);
if ((sai.sin_addr.s_addr = get_ip(current->setting[STR_WINGATE].str_var)) == -1)
{
close(s);
return(-1);
}
current->vhost_type &= ~(VH_WINGATE_FAIL|VH_IPALIAS);
#ifdef DEBUG
debug("(SockConnect) WINGATE host resolved OK\n");
#endif /* DEBUG */
}
else
#endif /* WINGATE */
{
/*
* Normal connect, no bounces...
*/
#ifdef IDWRAP
if (use_vhost)
{
t = sizeof(sai);
if (getsockname(s,(struct sockaddr*)&sai,&t) == 0)
{
if (current->identfile)
Free((char**)&current->identfile);
sprintf(identfile,IDWRAP_PATH "%i.%i",ntohs(sai.sin_port),port);
id = current->setting[STR_IDENT].str_var;
if (symlink((id) ? id : BOTLOGIN,identfile) == 0)
{
set_mallocdoer(SockConnect);
current->identfile = Strdup(identfile);
#ifdef DEBUG
debug("(SockConnect) symlink: %s -> %s\n",identfile,(id) ? id : BOTLOGIN);
#endif /* DEBUG */
}
}
memset((char*)&sai,0,sizeof(sai));
sai.sin_family = AF_INET;
}
#endif /* IDWRAP */
sai.sin_port = htons(port);
if ((sai.sin_addr.s_addr = get_ip(host)) == -1)
{
close(s);
return(-1);
}
sai.sin_family = AF_INET;
}
if ((connect(s,(struct sockaddr*)&sai,sizeof(sai)) < 0) && (errno != EINPROGRESS))
{
#ifdef DEBUG
debug("[CbN] unable to connect. errno = %i\n",errno);
#endif /* DEBUG */
close(s);
return(-1);
}
#ifdef DEBUG
debug("(SockConnect) {%i} %s %i%s\n",s,nullstr(host),port,(use_vhost) ? " [VHOST]" : "");
#endif /* DEBUG */
return(s);
}
int SockAccept(int sock)
{
struct sockaddr_in sai;
int s,sz;
sz = sizeof(sai);
s = accept(sock,(struct sockaddr*)&sai,&sz);
if (s >= 0)
{
SockFlags(s);
}
return(s);
}
/*
* Format text and send to a socket or file descriptor
*/
int to_file(int sock, const char *format, ...)
{
va_list msg;
#ifdef DEBUG
char *line,*rest;
int i;
#endif /* DEBUG */
if (sock == -1)
return(-1);
va_start(msg,format);
vsprintf(gsockdata,format,msg);
va_end(msg);
#ifdef DEBUG
i = write(sock,gsockdata,strlen(gsockdata));
rest = gsockdata;
while((line = get_token(&rest,"\n"))) /* rest cannot be NULL */
debug("(out) {%i} %s\n",sock,nullstr(line));
if (i < 0)
debug("(out) {%i} errno = %i\n",sock,errno);
return(i);
#else /* DEBUG */
return(write(sock,gsockdata,strlen(gsockdata)));
#endif /* DEBUG */
}
/*
* Format a message and send it to the current bots server
* to_server needs a newline (\n) it wont manufacture it itself.
*/
void to_server(char *format, ...)
{
va_list msg;
#ifdef DEBUG
char *line,*rest;
#endif /* DEBUG */
if (current->sock == -1)
return;
va_start(msg,format);
vsprintf(gsockdata,format,msg);
va_end(msg);
/*
* each line we send to the server pushes the sendq time
* forward *two* seconds
*/
current->sendq_time += 2;
if (write(current->sock,gsockdata,strlen(gsockdata)) < 0)
{
#ifdef DEBUG
debug("[StS] {%i} errno = %i\n",current->sock,errno);
#endif /* DEBUG */
close(current->sock);
current->sock = -1;
current->connect = CN_NOSOCK;
return;
}
#ifdef DEBUG
rest = gsockdata;
while((line = get_token(&rest,"\n"))) /* rest cannot be NULL */
debug("[StS] {%i} %s\n",current->sock,line);
#endif /* DEBUG */
}
void to_user_q(const char *target, const char *format, ...)
{
va_list args;
Client *client;
Strp *new,**pp;
char message[MAXLEN];
char nick[MAXHOSTLEN];
char *fmt;
va_start(args,format);
vsprintf(message,format,args);
va_end(args);
Strcat(message,"\n");
fmt = "NOTICE %s :%s";
if (CurrentChan)
{
target = CurrentChan->name;
fmt = "PRIVMSG %s :%s";
}
if (!ischannel(target))
target = nickcpy(nick,target);
if ((client = find_client(target)))
{
if (write(client->sock,message,strlen(message)) < 0)
client->flags = DCC_DELETE;
#ifdef DEBUG
debug("(to_user) {%i} [%s] %s",client->sock,target,message);
#endif /* DEBUG */
return;
}
#ifdef REDIRECT
if (redirect.to && target == redirect.to)
{
send_redirect(message);
return;
}
#endif /* REDIRECT */
pp = &current->sendq;
while(*pp)
pp = &(*pp)->next;
set_mallocdoer(to_user_q);
*pp = new = (Strp*)Calloc(sizeof(Strp) + Strlen(fmt,target,message,NULL));
/* Calloc sets to zero new->next = NULL; */
sprintf(new->p,fmt,target,message);
}
/*
* Format a message and send it either through DCC if the user is
* connected to the partyline, or send it as a NOTICE if he's not
*/
void to_user(const char *target, const char *format, ...)
{
va_list args;
Client *client;
char message[MAXLEN];
char *s;
#ifdef DEBUG
if (!*target)
return;
#endif /* DEBUG */
s = message;
#ifdef REDIRECT
if (redirect.to)
client = NULL;
else
client = find_client(target);
if (!redirect.to && !client)
#else /* REDIRECT */
if ((client = find_client(target)) == NULL)
#endif /* REDIRECT */
{
if (current->sock == -1)
{
#ifdef DEBUG
debug("(to_user) [%s] current->sock == -1\n",target);
#endif /* DEBUG */
return;
}
s = Strcpy(message,"NOTICE ");
if (ischannel(target))
Strcat(message,target);
else
nickcpy(s,target);
s = Strcat(message," :");
}
va_start(args,format);
vsprintf(s,format,args);
va_end(args);
#ifdef REDIRECT
if (redirect.to)
{
send_redirect(message);
return;
}
#endif /* REDIRECT */
/*
* tag on a newline for DCC or server
*/
s = Strcat(message,"\n");
#ifdef DEBUG
*s = 0;
#endif /* DEBUG */
if (client)
{
if (write(client->sock,message,(s - message)) < 0)
client->flags = DCC_DELETE;
#ifdef DEBUG
debug("(to_user) {%i} [%s] %s",client->sock,target,message);
#endif /* DEBUG */
return;
}
current->sendq_time += 2;
if (write(current->sock,message,(s - message)) < 0)
{
#ifdef DEBUG
debug("(to_user) {%i} [%s] errno = %i\n",current->sock,target,errno);
#endif /* DEBUG */
close(current->sock);
current->sock = -1;
current->connect = CN_NOSOCK;
return;
}
#ifdef DEBUG
debug("(to_user) {%i} [%s] %s",current->sock,target,message);
#endif /* DEBUG */
}
/*
* Read any data waiting on a socket or file descriptor
* and return any complete lines to the caller
*/
char *sockread(int s, char *rest, char *line)
{
char *src,*dst,*rdst;
int n;
errno = EAGAIN;
src = rest;
dst = line;
while(*src)
{
if (*src == '\n' || *src == '\r')
{
gotline:
while(*src == '\n' || *src == '\r')
src++;
*dst = 0;
dst = rest;
while(*src)
*(dst++) = *(src++);
*dst = 0;
#ifdef DEBUG
debug("(in) {%i} %s\n",s,line);
#endif /* DEBUG */
return((*line) ? line : NULL);
}
*(dst++) = *(src++);
}
rdst = src;
n = read(s,gsockdata,MSGLEN-2);
switch(n)
{
case 0:
errno = EPIPE;
case -1:
return(NULL);
}
gsockdata[n] = 0;
src = gsockdata;
while(*src)
{
if (*src == '\r' || *src == '\n')
goto gotline;
if ((dst - line) >= (MSGLEN-2))
{
/*
* line is longer than buffer, let the wheel spin
*/
src++;
continue;
}
*(rdst++) = *(dst++) = *(src++);
}
*rdst = 0;
return(NULL);
}
void readline(int fd, int (*callback)(char *))
{
char linebuf[MSGLEN],readbuf[MSGLEN];
char *ptr;
int oc;
*readbuf = 0;
do
{
ptr = sockread(fd,readbuf,linebuf);
oc = errno;
if (ptr && *ptr)
{
if (callback(ptr) == TRUE)
oc = EPIPE;
}
}
while(oc == EAGAIN);
close(fd);
#ifdef DEBUG
debug("(readline) done reading lines\n");
#endif /* DEBUG */
}
void remove_ks(KillSock *ks)
{
KillSock *ksp;
close(ks->sock);
if (ks == killsocks)
{
killsocks = ks->next;
}
else
{
ksp = killsocks;
while(ksp && (ksp->next != ks))
ksp = ksp->next;
if (ksp)
{
ksp->next = ks->next;
}
}
#ifdef DEBUG
debug("(killsock) {%i} removing killsocket\n",ks->sock);
#endif /* DEBUG */
Free((char**)&ks);
}
int killsock(int sock)
{
KillSock *ks,*ksnext;
struct timeval t;
fd_set rd,wd;
char bitbucket[MSGLEN];
int hi,n;
if (sock >= 0)
{
set_mallocdoer(killsock);
ks = (KillSock*)Calloc(sizeof(KillSock));
ks->time = now;
ks->sock = sock;
ks->next = killsocks;
killsocks = ks;
#ifdef DEBUG
debug("(killsock) {%i} added killsocket\n",ks->sock);
#endif /* DEBUG */
return(TRUE);
}
if (killsocks == NULL)
return(FALSE);
if (sock == -1)
t.tv_sec = 0;
else
t.tv_sec = 1;
t.tv_usec = 0;
FD_ZERO(&rd);
FD_ZERO(&wd);
hi = -1;
for(ks=killsocks;ks;ks=ks->next)
{
if (ks->sock > hi)
hi = ks->sock;
FD_SET(ks->sock,&rd);
FD_SET(ks->sock,&wd);
}
if (select(hi+1,&rd,&wd,NULL,&t) == -1)
{
switch(errno)
{
case EINTR:
/* have to redo the select */
case ENOMEM:
/* should never happen, but still */
return(TRUE);
}
}
for(ks=killsocks;ks;)
{
ksnext = ks->next;
if (FD_ISSET(ks->sock,&rd))
{
n = read(ks->sock,&bitbucket,MSGLEN);
if ((n == 0) || ((n == -1) && (errno != EAGAIN)))
remove_ks(ks);
}
if ((now - ks->time) > KILLSOCKTIMEOUT)
remove_ks(ks);
ks = ksnext;
}
return(TRUE);
}

536
src/spy.c Normal file
View File

@@ -0,0 +1,536 @@
/*
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 SPY_C
#include "config.h"
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
#ifdef DEBUG
LS const char SPY_DEFS[7][12] =
{
"SPY_FILE",
"SPY_CHANNEL",
"SPY_DCC",
"SPY_STATUS",
"SPY_MESSAGE",
"SPY_RAWIRC",
"SPY_BOTNET"
};
#endif /* DEBUG */
void send_spy(const char *src, const char *format, ...)
{
Chan *chan;
Mech *backup;
Spy *spy;
va_list msg;
const char *tempsrc;
char tempdata[MAXLEN];
int fd;
int printed = FALSE;
tempsrc = (src == SPYSTR_STATUS) ? time2medium(now) : src;
#ifdef DEBUG
debug("(send_spy) src %s format = '%s'\n",src,format);
#endif /* DEBUG */
for(spy=current->spylist;spy;spy=spy->next)
{
if ((*src == '#' || *src == '*') && spy->t_src == SPY_CHANNEL)
{
if ((*src != '*') && Strcasecmp(spy->src,src))
continue;
if ((chan = find_channel_ac(spy->src)) == NULL)
continue;
if (find_chanuser(chan,CurrentNick) == NULL)
continue;
tempsrc = spy->src;
}
else
/*
* by using string constants we can compare addresses
*/
if (spy->src != src)
continue;
if (!printed)
{
printed = TRUE;
va_start(msg,format);
vsprintf(tempdata,format,msg);
va_end(msg);
}
switch(spy->t_dest)
{
case SPY_DCC:
to_file(spy->dcc->sock,"[%s] %s\n",tempsrc,tempdata);
break;
case SPY_CHANNEL:
if (spy->destbot >= 0)
{
backup = current;
for(current=botlist;current;current=current->next)
{
if (current->guid == spy->destbot)
{
to_server("PRIVMSG %s :[%s] %s\n",spy->dest,tempsrc,tempdata);
break;
}
}
current = backup;
}
else
{
to_user(spy->dest,"[%s] %s",tempsrc,tempdata);
}
break;
case SPY_FILE:
if ((fd = open(spy->dest,O_WRONLY|O_CREAT|O_APPEND,NEWFILEMODE)) >= 0)
{
to_file(fd,"[%s] %s\n",logtime(now),tempdata);
close(fd);
}
}
}
}
void send_global(const char *src, const char *format, ...)
{
va_list msg;
Mech *backup;
char tempdata[MAXLEN];
int printed = FALSE;
backup = current;
for(current=botlist;current;current=current->next)
{
if (current->spy & SPYF_ANY)
{
if (!printed)
{
printed = TRUE;
va_start(msg,format);
vsprintf(tempdata,format,msg);
va_end(msg);
}
send_spy(src,FMT_PLAIN,tempdata);
}
}
current = backup;
}
void spy_typecount(Mech *bot)
{
Spy *spy;
bot->spy = 0;
for(spy=bot->spylist;spy;spy=spy->next)
{
bot->spy |= SPYF_ANY;
bot->spy |= (1 << spy->t_src);
}
}
struct
{
char *idstring;
int typenum;
} spy_source_list[] =
{
{ SPYSTR_STATUS, SPY_STATUS },
{ SPYSTR_MESSAGE, SPY_MESSAGE },
{ SPYSTR_RAWIRC, SPY_RAWIRC },
{ SPYSTR_BOTNET, SPY_BOTNET },
{ NULL, 0 },
};
int spy_source(char *from, int *t_src, char **src)
{
int i;
for(i=0;spy_source_list[i].idstring;i++)
{
if (!Strcasecmp(*src,spy_source_list[i].idstring))
{
*src = spy_source_list[i].idstring;
*t_src = spy_source_list[i].typenum;
return(200);
}
}
*t_src = SPY_CHANNEL;
if (!ischannel(*src))
return(-1);
return(get_useraccess(from,*src));
}
/*
*
* commands related to spy-pipes
*
*/
void do_spy(COMMAND_ARGS)
{
/*
* on_msg checks: CARGS
*/
Spy *spy;
Mech *backup,*destbot;
char *src,*dest;
int t_src,t_dest;
int sz;
int guid;
if (!*rest)
{
if (!current->spylist)
{
to_user(from,"No active spy channels");
return;
}
if (dcc_only_command(from))
return;
table_buffer("\037source\037\t\037target\037");
for(spy=current->spylist;spy;spy=spy->next)
{
switch(spy->t_src)
{
case SPY_MESSAGE:
src = "messages";
break;
default:
src = spy->src;
}
dest = (spy->t_dest == SPY_FILE) ? " (file)" : "";
table_buffer("%s\t%s%s",src,spy->dest,dest);
}
table_send(from,2);
return;
}
src = chop(&rest);
dest = chop(&rest);
if (!src)
{
spy_usage:
usage(from); /* usage for CurrentCmd->name */
return;
}
t_dest = SPY_DCC;
guid = -1;
destbot = NULL;
if (*src >= '0' && *src <= '9')
{
guid = 0;
while(*src && *src != ':')
{
guid = *src - '0';
src++;
}
if (*src != ':' && !ischannel(src+1))
goto spy_usage;
src++;
t_src = SPY_CHANNEL;
/*
* TODO: check access
*/
#ifdef DEBUG
debug("(do_spy) spy source guid = %i, channel = %s\n",guid,src);
#endif /* DEBUG */
/*
* is it a bot?
* TODO: check botnet bots also
*/
for(backup=botlist;backup;backup=backup->next)
{
if (backup->guid == guid)
{
destbot = backup;
goto guid_ok;
}
}
to_user(from,"Unknown bot guid: %i",guid);
return;
guid_ok:
;
}
else
{
sz = spy_source(from,&t_src,&src);
if (sz < 0)
goto spy_usage;
if (sz < cmdaccess)
return;
}
if (dest)
{
/*
* log to a file
*/
if (*dest == '>')
{
dest++;
if (!*dest)
{
dest = chop(&rest);
if (!dest || !*dest)
goto spy_usage;
}
/*
* Dont just open anything.
*/
if (!is_safepath(dest))
goto spy_usage;
t_dest = SPY_FILE;
goto spy_dest_ok;
}
if (!ischannel(dest))
goto spy_usage;
if (get_useraccess(from,dest) < cmdaccess)
{
to_user(from,"You don't have enough access on %s",dest);
return;
}
t_dest = SPY_CHANNEL;
}
spy_dest_ok:
#ifdef DEBUG
debug("(do_spy) src = `%s'; t_src = %i (%s); dest = `%s'; t_dest = %i (%s)\n",
src,t_src,SPY_DEFS[t_src-1],nullstr(dest),t_dest,SPY_DEFS[t_dest-1]);
if (guid >= 0)
debug("(do_spy) spying from remote bot guid %i (%s) channel %s\n",guid,(destbot) ? destbot->nick : "unknown",src);
#endif /* DEBUG */
if (t_dest == SPY_DCC)
{
if (!CurrentDCC)
{
to_user(from,"Spying is only allowed in DCC chat");
return;
}
dest = CurrentDCC->user->name;
}
for(spy=current->spylist;spy;spy=spy->next)
{
if ((spy->t_src == t_src) && (spy->t_dest == t_dest) &&
!Strcasecmp(spy->src,src) && !Strcasecmp(spy->dest,dest))
{
to_user(from,"Requested spy channel is already active");
return;
}
}
set_mallocdoer(do_spy);
sz = sizeof(Spy);
if (t_dest != SPY_DCC)
sz += strlen(dest);
if (t_src == SPY_CHANNEL)
sz += strlen(src);
spy = Calloc(sz);
if (t_dest != SPY_DCC)
{
spy->dest = spy->p;
spy->src = Strcat(spy->p,dest) + 1;
}
else
{
spy->dest = CurrentDCC->user->name;
spy->dcc = CurrentDCC;
spy->src = spy->p;
}
if (t_src == SPY_CHANNEL)
{
Strcpy(spy->src,src);
}
else
{
spy->src = src;
}
spy->t_src = t_src;
spy->t_dest = t_dest;
/*
* finally link the spy record into the chain
* TODO: botnet bots
*/
if (guid >= 0)
{
if (destbot)
{
spy->destbot = current->guid;
spy->next = destbot->spylist;
destbot->spylist = spy;
spy_typecount(destbot);
}
}
else
{
spy->destbot = -1;
spy->next = current->spylist;
current->spylist = spy;
spy_typecount(current);
}
switch(t_src)
{
case SPY_STATUS:
send_spy(SPYSTR_STATUS,"(%s) Added to mech core",nickcpy(NULL,from));
break;
case SPY_MESSAGE:
src = "messages";
default:
to_user(from,"Spy channel for %s has been activated",src);
}
}
void do_rspy(COMMAND_ARGS)
{
/*
* on_msg checks: CARGS
*/
Spy *spy,**pspy;
char *src,*dest,*tmp;
int t_src,t_dest;
int n;
src = chop(&rest);
dest = chop(&rest);
t_dest = SPY_DCC;
if (!src)
{
rspy_usage:
usage(from); /* usage for CurrentCmd->name */
return;
}
n = spy_source(from,&t_src,&src);
if (n < 0)
goto rspy_usage;
if (n < cmdaccess)
return;
if (dest)
{
if (*dest == '>')
{
dest++;
if (!*dest)
{
dest = chop(&rest);
if (!dest || !*dest)
goto rspy_usage;
}
/*
* Dont just open anything.
*/
if (!is_safepath(dest))
goto rspy_usage;
t_dest = SPY_FILE;
goto rspy_dest_ok;
}
if (ischannel(dest))
t_dest = SPY_CHANNEL;
}
else
dest = from;
rspy_dest_ok:
#ifdef DEBUG
debug("(do_rspy) src = `%s'; t_src = %i (%s); dest = `%s'; t_dest = %i (%s)\n",
src,t_src,SPY_DEFS[t_src-1],dest,t_dest,SPY_DEFS[t_dest-1]);
#endif /* DEBUG */
/*
* check if the spy channel exists
*/
for(spy=current->spylist;spy;spy=spy->next)
{
if ((spy->t_src == t_src) && (spy->t_dest == t_dest) && (!Strcasecmp(spy->src,src)))
{
if ((t_dest == SPY_DCC) && (!nickcmp(spy->dest,dest)))
break;
else
if (!Strcasecmp(spy->dest,dest))
break;
}
}
if (!spy)
{
to_user(from,"No matching spy channel could be found");
return;
}
switch(t_src)
{
case SPY_STATUS:
tmp = (t_dest == SPY_DCC) ? nickcpy(NULL,spy->dest) : spy->dest;
send_spy(SPYSTR_STATUS,"(%s) Removed from mech core",tmp);
break;
case SPY_MESSAGE:
src = "messages";
default:
to_user(from,"Spy channel for %s has been removed",src);
break;
}
pspy = &current->spylist;
while(*pspy)
{
if (*pspy == spy)
{
*pspy = spy->next;
Free((char**)&spy);
return;
}
pspy = &(*pspy)->next;
}
spy_typecount(current);
}

144
src/stats.c Normal file
View File

@@ -0,0 +1,144 @@
/*
EnergyMech, IRC bot software
Copyright (c) 2001-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 STATS_C
#include "config.h"
#ifdef STATS
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
#include <math.h>
void stats_loghour(Chan *chan, char *filename, int hour)
{
ChanStats *stats;
time_t when;
int fd;
if (!(stats = chan->stats))
return;
when = (now - (now % 3600));
if ((fd = open(filename,O_WRONLY|O_APPEND|O_CREAT,NEWFILEMODE)) >= 0)
{
stats->userseconds += stats->users * (when - stats->lastuser);
to_file(fd,"H %s %i %i %i %i\n",chan->name,hour,
(stats->flags & CSTAT_PARTIAL) ? -stats->userseconds : stats->userseconds,
stats->userpeak,stats->userlow);
close(fd);
}
stats->LHuserseconds = stats->userseconds;
stats->userseconds = 0;
stats->lastuser = when;
stats->flags = 0;
}
void stats_plusminususer(Chan *chan, int plusminus)
{
ChanStats *stats;
ChanUser *cu;
if (!(stats = chan->stats))
{
set_mallocdoer(stats_plusminususer);
chan->stats = stats = (ChanStats*)Calloc(sizeof(ChanStats)); /* Calloc sets memory to 0 */
for(cu=chan->users;cu;cu=cu->next)
stats->users++;
stats->userpeak = stats->users;
stats->userlow = stats->users;
stats->lastuser = now;
stats->flags = CSTAT_PARTIAL;
}
/*
* add (number of users until now * seconds since last user entered/left)
*/
stats->userseconds += stats->users * (now - stats->lastuser);
stats->lastuser = now;
stats->users += plusminus; /* can be both negative (-1), zero (0) and positive (+1) */
if (stats->userpeak < stats->users)
stats->userpeak = stats->users;
if (stats->userlow > stats->users)
stats->userlow = stats->users;
#ifdef DEBUG
debug("(stats_plusminususer) %s: %i users, %i userseconds, %i high, %i low; %s (%lu)\n",
chan->name,stats->users,stats->userseconds,stats->userpeak,stats->userlow,
atime(stats->lastuser),stats->lastuser);
#endif /* DEBUG */
}
void do_info(COMMAND_ARGS)
{
ChanStats *stats;
Chan *chan;
char *p;
char text[MSGLEN];
ulong avg;
if (current->chanlist == NULL)
{
to_user(from,ERR_NOCHANNELS);
return;
}
to_user(from,"\037channel\037 "
"\037average\037 \037peak\037 \037low\037");
for(chan=current->chanlist;chan;chan=chan->next)
{
*(p = text) = 0;
p = Strcat(p,chan->name);
if (chan == current->activechan)
p = Strcat(p," (current)");
if ((stats = chan->stats))
{
if (stats && stats->flags == CSTAT_PARTIAL)
p = Strcat(p," (partial)");
while(p < text+35)
*(p++) = ' ';
if (stats->LHuserseconds > 0)
{
avg = stats->LHuserseconds / (60*60);
}
else
{
avg = (stats->userpeak + stats->userlow) / 2;
}
sprintf(p,"%-7lu %-4i %i",avg,stats->userpeak,stats->userlow);
to_user(from,FMT_PLAIN,text);
sprintf(text,"Messages: %i Notices: %i Joins: %i Parts: %i Kicks: %i Quits: %i",
stats->privmsg,stats->notice,stats->joins,stats->parts,stats->kicks,stats->quits);
}
else
{
Strcpy(p," (no current data)");
}
to_user(from,FMT_PLAIN,text);
}
}
#endif /* STATS */

822
src/structs.h Normal file
View File

@@ -0,0 +1,822 @@
/*
EnergyMech, IRC bot software
Parts Copyright (c) 1997-2009 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.
*/
#ifndef STRUCTS_H
#define STRUCTS_H 1
typedef union usercombo
{
struct
{
ulong access:8, /* access level (0-200) [0-255] */
prot:3, /* protlevel (0-4) [0-7] */
#ifdef BOTNET
noshare:1, /* dont share this user over botnet */
readonly:1, /* botnet cannot alter this user */
#endif /* BOTNET */
#ifdef GREET
greetfile:1, /* greeting is filename */
randline:1, /* grab random line from filename */
#endif /* GREET */
#ifdef BOUNCE
bounce:1, /* user has access to bouncer */
#endif /* BOUNCE */
echo:1, /* partyline echo of own messages */
aop:1, /* auto-opping */
avoice:1; /* auto-voicing */
} x;
ulong comboflags;
} usercombo;
#ifndef GENCMD_C
typedef struct ircLink
{
struct ircLink *next;
int servsock;
int usersock;
int status;
time_t active;
char *userLine;
char *nickLine;
char *nick; /* which nick to speak to */
char *handle;
#ifdef IDWRAP
char *idfile;
#endif /* IDWRAP */
char servmem[MSGLEN];
char usermem[MSGLEN];
} ircLink;
typedef struct
{
int tenminute;
int hour;
} SequenceTime;
typedef struct DEFstruct
{
int id;
char *idstr;
} DEFstruct;
typedef struct Alias
{
struct Alias *next;
char *format;
char alias[1];
} Alias;
typedef struct nfLog
{
struct nfLog *next;
time_t signon;
time_t signoff;
char *realname;
char userhost[2];
} nfLog;
typedef struct Notify
{
struct Notify *next;
int status;
time_t checked; /* when nick was last checked */
nfLog *log; /* online + offline + userhost + realname */
char *info;
char *endofmask;
char *mask;
char nick[3];
} Notify;
typedef struct IReq
{
struct IReq *next;
time_t when;
int t;
char *nick;
char from[2];
} IReq;
typedef struct Seen
{
struct Seen *next;
time_t when;
int t;
/*
* dont mess with the order of these
*/
char *pa;
char *pb;
char *userhost;
char nick[4];
} Seen;
typedef union UniVar
{
union UniVar *proc_var;
char *str_var;
char char_var;
int int_var;
} UniVar;
typedef struct Setting
{
uchar type;
uchar uaccess; /* user access to touch/view this setting */
short min;
void *setto; /* type-casted to whatever */
char *name;
int max;
void (*func)(const struct Setting *);
} Setting;
typedef struct Strp
{
struct Strp *next;
char p[1];
} Strp;
typedef struct KickSay
{
struct KickSay *next;
int action;
/*
* dont mess with the order of these
*/
char *chan;
char *reason;
char mask[5];
} KickSay;
typedef struct Shit
{
struct Shit *next;
int action;
time_t time;
time_t expire;
/*
* dont mess with the order of these
*/
char *chan;
char *from;
char *reason;
char mask[4];
} Shit;
/*
* this struct is put to use in global.h
*/
typedef struct User
{
struct User *next; /* linked list */
Strp *mask;
Strp *chan;
union usercombo x;
#ifdef GREET
char *greet;
#endif /* GREET */
#ifdef NOTE
Strp *note;
#endif /* NOTE */
#ifdef BOTNET
int modcount;
int guid;
int tick;
int addsession;
#endif /* BOTNET */
/*
* dont mess with the order of these
*/
char *pass;
char name[2];
} User;
typedef struct Client
{
struct Client *next;
User *user;
int sock;
int flags;
int inputcount; /* used to enforce input limit */
time_t lasttime; /* can be used for idletime */
#ifdef DCC_FILE
int fileno;
int fileend;
time_t start;
char *whom;
char filename[2];
#endif /* DCC_FILE */
char sockdata[MSGLEN]; /* input buffer */
} Client;
typedef struct ShortClient
{
struct Client *next;
User *user;
int sock;
int flags;
int inputcount; /* used to enforce input limit */
time_t lasttime; /* can be used for idletime */
} ShortClient;
typedef struct Auth
{
struct Auth *next;
time_t active;
User *user;
char nuh[1];
} Auth;
typedef struct ChanUser
{
struct ChanUser *next;
User *user;
Shit *shit;
int flags;
/* distance between &_num -> &_time is used in check_mass */
int floodnum;
time_t floodtime;
int bannum;
time_t bantime;
int deopnum;
time_t deoptime;
int kicknum;
time_t kicktime;
int nicknum;
time_t nicktime;
int capsnum;
time_t capstime;
time_t idletime;
#ifdef CHANBAN
time_t lastwhois; /* time when the last whois was made to check channels */
#endif /* CHANBAN */
char *nick; /* nick can change without the user reconnecting */
char userhost[1]; /* ident & host is static */
} ChanUser;
typedef struct qKick
{
struct qKick *next;
char *reason;
char nick[2];
} qKick;
typedef struct qMode
{
struct qMode *next;
int pri; /* urgency factor */
int type;
void *data; /* nick (ChanUser), key, banmask, limit */
char plusminus; /* +/- */
char modeflag; /* ov, iklmnpst */
} qMode;
typedef struct Ban
{
struct Ban *next;
time_t time;
#ifdef IRCD_EXTENSIONS
ulong imode:1,
emode:1;
#endif /* IRCD_EXTENSIONS */
char *bannedby;
char banstring[2];
} Ban;
typedef struct ChanStats
{
int userseconds; /* number of users on channel * number of seconds (one hour, 3600 seconds) */
int LHuserseconds;
int users;
time_t lastuser; /* last time a user joined or left (part, quit, kick) */
int flags;
int userpeak;
int userlow;
int joins;
int parts;
int kicks;
int quits;
int privmsg;
int notice;
} ChanStats;
typedef struct ShortChan
{
struct ShortChan *next;
char *name;
} ShortChan;
typedef struct Chan
{
struct Chan *next;
char *name; /* name of the channel */
char *key; /* channel key, if any */
char *topic; /* channel topic, if any */
char *kickedby; /* n!u@h of whomever kicks the bot */
Ban *banlist; /* banlist */
qKick *kicklist; /* KICK sendq */
qMode *modelist; /* MODE sendq */
ChanUser *users; /* users */
ChanUser *cacheuser; /* cache for find_chanuser() */
int limit; /* channel limit */
ulong
bot_is_op:1, /* set if the bot is opped */
private:1, /* channel mode: +p */
secret:1, /* channel mode: +s */
moderated:1, /* channel mode: +m */
topprot:1, /* channel mode: +t */
limitmode:1, /* channel mode: +l */
invite:1, /* channel mode: +i */
nomsg:1, /* channel mode: +n */
keymode:1, /* channel mode: +k */
hiddenkey:1, /* Undernet screwup */
sync:1, /* join sync status */
wholist:1, /* first /WHO */
active:1, /* active or inactive channel */
rejoin:1; /* trying to rejoin it? */
int this10,this60;
int last10,last60;
#ifdef DYNAMODE
time_t lastlimit;
#endif /* DYNAMODE */
#ifdef STATS
ChanStats *stats;
#endif /* STATS */
UniVar setting[CHANSET_SIZE]; /* channel vars */
} Chan;
typedef struct Spy
{
struct Spy *next;
int t_src;
int t_dest;
Client *dcc;
int destbot;
char *src;
char *dest;
char p[2];
} Spy;
typedef struct Server
{
struct Server *next;
int ident;
int usenum;
int servergroup;
int port;
int err;
time_t lastconnect;
time_t lastattempt;
time_t maxontime;
char realname[NAMEBUF];
char name[NAMEBUF];
char pass[PASSLEN];
} Server;
typedef struct ServerGroup
{
struct ServerGroup *next;
int servergroup;
char name[1];
} ServerGroup;
typedef struct Mech
{
struct Mech *next;
int guid; /* globally uniqe ID */
int connect;
int sock;
struct in_addr ip; /* for DCC */
int server; /* ident of my current server */
int nextserver;
/*
* Line buffer for non-essential stuff
*/
Strp *sendq;
time_t sendq_time;
/*
* Basic bot information
*/
char *nick; /* current nickname */
char *wantnick; /* wanted nickname */
char *userhost;
int vhost_type;
ulong reset:1,
rejoin:1,
away:1;
User *userlist;
time_t ul_save; /* increment for each change, save if needed */
Chan *chanlist;
Chan *activechan;
Client *clientlist;
Auth *authlist;
Shit *shitlist;
KickSay *kicklist;
IReq *parselist;
#ifdef NOTIFY
Notify *notifylist;
#endif /* NOTIFY */
Spy *spylist;
int spy;
#ifdef NOTIFY
time_t lastnotify; /* ... */
#endif /* NOTIFY */
time_t lastreset; /* last time bot was reset */
time_t lastantiidle; /* avoid showing large idle times */
time_t lastrejoin; /* last time channels were reset */
#ifdef CHANBAN
time_t lastchanban; /* last time a chanban check was run */
#endif /* CHANBAN */
time_t conntry; /* when connect try started */
time_t activity; /* Away timer (AAWAY) */
time_t ontime; /* how long the bot has been connected */
#ifdef IRCD_EXTENSIONS
int ircx_flags;
#endif /* IRCD_EXTENSIONS */
/*
* Buffers for do_die() command.
*/
char *signoff;
char *from;
#ifdef IDWRAP
char *identfile;
#endif /* IDWRAP */
/* big buffers at the end */
UniVar setting[SIZE_VARS]; /* global vars + channel defaults */
char modes[32];
char *lastcmds[LASTCMDSIZE];
/*
* Server socket input buffer
*/
char sockdata[MSGLEN];
} Mech;
typedef struct aME
{
void *area;
void *doer;
int size;
time_t when;
char touch;
} aME;
typedef struct aMEA
{
struct aMEA *next;
aME mme[MRSIZE];
} aMEA;
typedef struct KillSock
{
struct KillSock *next;
time_t time;
int sock;
} KillSock;
typedef struct Note
{
struct Note *next;
time_t start;
char *user;
char *to;
char from[3];
} Note;
typedef struct PartyUser
{
struct PartyUser *next;
} PartyUser;
typedef struct BotInfo
{
struct BotInfo *next;
int guid;
int hops;
char *version;
char *server;
char nuh[4];
} BotInfo;
typedef struct BotNet
{
struct BotNet *next;
int sock;
int status;
int has_data;
/*
* do not touch the above vars!
* they are copied partially in net.c
*/
int guid; /* remote bot guid */
int lsid; /* local session id */
int rsid; /* remote session id */
struct
{
ulong pta:1; /* plain text auth */
ulong md5:1; /* md5 */
} opt;
Mech *controller;
int tick; /* tick of the remote bot */
int addsession;
time_t tick_last;
time_t when;
struct BotInfo *botinfo;
int list_complete;
char sockdata[MSGLEN];
} BotNet;
typedef struct NetCfg
{
struct NetCfg *next;
int guid;
ushort port;
ushort linked:1;
char *host;
char pass[2];
} NetCfg;
typedef struct WebDoc
{
struct WebDoc *next;
char *url;
void (*proc)();
} WebDoc;
typedef struct WebSock
{
struct WebSock *next;
int sock;
int status;
time_t when;
WebDoc *docptr;
Mech *ebot;
Chan *echan;
char *url;
char sockdata[MSGLEN];
} WebSock;
typedef struct
{
time_t last;
time_t next;
ulong second1; //:30;
ulong second2; //:30;
ulong minute1; //:30;
ulong minute2; //:30;
ulong hour; //:24;
ulong weekday; //:7;
} HookTimer;
typedef struct Hook
{
struct Hook *next;
int (*func)();
int guid; /* guid filter */
int flags;
union {
void *any;
char *command;
char *host;
HookTimer *timer;
} type;
char self[2];
} Hook;
typedef struct TrivScore
{
struct TrivScore *next;
int score_wk;
int score_last_wk;
int week_nr;
int score_mo;
int score_last_mo;
int month_nr;
char nick[1];
} TrivScore;
#endif /* GENCMD_C */
typedef struct OnMsg
{
const char *name;
void (*func)(char *, char *, char *, int);
ulong defaultaccess:8, /* defaultaccess */
dcc:1,
cc:1,
pass:1,
args:1,
nopub:1,
nocmd:1,
gaxs:1,
caxs:1,
redir:1,
lbuf:1,
cbang:1,
acchan:1;
char *cmdarg;
} OnMsg;
typedef unsigned char OnMsg_access;
typedef struct dnsAuthority
{
struct dnsAuthority *next;
struct in_addr ip;
unsigned char count;
char hostname[1];
} dnsAuthority;
typedef struct dnsList
{
struct dnsList *next;
time_t when;
struct in_addr ip;
ushort id;
int findauth;
dnsAuthority *auth;
dnsAuthority *auth2;
char *cname;
char host[1];
} dnsList;
typedef struct dnsQuery
{
ushort qid; /* query id */
ushort flags;
ushort questions;
ushort answers;
ushort authorities;
ushort resources;
} dnsQuery;
#endif /* STRUCTS_H */

654
src/tcl.c Normal file
View File

@@ -0,0 +1,654 @@
/*
EnergyMech, IRC bot software
Copyright (c) 2001-2009 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 TCL_C
#include "config.h"
#ifdef TCL
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
#include <tcl.h>
LS Tcl_Interp *energymech_tcl = NULL;
#define tclv_READ TCL_TRACE_READS
#define tclv_WRITE TCL_TRACE_WRITES
#define tclv_RDWR (tclv_READ|tclv_WRITE)
#define TVINFO_UNTYPED 0x0ffff
#define TVINFO_INT 0x10000
#define TVINFO_CHAR 0x20000
enum {
TVINFO_pointer,
TVINFO_guid,
TVINFO_nick,
TVINFO_wantnick,
TVINFO_server,
TVINFO_nextserver,
TVINFO_currentchan,
};
typedef struct Tcl_TVInfo
{
int type;
int flags;
char *name;
const char *data;
Tcl_Obj *n1;
} Tcl_TVInfo;
LS Tcl_TVInfo vinfolist[] =
{
{ TVINFO_pointer | TVINFO_CHAR, tclv_READ, "mech_currentnick", CurrentNick },
{ TVINFO_guid | TVINFO_INT, tclv_READ, "mech_guid" },
{ TVINFO_nick | TVINFO_CHAR, tclv_READ, "mech_nick" },
{ TVINFO_wantnick | TVINFO_CHAR, tclv_RDWR, "mech_wantnick" },
{ TVINFO_server | TVINFO_INT, tclv_READ, "mech_server" },
{ TVINFO_nextserver | TVINFO_INT, tclv_RDWR, "mech_nextserver" },
{ TVINFO_currentchan | TVINFO_CHAR, tclv_READ, "mech_currentchan" },
{ TVINFO_pointer | TVINFO_CHAR, tclv_READ, "mech_version", VERSION },
{ TVINFO_pointer | TVINFO_CHAR, tclv_READ, "mech_srcdate", SRCDATE },
{ TVINFO_pointer | TVINFO_CHAR, tclv_READ, "mech_class", BOTCLASS },
{ 0, }};
/*
*
*
*
*/
char *tcl_var_read(Tcl_TVInfo *vinfo, Tcl_Interp *I, char *n1, char *n2, int flags)
{
Tcl_Obj *obj;
union {
int i;
const char *c;
} rdata;
switch(vinfo->type & TVINFO_UNTYPED)
{
case TVINFO_pointer:
rdata.c = vinfo->data;
break;
case TVINFO_guid:
rdata.i = (current) ? current->guid : -1;
break;
case TVINFO_nick:
rdata.c = (current) ? current->nick : "(undefined variable)";
break;
case TVINFO_wantnick:
rdata.c = (current) ? current->wantnick : "(undefined variable)";
break;
case TVINFO_server:
rdata.i = (current) ? current->server : -1;
break;
case TVINFO_nextserver:
rdata.i = (current) ? current->nextserver : -1;
break;
case TVINFO_currentchan:
rdata.c = (current && current->activechan) ? current->activechan->name : "(undefined variable)";
break;
default:
return("(undefined variable)");
}
if (vinfo->type & TVINFO_INT)
{
obj = Tcl_NewIntObj(rdata.i);
}
else
/* if (vinfo->type & TVINFO_CHAR) */
{
obj = Tcl_NewStringObj((char*)rdata.c,strlen(rdata.c));
}
Tcl_ObjSetVar2(energymech_tcl,vinfo->n1,NULL,obj,TCL_GLOBAL_ONLY);
return(NULL);
}
char *tcl_var_write(Tcl_TVInfo *vinfo, Tcl_Interp *I, char *n1, char *n2, int flags)
{
return("not yet implemented");
}
/*
*
*
*
*/
int tcl_timer_jump(Hook *hook)
{
return(0);
}
int tcl_parse_jump(char *from, char *rest, Hook *hook)
{
Tcl_Obj *tcl_result;
int i;
#ifdef DEBUG
debug("(tcl_parse_jump) %s %s %s\n",
nullstr(hook->self),nullstr(from),nullstr(rest));
#endif /* DEBUG */
if (from)
nickcpy(CurrentNick,from);
else
*CurrentNick = 0;
Tcl_SetVar(energymech_tcl,"_from",from,0);
Tcl_SetVar(energymech_tcl,"_rest",rest,0);
i = 0;
if (Tcl_VarEval(energymech_tcl,hook->self," $_from $_rest",NULL) == TCL_OK)
{
tcl_result = Tcl_GetObjResult(energymech_tcl);
Tcl_GetIntFromObj(energymech_tcl,tcl_result,&i);
}
#ifdef DEBUG
if (energymech_tcl->result && *energymech_tcl->result)
debug("(tcl_parse_jump) result = %s\n",nullstr(energymech_tcl->result));
#endif /* DEBUG */
return(i);
}
#ifdef DCC_FILE
void tcl_dcc_complete(Client *client, int cps)
{
Tcl_Obj *obj;
Tcl_Obj *vname;
Hook *hook;
vname = Tcl_NewStringObj("_cps",3);
for(hook=hooklist;hook;hook=hook->next)
{
if (hook->flags == HOOK_DCC_COMPLETE &&
hook->guid && current && hook->guid == current->guid)
{
Tcl_SetVar(energymech_tcl,"_filetarget",client->whom,0);
Tcl_SetVar(energymech_tcl,"_filename",client->filename,0);
obj = Tcl_NewIntObj(cps);
Tcl_ObjSetVar2(energymech_tcl,vname,NULL,obj,TCL_GLOBAL_ONLY);
Tcl_VarEval(energymech_tcl,hook->self," $_filetarget $_filename $_cps",NULL);
#ifdef DEBUG
if (energymech_tcl->result && *energymech_tcl->result)
debug("(tcl_dcc_complete) result = %s\n",nullstr(energymech_tcl->result));
#endif /* DEBUG */
}
}
}
#endif /* DCC_FILE */
int tcl_hook(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[])
{
Hook *hook;
HookTimer hooktimer;
char *type,*command,*self;
int guid,mode;
int sz1,sz2;
guid = 0;
if (objc == 5)
{
if (Tcl_GetIntFromObj(energymech_tcl,objv[4],&guid) == TCL_ERROR)
return(TCL_ERROR);
}
else
if (objc != 4)
{
return(TCL_ERROR);
}
type = Tcl_GetStringFromObj(objv[1],&mode);
command = Tcl_GetStringFromObj(objv[2],&sz1);
self = Tcl_GetStringFromObj(objv[3],&sz2);
if (!mode || !sz1 || !sz2)
return(TCL_ERROR);
if (!Strcasecmp(type,"command"))
mode = HOOK_COMMAND;
else
if (!Strcasecmp(type,"dcc_complete"))
mode = HOOK_DCC_COMPLETE;
else
if (!Strcasecmp(type,"parse"))
mode = HOOK_PARSE;
else
if (!Strcasecmp(type,"timer"))
{
if (compile_timer(&hooktimer,command) < 0)
return(TCL_ERROR);
mode = HOOK_TIMER;
sz1 = sizeof(HookTimer);
}
else
{
return(TCL_ERROR);
}
set_mallocdoer(tcl_hook);
hook = (Hook*)Calloc(sizeof(Hook) + sz1 + sz2);
hook->guid = guid;
hook->flags = mode;
hook->next = hooklist;
hooklist = hook;
hook->type.any = (void*)(Strcpy(hook->self,self) + 1);
switch(mode)
{
case HOOK_COMMAND:
case HOOK_PARSE:
Strcpy(hook->type.command,command);
hook->func = tcl_parse_jump;
break;
default:
/* case HOOK_TIMER: */
memcpy(hook->type.timer,&hooktimer,sizeof(HookTimer));
hook->func = tcl_timer_jump;
break;
}
#ifdef DEBUG
debug("(tcl_hook) hooked %s `%s' --> %s\n",
nullstr(type),nullstr(command),nullstr(self));
#endif /* DEBUG */
return(TCL_OK);
}
int tcl_unhook(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[])
{
return(TCL_ERROR);
}
int tcl_userlevel(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[])
{
Tcl_Obj *tcl_result;
char *nuh,*chan;
int n;
if (!current)
return(TCL_ERROR);
chan = NULL;
if (objc == 3)
{
if ((chan = Tcl_GetStringFromObj(objv[2],NULL)) == NULL)
return(TCL_ERROR);
}
else
if (objc != 2)
return(TCL_ERROR);
if ((nuh = Tcl_GetStringFromObj(objv[1],NULL)) == NULL)
return(TCL_ERROR);
n = get_useraccess(nuh,chan);
tcl_result = Tcl_GetObjResult(energymech_tcl);
Tcl_SetIntObj(tcl_result,n);
return(TCL_OK);
}
#ifdef DEBUG
int tcl_debug(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[])
{
char *text;
if (objc != 2)
return(TCL_ERROR);
if ((text = Tcl_GetStringFromObj(objv[1],NULL)) == NULL)
return(TCL_ERROR);
debug("(tcl_debug) %s\n",text);
return(TCL_OK);
}
#endif /* DEBUG */
int tcl_to_server(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[])
{
Strp *sp,**pp;
Tcl_Obj *tcl_result;
char *line;
int n,sz,sendqmax;
if (!current)
return(TCL_ERROR);
sendqmax = -1;
if (objc == 3)
{
if (Tcl_GetIntFromObj(energymech_tcl,objv[2],&sendqmax) == TCL_ERROR)
return(TCL_ERROR);
}
else
if (objc != 2)
return(TCL_ERROR);
if ((line = Tcl_GetStringFromObj(objv[1],&sz)) == NULL)
return(TCL_ERROR);
#ifdef DEBUG
debug("(tcl_to_server) max = %i; line = %s",sendqmax,line);
#endif /* DEBUG */
if (sendqmax >= 0)
{
n = 0;
pp = &current->sendq;
while(*pp)
{
n++;
pp = &(*pp)->next;
}
if (sendqmax && n >= sendqmax)
{
n = -n;
}
else
if (sz)
{
*pp = sp = (Strp*)Calloc(sizeof(Strp) + sz);
/* Calloc sets to zero sp->next = NULL; */
Strcpy(sp->p,line);
}
}
else
{
if ((n = write(current->sock,line,sz)) < 0)
{
#ifdef DEBUG
debug("(tcl_to_server) {%i} errno = %i\n",current->sock,errno);
#endif /* DEBUG */
close(current->sock);
current->sock = -1;
current->connect = CN_NOSOCK;
return(TCL_ERROR);
}
current->sendq_time += 2;
}
tcl_result = Tcl_GetObjResult(energymech_tcl);
Tcl_SetIntObj(tcl_result,n);
return(TCL_OK);
}
int tcl_to_file(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[])
{
Tcl_Obj *tcl_result;
char *text;
int fd,sz;
int r;
if (objc != 3)
return(TCL_ERROR);
if ((Tcl_GetIntFromObj(energymech_tcl,objv[1],&fd) == TCL_ERROR)
|| ((text = Tcl_GetStringFromObj(objv[2],&sz)) == NULL))
return(TCL_ERROR);
r = write(fd,text,sz);
tcl_result = Tcl_GetObjResult(energymech_tcl);
Tcl_SetIntObj(tcl_result,r);
return(TCL_OK);
}
#ifdef DCC_FILE
int tcl_dcc_sendfile(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[])
{
Tcl_Obj *tcl_result;
char *filename,*target;
int sz;
if (objc != 3)
return(TCL_ERROR);
if ((target = Tcl_GetStringFromObj(objv[1],NULL)) == NULL)
return(TCL_ERROR);
if ((filename = Tcl_GetStringFromObj(objv[2],NULL)) == NULL)
return(TCL_ERROR);
if ((sz = dcc_sendfile(target,filename)) < 0)
return(TCL_ERROR);
tcl_result = Tcl_GetObjResult(energymech_tcl);
Tcl_SetIntObj(tcl_result,sz);
return(TCL_OK);
}
#endif /* DCC_FILE */
#ifdef RAWDNS
int tcl_dns_jump(char *host, char *resolved, Hook *hook)
{
Tcl_Obj *tcl_result;
int i;
#ifdef DEBUG
debug("(tcl_dns_jump) %s %s %s\n",
nullstr(hook->self),nullstr(host),nullstr(resolved));
#endif /* DEBUG */
Tcl_SetVar(energymech_tcl,"_host",host,0);
Tcl_SetVar(energymech_tcl,"_resolved",resolved,0);
i = 0;
if (Tcl_VarEval(energymech_tcl,hook->self," $_host $_resolved",NULL) == TCL_OK)
{
tcl_result = Tcl_GetObjResult(energymech_tcl);
Tcl_GetIntFromObj(energymech_tcl,tcl_result,&i);
}
#ifdef DEBUG
if (energymech_tcl->result && *energymech_tcl->result)
debug("(tcl_dns_jump) result = %s\n",nullstr(energymech_tcl->result));
#endif /* DEBUG */
return(i);
}
int tcl_dns(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[])
{
Tcl_Obj *tcl_result;
Hook *hook;
char *host,*callback;
if (objc != 3)
return(TCL_ERROR);
if ((host = Tcl_GetStringFromObj(objv[1],NULL)) == NULL)
return(TCL_ERROR);
if ((callback = Tcl_GetStringFromObj(objv[2],NULL)) == NULL)
return(TCL_ERROR);
#ifdef DEBUG
debug("(tcl_dns) resolving: %s (callback %s)\n",host,callback);
#endif /* DEBUG */
set_mallocdoer(tcl_dns);
hook = (Hook*)Calloc(sizeof(Hook) + strlen(host));
hook->guid = (current) ? current->guid : 0;
hook->flags = HOOK_DNS;
hook->next = hooklist;
hooklist = hook;
hook->type.host = Strcpy(hook->self,callback) + 1;
Strcpy(hook->type.host,host);
hook->func = tcl_dns_jump;
rawdns(host);
return(TCL_OK);
}
#endif /* RAWDNS */
/*
*
*
*
*/
LS struct
{
char *cmdname;
void *func;
} tcl2mech[] =
{
{ "to_server", tcl_to_server },
{ "to_file", tcl_to_file },
{ "mech_userlevel", tcl_userlevel },
{ "mech_hook", tcl_hook },
{ "mech_unhook", tcl_unhook },
#ifdef DEBUG
{ "mech_debug", tcl_debug },
#endif /* DEBUG */
#ifdef DCC_FILE
{ "mech_dcc_sendfile", tcl_dcc_sendfile },
#endif /* DCC_FILE */
#ifdef RAWDNS
{ "mech_dns", tcl_dns },
#endif /* RAWDNS */
{ NULL, }};
void init_tcl(void)
{
#ifdef DEBUG
void *res;
int resi;
#endif /* DEBUG */
int i;
if ((energymech_tcl = Tcl_CreateInterp()) == NULL)
return;
if (Tcl_Init(energymech_tcl) != TCL_OK)
{
Tcl_DeleteInterp(energymech_tcl);
energymech_tcl = NULL;
return;
}
#ifdef DEBUG
Tcl_SetVar(energymech_tcl,"define_debug","1",0);
#endif /* DEBUG */
for(i=0;tcl2mech[i].cmdname;i++)
{
#ifdef DEBUG
res =
#endif /* DEBUG */
Tcl_CreateObjCommand(energymech_tcl,tcl2mech[i].cmdname,tcl2mech[i].func,NULL,NULL);
#ifdef DEBUG
debug("(init_tcl) create tcl command: %s (%s)\n",tcl2mech[i].cmdname,(res) ? "SUCCESS" : "FAIL");
#endif /* DEBUG */
}
/*
* trace list of variables
*/
for(i=0;vinfolist[i].name;i++)
{
/*
* make the variable name into a tcl object
*/
vinfolist[i].n1 = Tcl_NewStringObj(vinfolist[i].name,strlen(vinfolist[i].name));
Tcl_IncrRefCount(vinfolist[i].n1);
/*
* trace read ops
*/
#ifdef DEBUG
resi =
#endif /* DEBUG */
Tcl_TraceVar(energymech_tcl,vinfolist[i].name,TCL_TRACE_READS | TCL_GLOBAL_ONLY,
(Tcl_VarTraceProc*)tcl_var_read,&vinfolist[i]);
#ifdef DEBUG
debug("(init_tcl) trace tcl variable (read): %s (%s)\n",
vinfolist[i].name,(resi == TCL_OK) ? "SUCCESS" : "FAIL");
#endif /* DEBUG */
/*
* trace write ops
*/
if ((vinfolist[i].flags & tclv_WRITE) == 0)
continue;
#ifdef DEBUG
resi =
#endif /* DEBUG */
Tcl_TraceVar(energymech_tcl,vinfolist[i].name,TCL_TRACE_WRITES | TCL_GLOBAL_ONLY,
(Tcl_VarTraceProc*)tcl_var_write,(ClientData)&vinfolist[i]);
#ifdef DEBUG
debug("(init_tcl) trace tcl variable (write): %s (%s)\n",
vinfolist[i].name,(resi == TCL_OK) ? "SUCCESS" : "FAIL");
#endif /* DEBUG */
}
}
/*
*
*
*
*/
void do_tcl(COMMAND_ARGS)
{
int res;
if (!energymech_tcl)
{
init_tcl();
if (!energymech_tcl)
return;
}
#ifdef PLEASE_HACK_MY_SHELL
if (CurrentCmd->name == C_TCL)
{
res = Tcl_Eval(energymech_tcl,rest);
to_user(from,"tcl command %s",(res == TCL_OK) ? "executed ok" : "failed");
}
else
#endif /* PLEASE_HACK_MY_SHELL */
{
res = Tcl_EvalFile(energymech_tcl,rest);
to_user(from,"tcl script %s",(res == TCL_OK) ? "loaded ok" : "failed to load");
#ifdef DEBUG
debug("(do_tcl) tcl script \"%s\" %s\n",rest,(res == TCL_OK) ? "loaded ok" : "failed to load");
#endif /* DEBUG */
}
}
#endif /* TCL */

84
src/telnet.c Normal file
View File

@@ -0,0 +1,84 @@
/*
EnergyMech, IRC bot software
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 TELNET_C
#include "config.h"
#ifdef TELNET
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
int check_telnet(int s, char *rest)
{
Client *client;
User *user;
user = NULL;
for(current=botlist;current;current=current->next)
{
for(user=current->userlist;user;user=user->next)
{
if (!Strcasecmp(user->name,rest))
goto check_telnet_malloc;
}
}
if (!current)
current = botlist;
check_telnet_malloc:
to_file(s,TEXT_ENTERPASSWORD "\n");
set_mallocdoer(check_telnet);
client = (Client*)Calloc(sizeof(Client));
client->user = user;
client->sock = s;
#ifdef DCC_FILE
client->fileno = -1;
#endif /* DCC_FILE */
client->flags = DCC_TELNETPASS;
client->lasttime = now;
client->next = current->clientlist;
current->clientlist = client;
#ifdef DEBUG
current = NULL;
debug("(check_telnet) catching telnet client\n");
#endif /* DEBUG */
return(TRUE);
}
void check_telnet_pass(Client *client, char *rest)
{
char *pass;
pass = chop(&rest);
if (!pass || !client->user || !client->user->pass || !passmatch(pass,client->user->pass))
{
client->flags = DCC_DELETE;
return;
}
Strcpy(CurrentNick,client->user->name);
dcc_banner(client);
client->flags = DCC_TELNET|DCC_ACTIVE;
}
#endif /* TELNET */

202
src/text.h Normal file
View File

@@ -0,0 +1,202 @@
/*
EnergyMech, IRC bot software
Copyright (c) 2000-2009 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.
*/
#ifndef TEXT_H
#define TEXT_H 1
/*
* These are more or less globally used..
*/
#define FMT_PLAIN "%s"
#define FMT_PLAINLINE "%s\n"
#define MATCH_ALL "*"
#define TEXT_NOTINSERVLIST "(not in serverlist)"
#define TEXT_NONE "(none)"
#define TEXT_LISTSAVED "Lists saved to file %s"
#define TEXT_LISTREAD "Lists read from file %s"
#define ERR_NOSAVE "Lists could not be saved to file %s"
#define ERR_NOREAD "Lists could not be read from file %s"
#define ERR_NOUSERFILENAME "No userfile has been set"
#define TEXT_UNKNOWNUSER "Unknown user: %s"
/*
* alias.c
*/
#define TEXT_NOALIASES "No aliases has been set"
/*
* channel.c
*/
#define TEXT_SENTWALLOP "Sent wallop to %s"
#define TEXT_TOPICCHANGED "Topic changed on %s"
#define TEXT_CHANINVALID "Invalid channel name"
/*
* ctcp.c
*/
#define TEXT_DCC_ONLY "Multiline output from \"%s\" command requires DCC chat"
#define TEXT_DCC_GOODBYE "Hasta la vista!"
#define TEXT_NOTCONNECTED "(not connected)"
#define TEXT_WHOMUSERLINE "%s\tu%i\t%s (idle %i min, %i sec)"
#define TEXT_WHOMSELFLINE "\037%s\037\t%s\t%s"
#define TEXT_WHOMBOTLINE "%s\t%s\t%s"
#define TEXT_WHOMBOTGUID "%s\t%s\t%s [%s] [%i]"
/*
* core.c
*/
#define TEXT_EMPTYSERVLIST "No servers in serverlist!"
#define TEXT_NOSERVMATCHP "No matching entries was found for %s:%i"
#define TEXT_NOSERVMATCH "No matching entries was found for %s:*"
#define TEXT_SERVERDELETED "Server has been deleted: %s:%i"
#define TEXT_MANYSERVMATCH "Several entries for %s exists, please specify port also"
/* do_core() */
#define TEXT_CURRNICKWANT "Current nick\t%s (Wanted: %s)"
#define TEXT_CURRNICKHAS "Current nick\t%s"
#define TEXT_CURRGUID "Guid\t%i"
#define TEXT_USERLISTSTATS "Users in userlist\t%i (%i Superuser%s, %i Bot%s)"
#define TEXT_ACTIVECHANS "Active channels\t%s"
#define TEXT_MOREACTIVECHANS "\t%s"
#define TEXT_VIRTHOST "Virtual host\t%s (IP Alias%s)"
#define TEXT_VIRTHOSTWINGATE "Virtual host\t%s:%i (WinGate%s)"
#define TEXT_VHINACTIVE " - Inactive"
#define TEXT_CURRSERVER "Current Server\t%s:%i"
#define TEXT_CURRSERVERNOT "Current Server\t" TEXT_NOTINSERVLIST
#define TEXT_SERVERONTIME "Server Ontime\t%s"
#define TEXT_BOTMODES "Mode\t+%s"
#define TEXT_CURRENTTIME "Current Time\t%s"
#define TEXT_BOTSTARTED "Started\t%s"
#define TEXT_BOTUPTIME "Uptime\t%s"
#define TEXT_BOTVERSION "Version\t%s (%s)"
#define TEXT_BOTFEATURES "Features\t%s"
#define TEXT_CSERV "Current Server: %s:%i"
#define TEXT_CSERVNOT "Current Server: " TEXT_NOTINSERVLIST
#define TEXT_AGO " ago"
#define TEXT_CURRENT " (current)"
#define TEXT_NEVER "(never)"
#define TEXT_SP_NOAUTH "(no authorization)"
#define TEXT_SP_KLINED "(K-lined)"
#define TEXT_SP_FULLCLASS "(connection class full)"
#define TEXT_SP_TIMEOUT "(connection timed out)"
#define TEXT_SP_ERRCONN "(unable to connect)"
#define TEXT_SP_DIFFPORT "(use a different port)"
#define TEXT_SP_NO_DNS "(DNS problem)"
#define TEXT_NOLONGERAWAY "No longer set /away"
#define TEXT_NOWSETAWAY "Now set /away"
#define TEXT_NAMETOOLONG "Hostname exceeds maximum length"
#define TEXT_SHUTDOWNBY "Shutdown initiated by %s[100], flatlining ..."
/*
* main.c
*/
#define TEXT_SIGINT "Lurking interrupted by luser ... er, owner. (SIGINT)"
#define TEXT_SIGSEGV "Mary had a little signal segmentation fault (SIGSEGV)"
#define TEXT_SIGBUS "Another one drives the bus! (SIGBUS)"
#define TEXT_SIGTERM "What have I done to deserve this?? aaaaaarrghhh! (SIGTERM)"
#define TEXT_SIGUSR1 "QUIT :Switching servers... (SIGUSR1)\n"
#define TEXT_USAGE "Usage: %s [switches [args]]\n"
#define TEXT_FSWITCH " -f <file> read configuration from <file>\n"
#define TEXT_CSWITCH " -c make core file instead of coredebug/reset\n"
#define TEXT_HSWITCH " -h show this help\n"
#define TEXT_VSWITCH " -v show EnergyMech version\n"
#define TEXT_HDR_VERS "EnergyMech %s, %s\n"
#define TEXT_HDR_DATE "Compiled on " __DATE__ " " __TIME__ "\n"
#define TEXT_HDR_FEAT "Features: %s\n"
#define ERR_MISSINGCONF "init: No configfile specified\n"
#define ERR_UNKNOWNOPT "init: Unknown option %s\n"
#define ERR_SAMEUSERLIST "init: Error: UserList for %s matches the userlist for %s\n"
#define ERR_SAMEUSERLIST2 " Bots can not share the same userlist, please specify a new one.\n"
#define INFO_USINGCONF "init: Using config file: %s\n"
#define INFO_RUNNING "init: EnergyMech running...\n"
#define TEXT_ALREADYSHITTED "%s is in my shitlist already for this channel"
#define TEXT_SHITLOWACCESS "Unable to shit %s, insufficient access"
#define TEXT_DEFAULTSHIT "Leave Lamer!"
#define TEXT_HASSHITTED "The user has been shitted as %s on %s"
#define TEXT_SHITEXPIRES "The shit entry will expire: %s"
#define TEXT_SEENNOSAVE "SeenList could not be saved to file %s"
#define TEXT_SEENNOLOAD "SeenList could not be loaded from file %s"
/*
* ons.c
*/
#define TEXT_LASTHDR str_underline("Last %i Commands")
#define KICK_BANNED "banned"
#define KICK_REVENGE "revenge"
#define KICK_CAPS "excessive caps"
#define KICK_MASSMODES "massmodes"
#define KICK_NICKFLOOD "nickflood"
#define KICK_TEXTFLOOD "textflood"
#define KICK_BAD_IDENT "bad ident"
#define KICK_DEFAULT "Requested Kick"
/*
* telnet
*/
#define TEXT_ENTERNICKNAME "Please enter your nickname."
#define TEXT_ENTERPASSWORD "Please enter your password."
/*
* shit.c
*/
#define TEXT_CLEAREDSHITLIST "Shitlist has been cleared"
/*
* user.c
*/
#define TEXT_PASS_SHORT "password too short"
#define TEXT_PASS_LONG "password too long"
#define TEXT_PASS_INCORRECT "password incorrect"
#define TEXT_PASS_NEWSET "new password has been set"
#define TEXT_PARTYECHOON "Partyline echo is now On"
#define TEXT_PARTYECHOOFF "Partyline echo is now Off"
#define TEXT_USERCHANGED "User %s has been modified"
#define TEXT_USERNOTCHANGED "User %s is unmodified"
#define TEXT_NOACCESSON "Access denied (you have no access on %s)"
#define TEXT_USEROWNSYOU "Access denied (%s has higher access than you)"
#endif /* TEXT_H */

349
src/toybox.c Normal file
View File

@@ -0,0 +1,349 @@
/*
EnergyMech, IRC bot software
Copyright (c) 2000-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 TOYBOX_C
#include "config.h"
#ifdef TOYBOX
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
#define BIGSAY_DEFAULTFONT "default"
#define FONT_EXTENSION ".bigchars"
typedef struct BigC
{
struct BigC *next;
int width;
Strp *data;
char chars[1];
} BigC;
LS char *fontname = NULL;
LS BigC *newchar;
LS BigC *fontlist = NULL;
LS int charlines;
LS int charheight;
LS int spacewidth;
LS int kerning;
LS BigC *orig_fontlist = NULL;
LS int orig_charlines;
LS int orig_charheight;
LS int orig_spacewidth;
LS int orig_kerning;
int read_bigcharset_callback(char *rest)
{
Strp *sp,**pp;
char *opt;
int *n,sz;
if (charlines)
{
charlines--;
sz = strlen(rest);
if (sz > newchar->width)
newchar->width = sz;
pp = &newchar->data;
while(*pp)
pp = &(*pp)->next;
set_mallocdoer(read_bigcharset_callback);
*pp = sp = (Strp*)Calloc(sizeof(Strp) + sz);
/* Calloc sets to zero sp->next = NULL; */
Strcpy(sp->p,rest);
return(FALSE);
}
opt = chop(&rest);
n = NULL;
if (!Strcasecmp(opt,"chars") && charheight)
{
charlines = charheight;
opt = chop(&rest);
set_mallocdoer(read_bigcharset_callback);
newchar = (BigC*)Calloc(sizeof(BigC) + strlen(opt));
/* Calloc sets to zero
newchar->width = 0;
newchar->data = NULL;
*/
newchar->next = fontlist;
fontlist = newchar;
Strcpy(newchar->chars,opt);
}
else
if (!Strcasecmp(opt,"spacewidth"))
{
n = &spacewidth;
}
else
if (!Strcasecmp(opt,"charheight"))
{
n = &charheight;
}
else
if (!Strcasecmp(opt,"kerning"))
{
n = &kerning;
}
else
if (!Strcasecmp(opt,"fontname"))
{
opt = chop(&rest);
if (fontname && !Strcasecmp(fontname,opt))
{
fontlist = orig_fontlist;
charlines = orig_charlines;
charheight = orig_charheight;
spacewidth = orig_spacewidth;
kerning = orig_kerning;
orig_fontlist = NULL;
return(TRUE);
}
Free((char**)&fontname);
set_mallocdoer(read_bigcharset_callback);
fontname = Strdup(opt);
}
if (n)
{
*n = a2i(rest);
if (errno) *n = 0;
}
return(FALSE);
}
int read_bigcharset(char *fname)
{
BigC *bigc;
Strp *sp;
int fd;
if ((fd = open(fname,O_RDONLY)) < 0)
{
Strcat(fname,FONT_EXTENSION);
if ((fd = open(fname,O_RDONLY)) < 0)
return(-1);
}
orig_fontlist = fontlist;
orig_charlines = charlines;
orig_charheight = charheight;
orig_spacewidth = spacewidth;
orig_kerning = kerning;
charlines = 0;
spacewidth = 0;
charheight = 0;
kerning = 0;
readline(fd,&read_bigcharset_callback); /* readline closes fd */
/*
* free the old font if there is one
*/
while(orig_fontlist)
{
bigc = orig_fontlist;
orig_fontlist = bigc->next;
while(bigc->data)
{
sp = bigc->data;
bigc->data = sp->next;
Free((char**)&sp);
}
Free((char**)&bigc);
}
return(0);
}
/*
*
*
*
*/
void do_bigsay(COMMAND_ARGS)
{
/*
* on_msg checks CARGS + CAXS
*/
BigC *bigc;
Strp *sp;
char output[MSGLEN];
char *pt,*tail,*temp;
int i,x,sz;
#ifdef DEBUG
debug("(do_bigsay) rest = \"%s\"\n",rest);
#endif /* DEBUG */
Strcpy(output,BIGSAY_DEFAULTFONT);
if (read_bigcharset(output) < 0)
{
to_user(from,ERR_FILEOPEN,output);
return;
}
for(i=0;i<charheight;i++)
{
sz = 0;
*output = 0;
tail = output;
for(pt=rest;*pt;pt++)
{
/* find a matching character */
if (*pt == ' ')
{
x = spacewidth;
while(x--)
*(tail++) = ' ';
*tail = 0;
continue;
}
for(bigc=fontlist;bigc;bigc=bigc->next)
{
if (STRCHR(bigc->chars,*pt))
{
sp = bigc->data;
for(x=0;x<i;x++)
if (sp) sp = sp->next;
temp = Strcat(tail,sp->p);
while(temp < (tail + bigc->width))
*(temp++) = ' ';
if (pt[1])
{
x = kerning;
while(x--)
*(temp++) = ' ';
}
*temp = 0;
tail = temp;
break;
}
}
}
temp = NULL;
for(tail=output;*tail;tail++)
{
if (!temp && *tail == ' ')
temp = tail;
if (*tail != ' ')
temp = NULL;
}
if (temp)
{
if (temp == output)
temp++;
*temp = 0;
}
to_user_q(from,FMT_PLAIN,output);
}
}
void do_random_msg(COMMAND_ARGS)
{
char *filename,*message;
filename = CurrentCmd->cmdarg;
if (*rest)
{
to = chop(&rest);
if (ischannel(to) && (get_authaccess(from,to) < cmdaccess))
return;
}
else
if (!ischannel(to))
{
usage(from); /* usage for CurrentCmd->name */
return;
}
if ((message = randstring(filename)) == NULL)
{
to_user(from,ERR_FILEOPEN,filename);
return;
}
/*
* send message to target nick/channel
*/
to_server("PRIVMSG %s :%s\n",to,message);
/*
* if its not a channel we send a copy to the user who did the command also
*/
if (!ischannel(to))
{
to_user(from,"(%s) %s",to,message);
}
}
void do_randtopic(COMMAND_ARGS)
{
/*
* on_msg checks CAXS
*/
Chan *chan = CurrentChan;
char *topic;
/*
* the bot can set a random topic if chanmode is -t
*/
if (chan->bot_is_op || chan->topprot == FALSE)
{
if ((topic = randstring(RANDTOPICSFILE)) == NULL)
{
to_user(from,ERR_FILEOPEN,RANDTOPICSFILE);
return;
}
to_server("TOPIC %s :%s\n",to,topic);
to_user(from,TEXT_TOPICCHANGED,to);
return;
}
to_user(from,ERR_NOTOPPED,to);
}
void do_8ball(COMMAND_ARGS)
{
char *message;
if ((message = randstring(RAND8BALLFILE)) == NULL)
{
to_user_q(from,ERR_FILEOPEN,RAND8BALLFILE);
return;
}
to_user_q(from,FMT_PLAIN,message);
}
#endif /* TOYBOX */

636
src/trivia.c Normal file
View File

@@ -0,0 +1,636 @@
/*
EnergyMech, IRC bot software
Copyright (c) 2001-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 TRIVIA_C
#include "config.h"
#ifdef TRIVIA
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
#define TRIV_WAIT_QUESTION 0
#define TRIV_HINT_TWO 1
#define TRIV_HINT_THREE 2
#define TRIV_NO_ANSWER 3
#define TRIV_HINT_DELAY 15
#define TRIV_HINT_DELAY_STR1 "15"
#define TRIV_HINT_DELAY_STR2 "30"
#define TRIV_METACHARS " .,-'%&/?!:;\""
#define DAY_IN_SECONDS (24*60*60)
#define WEEK_IN_SECONDS (7*24*60*60)
LS TrivScore *lastwinner;
LS Chan *triv_chan = NULL;
LS Strp *triv_answers = NULL;
LS time_t triv_ask_time;
LS time_t triv_next_time = 0;
LS time_t triv_weektop10;
LS int triv_mode;
LS int triv_score;
LS int triv_streak;
LS int triv_halt_flag;
/*
*
* scorings
*
*/
void trivia_week_toppers(void)
{
char triv_str[MSGLEN];
TrivScore *chosen[10];
TrivScore *su;
char *p;
int week;
int i,x;
chosen[0] = NULL;
week = (now + (3 * DAY_IN_SECONDS)) / WEEK_IN_SECONDS;
for(su=scorelist;su;su=su->next)
{
if (su->week_nr != week)
continue;
for(i=0;i<10;i++)
{
if (!chosen[i] || (chosen[i]->score_wk < su->score_wk))
{
for(x=8;x>=i;x--)
chosen[x+1] = chosen[x];
chosen[i] = su;
break;
}
}
}
if (chosen[0])
{
p = triv_str;
for(i=0;i<10;i++)
{
if (!chosen[i])
break;
if (i)
{
*(p++) = ' ';
*(p++) = ' ';
}
sprintf(p,"#%i: %s (%ipts)",i+1,chosen[i]->nick,chosen[i]->score_wk);
p = STREND(p);
}
to_server("PRIVMSG %s :This Weeks Top 10: %s\n",triv_chan->name,triv_str);
}
}
/*
*
*
*
*/
void hint_one(void)
{
char triv_str[MSGLEN];
char *src,*dst;
sprintf(triv_str,"PRIVMSG %s :1st hint: ",triv_chan->name);
dst = STREND(triv_str);
src = triv_answers->p;
while(*src)
{
if (STRCHR(TRIV_METACHARS,*src))
*(dst++) = *src;
else
*(dst++) = triv_qchar;
src++;
}
*dst = 0;
to_server("%s Question score: %i points\n",triv_str,triv_score);
}
void hint_two(void)
{
char triv_str[MSGLEN];
char *src,*dst;
int n;
sprintf(triv_str,"PRIVMSG %s :2nd hint: ",triv_chan->name);
dst = STREND(triv_str);
src = triv_answers->p;
n = a2i(src);
if (!errno)
{
if (n > 99 && *src) *(dst++) = *(src++);
if (n > 999 && *src) *(dst++) = *(src++);
if (n > 9999 && *src) *(dst++) = *(src++);
}
else
{
n = strlen(src);
if (n > 2 && *src) *(dst++) = *(src++);
if (n > 4 && *src) *(dst++) = *(src++);
if (n > 6 && *src) *(dst++) = *(src++);
}
while(*src)
{
if (STRCHR(TRIV_METACHARS,*src))
*(dst++) = *src;
else
*(dst++) = triv_qchar;
src++;
}
*dst = 0;
to_server("%s " TRIV_HINT_DELAY_STR2 " seconds remaining.\n",triv_str);
}
void hint_three(void)
{
char triv_str[MSGLEN];
char *src,*dst;
int n;
sprintf(triv_str,"PRIVMSG %s :3rd hint: ",triv_chan->name);
dst = STREND(triv_str);
src = triv_answers->p;
n = a2i(src);
if (!errno)
{
if (n > 9 && *src) *(dst++) = *(src++);
if (n > 99 && *src) *(dst++) = *(src++);
if (n > 999 && *src) *(dst++) = *(src++);
}
else
{
n = strlen(src);
if (n > 1 && *src) *(dst++) = *(src++);
if (n > 3 && *src) *(dst++) = *(src++);
if (n > 4 && *src) *(dst++) = *(src++);
}
while(*src)
{
if (STRCHR(TRIV_METACHARS "aeiouyAEIOUY",*src))
*(dst++) = *src;
else
*(dst++) = triv_qchar;
src++;
}
*dst = 0;
to_server("%s " TRIV_HINT_DELAY_STR1 " seconds remaining.\n",triv_str);
}
/*
*
*
*
*/
void trivia_cleanup(void)
{
Strp *ans;
triv_mode = TRIV_WAIT_QUESTION;
triv_next_time = now + triv_qdelay;
while((ans = triv_answers))
{
triv_answers = ans->next;
Free((char**)&ans);
}
}
void trivia_check(Chan *chan, char *rest)
{
TrivScore *su;
Strp *ans;
int week;
if (chan != triv_chan)
return;
for(ans=triv_answers;ans;ans=ans->next)
{
if (!Strcasecmp(ans->p,rest))
goto have_answer;
}
return;
have_answer:
week = (now + (3 * DAY_IN_SECONDS)) / WEEK_IN_SECONDS;
for(su=scorelist;su;su=su->next)
{
if (!nickcmp(su->nick,CurrentNick))
{
su->score_mo += triv_score;
if (su->week_nr == week)
su->score_wk += triv_score;
else
{
if (su->week_nr == (week - 1))
su->score_last_wk = su->score_wk;
else
su->score_last_wk = 0;
su->week_nr = week;
su->score_wk = triv_score;
}
break;
}
}
if (!su)
{
set_mallocdoer(trivia_check);
su = (TrivScore*)Calloc(sizeof(TrivScore) + strlen(CurrentNick));
su->next = scorelist;
scorelist = su;
su->score_wk = su->score_mo = triv_score;
su->week_nr = week;
/* su->month_nr = 0; * fix this */
Strcpy(su->nick,CurrentNick);
}
to_server("PRIVMSG %s :Yes, %s! got the answer -> %s <- in %i seconds, and gets %i points!\n",
triv_chan->name,CurrentNick,triv_answers->p,
(int)(now - triv_ask_time),triv_score);
if (su == lastwinner)
{
triv_streak++;
if (su->score_wk == su->score_mo)
{
to_server("PRIVMSG %s :%s has won %i in a row! Total score this Week: %i points\n",
triv_chan->name,CurrentNick,triv_streak,su->score_wk);
}
else
{
to_server("PRIVMSG %s :%s has won %i in a row! Total score this Week: %i points, and this Month: %i points\n",
triv_chan->name,CurrentNick,triv_streak,su->score_wk,su->score_mo);
}
}
else
{
lastwinner = su;
triv_streak = 1;
if (su->score_wk == su->score_mo)
{
to_server("PRIVMSG %s :%s has won the question! Total score this Week: %i points\n",
triv_chan->name,CurrentNick,su->score_wk);
}
else
{
to_server("PRIVMSG %s :%s has won the question! Total score this Week: %i points, and this Month: %i points\n",
triv_chan->name,CurrentNick,su->score_wk,su->score_mo);
}
}
trivia_cleanup();
}
void trivia_no_answer(void)
{
to_server("PRIVMSG %s :Time's up! The answer was -> %s <-\n",
triv_chan->name,triv_answers->p);
trivia_cleanup();
}
char *random_question(char *triv_rand)
{
char *p;
off_t sz;
int fd,ifd;
int n;
struct
{
int off;
int sz;
} entry;
if ((fd = open(triv_qfile,O_RDONLY)) < 0)
return(NULL);
Strcpy(triv_rand,triv_qfile);
if ((p = STRCHR(triv_rand,'.')) == NULL)
p = STREND(triv_rand);
Strcpy(p,".index");
if ((ifd = open(triv_rand,O_RDONLY)) < 0)
return(NULL);
sz = lseek(ifd,0,SEEK_END);
sz = sz / sizeof(entry);
n = RANDOM(1,sz);
n--;
lseek(ifd,(n * sizeof(entry)),SEEK_SET);
read(ifd,&entry,sizeof(entry));
lseek(fd,entry.off,SEEK_SET);
read(fd,triv_rand,entry.sz);
triv_rand[entry.sz] = 0;
close(fd);
close(ifd);
return(triv_rand);
}
void trivia_question(void)
{
char buffer[MSGLEN];
Strp *ans,**pp;
char *question,*answer,*rest;
if (triv_halt_flag)
{
to_server("PRIVMSG %s :Trivia has been stopped!\n",triv_chan->name);
goto stop_trivia;
}
if ((rest = random_question(buffer)) == NULL)
{
bad_question:
to_server("PRIVMSG %s :Bad Question File\n",triv_chan->name);
stop_trivia:
trivia_cleanup();
triv_chan = NULL;
triv_next_time = 0;
triv_halt_flag = FALSE;
short_tv &= ~TV_TRIVIA;
return;
}
question = get_token(&rest,MATCH_ALL);
pp = &triv_answers;
while((answer = get_token(&rest,MATCH_ALL)))
{
set_mallocdoer(trivia_question);
*pp = ans = (Strp*)Calloc(sizeof(Strp) + strlen(answer));
pp = &ans->next;
Strcpy(ans->p,answer);
}
*pp = NULL;
if (triv_answers == NULL)
goto bad_question;
triv_score = (RANDOM(2,9) + RANDOM(2,10) + RANDOM(2,10)) / 3;
triv_ask_time = now;
if (now > (triv_weektop10 + 1200))
{
trivia_week_toppers();
triv_weektop10 = now;
}
to_server("PRIVMSG %s :%s\n",triv_chan->name,question);
hint_one();
}
void trivia_tick(void)
{
Chan *chan;
Mech *bot;
if (triv_next_time && (now >= triv_next_time))
{
for(bot=botlist;bot;bot=bot->next)
{
for(chan=bot->chanlist;chan;chan=chan->next)
{
if (triv_chan == chan)
{
current = bot;
triv_next_time = now + TRIV_HINT_DELAY;
switch(triv_mode)
{
case TRIV_WAIT_QUESTION:
trivia_question();
break;
case TRIV_HINT_TWO:
hint_two();
break;
case TRIV_HINT_THREE:
hint_three();
break;
case TRIV_NO_ANSWER:
trivia_no_answer();
return; /* dont increment with triv_mode */
}
triv_mode++;
#ifdef DEBUG
current = NULL;
#endif /* DEBUG */
return;
}
}
}
}
}
/*
*
* File operations
*
*/
void write_triviascore(void)
{
TrivScore *su;
int fd;
if (scorelist)
{
if ((fd = open(TRIVIASCOREFILE,O_WRONLY|O_TRUNC|O_CREAT,NEWFILEMODE)) < 0)
return;
to_file(fd,COMMENT_STRCHR " nick score_wk score_mo score_last_wk score_last_mo\n");
for(su=scorelist;su;su=su->next)
{
to_file(fd,"%s %i %i %i %i %i %i\n",su->nick,su->score_wk,su->score_mo,
su->score_last_wk,su->score_last_mo,su->week_nr,su->month_nr);
}
close(fd);
}
}
int trivia_score_callback(char *rest)
{
TrivScore *su;
char *nick,*wk,*mo,*lwk,*lmo,*wnr,*mnr;
int score_wk,score_mo,score_last_wk,score_last_mo;
int week_nr,month_nr;
int err;
if (*rest != COMMENT_CHAR)
{
nick = chop(&rest);
wk = chop(&rest);
mo = chop(&rest);
lwk = chop(&rest);
lmo = chop(&rest);
wnr = chop(&rest);
mnr = chop(&rest);
if (mnr)
{
score_wk = a2i(wk);
err = errno;
score_mo = a2i(mo);
err += errno;
score_last_wk = a2i(lwk);
err += errno;
score_last_mo = a2i(lmo);
err += errno;
week_nr = a2i(wnr);
err += errno;
month_nr = a2i(mnr);
err += errno;
if (!err)
{
set_mallocdoer(trivia_score_callback);
su = (TrivScore*)Calloc(sizeof(TrivScore) + strlen(nick));
su->next = scorelist;
scorelist = su;
su->score_wk = score_wk;
su->score_mo = score_mo;
su->score_last_wk = score_last_wk;
su->score_last_mo = score_last_mo;
su->week_nr = week_nr;
su->month_nr = month_nr;
Strcpy(su->nick,nick);
}
}
}
return(FALSE);
}
void read_triviascore(void)
{
TrivScore *su;
int fd;
if ((fd = open(TRIVIASCOREFILE,O_RDONLY)) < 0)
return;
while(scorelist)
{
su = scorelist;
scorelist = su->next;
Free((char**)&su);
}
readline(fd,&trivia_score_callback); /* readline closes fd */
}
/*
*
*
*
*/
void do_trivia(COMMAND_ARGS)
{
/*
* on_msg checks CAXS + CARGS
*/
Chan *chan;
int uaccess;
uaccess = get_maxaccess(from);
if ((chan = find_channel_ac(to)) == NULL)
{
if (uaccess) to_user(from,ERR_CHAN,to);
return;
}
if (!Strcasecmp(rest,"start"))
{
if (triv_chan)
{
if (triv_chan == chan)
{
triv_halt_flag = FALSE;
return;
}
if (uaccess) to_user(from,"trivia is already activated on %s!",
(get_useraccess(from,triv_chan->name)) ? triv_chan->name : "another channel");
return;
}
to_server("PRIVMSG %s :Trivia starting! Get ready...\n",chan->name);
triv_chan = chan;
triv_mode = TRIV_WAIT_QUESTION;
triv_next_time = now + triv_qdelay;
triv_weektop10 = now;
lastwinner = NULL;
short_tv |= TV_TRIVIA;
if (!scorelist)
{
read_triviascore();
}
}
else
if (!Strcasecmp(rest,"stop"))
{
if (chan == triv_chan)
{
if (chan == triv_chan)
to_server("PRIVMSG %s :Trivia shutting down...\n",chan->name);
triv_halt_flag = TRUE;
}
}
else
if (!Strcasecmp(rest,"top10"))
{
int n;
if (triv_chan)
{
uaccess = get_authaccess(from,triv_chan->name);
if (now > (triv_weektop10 + 300))
n = 1;
else
n = uaccess;
if (n)
{
trivia_week_toppers();
if (!uaccess) triv_weektop10 = now;
}
}
}
}
#endif /* TRIVIA */

269
src/uptime.c Normal file
View File

@@ -0,0 +1,269 @@
/*
EnergyMech, IRC bot software
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 UPTIME_C
#include "config.h"
#ifdef UPTIME
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
/*
* Uptime stuffies
*/
typedef struct
{
int regnr;
int pid;
int type;
ulong cookie;
ulong uptime;
ulong ontime;
ulong now;
ulong sysup;
} PackStub;
typedef struct
{
int regnr;
int pid;
int type;
ulong cookie;
ulong uptime;
ulong ontime;
ulong now;
ulong sysup;
char string[512];
} PackUp;
void init_uptime(void)
{
struct sockaddr_in sai;
uptimecookie = rand();
if (!uptimehost)
{
set_mallocdoer(init_uptime);
uptimehost = Strdup(defaultuptimehost);
}
if ((uptimesock = socket(AF_INET,SOCK_DGRAM,0)) < 0)
{
uptimesock = -1;
return;
}
memset(&sai,0,sizeof(sai));
sai.sin_family = AF_INET;
sai.sin_addr.s_addr = INADDR_ANY;
if (bind(uptimesock,(struct sockaddr*)&sai,sizeof(sai)) < 0)
{
close(uptimesock);
uptimesock = -1;
return;
}
SockFlags(uptimesock);
}
void send_uptime(int type)
{
PackUp upPack;
struct sockaddr_in sai;
struct stat st;
Server *sp;
const char *server,*nick;
int sz;
if (uptimeport == 0)
return;
#ifdef RAWDNS
if (uptimeip == -1 && uptimehost)
{
char *host;
uptimelast = now + 10;
if ((host = poll_rawdns(uptimehost)))
{
if ((uptimeip = inet_addr(host)) != -1)
{
Free((char**)&uptimehost);
set_mallocdoer(send_uptime);
uptimehost = Strdup(host);
}
}
else
{
if (type < UPTIME_GENERICDEATH)
rawdns(uptimehost);
return;
}
}
#endif /* RAWDNS */
/*
* update the time when we last sent packet
*/
sz = (uptimelast + 1) & 7;
uptimelast = (now & ~7) + 21600 + sz; /* 21600 seconds = 6 hours */
uptimecookie = (uptimecookie + 1) * 18457;
upPack.cookie = htonl(uptimecookie);
upPack.now = htonl(now);
upPack.regnr = uptimeregnr;
upPack.type = htonl(type);
upPack.uptime = htonl(uptime);
upPack.ontime = 0; /* set a few lines down */
/*
* callouts to other functions should be done last (think compiler optimizations)
*/
upPack.pid = htonl(getpid());
/*
* this trick for most systems gets the system uptime
*/
if (stat("/proc",&st) < 0)
{
upPack.sysup = 0;
}
else
{
upPack.sysup = htonl(st.st_ctime);
}
server = "unknown";
nick = BOTLOGIN;
/*
* set bot related stuff from the first bot in the list
*/
if (botlist)
{
nick = botlist->nick;
upPack.ontime = htonl(botlist->conntry);
if ((sp = find_server(botlist->server)))
{
server = (*sp->realname) ? sp->realname : sp->name;
}
}
if (uptimenick)
{
nick = uptimenick;
}
#ifndef RAWDNS
if ((uptimeip == -1) || ((uptimelast & 7) == 0))
{
uptimeip = get_ip(uptimehost);
if (uptimeip == -1)
return;
}
#endif /* ! RAWDNS */
sz = sizeof(PackStub) + 3 + Strlen(nick,server,VERSION,NULL);
if (sz > sizeof(PackUp))
return;
sprintf(upPack.string,"%s %s %s",nick,server,VERSION);
/*
* udp sending...
*/
memset((char*)&sai,0,sizeof(sai));
sai.sin_family = AF_INET;
sai.sin_addr.s_addr = uptimeip;
sai.sin_port = htons(uptimeport);
sendto(uptimesock,(void*)&upPack,sz,0,(struct sockaddr*)&sai,sizeof(sai));
}
void uptime_death(int type)
{
#ifdef DEBUG
debug("(uptime_death) sending death message\n");
#endif /* DEBUG */
time(&now);
uptimelast = 0; /* avoid resolving the hostname */
send_uptime(type);
uptimeport = 0; /* avoid sending more packets */
}
void process_uptime(void)
{
struct sockaddr_in sai;
int res,sz;
struct
{
int regnr;
ulong cookie;
} regPack;
if (uptimesock == -1)
return;
if (FD_ISSET(uptimesock,&read_fds))
{
sz = sizeof(sai);
res = recvfrom(uptimesock,(void*)&regPack,sizeof(regPack),0,(struct sockaddr*)&sai,&sz);
if (res == sizeof(regPack))
{
if (uptimecookie == ntohl(regPack.cookie))
{
if (uptimeregnr == 0)
uptimeregnr = ntohl(regPack.regnr);
}
}
}
if (uptimelast < now)
{
send_uptime(UPTIME_BOTTYPE);
}
}
/*
*
* commands related to uptimes
*
*/
void do_upsend(COMMAND_ARGS)
{
/*
* on_msg checks: GAXS
*/
send_uptime(UPTIME_BOTTYPE);
}
#endif /* UPTIME */

183
src/usage.h Normal file
View File

@@ -0,0 +1,183 @@
/*
EnergyMech, IRC bot software
Copyright (c) 2000-2009 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.
*/
typedef struct
{
const char *command;
char *usage;
} UsageList;
LS const UsageList ulist[] =
{
#ifdef TOYBOX
{ C_8BALL, "[text]" },
#endif /* TOYBOX */
{ C_ACCESS, "[channel] [nick|userhost]" },
#ifdef ALIAS
{ C_ALIAS, "[alias [replacement format]]" },
#endif /* ALIAS */
{ C_AWAY, "[message]" },
{ C_BAN, "[channel] <nick|mask>" },
{ C_BANLIST, "[channel]" },
#ifdef TOYBOX
{ C_BIGSAY, "[channel] <message>" },
#endif /* TOYBOX */
{ C_BYE, NULL },
{ C_CCHAN, "[channel]" },
#ifdef DYNCMD
{ C_CHACCESS, "<command> [DISABLE|level]" },
#endif /* DYNCMD */
{ C_CHANNELS, NULL },
{ C_CHAT, NULL },
{ C_CLEARSHIT, NULL },
#if defined(BOTNET) && defined(REDIRECT)
{ C_CMD, "[guid] <command>" },
#endif /* BOTNET && REDIRECT */
{ C_CORE, NULL },
{ C_CSERV, NULL },
#ifdef CTCP
{ C_CTCP, "<nick|channel> <ctcp command>" },
#endif /* CTCP */
{ C_CYCLE, "[channel]" },
#ifdef DEBUG
{ C_DEBUG, NULL },
#endif /* DEBUG */
{ C_DEOP, "[channel] <nick|pattern [...]>" },
{ C_DIE, "[reason]" },
#ifdef RAWDNS
{ C_DNS, "<nick|host>" },
{ C_DNSSERVER, "[+|-serverip]" },
#endif /* RAWDNS */
{ C_DO, "<raw_irc>" },
{ C_DOWN, "[channel]" },
{ C_ECHO, "<ON|OFF>" },
{ C_ESAY, "[channel] <message>" },
{ C_FORGET, "<channel>" },
#ifdef GREET
{ C_GREET, "<handle> [greeting|\"@\"greetfile|\"%\"greetfile]" },
#endif /* GREET */
{ C_HELP, "[topic|command|level|pattern]" },
{ C_IDLE, "<nick>" },
#ifdef TOYBOX
{ C_INSULT, "[channel|nick]" },
#endif /* TOYBOX */
{ C_INVITE, "[channel] [nick]" },
{ C_JOIN, "<channel> [key]" },
{ C_KB, "[channel] <nick> [reason]" },
{ C_KICK, "[channel] <nick> [reason]" },
{ C_KS, "<channel> [action] <\"pattern\"> <reason>" },
{ C_LAST, "[number of commands]" },
#ifdef BOTNET
{ C_LINK, "[[+|-]guid [pass [host port]]" },
#endif /* BOTNET */
{ C_LOAD, NULL },
{ C_LUSERS, NULL },
{ C_ME, "[channel] <action>" },
{ C_MODE, "[channel|botnick] <mode ...>" },
{ C_MSG, "<nick|channel> <message>" },
{ C_NAMES, "[channel]" },
{ C_NEXTSERVER, NULL },
{ C_NICK, "[guid] <nick>" },
#ifdef NOTE
{ C_NOTE, "<handle>" },
#endif /* NOTE */
#ifdef NOTIFY
{ C_NOTIFY, "[options] [nick]" }, /* */
#endif /* NOTIFY */
{ C_ONTIME, NULL },
{ C_OP, "[channel] [nick|mask]" },
{ C_PART, "<channel>" },
{ C_PASSWD, "[oldpassword] <newpassword>" },
#ifdef TOYBOX
{ C_PICKUP, "[channel|nick]" },
#endif /* TOYBOX */
#ifdef CTCP
{ C_PING, "<channel|nick>" },
#endif /* CTCP */
{ C_QSHIT, "<nick> [reason]" },
#ifdef NOTE
{ C_READ, "[-]<number>" },
#endif /* NOTE */
{ C_RESET, NULL },
{ C_RKS, "<channel> <pattern>" },
#ifdef TOYBOX
{ C_RSAY, "[channel|nick]" }, /* */
#endif /* TOYBOX */
{ C_RSHIT, "<channel> <nick|mask>" },
{ C_RSPY, "<STATUS|MESSAGE|RAWIRC|channel> [channel|\">\" filename]" },
#ifdef TOYBOX
{ C_RT, "<channel>" },
#endif /* TOYBOX */
{ C_SAVE, NULL },
{ C_SAY, "<channel> <message>" },
{ C_SCREW, "[channel] <nick> [reason]" },
#ifdef SEEN
{ C_SEEN, "<nick>" },
#endif /* SEEN */
#ifdef DCC_FILE
{ C_SEND, "[to] <filename>" },
#endif /* DCC_FILE */
{ C_SERVER, "[[+|-]servername] [port] [pass]" },
{ C_SERVERGROUP,"[identifier]" },
{ C_SET, "[channel|*] [setting [value]]" },
{ C_SETPASS, "<handle> <password>" },
{ C_SHIT, "<channel|*> <nick|mask> <action> [expire] <reason>" },
{ C_SHITLIST, NULL },
{ C_SHOWIDLE, "[channel] [seconds]" },
{ C_SHUTDOWN, NULL },
{ C_SITEBAN, "[channel] <nick|userhost>" },
{ C_SITEKB, "[channel] <nick> [reason]" },
{ C_SPY, "[STATUS|MESSAGE|RAWIRC|[guid\":\"|botnick\":\"] [channel|\">\" filename]" },
{ C_STATS, "<type> [servername]" },
#ifdef TCL
#ifdef PLEASE_HACK_MY_SHELL
{ C_TCL, "<command>" },
#endif /* PLEASE_HACK_MY_SHELL */
{ C_TCLSCRIPT, "<filename>" },
#endif /* TCL */
{ C_TIME, NULL },
{ C_TOPIC, "[channel] <text>" },
#ifdef TRIVIA
{ C_TRIVIA, "[START|STOP|TOP10]" },
#endif /* TRIVIA */
#ifdef ALIAS
{ C_UNALIAS, "<alias>" },
#endif /* ALIAS */
{ C_UNBAN, "[channel] [nick|userhost]" },
{ C_UNVOICE, "[channel] <nick|pattern [...]>" },
{ C_UP, "[channel]" },
#ifdef UPTIME
{ C_UPSEND, NULL },
#endif /* UPTIME */
{ C_UPTIME, NULL },
{ C_USAGE, "<command>" },
{ C_USER, "[+|-] <handle> [modifiers [...]]" },
{ C_USERHOST, "<nick>" },
{ C_USERLIST, "[+minlevel] [-maxlevel] [channel] [mask] [-B] [-C]" },
{ C_VER, NULL },
{ C_VERIFY, "<password>" },
{ C_VOICE, "[channel] [nick|pattern [...]]" },
{ C_WALL, "[channel] <message>" },
{ C_WHO, "<channel> [-ops|-nonops] [pattern]" },
{ C_WHOIS, "<nick>" },
{ C_WHOM, NULL },
{ NULL, }};

1697
src/user.c Normal file

File diff suppressed because it is too large Load Diff

558
src/vars.c Normal file
View File

@@ -0,0 +1,558 @@
/*
EnergyMech, IRC bot software
Parts Copyright (c) 1997-2009 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 VARS_C
#include "config.h"
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
#include "settings.h"
void set_str_varc(Chan *channel, int which, char *value)
{
char *temp,**dst;
if (value && *value)
{
set_mallocdoer(set_str_varc);
temp = Strdup(value);
}
else
temp = NULL;
dst = (channel) ? (char**)&channel->setting[which] : (char**)&current->setting[which];
if (*dst)
Free(dst);
*dst = temp;
}
/*
* The rest
*/
int find_setting(char *name)
{
int i;
for(i=0;VarName[i].name;i++)
{
if (!Strcasecmp(name,VarName[i].name))
return(i);
}
return(-1);
}
void copy_vars(UniVar *dst, UniVar *src)
{
int i;
for(i=0;i<CHANSET_SIZE;i++)
{
if (IsStr(i))
{
if (src[i].str_var)
{
set_mallocdoer(copy_vars);
dst[i].str_var = Strdup(src[i].str_var);
}
}
else
{
dst[i].int_var = src[i].int_var;
}
}
}
void set_binarydefault(UniVar *dst)
{
int i;
for(i=0;VarName[i].name;i++)
dst[i].str_var = VarName[i].setto;
}
void delete_vars(UniVar *vars, int which)
{
while(--which)
{
if (IsStr(which) && !IsProc(which))
{
#ifdef DEBUG
debug("(delete_vars) deleting string var `%s'\n",VarName[which].name);
#endif /* DEBUG */
Free((char**)&vars[which].str_var);
}
}
#ifdef DEBUG
debug("(delete_vars) all done\n");
#endif /* DEBUG */
}
void var_resolve_host(const struct Setting *varname)
{
}
/*
* support functions for esay
*/
char *ec_end;
char *ec_dest;
char *ec_src;
void nobo_strcpy(const char *src)
{
while(*src && ec_dest < ec_end)
*(ec_dest++) = *(src++);
*ec_dest = 0;
}
void ec_access(char *from, char *to)
{
char num[20];
sprintf(num,"%i",get_useraccess(from,to));
nobo_strcpy(num);
}
void ec_cc(char *from, char *to)
{
nobo_strcpy((current->activechan) ? current->activechan->name : TEXT_NONE);
}
void ec_channels(char *from, char *to)
{
Chan *chan;
int n;
if ((chan = current->chanlist) == NULL)
{
nobo_strcpy(ERR_NOCHANNELS);
return;
}
for(n=0;chan;chan=chan->next)
{
if (chan->active)
{
if (n && ec_dest < ec_end)
*(ec_dest++) = ' ';
if (chan->bot_is_op && ec_dest < ec_end)
*(ec_dest++) = '@';
nobo_strcpy(chan->name);
}
}
}
void ec_time(char *from, char *to)
{
nobo_strcpy(time2away(now));
}
void ec_set(char *from, char *to)
{
Chan *chan;
UniVar *varval;
char num[20];
char *src;
int which,uaccess;
src = ec_src;
while(*src && *src != ')')
src++;
if (*src != ')')
return;
*(src++) = 0;
if ((which = find_setting(ec_src)) >= 0)
{
if (which >= CHANSET_SIZE)
{
uaccess = get_useraccess(from,ANY_CHANNEL);
varval = &current->setting[which];
}
else
if ((chan = find_channel_ny(to)))
{
uaccess = get_useraccess(from,to);
varval = &chan->setting[which];
}
else
{
nobo_strcpy("(unknown channel)");
return;
}
if (uaccess < VarName[which].uaccess)
return;
if (IsProc(which))
varval = varval->proc_var;
if (IsChar(which))
{
num[0] = varval->char_var;
num[1] = 0;
nobo_strcpy(num);
}
else
if (IsInt(which))
{
sprintf(num,"%i",varval->int_var);
nobo_strcpy(num);
}
else
if (IsTog(which))
{
nobo_strcpy((varval->int_var) ? "on" : "off");
}
else
if (IsStr(which))
{
nobo_strcpy(nullstr(varval->str_var));
}
}
else
{
nobo_strcpy("(unknown setting)");
}
ec_src = src;
}
void ec_on(char *from, char *to)
{
nobo_strcpy(idle2str(now - current->ontime,FALSE));
}
void ec_server(char *from, char *to)
{
Server *sv;
char *s;
if ((sv = find_server(current->server)))
s = (*sv->realname) ? sv->realname : sv->name;
else
s = TEXT_NOTINSERVLIST;
nobo_strcpy(s);
}
void ec_up(char *from, char *to)
{
nobo_strcpy(idle2str(now - uptime,FALSE));
}
void ec_ver(char *from, char *to)
{
nobo_strcpy(BOTCLASS);
nobo_strcpy(" ");
nobo_strcpy(VERSION);
}
LS const struct
{
void (*func)(char *, char *);
char name[12];
char len;
} ecmd[] =
{
{ ec_access, "$access", 7 },
{ ec_cc, "$cc", 3 },
{ ec_channels, "$channels", 9 },
{ ec_time, "$time", 5 },
{ ec_set, "$var(", 5 },
{ ec_on, "$on", 3 },
{ ec_server, "$server", 7 },
{ ec_up, "$up", 3 },
{ ec_ver, "$ver", 4 },
{ NULL, "", 0 },
};
/*
*
* commands for variables
*
*/
void do_esay(COMMAND_ARGS)
{
/*
* on_msg checks CAXS + CARGS
*/
char output[MSGLEN];
char c,*chp;
int i,n;
ec_end = output + MSGLEN - 20;
ec_src = rest;
rest = STREND(rest);
ec_dest = output;
c = 0;
chp = NULL;
while(*ec_src)
{
if (*ec_src != '$')
{
*(ec_dest++) = *(ec_src++);
continue;
}
for(i=0;ecmd[i].len;i++)
{
if ((rest - ec_src) >= ecmd[i].len)
{
chp = ec_src + ecmd[i].len;
c = *chp;
*chp = 0;
}
n = Strcasecmp(ecmd[i].name,ec_src);
if (c)
{
*chp = c;
c = 0;
}
if (!n)
{
ec_src += ecmd[i].len;
ecmd[i].func(from,to);
break;
}
}
if (!ecmd[i].len)
{
*(ec_dest++) = *(ec_src++);
}
}
*ec_dest = 0;
to_user_q(from,FMT_PLAIN,output);
}
void do_set(COMMAND_ARGS)
{
/*
* on_msg checks:
*/
Chan *chan;
UniVar *univar,*varval;
char tmp[MSGLEN];
char *pp,*channel,*name;
int n,which,i,sz,limit,uaccess;
/*
*
*/
channel = get_channel2(to,&rest);
chan = find_channel_ny(channel);
name = chop(&rest);
/*
* empty args, its "set" or "set #channel"
*/
if (!name)
{
if (!chan)
{
to_user(from,ERR_CHAN,channel);
return;
}
if (!CurrentDCC)
return;
i = CHANSET_SIZE;
limit = SIZE_VARS - 1;
univar = current->setting;
*tmp = 0;
if ((uaccess = get_useraccess(from,GLOBAL_CHANNEL)))
to_user(from,str_underline("Global settings"));
second_pass:
for(;i<limit;i++)
{
if (uaccess < VarName[i].uaccess)
continue;
varval = (IsProc(i)) ? current->setting[i].proc_var : &univar[i];
sz = Strlen2(tmp,VarName[i].name);
if (IsStr(i))
{
sz += (varval->str_var) ? strlen(varval->str_var) : 7;
}
if (sz > 58)
{
to_user(from,FMT_PLAIN,tmp);
*tmp = 0;
}
if (IsInt(i))
{
pp = tolowercat(tmp,VarName[i].name);
sprintf(pp,(IsChar(i)) ? "=`%c' " : "=%i ",varval->int_var);
}
else
if (IsStr(i))
{
pp = tolowercat(tmp,VarName[i].name);
sprintf(pp,(varval->str_var) ? "=\"%s\" " : "=(unset) ",varval->str_var);
}
else
if (IsTog(i))
{
pp = Strcat(tmp,(varval->int_var) ? "+" : "-");
pp = tolowercat(pp,VarName[i].name);
pp[0] = ' ';
pp[1] = 0;
}
}
if (*tmp && tmp[1])
to_user(from,FMT_PLAIN,tmp);
if (limit != CHANSET_SIZE)
{
to_user(from,"\037Channel settings: %s\037",(chan) ? chan->name : rest);
i = 0;
limit = CHANSET_SIZE;
univar = chan->setting;
*tmp = 0;
uaccess = get_useraccess(from,(chan) ? chan->name : rest);
goto second_pass;
}
return;
}
/*
* alter a setting
*/
if ((which = find_setting(name)) == -1)
{
set_usage:
usage(from); /* usage for CurrentCmd->name */
return;
}
if ((which < CHANSET_SIZE) && *channel != '*')
{
if (!chan)
{
to_user(from,ERR_CHAN,channel);
return;
}
/*
* its a channel setting
*/
channel = chan->name;
varval = &chan->setting[which];
}
else
{
/*
* its a global setting
*/
channel = MATCH_ALL;
varval = &current->setting[which];
}
if (VarName[which].uaccess > get_authaccess(from,channel))
return;
/*
* Check each type and process `rest' if needed.
*/
n = 0;
if (IsChar(which))
{
if (rest[1])
goto set_usage;
}
else
if (IsNum(which))
{
if (IsTog(which))
{
if (!Strcasecmp(rest,"ON"))
{
n = 1;
goto num_data_ok;
}
else
if (!Strcasecmp(rest,"OFF"))
{
/* n is 0 by default */
goto num_data_ok;
}
}
n = a2i((rest = chop(&rest)));
if (errno || n < VarName[which].min || n > VarName[which].max)
{
to_user(from,"Possible values are %i through %i",VarName[which].min,VarName[which].max);
return;
}
}
num_data_ok:
/*
*
*/
if ((which < CHANSET_SIZE) && *channel == '*')
{
for(chan=current->chanlist;chan;chan=chan->next)
{
if (IsNum(which))
{
chan->setting[which].int_var = n;
}
else
if (IsStr(which))
{
Free((char**)&chan->setting[which].str_var);
if (*rest)
{
set_mallocdoer(do_set);
chan->setting[which].str_var = Strdup(rest);
}
}
}
channel = "(all channels)";
}
else
{
if (IsProc(which))
varval = varval->proc_var;
if (IsChar(which))
varval->char_var = *rest;
else
if (IsNum(which))
varval->int_var = n;
else
{
if (varval->str_var)
Free((char**)&varval->str_var);
if (*rest)
{
set_mallocdoer(do_set);
varval->str_var = Strdup(rest);
}
}
}
to_user(from,"Var: %s On: %s Set to: %s",VarName[which].name,
(which >= CHANSET_SIZE) ? "(global)" : channel,(*rest) ? rest : NULLSTR);
if (VarName[which].func)
VarName[which].func(&VarName[which]);
}

526
src/web.c Normal file
View File

@@ -0,0 +1,526 @@
/*
EnergyMech, IRC bot software
Copyright (c) 1997-2001 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 WEB_C
#include "config.h"
#ifdef WEB
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#define WEB_DEAD 0
#define WEB_WAITURL 1
#define WEB_WAITCR 2
#define WEBROOT "web/"
LS WebSock *weblist;
LS WebDoc docraw = { NULL, NULL, &web_raw };
#if 0
{
":last20lines>"
};
#endif
LS WebDoc doclist[] =
{
{ NULL, "/internalstatus.html", &web_botstatus },
#ifdef DEBUG
{ NULL, "/internaldebug.html", &web_debug },
#endif /* DEBUG */
/**/
{ NULL, NULL, NULL },
};
char *webread(int s, char *rest, char *line)
{
char tmp[MSGLEN];
char *pt,*tp,*np;
int l;
np = NULL;
pt = rest;
while(*pt)
{
if ((*pt == '\r') && (!np))
np = pt;
if (*pt == '\n')
{
if (np)
*np = 0;
*pt = 0;
Strcpy(line,rest);
pt++;
Strcpy(rest,pt);
#ifdef DEBUG
debug("[WoR] {%i} `%s'\n",s,line);
#endif /* DEBUG */
errno = EAGAIN;
return(line);
}
pt++;
}
l = pt - rest;
tp = pt;
memset(tmp,0,sizeof(tmp));
switch(read(s,tmp,MSGLEN-2))
{
case 0:
errno = EPIPE;
case -1:
return(NULL);
}
np = NULL;
pt = tmp;
while(*pt)
{
if ((*pt == '\r') && (!np))
np = tp;
if (*pt == '\n')
{
if (np)
*np = 0;
*tp = *pt = 0;
Strcpy(line,rest);
pt++;
Strcpy(rest,pt);
#ifdef DEBUG
debug("[WoR] {%i} `%s'\n",s,line);
#endif /* DEBUG */
errno = EAGAIN;
return(line);
}
if (l >= MSGLEN-2)
{
pt++;
continue;
}
*(tp++) = *(pt++);
l++;
}
*tp = 0;
return(NULL);
}
#define NOBO if (dest == &mem[MSGLEN-2]) { write(s,mem,dest-mem); dest = mem; }
void eml_fmt(WebSock *client, char *format)
{
char mem[MSGLEN];
char *src,*dest,*org;
int out;
int s = client->sock;
org = NULL;
out = TRUE;
dest = mem;
restart:
while(*format)
{
if (*format != '%')
{
if (out)
{
NOBO;
*(dest++) = *format;
}
format++;
goto restart;
}
format++;
switch(*format)
{
case '%':
NOBO;
*(dest++) = *(format++);
goto restart;
case 'B':
client->ebot = botlist;
break;
case 'C':
client->echan = (client->ebot) ? client->ebot->chanlist : NULL;
break;
case 'b':
src = (client->ebot) ? client->ebot->nick : (char*)NULLSTR;
while(*src)
{
NOBO;
*(dest++) = *(src++);
}
break;
case 'O':
#ifdef DEBUG
debug("> setting org\n");
#endif /* DEBUG */
org = format+1;
break;
case 'R':
if (out && org)
{
#ifdef DEBUG
debug("> repeat jump\n");
#endif /* DEBUG */
format = org;
goto restart;
}
break;
case '?':
format++;
switch(*format)
{
case 'b':
out = (client->ebot) ? 1 : 0;
#ifdef DEBUG
debug("> ?b: out = %i\n",out);
#endif /* DEBUG */
break;
case 'c':
out = (client->echan) ? 1 : 0;
#ifdef DEBUG
debug("> ?c: out = %i\n",out);
#endif /* DEBUG */
break;
case '1':
out = 1;
break;
}
break;
case '+':
format++;
switch(*format)
{
case 'b':
client->ebot = (client->ebot) ? client->ebot->next : NULL;
#ifdef DEBUG
debug("> +b: ebot = %p\n",client->ebot);
#endif /* DEBUG */
break;
case 'c':
client->echan = (client->echan) ? client->echan->next : NULL;
#ifdef DEBUG
debug("> +c: echan = %p\n",client->echan);
#endif /* DEBUG */
break;
}
break;
}
format++;
}
if (dest-mem > 0)
write(s,mem,dest-mem);
write(s,"\r\n",2);
}
void web_raw(WebSock *client, char *url)
{
struct stat s;
char path[MSGLEN];
char *src,*dest;
ino_t ino;
int fd;
int eml;
size_t sz;
eml = (matches("*.html",url)) ? TRUE : FALSE;
if (stat(WEBROOT "..",&s) < 0)
goto error;
ino = s.st_ino;
dest = Strcpy(path,WEBROOT);
src = url;
if (*src == '/')
src++;
while(*src)
{
if (*src == '/')
{
*dest = 0;
if (stat(path,&s) < 0)
{
#ifdef DEBUG
debug("(web_raw) unable to stat `%s'\n",path);
#endif /* DEBUG */
goto error;
}
if (s.st_ino == ino)
{
#ifdef DEBUG
debug("(web_raw) attempt to access docs outside WEBROOT (%s)\n",url);
#endif /* DEBUG */
goto error;
}
}
if (dest == &path[MSGLEN-2])
goto error;
*(dest++) = *(src++);
}
*dest = 0;
if ((fd = open(path,O_RDONLY)) < 0)
{
#ifdef DEBUG
debug("(web_raw) open failed = `%s'\n",path);
#endif /* DEBUG */
goto error;
}
sz = lseek(fd,0,SEEK_END);
lseek(fd,0,SEEK_SET);
#ifdef DEBUG
debug("(web_raw) file open for reading `%s'\n",path);
#endif /* DEBUG */
src = Calloc(sz+1);
read(fd,src,sz);
if (eml)
{
to_file(client->sock,"%s\r\n",src);
}
else
{
eml_fmt(client,src);
}
Free((char**)&src);
close(fd);
return;
error:
web_404(client,url);
}
void web_botstatus(WebSock *client, char *url)
{
Server *sp;
Mech *bot;
Chan *chan;
to_file(client->sock,"HTTP/1.0 200 OK\r\n");
to_file(client->sock,"Server: %s %s\r\n",BOTCLASS,VERSION);
to_file(client->sock,"Connection: close\r\n");
to_file(client->sock,"Content-Type: text/html\r\n\r\n");
bot = botlist;
to_file(client->sock,
"<html><head><title>EnergyMech Status</title></head>\r\n"
"<body>\r\n"
"<h1>EnergyMech Status</h1>\r\n"
"Uptime: %s<br><br>\r\n"
"<u>Current bots</u>:<br>\r\n",
idle2str(now - uptime,FALSE));
for(;bot;bot=bot->next)
{
sp = find_server(bot->server);
to_file(client->sock,
"Nick: %s (want %s)<br>\r\n"
"On server: %s<br>\r\n",
bot->nick,bot->wantnick,
(sp) ? ((sp->realname[0]) ? sp->realname : sp->name) : TEXT_NOTINSERVLIST);
to_file(client->sock,"Channels: ");
for(chan=bot->chanlist;chan;chan=chan->next)
to_file(client->sock,"%s ",chan->name);
to_file(client->sock,"<br><br>\r\n");
}
to_file(client->sock,"</body></html>\r\n");
}
#ifdef DEBUG
void web_debug(WebSock *client, char *url)
{
int backup_fd,backup_dodebug;
backup_dodebug = dodebug;
backup_fd = debug_fd;
to_file(client->sock,"HTTP/1.0 200 OK\r\n");
to_file(client->sock,"Server: %s %s\r\n",BOTCLASS,VERSION);
to_file(client->sock,"Connection: close\r\n");
to_file(client->sock,"Content-Type: text/html\r\n\r\n");
to_file(client->sock,"<pre>\r\n");
debug_fd = client->sock;
dodebug = TRUE;
run_debug();
debug_fd = backup_fd;
dodebug = backup_dodebug;
}
#endif /* DEBUG */
void web_404(WebSock *client, char *url)
{
to_file(client->sock,"HTTP/1.0 404 Not Found\r\n");
to_file(client->sock,"Server: %s %s\r\n",BOTCLASS,VERSION);
to_file(client->sock,"Connection: close\r\n");
to_file(client->sock,"Content-Type: text/html\r\n\r\n");
to_file(client->sock,
"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
"<HTML><HEAD>"
"<TITLE>404 Not Found</TITLE>"
"</HEAD><BODY>"
"<H1>Not Found</H1>"
"The requested URL %s was not found on this server.<P>"
"</BODY></HTML>",
url);
}
void parse(WebSock *client, char *rest)
{
char *method,*url,*proto;
int i;
switch(client->status)
{
case WEB_WAITURL:
method = chop(&rest);
url = chop(&rest);
proto = chop(&rest);
if (!method || !proto || Strcasecmp(method,"GET"))
{
client->status = WEB_DEAD;
return;
}
client->docptr = &docraw;
for(i=0;doclist[i].proc;i++)
{
if (!Strcasecmp(doclist[i].url,url))
{
client->docptr = &doclist[i];
break;
}
}
client->url = Strdup(url);
client->status = WEB_WAITCR;
break;
case WEB_WAITCR:
if (*rest == 0)
{
#ifdef DEBUG
debug("(web.c->parse) web document output\n");
#endif /* DEBUG */
if (client->docptr)
client->docptr->proc(client,client->url);
client->status = WEB_DEAD;
}
break;
}
}
void select_web(void)
{
WebSock *client;
if ((webport > 0) && (websock == -1))
{
websock = SockListener(webport);
#ifdef DEBUG
if (websock != -1)
debug("(web_select) websock is active (%i)\n",webport);
#endif /* DEBUG */
}
if (websock != -1)
{
chkhigh(websock);
FD_SET(websock,&read_fds);
}
for(client=weblist;client;client=client->next)
{
chkhigh(client->sock);
FD_SET(client->sock,&read_fds);
}
}
void process_web(void)
{
WebSock *client,*new,**cptr;
char linebuf[MSGLEN];
char *rest;
int s;
if ((websock != -1) && (FD_ISSET(websock,&read_fds)))
{
if ((s = SockAccept(websock)) >= 0)
{
new = (WebSock*)Calloc(sizeof(WebSock));
new->sock = s;
new->status = WEB_WAITURL;
new->when = now;
new->next = weblist;
weblist = new;
}
}
for(client=weblist;client;client=client->next)
{
if (FD_ISSET(client->sock,&read_fds))
{
read_again:
errno = EAGAIN;
rest = webread(client->sock,client->sockdata,linebuf);
if (rest)
{
parse(client,rest);
goto read_again;
}
switch(errno)
{
case EINTR:
case EAGAIN:
break;
default:
#ifdef DEBUG
debug("(web_process) client error = %i\n",errno);
#endif /* DEBUG */
client->status = WEB_DEAD;
}
}
}
cptr = &weblist;
while(*cptr)
{
client = *cptr;
if (client->status == WEB_DEAD)
{
#ifdef DEBUG
debug("(web_process) {%i} dropping client\n",client->sock);
#endif /* DEBUG */
close(client->sock);
*cptr = client->next;
if (client->url)
Free((char**)&client->url);
Free((char**)&client);
}
else
cptr = &client->next;
}
}
#endif /* WEB */