diff options
-rw-r--r-- | Changes | 3 | ||||
-rw-r--r-- | docs/EVENTS | 153 | ||||
-rw-r--r-- | docs/WIN32.txt | 12 | ||||
-rw-r--r-- | include/events.h | 42 | ||||
-rw-r--r-- | include/extern.h | 5 | ||||
-rw-r--r-- | include/modules.h | 64 | ||||
-rw-r--r-- | include/services.h | 1 | ||||
-rw-r--r-- | makefile.inc.win32 | 9 | ||||
-rw-r--r-- | src/Makefile | 7 | ||||
-rw-r--r-- | src/botserv.c | 9 | ||||
-rw-r--r-- | src/chanserv.c | 7 | ||||
-rw-r--r-- | src/events.c | 779 | ||||
-rw-r--r-- | src/init.c | 3 | ||||
-rw-r--r-- | src/main.c | 10 | ||||
-rw-r--r-- | src/makefile.win32 | 10 | ||||
-rw-r--r-- | src/misc.c | 10 | ||||
-rw-r--r-- | src/modules/events.c | 53 | ||||
-rw-r--r-- | src/modules/makefile.inc.win32 | 2 | ||||
-rw-r--r-- | src/nickserv.c | 4 | ||||
-rw-r--r-- | src/process.c | 2 | ||||
-rw-r--r-- | src/send.c | 2 | ||||
-rw-r--r-- | src/users.c | 2 | ||||
-rw-r--r-- | version.log | 6 |
23 files changed, 1178 insertions, 17 deletions
@@ -1,8 +1,11 @@ Anope Version S V N ------------------- Provided by Anope Dev. <dev@anope.org> - 2005 +02/13 A Internal Event support, see EVENTS in the doc folder for help [ #00] 02/05 A Support for Unreal 3.2 +I channel mode. [ #00] 02/03 A Merged anope-win32 branch into the main, now Win32 ready. [ #00] +02/13 F nickIsServices() works if format is nick@services [ #00] +02/12 F Win32 builds can now build with encryption [ #00] 02/10 F mod_current_buffer was not set in all possible cases [#296] 02/07 F Updated userkey information in example.conf. [ #00] 02/06 F Win32 Module Load Errors. [#294] diff --git a/docs/EVENTS b/docs/EVENTS new file mode 100644 index 000000000..4d4819588 --- /dev/null +++ b/docs/EVENTS @@ -0,0 +1,153 @@ +Internal Events
+
+1. Intro
+2. Complex Events
+3. Triggered Events
+4. Triggered Events List
+
+==============================================================================================
+1. Introduction to Internal Events
+==============================================================================================
+
+ Internal Events are setup to give module developers more information about what the core
+is doing at different times. This information can be as complex as data we are feeding to the
+uplink, to simple triggered events such as the databases being saved. A list of triggered
+events can be found below. Additional there is a module included with the core which can
+provide some clue as to how to use the code in your modules. The rest of this document assumes
+that you are used to writting modules.
+
+==============================================================================================
+2. Complex Events
+==============================================================================================
+
+ This type of events are based around what happens when we talk to the IRCD, much like
+MESSAGE events that the IRCD sends to us. The events are triggered when Anope writes to the
+ircd. To watch for these events you must have some knowledge of how the IRCD command system
+works. In our example we will trap for NICK events.
+
+A. All functions most be formatted as
+
+ int functioname(char *source, int ac, char **av);
+
+B. In AnopeInit you must declare EvtMessage in some fashion, it is into this variable that
+ we will create the event handler. Here is what the base AnopeInit should look like at
+ this point.
+
+ int AnopeInit(int argc, char **argv)
+ {
+ EvtMessage *msg = NULL;
+ int status;
+
+ moduleAddAuthor(AUTHOR);
+ moduleAddVersion(VERSION);
+ return MOD_CONT;
+ }
+
+C. Pass "createEventHandler" the name of the message in this case NICK, and the function
+ that was created in Step A. At this point you should assign the return of
+ "createEventHandler" to the EvtMessage variable.
+
+ msg = createEventHandler("NICK", my_nick);
+
+D. The Handler is not ready for use, now you must add it to the hash, with
+ "moduleAddEventHandler", you will want to pass to this function the return
+ of "createEventHandler"
+
+ status = moduleAddEventHandler(msg);
+
+ it will return the module error code so you can confirm that it was added
+ correctly.
+
+E. With that setup in your function you will be passed 3 items. The source most of the time
+ this will be set to ServerName or NULL, consult our ircd documentation about how messages
+ are formatted. AC is the count of variables you will find in AV.
+
+ int my_nick(char *source, int ac, char **av)
+ {
+ alog("Internal Event - nick is %s",av[0]);
+ return MOD_CONT;
+ }
+
+==============================================================================================
+3. Triggered Events
+==============================================================================================
+
+ These events also known as "event hooks" are internal events such as expiring of nicks to
+the saving of databases.
+
+A. All functions most be formatted as
+
+ int functioname(char *message);
+
+B. In AnopeInit you must declare EvtHook in some fashion, it is into this variable that
+ we will create the event handler. Here is what the base AnopeInit should look like at
+ this point.
+
+ int AnopeInit(int argc, char **argv)
+ {
+ EvtHook *hook = NULL;
+ int status;
+
+ moduleAddAuthor(AUTHOR);
+ moduleAddVersion(VERSION);
+ return MOD_CONT;
+ }
+
+C. Pass "createEventHook" the name of the event, in this case we are going to hook to the
+ saving of databases, "EVENT_DB_SAVING"
+
+ hook = createEventHook(EVENT_DB_SAVING, my_save);
+
+D. The Handler is not ready for use, now you must add it to the hash, with
+ "moduleAddEventHook", you will want to pass to this function the return
+ of "createEventHook"
+
+ status = moduleAddEventHook(hook);
+
+ it will return the module error code so you can confirm that it was added
+ correctly.
+
+E. With that setup in your function you will be passed 1 items, the message is very simple
+ it could be as simple as a start, stop or message. In the case of saving it has a start
+ and stop
+
+ int my_save(char *source)
+ {
+
+ if (!stricmp(source, EVENT_START)) {
+ alog("Saving the databases! has started");
+ } else {
+ alog("Saving the databases is complete");
+ }
+ return MOD_CONT;
+ }
+
+==============================================================================================
+4. Triggered Events List
+==============================================================================================
+| Event Hook | Event Argument |
+==============================================================================================
+| EVENT_DB_SAVING | EVENT_START, EVENT_STOP |
+| EVENT_NEWNICK | Nick as it connected |
+| EVENT_BOT_UNASSIGN | Channel name |
+| EVENT_BOT_JOIN | Channel name |
+| EVENT_BOT_CREATE | Bot Nick |
+| EVENT_BOT_CHANGE | Bot Nick |
+| EVENT_BOT_DEL | Bot Nick |
+| EVENT_BOT_ASSIGN | Bot Nick |
+| EVENT_TOPIC_UPDATED | Channel Name |
+| EVENT_CHAN_EXPIRE | Channel Name |
+| EVENT_CHAN_REGISTERED | Channel Name |
+| EVENT_CHAN_DROP | Channel Name |
+| EVENT_CHAN_FORBIDDEN | Channel Name |
+| EVENT_CHAN_SUSPENDED | Channel Name |
+| EVENT_CONNECT | EVENT_START, EVENT_STOP |
+| EVENT_DB_EXPIRE | EVENT_START, EVENT_STOP |
+| EVENT_RESTART | EVENT_START |
+| EVENT_SHUTDOWN | EVENT_START, EVENT_STOP |
+| EVENT_SIGNAL | quit message |
+| EVENT_NICK_REGISTED | Nick |
+| EVENT_NICK_DROPPED | Nick |
+| EVENT_NICK_FORBIDDEN | Nick |
+| EVENT_CHANGE_NICK | Nick |
+==============================================================================================
\ No newline at end of file diff --git a/docs/WIN32.txt b/docs/WIN32.txt index 21adb7e41..b2caf96bf 100644 --- a/docs/WIN32.txt +++ b/docs/WIN32.txt @@ -53,16 +53,22 @@ the following free components from Microsoft. Once downloaded install these pack (ie.. PROXY_SCANNER=1), note the proxy scan is not the best and its recommended to use another thrid party scanner. - D. If you are using Visual Studio 6, this next line can be very important. If you are an + D. Do you want to use the MD5 message-digest algorithm to encrypt passwords? + (Selecting "yes" protects your passwords from being stolen if someone + gains access to the Services databases, but makes it impossible to recover + forgotten passwords. There is no way to reverse this operation, so make + sure you really want to enable it.). Change DB_ENCRYPTION to be equal to 1 + + E. If you are using Visual Studio 6, this next line can be very important. If you are an error during compile about "unresolved external symbol __ftol2", remove the # in front of VC6=/QIfist and attempt to compile again. - E. When compiling if you get an error about 'Cannot find wsock32.lib' or 'Cannot find + F. When compiling if you get an error about 'Cannot find wsock32.lib' or 'Cannot find msvcrt.lib' You need to define the libpath, in the LIBPATH directive. You can define the path one of two ways, either with \ or / if you use \ you must add a secondary \ so c:\mysql would be c:\\sdk\lib be sure to remove the # in front of LFLAGS - F. Most import is to set the DATDEST to be the folder name where data will be stored. + G. Most import is to set the DATDEST to be the folder name where data will be stored. This does not need to be the full path just the folder under the main executable in which data will exist. In our example we will use "data" diff --git a/include/events.h b/include/events.h new file mode 100644 index 000000000..7595d466d --- /dev/null +++ b/include/events.h @@ -0,0 +1,42 @@ +/* Prototypes and external variable declarations. + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for furhter details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id:$ + * + */ + +#define EVENT_START "start" +#define EVENT_STOP "stop" + +#define EVENT_DB_SAVING "db_saving" +#define EVENT_NEWNICK "newnick" +#define EVENT_BOT_UNASSIGN "bot_unassign" +#define EVENT_BOT_JOIN "bot_join" +#define EVENT_BOT_CREATE "bot_create" +#define EVENT_BOT_CHANGE "bot_change" +#define EVENT_BOT_DEL "bot_del" +#define EVENT_BOT_ASSIGN "bot_assign" +#define EVENT_TOPIC_UPDATED "chan_topic_updated" +#define EVENT_CHAN_EXPIRE "chan_expire" +#define EVENT_CHAN_REGISTERED "chan_registered" +#define EVENT_CHAN_DROP "chan_dropped" +#define EVENT_CHAN_FORBIDDEN "chan_forbidden" +#define EVENT_CHAN_SUSPENDED "chan_suspended" +#define EVENT_CHAN_UNSUSPEND "chan_unsuspend" +#define EVENT_CONNECT "connect" +#define EVENT_DB_EXPIRE "db_expire" +#define EVENT_RESTART "restart" +#define EVENT_SHUTDOWN "shutdown" +#define EVENT_SIGNAL "signal" +#define EVENT_NICK_REGISTED "nick_registered" +#define EVENT_NICK_DROPPED "nick_dropped" +#define EVENT_NICK_FORBIDDEN "nick_forbidden" +#define EVENT_CHANGE_NICK "change_nick" + diff --git a/include/extern.h b/include/extern.h index 40e275da2..58495a314 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1168,4 +1168,9 @@ E int decode_ip(char *buf); E char *host_resolve(char *host); +extern void event_message_process(char *eventbuf); +extern void eventprintf(char *fmt, ...); +extern void event_process_hook(char *name, char *eventbuf); +extern void send_event(char *name, const char *fmt, ...); + #endif /* EXTERN_H */ diff --git a/include/modules.h b/include/modules.h index 91bdb7a88..15e1cc1e1 100644 --- a/include/modules.h +++ b/include/modules.h @@ -62,6 +62,8 @@ typedef void * ano_module_t; #define OPERSERV OS_cmdTable #define IRCD IRCD_cmdTable #define MODULE_HASH Module_table +#define EVENT EVENT_cmdTable +#define EVENTHOOKS HOOK_cmdTable /********************************************************************** * Module Returns @@ -103,7 +105,10 @@ typedef struct ModuleHash_ ModuleHash; typedef struct Message_ Message; typedef struct MessageHash_ MessageHash; typedef struct ModuleCallBack_ ModuleCallBack; - +typedef struct EvtMessage_ EvtMessage; +typedef struct EvtMessageHash_ EvtMessageHash; +typedef struct EvtHook_ EvtHook; +typedef struct EvtHookHash_ EvtHookHash; extern MDE CommandHash *HOSTSERV[MAX_CMD_HASH]; extern MDE CommandHash *BOTSERV[MAX_CMD_HASH]; @@ -113,6 +118,8 @@ extern MDE CommandHash *CHANSERV[MAX_CMD_HASH]; extern MDE CommandHash *HELPSERV[MAX_CMD_HASH]; extern MDE CommandHash *OPERSERV[MAX_CMD_HASH]; extern MDE MessageHash *IRCD[MAX_CMD_HASH]; +extern EvtMessageHash *EVENT[MAX_CMD_HASH]; +extern EvtHookHash *EVENTHOOKS[MAX_CMD_HASH]; struct Module_ { char *name; @@ -202,6 +209,36 @@ struct ModuleCallBack_ { ModuleCallBack *next; }; +struct EvtMessage_ { + char *name; + int (*func)(char *source, int ac, char **av); + int core; + char *mod_name; + EvtMessage *next; +}; + +struct EvtMessageHash_ { + char *name; + EvtMessage *evm; + EvtMessageHash *next; +}; + + +struct EvtHook_ { + int (*func)(char *source); + int core; + char *name; + char *mod_name; + EvtHook *next; +}; + +struct EvtHookHash_ { + char *name; + EvtHook *evh; + EvtHookHash *next; +}; + + /*************************************************************************/ /* Module Managment Functions */ Module *createModule(char *filename); /* Create a new module, using the given name */ @@ -243,8 +280,9 @@ MDE int addCommand(CommandHash *cmdTable[], Command *c,int pos); MDE int delCommand(CommandHash *cmdTable[], Command *c,char *mod_name); /* Del a command from a cmd table */ MDE int moduleDelCommand(CommandHash *cmdTable[],char *name); /* Del a command from a cmd table */ Command *findCommand(CommandHash *cmdTable[], const char *name); /* Find a command */ + /*************************************************************************/ -/*************************************************************************/ + /* Message Managment Functions */ MDE Message *createMessage(char *name,int (*func)(char *source, int ac, char **av)); Message *findMessage(MessageHash *msgTable[], const char *name); /* Find a Message */ @@ -255,7 +293,29 @@ int delMessage(MessageHash *msgTable[], Message *m, char *mod_name); /* Del a M MDE int moduleDelMessage(char *name); int destroyMessage(Message *m); /* destroy a Message*/ Message *findMessage(MessageHash *msgTable[], const char *name); + /*************************************************************************/ + +MDE EvtMessage *createEventHandler(char *name, int (*func) (char *source, int ac, char **av)); +EvtMessage *findEventHandler(EvtMessageHash * msgEvtTable[], const char *name); +int addCoreEventHandler(EvtMessageHash * msgEvtTable[], EvtMessage * evm); +MDE int moduleAddEventHandler(EvtMessage * evm); +MDE int moduleEventDelHandler(char *name); +int delEventHandler(EvtMessageHash * msgEvtTable[], EvtMessage * evm, char *mod_name); +int destroyEventHandler(EvtMessage * evm); +int addEventHandler(EvtMessageHash * msgEvtTable[], EvtMessage * evm); + +MDE EvtHook *createEventHook(char *name, int (*func) (char *source)); +EvtHook *findEventHook(EvtHookHash * HookEvtTable[], const char *name); +int addCoreEventHook(EvtHookHash * HookEvtTable[], EvtHook * evh); +MDE int moduleAddEventHook(EvtHook * evh); +MDE int moduleEventDelHook(const char *name); +int delEventHook(EvtHookHash * HookEvtTable[], EvtHook * evh, char *mod_name); +int destroyEventHook(EvtHook * evh); +extern char *mod_current_evtbuffer; + +/*************************************************************************/ + MDE int moduleAddCallback(char *name,time_t when,int (*func)(int argc, char *argv[]),int argc, char **argv); MDE void moduleDelCallback(char *name); MDE void moduleCallBackRun(void); diff --git a/include/services.h b/include/services.h index 730c04f3d..b6a141a6f 100644 --- a/include/services.h +++ b/include/services.h @@ -177,6 +177,7 @@ extern int toupper(char), tolower(char); /* Miscellaneous definitions. */ #include "defs.h" #include "slist.h" +#include "events.h" /*************************************************************************/ diff --git a/makefile.inc.win32 b/makefile.inc.win32 index 5c6e4717b..8486f8139 100644 --- a/makefile.inc.win32 +++ b/makefile.inc.win32 @@ -40,6 +40,9 @@ USE_MYSQL=0 # Set this to 1 to enable the proxy scanner PROXY_SCANNER=0 +# Set this to 1 to enable the proxy scanner +DB_ENCRYPTION=0 + # If you want to change the names/locations of files/folders, you # can do that here. PROGRAM=anope.exe @@ -56,7 +59,7 @@ DATDEST=data LIBPATH= # If you edited the line above, uncomment the next line. -#LFLAGS=/LIBPATH:"$(LIBPATH)" +LFLAGS=/LIBPATH:"$(LIBPATH)" ############################################################### @@ -156,6 +159,10 @@ LIBS=$(LIBS) libmysql.lib zlib.lib BASE_CFLAGS=/D USE_THREADS $(BASE_CFLAGS) !ENDIF +!IF $(DB_ENCRYPTION) == 1 +BASE_CFLAGS=/D USE_ENCRYPTION $(BASE_CFLAGS) +!ENDIF + # Note that changing any of these options (or, in fact, anything in this # file) will automatically cause a full rebuild of Services. diff --git a/src/Makefile b/src/Makefile index 1e576a74a..f1c6a4169 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,13 +2,13 @@ MYSQL_OBJ = $(MYSQL:.c=.o) RDB_OBJ = $(RDB:.c=.o) IRCD_OBJ = $(IRCDFILE:.c=.o) OBJS = actions.o base64.o botserv.o channels.o chanserv.o commands.o compat.o converter.o \ - config.o datafiles.o encrypt.o helpserv.o hostserv.o init.o language.o list.o log.o mail.o main.o \ + config.o datafiles.o encrypt.o events.o helpserv.o hostserv.o init.o language.o list.o log.o mail.o main.o \ memory.o memoserv.o messages.o misc.o modules.o news.o nickserv.o operserv.o \ process.o proxy.o send.o servers.o sessions.o slist.o sockutil.o \ timeout.o users.o \ $(VSNPRINTF_O) $(RDB_OBJ) $(MYSQL_OBJ) $(IRCD_OBJ) SRCS = actions.c base64.c botserv.c channels.c chanserv.c commands.c compat.c converter.c \ - config.c datafiles.c encrypt.c helpserv.c hostserv.c init.c language.c list.c log.c mail.c main.c \ + config.c datafiles.c encrypt.c events.c helpserv.c hostserv.c init.c language.c list.c log.c mail.c main.c \ memory.c memoserv.c messages.c misc.c modules.c news.c nickserv.c operserv.c \ process.c proxy.c send.c servers.c sessions.c slist.c sockutil.c \ timeout.c users.c \ @@ -54,6 +54,7 @@ config.o: config.c $(INCLUDES) converter.o: converter.c $(INCLUDES) datafiles.o: datafiles.c $(INCLUDES) encrypt.o: encrypt.c $(INCLUDES) +events.o: events.c $(INCLUDES) init.o: init.c $(INCLUDES) helpserv.o: helpserv.c $(INCLUDES) hostserv.o: hostserv.c $(INCLUDES) @@ -65,7 +66,7 @@ main.o: main.c $(INCLUDES) memory.o: memory.c $(INCLUDES) memoserv.o: memoserv.c $(INCLUDES) messages.o: messages.c $(INCLUDES) -modules.o: modules.c $(INCLUDES) +modules.o: modules.c $(INCLUDES) misc.o: misc.c $(INCLUDES) news.o: news.c $(INCLUDES) nickserv.o: nickserv.c $(INCLUDES) diff --git a/src/botserv.c b/src/botserv.c index 1931b8f6c..6cfae0989 100644 --- a/src/botserv.c +++ b/src/botserv.c @@ -849,6 +849,8 @@ BotInfo *findbot(char *nick) static void unassign(User * u, ChannelInfo * ci) { + send_event(EVENT_BOT_UNASSIGN, ci->name); + if (ci->c && ci->c->usercount >= BSMinUsers) { anope_cmd_part(ci->bi->nick, ci->name, "UNASSIGN from %s", u->nick); @@ -995,6 +997,7 @@ void bot_join(ChannelInfo * ci) } anope_cmd_join(ci->bi->nick, ci->c->name, ci->c->creation_time); anope_cmd_bot_chan_mode(ci->bi->nick, ci->c->name); + send_event(EVENT_BOT_JOIN, ci->name); } /*************************************************************************/ @@ -1353,6 +1356,8 @@ static int do_bot(User * u) notice_lang(s_BotServ, u, BOT_BOT_ADDED, bi->nick, bi->user, bi->host, bi->real); + + send_event(EVENT_BOT_CREATE, bi->nick); } } else if (!stricmp(cmd, "CHANGE")) { char *oldnick = strtok(NULL, " "); @@ -1478,6 +1483,8 @@ static int do_bot(User * u) notice_lang(s_BotServ, u, BOT_BOT_CHANGED, oldnick, bi->nick, bi->user, bi->host, bi->real); + + send_event(EVENT_BOT_CHANGE, bi->nick); } } else if (!stricmp(cmd, "DEL")) { char *nick = strtok(NULL, " "); @@ -1489,6 +1496,7 @@ static int do_bot(User * u) else if (!(bi = findbot(nick))) notice_lang(s_BotServ, u, BOT_DOES_NOT_EXIST, nick); else { + send_event(EVENT_BOT_DEL, bi->nick); anope_cmd_quit(bi->nick, "Quit: Help! I'm being deleted by %s!", u->nick); @@ -1587,6 +1595,7 @@ static int do_assign(User * u) bot_join(ci); } notice_lang(s_BotServ, u, BOT_ASSIGN_ASSIGNED, bi->nick, ci->name); + send_event(EVENT_BOT_ASSIGN, bi->nick); } return MOD_CONT; } diff --git a/src/chanserv.c b/src/chanserv.c index ce8863133..30d794231 100644 --- a/src/chanserv.c +++ b/src/chanserv.c @@ -1740,6 +1740,7 @@ void record_topic(const char *chan) ci->last_topic = NULL; strscpy(ci->last_topic_setter, c->topic_setter, NICKMAX); ci->last_topic_time = c->topic_time; + send_event(EVENT_TOPIC_UPDATED, chan); } /*************************************************************************/ @@ -1871,6 +1872,7 @@ void expire_chans() next = ci->next; if (!ci->c && now - ci->last_used >= CSExpire && !(ci->flags & (CI_VERBOTEN | CI_NO_EXPIRE))) { + send_event(EVENT_CHAN_EXPIRE, ci->name); alog("Expiring channel %s (founder: %s)", ci->name, (ci->founder ? ci->founder->display : "(none)")); delchan(ci); @@ -2789,6 +2791,7 @@ static int do_register(User * u) anope_cmd_mode(s_ChanServ, chan, "%s %s", ircd->ownerset, u->nick); } + send_event(EVENT_CHAN_REGISTERED, chan); } return MOD_CONT; } @@ -2945,6 +2948,7 @@ static int do_drop(User * u) chan); notice_lang(s_ChanServ, u, CHAN_DROPPED, chan); + send_event(EVENT_CHAN_DROP, chan); } return MOD_CONT; } @@ -6371,6 +6375,7 @@ static int do_forbid(User * u) alog("%s: %s set FORBID for channel %s", s_ChanServ, u->nick, ci->name); notice_lang(s_ChanServ, u, CHAN_FORBID_SUCCEEDED, chan); + send_event(EVENT_CHAN_FORBIDDEN, chan); } else { alog("%s: Valid FORBID for %s by %s failed", s_ChanServ, ci->name, u->nick); @@ -6444,6 +6449,7 @@ static int do_suspend(User * u) alog("%s: %s set SUSPEND for channel %s", s_ChanServ, u->nick, ci->name); notice_lang(s_ChanServ, u, CHAN_SUSPEND_SUCCEEDED, chan); + send_event(EVENT_CHAN_SUSPENDED, chan); } else { alog("%s: Valid SUSPEND for %s by %s failed", s_ChanServ, ci->name, u->nick); @@ -6486,6 +6492,7 @@ static int do_unsuspend(User * u) alog("%s: %s set UNSUSPEND for channel %s", s_ChanServ, u->nick, ci->name); notice_lang(s_ChanServ, u, CHAN_UNSUSPEND_SUCCEEDED, chan); + send_event(EVENT_CHAN_UNSUSPEND, chan); } else { alog("%s: Valid UNSUSPEND for %s by %s failed", s_ChanServ, chan, u->nick); diff --git a/src/events.c b/src/events.c new file mode 100644 index 000000000..e4735efbf --- /dev/null +++ b/src/events.c @@ -0,0 +1,779 @@ +/* Events functions. + * + * (C) 2004-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * + */ + +#include "modules.h" +#include "language.h" +#include "version.h" + +extern Module *mod_current_module; +extern char *mod_current_module_name; +char *mod_current_evtbuffer = NULL; + +EvtMessageHash *EVENT[MAX_CMD_HASH]; +EvtHookHash *EVENTHOOKS[MAX_CMD_HASH]; + +EvtMessage *find_event(const char *name) +{ + EvtMessage *m; + m = findEventHandler(EVENT, name); + return m; +} + +EvtHook *find_eventhook(const char *name) +{ + EvtHook *m; + m = findEventHook(EVENTHOOKS, name); + return m; +} + +void send_event(char *name, const char *fmt, ...) +{ + va_list args; + char buf[16384]; /* Really huge, to try and avoid truncation */ + *buf = '\0'; + + if (fmt) { + va_start(args, fmt); + vsnprintf(buf, BUFSIZE - 1, fmt, args); + va_end(args); + } + event_process_hook(name, buf); +} + +void eventprintf(char *fmt, ...) +{ + va_list args; + char buf[16384]; /* Really huge, to try and avoid truncation */ + char *event; + + va_start(args, fmt); + vsnprintf(buf, sizeof(buf), fmt, args); + event = sstrdup(buf); + event_message_process(event); + va_end(args); + if (event) { + free(event); + } + return; +} + +void event_message_process(char *eventbuf) +{ + int retVal = 0; + EvtMessage *current = NULL; + char source[64]; + char cmd[64]; + char buf[512]; /* Longest legal IRC command line */ + char *s; + int ac; /* Parameters for the command */ + char **av; + EvtMessage *evm; + + /* zero out the buffers before we do much else */ + *buf = '\0'; + *source = '\0'; + *cmd = '\0'; + + strscpy(buf, eventbuf, sizeof(buf)); + + doCleanBuffer((char *) buf); + + /* Split the buffer into pieces. */ + if (*buf == ':') { + s = strpbrk(buf, " "); + if (!s) + return; + *s = 0; + while (isspace(*++s)); + strscpy(source, buf + 1, sizeof(source)); + memmove(buf, s, strlen(s) + 1); + } else { + *source = 0; + } + if (!*buf) + return; + s = strpbrk(buf, " "); + if (s) { + *s = 0; + while (isspace(*++s)); + } else + s = buf + strlen(buf); + strscpy(cmd, buf, sizeof(cmd)); + ac = split_buf(s, &av, 1); + + /* Do something with the message. */ + evm = find_event(cmd); + if (evm) { + if (evm->func) { + mod_current_module_name = evm->mod_name; + retVal = evm->func(source, ac, av); + mod_current_module_name = NULL; + if (retVal == MOD_CONT) { + current = evm->next; + while (current && current->func && retVal == MOD_CONT) { + mod_current_module_name = current->mod_name; + retVal = current->func(source, ac, av); + mod_current_module_name = NULL; + current = current->next; + } + } + } + } + /* Free argument list we created */ + free(av); +} + +void event_process_hook(char *name, char *eventbuf) +{ + int retVal = 0; + EvtHook *current = NULL; + EvtHook *evh; + if (mod_current_evtbuffer) { + free(mod_current_evtbuffer); + } + if (eventbuf) { + mod_current_evtbuffer = sstrdup(eventbuf); + } else { + mod_current_evtbuffer = NULL; + } + /* Do something with the message. */ + evh = find_eventhook(name); + if (evh) { + if (evh->func) { + mod_current_module_name = evh->mod_name; + retVal = evh->func(eventbuf); + mod_current_module_name = NULL; + if (retVal == MOD_CONT) { + current = evh->next; + while (current && current->func && retVal == MOD_CONT) { + mod_current_module_name = current->mod_name; + retVal = current->func(eventbuf); + mod_current_module_name = NULL; + current = current->next; + } + } + } + } +} + +/** + * Displays a message list for a given message. + * Again this is of little use other than debugging. + * @param m the message to display + * @return 0 is returned and has no meaning + */ +int displayEventMessage(EvtMessage * evm) +{ + EvtMessage *msg = NULL; + int i = 0; + alog("Displaying message list for %s", evm->name); + for (msg = evm; msg; msg = msg->next) { + alog("%d: 0x%p", ++i, (void *) msg); + } + alog("end"); + return 0; +} + +/** + * Displays a message list for a given message. + * Again this is of little use other than debugging. + * @param m the message to display + * @return 0 is returned and has no meaning + */ +int displayEventHook(EvtHook * evh) +{ + EvtHook *msg = NULL; + int i = 0; + alog("Displaying message list for %s", evh->name); + for (msg = evh; msg; msg = msg->next) { + alog("%d: 0x%p", ++i, (void *) msg); + } + alog("end"); + return 0; +} + +/** + * Display the message call stak. + * Prints the call stack for a message based on the message name, again useful for debugging and little lese :) + * @param name the name of the message to print info for + * @return the return int has no relevence atm :) + */ +int displayHookFromHash(char *name) +{ + EvtHookHash *current = NULL; + int index = 0; + index = CMD_HASH(name); + if (debug > 1) { + alog("trying to display message %s", name); + } + for (current = EVENTHOOKS[index]; current; current = current->next) { + if (stricmp(name, current->name) == 0) { + displayEventHook(current->evh); + } + } + if (debug > 1) { + alog("done displaying message %s", name); + } + return 0; +} + +/** + * Display the message call stak. + * Prints the call stack for a message based on the message name, again useful for debugging and little lese :) + * @param name the name of the message to print info for + * @return the return int has no relevence atm :) + */ +int displayEvtMessageFromHash(char *name) +{ + EvtMessageHash *current = NULL; + int index = 0; + index = CMD_HASH(name); + if (debug > 1) { + alog("trying to display message %s", name); + } + for (current = EVENT[index]; current; current = current->next) { + if (stricmp(name, current->name) == 0) { + displayEventMessage(current->evm); + } + } + if (debug > 1) { + alog("done displaying message %s", name); + } + return 0; +} + +/******************************************************************************* + * Message Functions + *******************************************************************************/ + + /** + * Create a new Message struct. + * @param name the name of the message + * @param func a pointer to the function to call when we recive this message + * @return a new Message object + **/ +EvtMessage *createEventHandler(char *name, + int (*func) (char *source, int ac, + char **av)) +{ + EvtMessage *evm = NULL; + if (!func) { + return NULL; + } + if ((evm = malloc(sizeof(EvtMessage))) == NULL) { + fatal("Out of memory!"); + } + evm->name = sstrdup(name); + evm->func = func; + evm->mod_name = NULL; + evm->next = NULL; + return evm; +} + + /** + * Create a new Message struct. + * @param name the name of the message + * @param func a pointer to the function to call when we recive this message + * @return a new Message object + **/ +EvtHook *createEventHook(char *name, int (*func) (char *message)) +{ + EvtHook *evh = NULL; + if (!func) { + return NULL; + } + if ((evh = malloc(sizeof(EvtHook))) == NULL) { + fatal("Out of memory!"); + } + evh->name = sstrdup(name); + evh->func = func; + evh->mod_name = NULL; + evh->next = NULL; + return evh; +} + +/** + * find a message in the given table. + * Looks up the message <name> in the MessageHash given + * @param MessageHash the message table to search for this command, will almost always be IRCD + * @param name the name of the command were looking for + * @return NULL if we cant find it, or a pointer to the Message if we can + **/ +EvtMessage *findEventHandler(EvtMessageHash * msgEvtTable[], + const char *name) +{ + int idx; + EvtMessageHash *current = NULL; + if (!msgEvtTable || !name) { + return NULL; + } + idx = CMD_HASH(name); + + for (current = msgEvtTable[idx]; current; current = current->next) { + if (stricmp(name, current->name) == 0) { + return current->evm; + } + } + return NULL; +} + +/** + * find a message in the given table. + * Looks up the message <name> in the MessageHash given + * @param MessageHash the message table to search for this command, will almost always be IRCD + * @param name the name of the command were looking for + * @return NULL if we cant find it, or a pointer to the Message if we can + **/ +EvtHook *findEventHook(EvtHookHash * hookEvtTable[], const char *name) +{ + int idx; + EvtHookHash *current = NULL; + if (!hookEvtTable || !name) { + return NULL; + } + idx = CMD_HASH(name); + + for (current = hookEvtTable[idx]; current; current = current->next) { + if (stricmp(name, current->name) == 0) { + return current->evh; + } + } + return NULL; +} + +/** + * Add the given message (m) to the MessageHash marking it as a core command + * @param msgTable the MessageHash we want to add to + * @param m the Message we are adding + * @return MOD_ERR_OK on a successful add. + **/ +int addCoreEventHandler(EvtMessageHash * msgEvtTable[], EvtMessage * evm) +{ + if (!msgEvtTable || !evm) { + return MOD_ERR_PARAMS; + } + evm->core = 1; + return addEventHandler(msgEvtTable, evm); +} + +/** + * Add a message to the MessageHash. + * @param msgTable the MessageHash we want to add a message to + * @param m the Message we want to add + * @return MOD_ERR_OK on a successful add. + **/ +int addEventHandler(EvtMessageHash * msgEvtTable[], EvtMessage * evm) +{ + /* We can assume both param's have been checked by this point.. */ + int index = 0; + EvtMessageHash *current = NULL; + EvtMessageHash *newHash = NULL; + EvtMessageHash *lastHash = NULL; + + if (!msgEvtTable || !evm) { + return MOD_ERR_PARAMS; + } + + index = CMD_HASH(evm->name); + + for (current = msgEvtTable[index]; current; current = current->next) { + if (stricmp(evm->name, current->name) == 0) { /* the msg exist's we are a addHead */ + evm->next = current->evm; + current->evm = evm; + if (debug) + alog("existing msg: (0x%p), new msg (0x%p)", + (void *) evm->next, (void *) evm); + return MOD_ERR_OK; + } + lastHash = current; + } + + if ((newHash = malloc(sizeof(EvtMessageHash))) == NULL) { + fatal("Out of memory"); + } + newHash->next = NULL; + newHash->name = sstrdup(evm->name); + newHash->evm = evm; + + if (lastHash == NULL) + msgEvtTable[index] = newHash; + else + lastHash->next = newHash; + return MOD_ERR_OK; +} + +/** + * Add a message to the MessageHash. + * @param msgTable the MessageHash we want to add a message to + * @param m the Message we want to add + * @return MOD_ERR_OK on a successful add. + **/ +int addEventHook(EvtHookHash * hookEvtTable[], EvtHook * evh) +{ + /* We can assume both param's have been checked by this point.. */ + int index = 0; + EvtHookHash *current = NULL; + EvtHookHash *newHash = NULL; + EvtHookHash *lastHash = NULL; + + if (!hookEvtTable || !evh) { + return MOD_ERR_PARAMS; + } + + index = CMD_HASH(evh->name); + + for (current = hookEvtTable[index]; current; current = current->next) { + if (stricmp(evh->name, current->name) == 0) { /* the msg exist's we are a addHead */ + evh->next = current->evh; + current->evh = evh; + if (debug) + alog("existing msg: (0x%p), new msg (0x%p)", + (void *) evh->next, (void *) evh); + return MOD_ERR_OK; + } + lastHash = current; + } + + if ((newHash = malloc(sizeof(EvtHookHash))) == NULL) { + fatal("Out of memory"); + } + newHash->next = NULL; + newHash->name = sstrdup(evh->name); + newHash->evh = evh; + + if (lastHash == NULL) + hookEvtTable[index] = newHash; + else + lastHash->next = newHash; + return MOD_ERR_OK; +} + +/** + * Add the given message (m) to the MessageHash marking it as a core command + * @param msgTable the MessageHash we want to add to + * @param m the Message we are adding + * @return MOD_ERR_OK on a successful add. + **/ +int addCoreEventHook(EvtHookHash * hookEvtTable[], EvtHook * evh) +{ + if (!hookEvtTable || !evh) { + return MOD_ERR_PARAMS; + } + evh->core = 1; + return addEventHook(hookEvtTable, evh); +} + +/** + * Add a module message to the IRCD message hash + * @param m the Message to add + * @param pos the Position to add the message to, e.g. MOD_HEAD, MOD_TAIL, MOD_UNIQUE + * @return MOD_ERR_OK on success, althing else on fail. + **/ +int moduleAddEventHandler(EvtMessage * evm) +{ + int status; + + if (!evm) { + return MOD_ERR_PARAMS; + } + + /* ok, this appears to be a module adding a message from outside of AnopeInit, try to look up its module struct for it */ + if ((mod_current_module_name) && (!mod_current_module)) { + mod_current_module = findModule(mod_current_module_name); + } + + if (!mod_current_module) { + return MOD_ERR_UNKNOWN; + } /* shouldnt happen */ + evm->core = 0; + if (!evm->mod_name) { + evm->mod_name = sstrdup(mod_current_module->name); + } + + status = addEventHandler(EVENT, evm); + if (debug) { + displayEvtMessageFromHash(evm->name); + } + return status; +} + +/** + * Add a module message to the IRCD message hash + * @param m the Message to add + * @param pos the Position to add the message to, e.g. MOD_HEAD, MOD_TAIL, MOD_UNIQUE + * @return MOD_ERR_OK on success, althing else on fail. + **/ +int moduleAddEventHook(EvtHook * evh) +{ + int status; + + if (!evh) { + return MOD_ERR_PARAMS; + } + + if ((mod_current_module_name) && (!mod_current_module)) { + mod_current_module = findModule(mod_current_module_name); + } + + if (!mod_current_module) { + return MOD_ERR_UNKNOWN; + } /* shouldnt happen */ + evh->core = 0; + if (!evh->mod_name) { + evh->mod_name = sstrdup(mod_current_module->name); + } + + status = addEventHook(EVENTHOOKS, evh); + if (debug) { + displayHookFromHash(evh->name); + } + return status; +} + +/** + * remove the given message from the IRCD message hash + * @param name the name of the message to remove + * @return MOD_ERR_OK on success, althing else on fail. + **/ +int moduleEventDelHandler(char *name) +{ + EvtMessage *evm; + int status; + + if (!mod_current_module) { + return MOD_ERR_UNKNOWN; + } + evm = findEventHandler(EVENT, name); + if (!evm) { + return MOD_ERR_NOEXIST; + } + + status = delEventHandler(EVENT, evm, mod_current_module->name); + if (debug) { + displayEvtMessageFromHash(evm->name); + } + return status; +} + +/** + * remove the given message from the IRCD message hash + * @param name the name of the message to remove + * @return MOD_ERR_OK on success, althing else on fail. + **/ +int moduleEventDelHook(const char *name) +{ + EvtHook *evh; + int status; + + if (!mod_current_module) { + return MOD_ERR_UNKNOWN; + } + evh = findEventHook(EVENTHOOKS, name); + if (!evh) { + return MOD_ERR_NOEXIST; + } + + status = delEventHook(EVENTHOOKS, evh, mod_current_module->name); + if (debug) { + displayHookFromHash(evh->name); + } + return status; +} + +/** + * remove the given message from the given message hash, for the given module + * @param msgTable which MessageHash we are removing from + * @param m the Message we want to remove + * @mod_name the name of the module we are removing + * @return MOD_ERR_OK on success, althing else on fail. + **/ +int delEventHandler(EvtMessageHash * msgEvtTable[], EvtMessage * evm, + char *mod_name) +{ + int index = 0; + EvtMessageHash *current = NULL; + EvtMessageHash *lastHash = NULL; + EvtMessage *tail = NULL, *last = NULL; + + if (!evm || !msgEvtTable) { + return MOD_ERR_PARAMS; + } + + index = CMD_HASH(evm->name); + + for (current = msgEvtTable[index]; current; current = current->next) { + if (stricmp(evm->name, current->name) == 0) { + if (!lastHash) { + tail = current->evm; + if (tail->next) { + while (tail) { + if (mod_name && tail->mod_name + && (stricmp(mod_name, tail->mod_name) == 0)) { + if (last) { + last->next = tail->next; + } else { + current->evm = tail->next; + } + return MOD_ERR_OK; + } + last = tail; + tail = tail->next; + } + } else { + msgEvtTable[index] = current->next; + free(current->name); + return MOD_ERR_OK; + } + } else { + tail = current->evm; + if (tail->next) { + while (tail) { + if (mod_name && tail->mod_name + && (stricmp(mod_name, tail->mod_name) == 0)) { + if (last) { + last->next = tail->next; + } else { + current->evm = tail->next; + } + return MOD_ERR_OK; + } + last = tail; + tail = tail->next; + } + } else { + lastHash->next = current->next; + free(current->name); + return MOD_ERR_OK; + } + } + } + lastHash = current; + } + return MOD_ERR_NOEXIST; +} + + +/** + * remove the given message from the given message hash, for the given module + * @param msgTable which MessageHash we are removing from + * @param m the Message we want to remove + * @mod_name the name of the module we are removing + * @return MOD_ERR_OK on success, althing else on fail. + **/ +int delEventHook(EvtHookHash * hookEvtTable[], EvtHook * evh, + char *mod_name) +{ + int index = 0; + EvtHookHash *current = NULL; + EvtHookHash *lastHash = NULL; + EvtHook *tail = NULL, *last = NULL; + + if (!evh || !hookEvtTable) { + return MOD_ERR_PARAMS; + } + + index = CMD_HASH(evh->name); + + for (current = hookEvtTable[index]; current; current = current->next) { + if (stricmp(evh->name, current->name)) { + if (!lastHash) { + tail = current->evh; + if (tail->next) { + while (tail) { + if (mod_name && tail->mod_name + && (stricmp(mod_name, tail->mod_name) == 0)) { + if (last) { + last->next = tail->next; + } else { + current->evh = tail->next; + } + return MOD_ERR_OK; + } + last = tail; + tail = tail->next; + } + } else { + hookEvtTable[index] = current->next; + free(current->name); + return MOD_ERR_OK; + } + } else { + tail = current->evh; + if (tail->next) { + while (tail) { + if (mod_name && tail->mod_name + && (stricmp(mod_name, tail->mod_name) == 0)) { + if (last) { + last->next = tail->next; + } else { + current->evh = tail->next; + } + return MOD_ERR_OK; + } + last = tail; + tail = tail->next; + } + } else { + lastHash->next = current->next; + free(current->name); + return MOD_ERR_OK; + } + } + } + lastHash = current; + } + return MOD_ERR_NOEXIST; +} + + +/** + * Destory a message, freeing its memory. + * @param m the message to be destroyed + * @return MOD_ERR_SUCCESS on success + **/ +int destroyEventHandler(EvtMessage * evm) +{ + if (!evm) { + return MOD_ERR_PARAMS; + } + if (evm->name) { + free(evm->name); + } + evm->func = NULL; + if (evm->mod_name) { + free(evm->mod_name); + } + evm->next = NULL; + return MOD_ERR_OK; +} + +/** + * Destory a message, freeing its memory. + * @param m the message to be destroyed + * @return MOD_ERR_SUCCESS on success + **/ +int destroyEventHook(EvtHook * evh) +{ + if (!evh) { + return MOD_ERR_PARAMS; + } + if (evh->name) { + free(evh->name); + } + evh->func = NULL; + if (evh->mod_name) { + free(evh->mod_name); + } + evh->next = NULL; + return MOD_ERR_OK; +} diff --git a/src/init.c b/src/init.c index e26378dfb..37725437d 100644 --- a/src/init.c +++ b/src/init.c @@ -683,6 +683,8 @@ int init(int ac, char **av) alog("Info: Not reflecting database records."); } #endif + send_event(EVENT_CONNECT, EVENT_START); + /* Connect to the remote server */ servsock = conn(RemoteServer, RemotePort, LocalHost, LocalPort); if (servsock < 0 && RemoteServer2) { @@ -715,6 +717,7 @@ int init(int ac, char **av) } anope_cmd_connect(servernum); + send_event(EVENT_CONNECT, EVENT_STOP); sgets2(inbuf, sizeof(inbuf), servsock); if (strnicmp(inbuf, "ERROR", 5) == 0) { diff --git a/src/main.c b/src/main.c index d75a88f00..e3786bbd6 100644 --- a/src/main.c +++ b/src/main.c @@ -101,6 +101,7 @@ static int started = 0; extern void expire_all(void) { + send_event(EVENT_DB_EXPIRE, EVENT_START); waiting = -3; if (debug) alog("debug: Running expire routines"); @@ -131,12 +132,15 @@ extern void expire_all(void) if (ProxyDetect) proxy_expire(); #endif + send_event(EVENT_DB_EXPIRE, EVENT_STOP); } /*************************************************************************/ void save_databases(void) { + send_event(EVENT_DB_SAVING, EVENT_START); + waiting = -2; if (debug) alog("debug: Saving FFF databases"); @@ -207,6 +211,7 @@ void save_databases(void) } } #endif + send_event(EVENT_DB_SAVING, EVENT_STOP); } /*************************************************************************/ @@ -216,6 +221,7 @@ void save_databases(void) static void services_restart(void) { alog("Restarting"); + send_event(EVENT_RESTART, EVENT_START); if (!quitmsg) quitmsg = "Restarting"; anope_cmd_squit(ServerName, quitmsg); @@ -255,6 +261,8 @@ static void services_shutdown(void) { User *u, *next; + send_event(EVENT_SHUTDOWN, EVENT_START); + if (!quitmsg) quitmsg = "Terminating, reason unknown"; alog("%s", quitmsg); @@ -272,6 +280,7 @@ static void services_shutdown(void) u = next; } } + send_event(EVENT_SHUTDOWN, EVENT_STOP); disconn(servsock); } @@ -430,6 +439,7 @@ void sighandler(int signum) if (signum == SIGSEGV) { do_backtrace(1); } + send_event(EVENT_SIGNAL, quitmsg); if (started) { services_shutdown(); diff --git a/src/makefile.win32 b/src/makefile.win32 index e7434cdba..64bf75eea 100644 --- a/src/makefile.win32 +++ b/src/makefile.win32 @@ -18,16 +18,16 @@ include ../Makefile.inc.win32 ########################################################################### OBJS = actions.obj base64.obj botserv.obj channels.obj chanserv.obj commands.obj compat.obj \ - converter.obj config.obj datafiles.obj encrypt.obj helpserv.obj hostserv.obj \ + converter.obj config.obj datafiles.obj encrypt.obj events.obj helpserv.obj hostserv.obj \ init.obj language.obj list.obj log.obj mail.obj main.obj memory.obj memoserv.obj \ messages.obj misc.obj modules.obj news.obj nickserv.obj operserv.obj \ process.obj proxy.obj send.obj servers.obj sessions.obj slist.obj sockutil.obj \ timeout.obj users.obj $(RDB_O) $(MYSQL_O) $(CAPAB_O) SRCS = actions.c base64.c botserv.c channels.c chanserv.c commands.c compat.c converter.c \ - config.c datafiles.c encrypt.c helpserv.c hostserv.c init.c language.c list.c log.c mail.c main.c \ - memory.c memoserv.c messages.c misc.c modules.c news.c nickserv.c operserv.c \ - process.c proxy.c send.c servers.obj sessions.c slist.c sockutil.c \ + config.c datafiles.c encrypt.c events.c helpserv.c hostserv.c init.c language.c list.c \ + log.c mail.c main.c memory.c memoserv.c messages.c misc.c modules.c news.c nickserv.c \ + operserv.c process.c proxy.c send.c servers.obj sessions.c slist.c sockutil.c \ timeout.c users.c $(RDB_C) $(MYSQL_C) $(CAPAB_C) ########################################################################### @@ -69,6 +69,7 @@ config.obj: config.c ..\include\services.h converter.obj: converter.c ..\include\services.h ..\include\datafiles.h datafiles.obj: datafiles.c ..\include\services.h ..\include\datafiles.h encrypt.obj: encrypt.c ..\include\encrypt.h ..\include\sysconf.h +events.obj: events.c ..\include\modules.h ..\include\language.h ..\include\version.h init.obj: init.c ..\include\services.h hostserv.obj: hostserv.c ..\include\services.h ..\include\pseudo.h language.obj: language.c ..\include\services.h ..\include\language.h @@ -79,6 +80,7 @@ main.obj: main.c ..\include\services.h ..\include\ memory.obj: memory.c ..\include\services.h memoserv.obj: memoserv.c ..\include\services.h ..\include\pseudo.h messages.obj: messages.c ..\include\services.h ..\include\messages.h ..\include\language.h +modules.obj: modules.c ..\include\modules.h ..\include\language.h ..\include\version.h misc.obj: misc.c ..\include\services.h ..\include\language.h news.obj: news.c ..\include\services.h ..\include\pseudo.h nickserv.obj: nickserv.c ..\include\services.h ..\include\pseudo.h diff --git a/src/misc.c b/src/misc.c index c1c2c7f7d..97b1af506 100644 --- a/src/misc.c +++ b/src/misc.c @@ -814,9 +814,17 @@ void EnforceQlinedNick(char *nick, char *killer) int nickIsServices(char *nick, int bot) { int found = 0; + char *s; if (!nick) { - return found; + return found; + } + + s = strchr(nick, '@'); + if (s) { + *s++ = 0; + if (stricmp(s, ServerName) != 0) + return found; } if (s_NickServ && (stricmp(nick, s_NickServ) == 0)) diff --git a/src/modules/events.c b/src/modules/events.c new file mode 100644 index 000000000..af53a3d40 --- /dev/null +++ b/src/modules/events.c @@ -0,0 +1,53 @@ +/** + * Simple module to show the usage of event messages and hooks + * This module is an example, and has no useful purpose! + * + * Please visit http://modules.anope.org for useful modules! + * + **/ + +#include "module.h" + +#define AUTHOR "Anope" +#define VERSION "1.1" + +int my_nick(char *source, int ac, char **av); +int my_save(char *message); + +int AnopeInit(int argc, char **argv) +{ + EvtMessage *msg = NULL; + EvtHook *hook = NULL; + int status; + msg = createEventHandler("NICK", my_nick); + status = moduleAddEventHandler(msg); + + hook = createEventHook(EVENT_DB_SAVING, my_save); + status = moduleAddEventHook(hook); + + moduleAddAuthor(AUTHOR); + moduleAddVersion(VERSION); + return MOD_CONT; +} + +void AnopeFini(void) +{ + /* unloading */ +} + +int my_nick(char *source, int ac, char **av) +{ + alog("Internal Event - nick is %s",av[0]); + return MOD_CONT; +} + +int my_save(char *message) +{ + if (!stricmp(message, EVENT_START)) { + alog("Saving the databases! has started"); + } else { + alog("Saving the databases is complete"); + } + return MOD_CONT; +} + diff --git a/src/modules/makefile.inc.win32 b/src/modules/makefile.inc.win32 index 95c0c84b1..f97acfd3d 100644 --- a/src/modules/makefile.inc.win32 +++ b/src/modules/makefile.inc.win32 @@ -1,2 +1,2 @@ -SRCS=hs_moo.c ircd_catserv.c +SRCS=hs_moo.c ircd_catserv.c events.c diff --git a/src/nickserv.c b/src/nickserv.c index bf8d5cd99..a3a81f5ab 100644 --- a/src/nickserv.c +++ b/src/nickserv.c @@ -2306,6 +2306,7 @@ static int do_confirm(User * u) else notice_lang(s_NickServ, u, NICK_REGISTERED_NO_MASK, u->nick); + send_event(EVENT_NICK_REGISTED, u->nick); #ifndef USE_ENCRYPTION notice_lang(s_NickServ, u, NICK_PASSWORD_IS, na->nc->pass); #endif @@ -2804,6 +2805,8 @@ static int do_drop(User * u) (na->nc->email ? na->nc->email : "none")); delnick(na); + send_event(EVENT_NICK_DROPPED, nick); + if (!is_mine) { if (WallDrop) anope_cmd_global(s_NickServ, "\2%s\2 used DROP on \2%s\2", @@ -4282,6 +4285,7 @@ static int do_forbid(User * u) alog("%s: %s set FORBID for nick %s", s_NickServ, u->nick, nick); notice_lang(s_NickServ, u, NICK_FORBID_SUCCEEDED, nick); + send_event(EVENT_NICK_FORBIDDEN, nick); } else { alog("%s: Valid FORBID for %s by %s failed", s_NickServ, nick, u->nick); diff --git a/src/process.c b/src/process.c index d4ea8b29e..f1e97fbed 100644 --- a/src/process.c +++ b/src/process.c @@ -246,7 +246,7 @@ void process() av[0] to see if its a service nick if so assign mod_current_buffer the value from AV[1] else just assign av[0] - TSL */ if (av[0]) { - if (nickIsServices(av[0], 0)) { + if (nickIsServices(av[0], 1)) { if (av[1]) { mod_current_buffer = sstrdup(av[1]); } else { diff --git a/src/send.c b/src/send.c index e30bbd88a..1ea115518 100644 --- a/src/send.c +++ b/src/send.c @@ -58,11 +58,13 @@ void vsend_cmd(const char *source, const char *fmt, va_list args) if (source) { sockprintf(servsock, ":%s %s\r\n", source, buf); + eventprintf(":%s %s", source, buf); if (debug) { alog("debug: Sent: :%s %s", source, buf); } } else { sockprintf(servsock, "%s\r\n", buf); + eventprintf("%s", buf); if (debug) { alog("debug: Sent: %s", buf); } diff --git a/src/users.c b/src/users.c index 1979f0283..85c89648c 100644 --- a/src/users.c +++ b/src/users.c @@ -645,6 +645,7 @@ User *do_nick(const char *source, char *nick, char *username, char *host, } else { user->svid = 1; } + send_event(EVENT_NEWNICK, nick); } else { /* An old user changing nicks. */ @@ -685,6 +686,7 @@ User *do_nick(const char *source, char *nick, char *username, char *host, } change_user_nick(user, nick); + send_event(EVENT_CHANGE_NICK, nick); if ((old_na ? old_na->nc : NULL) == (user->na ? user->na->nc : NULL)) diff --git a/version.log b/version.log index 03b53fc0c..e0817915e 100644 --- a/version.log +++ b/version.log @@ -8,10 +8,14 @@ VERSION_MAJOR="1" VERSION_MINOR="7" VERSION_PATCH="8" -VERSION_BUILD="573" +VERSION_BUILD="574" # $Log$ # +# BUILD : 1.7.8 (574) +# BUGS : N/A +# NOTES : Internal Events, Win32 can build with encryption, nickIsServices() works if format is nick@services +# # BUILD : 1.7.8 (573) # BUGS : 296 # NOTES : mod_current_buffer was not set in all possible cases |