mirror of
https://github.com/EnergyMech/energymech.git
synced 2025-12-29 16:14:43 +00:00
Initial Import
This commit is contained in:
222
src/Makefile.in
Normal file
222
src/Makefile.in
Normal 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
196
src/alias.c
Normal 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
449
src/auth.c
Normal 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 = ¤t->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 = ¤t->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 = ¤t->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
396
src/bounce.c
Normal 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
161
src/chanban.c
Normal 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 = ¤t->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
1105
src/channel.c
Normal file
File diff suppressed because it is too large
Load Diff
552
src/config.h.in
Normal file
552
src/config.h.in
Normal 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
1681
src/core.c
Normal file
File diff suppressed because it is too large
Load Diff
1041
src/ctcp.c
Normal file
1041
src/ctcp.c
Normal file
File diff suppressed because it is too large
Load Diff
1337
src/debug.c
Normal file
1337
src/debug.c
Normal file
File diff suppressed because it is too large
Load Diff
468
src/defines.h
Normal file
468
src/defines.h
Normal 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
939
src/dns.c
Normal 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
88
src/dynamode.c
Normal 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
1096
src/function.c
Normal file
File diff suppressed because it is too large
Load Diff
433
src/gencmd.c
Normal file
433
src/gencmd.c
Normal 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
450
src/global.h
Normal 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
164
src/greet.c
Normal 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 = ¤t->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
783
src/h.h
Normal 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
262
src/help.c
Normal 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
137
src/irc.c
Normal 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=¤t->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
265
src/kicksay.c
Normal 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 = ¤t->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
105
src/ld/mech.ldscript
Normal 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
1039
src/main.c
Normal file
File diff suppressed because it is too large
Load Diff
400
src/md5/md5.c
Normal file
400
src/md5/md5.c
Normal 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
27
src/md5/md5.h
Normal 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
53
src/mega.c
Normal 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"
|
||||
144
src/net_chan.c
Normal file
144
src/net_chan.c
Normal 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
215
src/note.c
Normal 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 = ¬elist;
|
||||
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
755
src/notify.c
Normal 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,¬ifylog_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 = ¤t->notifylist;
|
||||
readline(fd,¬ify_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 = ¤t->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 = ¤t->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 */
|
||||
1497
src/parse.c
Normal file
1497
src/parse.c
Normal file
File diff suppressed because it is too large
Load Diff
184
src/perl.c
Normal file
184
src/perl.c
Normal 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
610
src/prot.c
Normal 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
973
src/python.c
Normal 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 = ¤t->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
167
src/redirect.c
Normal 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 = ¤t->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
430
src/reset.c
Normal 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
313
src/seen.c
Normal 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
153
src/settings.h
Normal 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
401
src/shit.c
Normal 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 = ¤t->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
674
src/socket.c
Normal 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**)¤t->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 = ¤t->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
536
src/spy.c
Normal 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 = ¤t->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
144
src/stats.c
Normal 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
822
src/structs.h
Normal 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
654
src/tcl.c
Normal 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 = ¤t->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
84
src/telnet.c
Normal 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
202
src/text.h
Normal 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
349
src/toybox.c
Normal 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
636
src/trivia.c
Normal 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
269
src/uptime.c
Normal 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*)®Pack,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
183
src/usage.h
Normal 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
1697
src/user.c
Normal file
File diff suppressed because it is too large
Load Diff
558
src/vars.c
Normal file
558
src/vars.c
Normal 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**)¤t->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 = ¤t->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 = ¤t->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
526
src/web.c
Normal 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 */
|
||||
Reference in New Issue
Block a user