diff --git a/.gitignore b/.gitignore index 573768a..92ba050 100644 --- a/.gitignore +++ b/.gitignore @@ -32,15 +32,13 @@ root.zone* trick.conf mech.trivscore trivia/megatrivia.txt +*.log +*.stats # developer files .use_size conf debug* -*.log -*.stats -github - src/calc.c src/x src/y diff --git a/Makefile b/Makefile index 9306698..57c2fb5 100644 --- a/Makefile +++ b/Makefile @@ -56,10 +56,10 @@ TESTFILES = config/cc.c config/endian.c config/inet_addr.c config/inet_aton.c co TRIVFILES = trivia/mkindex.c SRCFILES = src/alias.c src/auth.c src/bounce.c src/channel.c src/core.c src/ctcp.c src/debug.c src/dns.c \ - src/function.c src/gencmd.c src/greet.c src/help.c src/hostinfo.c src/irc.c src/kicksay.c src/main.c src/mega.c \ - src/net.c src/note.c src/notify.c src/ons.c src/parse.c src/partyline.c src/perl.c src/prot.c \ + src/function.c src/gencmd.c src/greet.c src/help.c src/hostinfo.c src/irc.c src/main.c \ + src/net.c src/note.c src/ons.c src/parse.c src/partyline.c src/perl.c src/prot.c \ src/python.c src/reset.c src/seen.c src/shit.c src/io.c src/spy.c src/tcl.c \ - src/toybox.c src/trivia.c src/uptime.c src/user.c src/vars.c src/web.c \ + src/toybox.c src/uptime.c src/user.c src/vars.c src/web.c \ src/lib/md5.c src/lib/md5.h src/lib/string.c HDRFILES = src/defines.h src/global.h src/h.h src/settings.h src/structs.h src/text.h src/usage.h diff --git a/VERSIONS b/VERSIONS index e732d17..7ba9a6a 100644 --- a/VERSIONS +++ b/VERSIONS @@ -1,5 +1,7 @@ 3.1 -- WORK IN PROGRESS (~April, 2018) + * Fixed: Issue #25, clients lost when doing reset, no more + * Fixed: compiler warnings and missing defines/conflicting defines with certain options * Added: configure now saves the options selected in ./myconfig for later re-use * Fixed: Missing ifdef BOTNET in user.c * Added: Git version hash included in version string if git environment is found. diff --git a/configure b/configure index 068ae57..458b523 100755 --- a/configure +++ b/configure @@ -1499,16 +1499,6 @@ s|@PTSIZE_DEFINE64@|$PTSIZE_DEFINE64|; s|@UNALIGNED_MEM@|$UNALIGNED_MEM|; " < src/config.h.in >> src/config.h -if [ "$install" = yes ]; then - make $makejobs -C src energymech - exit -fi - -if [ "$compile" = yes ]; then - make $makejobs -C src energymech - exit -fi - save_myconfig() { names="alias botnet bounce chanban ctcp dccfile debug dynamode dyncmd greet hostinfo idwrap ircd_ext libmusl md5 netcfg newbie note notify perl profiling python rawdns redirect seen session sha stats suppress tcl @@ -1539,16 +1529,28 @@ if [ -w ./myconfig -o ! -e ./myconfig ]; then save_myconfig fi -echo '' -echo 'All done. You can now "make install"' -if [ ! "$cores" = 1 ]; then - echo "For speedy compiling, use \`\`make -j$cores''" +if [ "$install" = yes ]; then + make $makejobs -C src energymech + exit fi -echo '' -echo "Your chosen ./configure options have been saved to ./myconfig" -echo 'if you wish to save ./myconfig in its current state, chmod -w ./myconfig' -echo '' -echo 'Submit your bugreports at https://github.com/MadCamel/energymech/issues' -echo '' -echo 'You have read the README file I hope?' -echo '' + +if [ "$compile" = yes ]; then + make $makejobs -C src energymech + exit +fi + +$out '' +$out 'All done. You can now "make install"' +if [ ! "$cores" = 1 ]; then + $out "For speedy compiling, use \`\`make -j$cores''" +fi +$out '' +$out "Your chosen ./configure options have been saved to ./myconfig" +$out 'if you wish to save ./myconfig in its current state, chmod -w ./myconfig' +$out '' +$out 'Submit your bugreports at https://github.com/MadCamel/energymech/issues' +$out '' +$out 'You have read the README file I hope?' +$out '' + + diff --git a/src/Makefile.in b/src/Makefile.in index ac8342b..535abf2 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -48,14 +48,14 @@ INCS = $(BASEINCLUDES) mcmd.h text.h usercombo.h TESTFILES = aliastest safepathtest OFILES = alias.o auth.o bounce.o channel.o core.o ctcp.o debug.o dns.o function.o greet.o \ - help.o hostinfo.o io.o irc.o kicksay.o main.o net.o note.o notify.o ons.o parse.o partyline.o \ + help.o hostinfo.o io.o irc.o main.o net.o note.o ons.o parse.o partyline.o \ perl.o prot.o python.o reset.o seen.o shit.o spy.o tcl.o toybox.o \ - trivia.o uptime.o user.o vars.o web.o lib/string.o @MD5_O@ @SHA_O@ + uptime.o user.o vars.o web.o lib/string.o @MD5_O@ @SHA_O@ SRCFILES = alias.c auth.c bounce.c channel.c core.c ctcp.c debug.c dns.c function.c greet.c \ - help.c hostinfo.c io.c irc.c kicksay.c main.c net.c note.c notify.c ons.c parse.c partyline.c \ + help.c hostinfo.c io.c irc.c main.c net.c note.c ons.c parse.c partyline.c \ perl.c prot.c python.c reset.c seen.c shit.c spy.c tcl.c toybox.c \ - trivia.c uptime.c user.c vars.c web.c lib/string.c @MD5_C@ @SHA_C@ + uptime.c user.c vars.c web.c lib/string.c @MD5_C@ @SHA_C@ .PHONY: all clean mega-install mega mega-static test commands @@ -78,6 +78,8 @@ usercombo.h: gencmd githash.h: gencmd ./gencmd githash.h +global.h: githash.h + install: $(INSTALLNAME) $(CHMOD) $(INSTALLMODE) $(INSTALLNAME) $(MV) $(INSTALLNAME) $(INSTALLDIR) @@ -107,12 +109,12 @@ mega-install: mega $(SRCFILES) $(INCS) usage.h $(MV) $(INSTALLNAME) $(INSTALLDIR) mega: $(SRCFILES) $(INCS) usage.h - $(CROSS_COMPILE)$(CC) $(CFLAGS) -o $(INSTALLNAME) mega.c -DGENDATE="`./gencmd date`" -I. $(LPROF) $(LIBS) $(LDSCRIPT) $(PYINCLUDE) $(TCLINCLUDE) $(I_PERL) $(L_PERL) + $(CROSS_COMPILE)$(CC) $(CFLAGS) -o $(INSTALLNAME) main.c -DMEGA_C -DGENDATE="`./gencmd date`" -I. $(LPROF) $(LIBS) $(LDSCRIPT) $(PYINCLUDE) $(TCLINCLUDE) $(I_PERL) $(L_PERL) #@oc@ $(CROSS_COMPILE)objcopy -R .note -R .comment $(INSTALLNAME) @sz@ size $(INSTALLNAME) mega-static: $(SRCFILES) $(INCS) usage.h - $(CROSS_COMPILE)$(CC) $(CFLAGS) -o $(INSTALLNAME) mega.c -DGENDATE="`./gencmd date`" -I. $(LPROF) $(LIBS) $(LDSCRIPT) $(PYINCLUDE) $(TCLINCLUDE) $(I_PERL) $(L_PERL) -static + $(CROSS_COMPILE)$(CC) $(CFLAGS) -o $(INSTALLNAME) main.c -DMEGA_C -DGENDATE="`./gencmd date`" -I. $(LPROF) $(LIBS) $(LDSCRIPT) $(PYINCLUDE) $(TCLINCLUDE) $(I_PERL) $(L_PERL) -static #@oc@ $(CROSS_COMPILE)objcopy -R .note -R .comment $(INSTALLNAME) @sz@ size $(INSTALLNAME) @@ -188,9 +190,6 @@ io.o: io.c $(INCS) irc.o: irc.c $(INCS) $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) -kicksay.o: kicksay.c $(INCS) - $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) - main.o: main.c $(INCS) githash.h $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< -DGENDATE="`./gencmd date`" $(CPROF) $(PYINCLUDE) @@ -200,9 +199,6 @@ net.o: net.c $(INCS) note.o: note.c $(INCS) $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) -notify.o: notify.c $(INCS) - $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) - ons.o: ons.c $(INCS) $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) @@ -239,9 +235,6 @@ tcl.o: tcl.c $(INCS) toybox.o: toybox.c $(INCS) $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) -trivia.o: trivia.c $(INCS) - $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) - uptime.o: uptime.c $(INCS) $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) diff --git a/src/debug.c b/src/debug.c index dd52ffc..39ad1c0 100644 --- a/src/debug.c +++ b/src/debug.c @@ -108,7 +108,6 @@ LS const struct #endif { NULL, }}; - LS struct { void *func; diff --git a/src/h.h b/src/h.h index 2a767cd..3444ec2 100644 --- a/src/h.h +++ b/src/h.h @@ -576,7 +576,7 @@ LS void do_banlist(COMMAND_ARGS) __page(CMD1_SEG); #ifdef PYTHON -#ifdef DEBUG_C +#if defined(DEBUG_C) || defined(MEGA_C) PyObject *python_hook(PyObject *self, PyObject *args, PyObject *keywds); PyObject *python_unhook(PyObject *self, PyObject *args, PyObject *keywds); #endif @@ -655,7 +655,7 @@ LS void do_urlhist(COMMAND_ARGS) __page(CMD1_SEG); LS int tcl_timer_jump(Hook *hook); LS int tcl_parse_jump(char *from, char *rest, Hook *hook); LS void tcl_dcc_complete(Client *client, int cps); -#ifdef DEBUG_C +#if defined(DEBUG_C) || defined(MEGA_C) LS int tcl_hook(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[]); #endif //LS int tcl_unhook(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[]); @@ -673,32 +673,30 @@ LS void do_tcl(COMMAND_ARGS) __page(CMD1_SEG); /* toybox.c */ -LS int read_bigcharset_callback(char *rest); -LS int read_bigcharset(char *fname); -LS int read_ascii(char *rest); +LS int read_bigcharset_callback(char *); +LS int read_bigcharset(char *); +LS int read_ascii(char *); +LS void trivia_week_toppers(void); +LS void hint_one(void); +LS void hint_two(void); +LS void hint_three(void); +LS void trivia_cleanup(void); +LS void trivia_check(Chan *, char *); +LS void trivia_no_answer(void); +LS char *random_question(char *); +LS void trivia_question(void); +LS void trivia_tick(void); +LS void write_triviascore(void); +LS int trivia_score_callback(char *); +LS void read_triviascore(void); LS void do_bigsay(COMMAND_ARGS) __page(CMD1_SEG); LS void do_random_msg(COMMAND_ARGS) __page(CMD1_SEG); LS void do_randtopic(COMMAND_ARGS) __page(CMD1_SEG); LS void do_8ball(COMMAND_ARGS) __page(CMD1_SEG); LS void do_ascii(COMMAND_ARGS) __page(CMD1_SEG); LS void do_rand(COMMAND_ARGS) __page(CMD1_SEG); +LS void do_trivia(COMMAND_ARGS) __page(CMD1_SEG); -/* trivia.c */ - -void trivia_week_toppers(void); -void hint_one(void); -void hint_two(void); -void hint_three(void); -void trivia_cleanup(void); -void trivia_check(Chan *chan, char *rest); -void trivia_no_answer(void); -char *random_question(char *triv_rand); -void trivia_question(void); -void trivia_tick(void); -void write_triviascore(void); -int trivia_score_callback(char *rest); -void read_triviascore(void); -void do_trivia(COMMAND_ARGS) __page(CMD1_SEG); /* uptime.c */ diff --git a/src/kicksay.c b/src/kicksay.c deleted file mode 100644 index 7466dd5..0000000 --- a/src/kicksay.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - - 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 == '*' || !stringcasecmp(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 == '*' || !stringcasecmp(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 (partyline_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(FMT_4XSTRTAB,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 = asc2int(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) + StrlenX(channel,mask,rest,NULL)); - - kick->next = current->kicklist; - current->kicklist = kick; - kick->action = inum; - - if (!matches("\\*?*\\*",mask)) - kick->chan = stringcpy(kick->mask,mask) + 1; - else - { - kick->mask[0] = '*'; - stringcpy(kick->mask+1,mask); - kick->chan = stringcat(kick->mask,MATCH_ALL) + 1; - } - kick->reason = stringcpy(kick->chan,channel) + 1; - stringcpy(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 */ -} diff --git a/src/main.c b/src/main.c index 1779c79..1b80b08 100644 --- a/src/main.c +++ b/src/main.c @@ -18,6 +18,62 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#ifdef MEGA_C +#define MAIN_C +#include "config.h" +#include "defines.h" +#include "structs.h" +#include "global.h" +#ifdef TCL +#include +#endif +#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 "channel.c" +#include "core.c" +#include "ctcp.c" +#include "debug.c" +#undef DEBUG_C +#include "dns.c" +#include "function.c" +#include "greet.c" +#include "help.c" +#include "hostinfo.c" +#include "io.c" +#include "irc.c" +#include "lib/string.c" +#include "net.c" +#include "note.c" +#include "ons.c" +#include "parse.c" +#include "partyline.c" +#if defined(TCL) && defined(PERL) +#undef STRINGIFY +#endif +#include "perl.c" +#include "prot.c" +#include "python.c" +#include "reset.c" +#include "seen.c" +#include "shit.c" +#include "spy.c" +#include "tcl.c" +#include "toybox.c" +#include "uptime.c" +#include "user.c" +#include "vars.c" +#include "web.c" +#else /* ifdef MEGA_C */ + #define MAIN_C #include "config.h" @@ -28,6 +84,8 @@ #include "text.h" #include "mcmd.h" +#endif /* ifdef-else MEGA_C */ + /* * we generally try to mess around as little as possible here */ diff --git a/src/mega.c b/src/mega.c deleted file mode 100644 index d7fed12..0000000 --- a/src/mega.c +++ /dev/null @@ -1,50 +0,0 @@ -#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 "channel.c" -#include "core.c" -#include "ctcp.c" -#include "debug.c" -#include "dns.c" -#include "function.c" -#include "greet.c" -#include "help.c" -#include "hostinfo.c" -#include "io.c" -#include "irc.c" -#include "kicksay.c" -#include "lib/string.c" -#include "main.c" -#include "net.c" -#include "note.c" -#include "notify.c" -#include "ons.c" -#include "parse.c" -#include "partyline.c" -#include "perl.c" -#include "prot.c" -#include "python.c" -#include "reset.c" -#include "seen.c" -#include "shit.c" -#include "spy.c" -#include "tcl.c" -#include "toybox.c" -#include "trivia.c" -#include "uptime.c" -#include "user.c" -#include "vars.c" -#include "web.c" diff --git a/src/net.c b/src/net.c index 701093f..c6dae20 100644 --- a/src/net.c +++ b/src/net.c @@ -1354,8 +1354,13 @@ void parse_botnet(BotNet *bn, char *rest) #ifdef TELNET if (bn->status == BN_UNKNOWN) { - if (!stringcmp(rest,telnetprompt)) // another bot sent me its telnetprompt + if (rest[0] == 'B' && rest[1] == 'B' && (attrtab[(uchar)rest[2]] & NUM)) + { + basicBanner(bn,rest+2); return; + } + //if (!stringcmp(rest,telnetprompt)) // another bot sent me its telnetprompt // dont assume identical prompts + // return; #ifdef NETCFG if (strncmp(rest,"netcfg ",7) == 0) { diff --git a/src/notify.c b/src/notify.c deleted file mode 100644 index 57bd513..0000000 --- a/src/notify.c +++ /dev/null @@ -1,753 +0,0 @@ -/* - - 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;maskendofmask;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;ichecked > 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;ichecked = 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 = stringcat(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)); // realname is never NULL - nlog->signon = now; - nlog->next = nf->log; - nf->log = nlog; - nlog->realname = stringcat(nlog->userhost,userhost) + 1; - stringcpy(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 = asc2int(chop(&rest)); - if (errno) - return(FALSE); - - off = asc2int(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)); // rest is never NULL - nlog->signon = on; - nlog->signoff = off; - nlog->next = *pp; - *pp = nlog; - nlog->realname = stringcat(nlog->userhost,userhost) + 1; - stringcpy(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) + StrlenX(nick,rest,src,NULL)); - dst = stringcat(nf->nick,nick); - if (*rest) - { - nf->mask = dst + 1; - dst = stringcat(nf->mask,rest); - if (STRCHR(nf->mask,' ')) - nf->endofmask = dst; - } - if (src) - { - nf->info = dst + 1; - stringcpy(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 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(global_from,"\037nick\037 \037last seen\037 \037note\037"); - to_user(global_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(global_from," "); - to_user(global_from,(nf->status == NF_MASKONLINE) ? "Nick: \037%s\037" : "Nick: %s",nf->nick); - if (nf->info) - to_user(global_from,"Note: %s",nf->info); - if (nf->mask) - to_user(global_from,"Mask: %s",nf->mask); - if (nf->log) - { - to_user(global_from,"Online history:"); - for(nlog=nf->log;nlog;nlog=nlog->next) - { - opt = mem; - s = time2away(nlog->signon); - if (s[1] == ':') - *(opt++) = ' '; - *opt = 0; - opt = stringcat(opt,s); - while(opt < (mem+18)) - *(opt++) = ' '; - *opt = 0; - opt = stringcat(opt," -- "); - if (nlog->signoff) - { - s = time2away(nlog->signoff); - if (s[1] == ':') - *(opt++) = ' '; - *opt = 0; - } - else - { - s = " online now"; - } - opt = stringcat(opt,s); - while(opt < (mem+41)) - *(opt++) = ' '; - *opt = 0; - s = (nlog->realname) ? "%s: %s (%s)" : "%s: %s"; - to_user(global_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; - - global_from = from; - flags = nf_header = 0; - *message = 0; - - if (*rest) - { - while((opt = chop(&rest))) - { - if (!stringcmp(opt,"+")) - { - endoflist = ¤t->notifylist; - while(*endoflist) - endoflist = &(*endoflist)->next; - notify_callback(rest); - return; - } - if (!stringcmp(opt,"-")) - { - sub_notifynick(from,rest); - return; - } - for(n=0;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) - stringcat(message,", "); - stringcat(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 */ diff --git a/src/prot.c b/src/prot.c index 62d7a77..a56f9bf 100644 --- a/src/prot.c +++ b/src/prot.c @@ -598,11 +598,111 @@ void chanban_action(char *nick, char *channel, Shit *shit) #endif /* CHANBAN */ +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 == '*' || !stringcasecmp(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 == '*' || !stringcasecmp(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); +} + /* - * - * prot.c commands - * - */ +-+=====================================================================================================================+- + prot.c commands +-+=====================================================================================================================+- +*/ void do_opdeopme(COMMAND_ARGS) { @@ -797,3 +897,132 @@ void do_banlist(COMMAND_ARGS) to_user(from,"There are no active bans on %s",to); #endif /* IRCD_EXTENSIONS */ } + +#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 (partyline_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(FMT_4XSTRTAB,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 = asc2int(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) + StrlenX(channel,mask,rest,NULL)); + + kick->next = current->kicklist; + current->kicklist = kick; + kick->action = inum; + + if (!matches("\\*?*\\*",mask)) + kick->chan = stringcpy(kick->mask,mask) + 1; + else + { + kick->mask[0] = '*'; + stringcpy(kick->mask+1,mask); + kick->chan = stringcat(kick->mask,MATCH_ALL) + 1; + } + kick->reason = stringcpy(kick->chan,channel) + 1; + stringcpy(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 */ +} diff --git a/src/reset.c b/src/reset.c index 485b2ac..f354d5a 100644 --- a/src/reset.c +++ b/src/reset.c @@ -30,42 +30,29 @@ LS int client_type = DCC_ACTIVE; #endif /* TELNET */ +#define mkaxx(x) (0x40404040 + (0x0f0f & x) + ((0xf0f0 & x) << 12)) +#define getaxx(x) (((x & 0x0f0f0000) >> 12) | (x & 0x00000f0f)) + char *recover_client(char *env) { + union { + uint32_t num[2]; + char asc[8]; + } axx; struct sockaddr_in sai; Client *client; User *user; char *p,*handle; - int guid,fd,sz; + int guid = 0,fd = 0,sz; - guid = fd = 0; - p = env; - - /* - * get the guid number - */ - while(*p >= '0' && *p <= '9') - { - guid = (guid * 10) + (*p - '0'); - p++; - } - if (*p != ':') + if (env[8] != ':') return(env); - p++; - /* - * get the fd number - */ - while(*p >= '0' && *p <= '9') - { - fd = (fd * 10) + (*p - '0'); - p++; - } - if (*p != ':') - return(env); - p++; + memcpy(axx.asc,env,8); // compiler is not stupid and will optimize the shit out of this + guid = getaxx(axx.num[0]); + fd = getaxx(axx.num[1]); - handle = p; + handle = p = (env = env + 9); while(*p) { if (*p == ' ' || *p == 0) @@ -150,22 +137,21 @@ found_user: char *recover_debug(char *env) { + union { + uint32_t num; + char asc[4]; + } axx; struct stat s; - char *p; debug_fd = 0; - p = env; + if (env[4] != ' ' && env[4] != 0) + return(env); /* * get the fd number */ - while(*p >= '0' && *p <= '9') - { - debug_fd = (debug_fd * 10) + (*p - '0'); - p++; - } - if (*p != ' ' && *p != 0) - return(env); + memcpy(axx.asc,env,4); // compiler is not stupid and will optimize the shit out of this + debug_fd = getaxx(axx.num); if (fstat(debug_fd,&s) < 0) { @@ -176,71 +162,57 @@ char *recover_debug(char *env) else { dodebug = TRUE; - debug("(recover_debug) debug fd recovered\n"); + debug("(recover_debug) {%i} debug fd recovered\n",debug_fd); CoreClient.sock = debug_fd; } - return(p); + return(env+4); } #endif /* DEBUG */ -//execve( ./energymech, argv = { ./energymech }, envp = { MECHRESET=d3 f1881:2:X12 f99:4:X12 } ) +/* +(do_reset) mkaxx(3) = C@@@ +(do_reset) ircx mkaxx(12) = L@@@ +(do_reset) sock mkaxx(2) = B@@@ +(do_reset) guid mkaxx(1881) = IGE@ +[StS] {2} PING :OT1523818405 +(do_reset) MECHRESET=dC@@@ fXIGE@B@@@L@@@ tIGE@F@@@:joo [44] +execve( ./energymech, argv = { ./energymech }, envp = { MECHRESET=dC@@@ fXIGE@B@@@L@@@ tIGE@F@@@:joo } ) +*/ char *recover_server(char *env) { + union { + uint32_t num[4]; + char asc[16]; + } axx; struct sockaddr_in sai; char *p; - int guid,fd,sz; + int guid = 0,fd = 0,sz; #ifdef IRCD_EXTENSIONS int ircx = 0; #endif /* IRCD_EXTENSIONS */ - guid = fd = 0; - p = env; - - /* - * get the guid number - */ - while(*p >= '0' && *p <= '9') + switch(*env++) { - guid = (guid * 10) + (*p - '0'); - p++; - } - if (*p != ':') + case 'x': + sz = 8; + break; + case 'X': + sz = 12; + break; + default: 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) + if (env[sz] != ' ' && env[sz] != 0) return(env); -#endif /* ! IRCD_EXTENSIONS */ + memcpy(axx.asc,env,sz); // compiler is not stupid and will optimize the shit out of this + env += sz; + guid = getaxx(axx.num[0]); + fd = getaxx(axx.num[1]); #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); + ircx = getaxx(axx.num[2]); #ifdef DEBUG debug("(recover_server) guid = %i; fd = %i, ircx = %i\n",guid,fd,ircx); #endif /* DEBUG */ @@ -254,7 +226,7 @@ char *recover_server(char *env) if (getsockname(fd,(struct sockaddr*)&sai,&sz) < 0) { close(fd); - return(p); + return(env); } for(current=botlist;current;current=current->next) { @@ -282,19 +254,11 @@ char *recover_server(char *env) to_file(fd,"QUIT :I'm no longer wanted *cry*\n"); killsock(fd); } - return(p); + return(env); } -#ifdef IRCD_EXTENSIONS - -/* -#define IRCX_WALLCHOPS 1 -#define IRCX_WALLVOICES 2 -#define IRCX_IMODE 4 -#define IRCX_EMODE 8 -*/ - -#endif /* IRCD_EXTENSIONS */ +//(do_reset) MECHRESET=dC@@@ fXIGE@A@@@L@@@ tIGE@F@@@:joo [44] +//execve( ./energymech, argv = { ./energymech }, envp = { MECHRESET=dC@@@ fXIGE@A@@@L@@@ tIGE@F@@@:joo } ) void recover_reset(void) { @@ -329,17 +293,23 @@ void recover_reset(void) default: env++; } + while(*env == ' ') + env++; } } /* - * - * commands - * - */ +-+=====================================================================================================================+- + reset.c commands +-+=====================================================================================================================+- +*/ void do_reset(COMMAND_ARGS) { + union { + uint32_t num[8]; + char asc[32]; + } axx; Client *client; Mech *backup; char env[MSGLEN]; @@ -372,16 +342,16 @@ void do_reset(COMMAND_ARGS) *env = 0; p = stringcat(env,STR_MECHRESET); - n = 0; #ifdef DEBUG /* * debug stuff */ if (dodebug && (debug_fd >= 0)) { - sprintf(p,"d%i",debug_fd); + axx.num[0] = mkaxx(debug_fd); + axx.num[1] = 0; + sprintf(p,"d%s",axx.asc); p = STREND(p); - n++; } #endif /* DEBUG */ /* @@ -393,15 +363,17 @@ void do_reset(COMMAND_ARGS) if ((current->connect == CN_ONLINE) && ((MSGLEN - (p - env)) > 25)) { unset_closeonexec(current->sock); - if (n) - *(p++) = ' '; + axx.num[0] = mkaxx(current->guid); + axx.num[1] = mkaxx(current->sock); #ifdef IRCD_EXTENSIONS - sprintf(p,"f%i:%i:X%i",current->guid,current->sock,current->ircx_flags); + axx.num[2] = mkaxx(current->ircx_flags); + axx.num[3] = 0; + sprintf(p," fX%s",axx.asc); #else /* IRCD_EXTENSIONS */ - sprintf(p,"f%i:%i",current->guid,current->sock); + axx.num[2] = 0; + sprintf(p," fx%s",axx.asc); #endif /* IRCD_EXTENSIONS */ p = STREND(p); - n++; to_server("PING :OT%lu\n",current->ontime); } for(client=current->clientlist;client;client=client->next) @@ -417,16 +389,16 @@ void do_reset(COMMAND_ARGS) if ((MSGLEN - (p - env)) > sz) { unset_closeonexec(client->sock); - if (n) - *(p++) = ' '; + axx.num[0] = mkaxx(current->guid); + axx.num[1] = mkaxx(client->sock); + axx.num[2] = 0; #ifdef TELNET - sprintf(p,(client->flags & DCC_TELNET) ? "t%i:%i:%s" : "c%i:%i:%s", - current->guid,current->sock,client->user->name); + sprintf(p,(client->flags & DCC_TELNET) ? " t%s:%s" : " c%s:%s", + axx.asc,client->user->name); #else - sprintf(p,"c%i:%i:%s",current->guid,current->sock,client->user->name); + sprintf(p," c%s:%s",axx.asc,client->user->name); #endif /* TELNET */ p = STREND(p); - n++; } } } @@ -436,7 +408,7 @@ void do_reset(COMMAND_ARGS) debug("(do_reset) %s [%i]\n",env,(int)(p - env)); #endif /* DEBUG */ - mechresetenv = (n) ? env : NULL; + mechresetenv = (*env) ? env : NULL; do_exec = TRUE; mech_exec(); diff --git a/src/seen.c b/src/seen.c index 02d51b8..f37b2ac 100644 --- a/src/seen.c +++ b/src/seen.c @@ -21,8 +21,6 @@ #define SEEN_C #include "config.h" -#ifdef SEEN - #include "defines.h" #include "structs.h" #include "global.h" @@ -30,6 +28,612 @@ #include "text.h" #include "mcmd.h" +#ifdef NOTIFY + +#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 */ + +#define NFF_ALL 1 +#define NFF_NOMATCH 2 +#define NFF_RELOAD 4 +#define NFF_FULL 8 +#define NFF_SEEN 16 + +#define NF_OPTIONS 7 + +LS const char notify_opt[NF_OPTIONS][10] = +{ +"-ALL", +"-NOMATCH", +"-RELOAD", +"-FULL", +"-SEEN", +}; + +LS Notify **endoflist; +LS int lock_ison = FALSE; +LS int nf_header; + +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;maskendofmask;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;ichecked > 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;ichecked = 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 = stringcat(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)); // realname is never NULL + nlog->signon = now; + nlog->next = nf->log; + nf->log = nlog; + nlog->realname = stringcat(nlog->userhost,userhost) + 1; + stringcpy(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 = asc2int(chop(&rest)); + if (errno) + return(FALSE); + + off = asc2int(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)); // rest is never NULL + nlog->signon = on; + nlog->signoff = off; + nlog->next = *pp; + *pp = nlog; + nlog->realname = stringcat(nlog->userhost,userhost) + 1; + stringcpy(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) + StrlenX(nick,rest,src,NULL)); + dst = stringcat(nf->nick,nick); + if (*rest) + { + nf->mask = dst + 1; + dst = stringcat(nf->mask,rest); + if (STRCHR(nf->mask,' ')) + nf->endofmask = dst; + } + if (src) + { + nf->info = dst + 1; + stringcpy(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); +} + +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(global_from,"\037nick\037 \037last seen\037 \037note\037"); + to_user(global_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(global_from," "); + to_user(global_from,(nf->status == NF_MASKONLINE) ? "Nick: \037%s\037" : "Nick: %s",nf->nick); + if (nf->info) + to_user(global_from,"Note: %s",nf->info); + if (nf->mask) + to_user(global_from,"Mask: %s",nf->mask); + if (nf->log) + { + to_user(global_from,"Online history:"); + for(nlog=nf->log;nlog;nlog=nlog->next) + { + opt = mem; + s = time2away(nlog->signon); + if (s[1] == ':') + *(opt++) = ' '; + *opt = 0; + opt = stringcat(opt,s); + while(opt < (mem+18)) + *(opt++) = ' '; + *opt = 0; + opt = stringcat(opt," -- "); + if (nlog->signoff) + { + s = time2away(nlog->signoff); + if (s[1] == ':') + *(opt++) = ' '; + *opt = 0; + } + else + { + s = " online now"; + } + opt = stringcat(opt,s); + while(opt < (mem+41)) + *(opt++) = ' '; + *opt = 0; + s = (nlog->realname) ? "%s: %s (%s)" : "%s: %s"; + to_user(global_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); +} + +#endif /* ifdef NOTIFY */ + +#ifdef SEEN + int write_seenlist(void) { Seen *seen; @@ -213,10 +817,10 @@ step_two: } /* - * - * commands for seen features - * - */ +-+=====================================================================================================================+- + seen.c commands +-+=====================================================================================================================+- +*/ void do_seen(COMMAND_ARGS) { @@ -312,3 +916,121 @@ void do_seen(COMMAND_ARGS) } #endif /* SEEN */ + +#ifdef NOTIFY + +void do_notify(COMMAND_ARGS) +{ + char message[MSGLEN]; + Notify *nf; + nfLog *nlog; + char *opt; + int n,flags; + + global_from = from; + flags = nf_header = 0; + *message = 0; + + if (*rest) + { + while((opt = chop(&rest))) + { + if (!stringcmp(opt,"+")) + { + endoflist = ¤t->notifylist; + while(*endoflist) + endoflist = &(*endoflist)->next; + notify_callback(rest); + return; + } + if (!stringcmp(opt,"-")) + { + sub_notifynick(from,rest); + return; + } + for(n=0;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) + stringcat(message,", "); + stringcat(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 */ diff --git a/src/structs.h b/src/structs.h index 6c0f95d..2b68a93 100644 --- a/src/structs.h +++ b/src/structs.h @@ -276,7 +276,7 @@ typedef struct User #ifdef BOTNET int modcount; - int guid; + uint16_t guid; int tick; int addsession; #endif /* BOTNET */ @@ -519,7 +519,7 @@ typedef struct Mech { struct Mech *next; - int guid; /* globally uniqe ID */ + uint16_t guid; /* globally uniqe ID */ int connect; int sock; struct in_addr ip; /* for DCC */ @@ -656,7 +656,7 @@ typedef struct BotInfo { struct BotInfo *next; - int guid; + uint16_t guid; int hops; char *version; @@ -678,7 +678,7 @@ typedef struct BotNet * they are copied partially in that order in net.c */ - int guid; /* remote bot guid */ + uint16_t guid; /* remote bot guid */ int lsid; /* local session id */ int rsid; /* remote session id */ @@ -709,7 +709,7 @@ typedef struct NetCfg { struct NetCfg *next; - int guid; + uint16_t guid; uint16_t port; uint16_t linked; //:1; @@ -762,7 +762,7 @@ typedef struct Hook struct Hook *next; int (*func)(); - int guid; /* guid filter */ + uint16_t guid; /* guid filter */ int flags; union { void *any; diff --git a/src/toybox.c b/src/toybox.c index cd1b208..4915226 100644 --- a/src/toybox.c +++ b/src/toybox.c @@ -29,6 +29,36 @@ #include "text.h" #include "mcmd.h" +#ifdef TRIVIA + +#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; + +#endif /* TRIVIA */ + #define BIGSAY_DEFAULTFONT "default" #define FONT_EXTENSION ".bigchars" @@ -160,12 +190,522 @@ int read_ascii(char *rest) to_user_q(global_from,FMT_PLAIN,rest); } +#ifdef TRIVIA + +/* + * + * trivia 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 = asc2int(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 = asc2int(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 (!stringcasecmp(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 */ + stringcpy(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,tmpname[120]; + off_t sz; + int fd,ifd; + int n; + struct + { + int off; + int sz; + + } entry; + + if (STRCHR(triv_qfile,'/') || strlen(triv_qfile) > 100) // really bad filenames... + return(NULL); + + stringcat(stringcpy(tmpname,"trivia/"),triv_qfile); + + if ((fd = open(tmpname,O_RDONLY)) < 0) +#ifdef DEBUG + { + debug("(random_question) %s: %s\n",tmpname,strerror(errno)); + return(NULL); + } +#else + return(NULL); +#endif /* DEBUG */ + + stringcpy(triv_rand,tmpname); + if ((p = STRCHR(triv_rand,'.')) == NULL) + p = STREND(triv_rand); + stringcpy(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); + if (read(ifd,&entry,sizeof(entry)) == -1) + return(NULL); + + lseek(fd,entry.off,SEEK_SET); + if (read(fd,triv_rand,entry.sz) == -1) + return(NULL); + + triv_rand[entry.sz] = 0; + + close(fd); + close(ifd); + + return(triv_rand); +} + +void trivia_question(void) +{ + char buffer[MSGLEN]; + 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); + + while((answer = get_token(&rest,MATCH_ALL))) + append_strp(&triv_answers,answer); + + 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 = asc2int(wk); + err = errno; + score_mo = asc2int(mo); + err += errno; + score_last_wk = asc2int(lwk); + err += errno; + score_last_mo = asc2int(lmo); + err += errno; + week_nr = asc2int(wnr); + err += errno; + month_nr = asc2int(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; + stringcpy(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 */ +} + +#endif /* TRIVIA */ + +/* +-+=====================================================================================================================+- + toybox.c commands +-+=====================================================================================================================+- +*/ + void do_bigsay(COMMAND_ARGS) { /* @@ -465,3 +1005,80 @@ pick_randnum: } #endif /* TOYBOX */ + +#ifdef TRIVIA + +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 (!stringcasecmp(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 (!stringcasecmp(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 (!stringcasecmp(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 */ diff --git a/src/trivia.c b/src/trivia.c deleted file mode 100644 index d04a6b8..0000000 --- a/src/trivia.c +++ /dev/null @@ -1,643 +0,0 @@ -/* - - 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 = asc2int(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 = asc2int(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 (!stringcasecmp(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 */ - stringcpy(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,tmpname[120]; - off_t sz; - int fd,ifd; - int n; - struct - { - int off; - int sz; - - } entry; - - if (STRCHR(triv_qfile,'/') || strlen(triv_qfile) > 100) // really bad filenames... - return(NULL); - - stringcat(stringcpy(tmpname,"trivia/"),triv_qfile); - - if ((fd = open(tmpname,O_RDONLY)) < 0) -#ifdef DEBUG - { - debug("(random_question) %s: %s\n",tmpname,strerror(errno)); - return(NULL); - } -#else - return(NULL); -#endif /* DEBUG */ - - stringcpy(triv_rand,tmpname); - if ((p = STRCHR(triv_rand,'.')) == NULL) - p = STREND(triv_rand); - stringcpy(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); - if (read(ifd,&entry,sizeof(entry)) == -1) - return(NULL); - - lseek(fd,entry.off,SEEK_SET); - if (read(fd,triv_rand,entry.sz) == -1) - return(NULL); - - triv_rand[entry.sz] = 0; - - close(fd); - close(ifd); - - return(triv_rand); -} - -void trivia_question(void) -{ - char buffer[MSGLEN]; - 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); - - while((answer = get_token(&rest,MATCH_ALL))) - append_strp(&triv_answers,answer); - - 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 = asc2int(wk); - err = errno; - score_mo = asc2int(mo); - err += errno; - score_last_wk = asc2int(lwk); - err += errno; - score_last_mo = asc2int(lmo); - err += errno; - week_nr = asc2int(wnr); - err += errno; - month_nr = asc2int(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; - stringcpy(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 (!stringcasecmp(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 (!stringcasecmp(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 (!stringcasecmp(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 */