diff options
Diffstat (limited to 'src')
-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 |
14 files changed, 890 insertions, 10 deletions
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)) |