compat.c compat.h \
conf.c conf.h \
dict-splay.c dict.h \
+ eventhooks.c eventhooks.h \
getopt.c getopt.h \
getopt1.c getopt.h \
gline.c gline.h \
slab_read_OBJECTS = $(am_slab_read_OBJECTS)
slab_read_LDADD = $(LDADD)
am_x3_OBJECTS = base64.$(OBJEXT) chanserv.$(OBJEXT) compat.$(OBJEXT) conf.$(OBJEXT) \
- dict-splay.$(OBJEXT) getopt.$(OBJEXT) getopt1.$(OBJEXT) \
+ dict-splay.$(OBJEXT) eventhooks.$(OBJEXT) getopt.$(OBJEXT) getopt1.$(OBJEXT) \
gline.$(OBJEXT) global.$(OBJEXT) hash.$(OBJEXT) heap.$(OBJEXT) \
helpfile.$(OBJEXT) ioset.$(OBJEXT) \
log.$(OBJEXT) main.$(OBJEXT) math.$(OBJEXT) md5.$(OBJEXT) \
compat.c compat.h \
conf.c conf.h \
dict-splay.c dict.h \
+ eventhooks.c eventhooks.h \
getopt.c getopt.h \
getopt1.c getopt.h \
gline.c gline.h \
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compat.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dict-splay.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eventhooks.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gline.Po@am__quote@
/*** COLOR *****/
if((word2) && strcasecmp(word1, "what") == 0 && ((strcasecmp(word2, "color") == 0) || (strcasecmp(word2, "colour") == 0)))
eightball(eb, 1, accum);
- else if((word3) && strcasecmp(word1, "what's") == 0 && strcasecmp(word2, "the") == 0 && ((strcasecmp(word2, "color") == 0) || (strcasecmp(word2, "colour") == 0)))
+ else if((word3) && strcasecmp(word1, "what's") == 0 && strcasecmp(word2, "the") == 0 && ((strcasecmp(word3, "color") == 0) || (strcasecmp(word3, "colour") == 0)))
eightball(eb, 1, accum);
- else if((word3) && strcasecmp(word1, "whats") == 0 && strcasecmp(word2, "the") == 0 && ((strcasecmp(word2, "color") == 0) || (strcasecmp(word2, "colour") == 0)))
+ else if((word3) && strcasecmp(word1, "whats") == 0 && strcasecmp(word2, "the") == 0 && ((strcasecmp(word3, "color") == 0) || (strcasecmp(word3, "colour") == 0)))
eightball(eb, 1, accum);
/*** LOCATION *****/
else if(
--- /dev/null
+/* eventhooks.c - Event hooks
+ * Copyright 2000-2024 Evilnet Development
+ *
+ * This file is part of x3.
+ *
+ * x3 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 3 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 srvx; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include "eventhooks.h"
+
+struct eh_func_list *init_hook_func_list(struct eh_func_list *list, int defpos) {
+ if ((defpos != EH_ADD_TAIL) && (defpos != EH_ADD_HEAD))
+ list->add_default = EH_ADD_TAIL;
+ else
+ list->add_default = defpos;
+ list->head = NULL;
+ list->tail = NULL;
+ list->count = 0;
+ list->clean = NULL;
+
+ return list;
+}
+
+void reg_hook_func_pos(struct eh_func_list *list, eh_func_t func, void *extra, int pos) {
+ struct eh_func *newehf = malloc(sizeof(struct eh_func));
+ int addpos = pos;
+
+ if ((addpos != EH_ADD_HEAD) && (addpos != EH_ADD_TAIL))
+ addpos = list->add_default;
+
+ if (newehf == NULL)
+ return;
+
+ newehf->next = NULL;
+ newehf->func = func;
+ newehf->extra = extra;
+
+ if (list->head == NULL) {
+ list->head = newehf;
+ list->tail = newehf;
+ } else if (addpos > 0) {
+ newehf->next = list->head;
+ list->head = newehf;
+ } else {
+ list->tail->next = newehf;
+ list->tail = newehf;
+ }
+ list->count++;
+}
+
+void reg_hook_func(struct eh_func_list *list, eh_func_t func, void *extra) {
+ reg_hook_func_pos(list, func, extra, EH_ADD_DEFAULT);
+}
+
+void unreg_hook_func(struct eh_func_list *list, eh_func_t func, void *extra) {
+ struct eh_func *ehfi = list->head;
+ struct eh_func *ehfr = NULL;
+
+ if (ehfi != NULL) {
+ if ((ehfi->func == func) && (ehfi->extra == extra)) {
+ list->head = ehfi->next;
+ if (list->tail == ehfi)
+ list->tail = NULL;
+ if (list->clean != NULL)
+ list->clean(ehfi);
+ free(ehfi);
+ list->count--;
+ } else {
+ for (ehfi=list->head; ehfi!=NULL; ehfi=ehfi->next) {
+ if (ehfi->next != NULL) {
+ if ((ehfi->next->func == func) && (ehfi->next->extra == extra)) {
+ ehfr = ehfi->next;
+ ehfi->next = ehfi->next->next;
+ if (list->tail == ehfr)
+ list->tail = ehfi;
+ if (list->clean != NULL)
+ list->clean(ehfr);
+ free(ehfr);
+ list->count--;
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+void free_hook_func_list(struct eh_func_list *list) {
+ struct eh_func *ehfi = NULL;
+ struct eh_func *ehfn = NULL;
+ int i = 0;
+
+ if (list->head == NULL)
+ return;
+
+ for (ehfi=list->head; ehfi!=NULL; ehfi=ehfn) {
+ ehfn = ehfi->next;
+
+ if (list->clean != NULL)
+ list->clean(ehfi);
+
+ free(ehfi);
+ i++;
+ }
+
+ assert(i==list->count);
+
+ list->head = NULL;
+ list->tail = NULL;
+ list->count = 0;
+}
+
+void call_hook_func_args(struct eh_func_list *list, void *callextra) {
+ struct eh_func *ehfi = NULL;
+
+ for (ehfi=list->head; ehfi!=NULL; ehfi=ehfi->next) {
+ if (ehfi->func(ehfi->extra, callextra) != EH_CONT)
+ break;
+ }
+}
+
+void call_hook_func_noargs(struct eh_func_list *list) {
+ call_hook_func_args(list, NULL);
+}
--- /dev/null
+/* eventhooks.h - Event hooks
+ * Copyright 2000-2024 Evilnet Development
+ *
+ * This file is part of x3.
+ *
+ * x3 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 3 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 srvx; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef INCLUDED_eventhooks_h
+#define INCLUDED_eventhooks_h
+
+#define EH_ADD_HEAD 1
+#define EH_ADD_TAIL -1
+#define EH_ADD_DEFAULT 0
+
+#define DEFINE_EH_FUNC_LIST(l, d, cf) struct eh_func_list l = {NULL, NULL, d, 0, cf}
+#define INIT_EH_FUNC_LIST(d) {NULL, NULL, d, 0}
+
+#define EH_CONT 0
+#define EH_STOP 1
+
+struct eh_func;
+
+typedef int (*eh_func_t) (void *extra, void *callextra);
+typedef void (*eh_clean_func_t) (struct eh_func *ehf);
+
+struct eh_func {
+ struct eh_func *next;
+ eh_func_t func;
+ void *extra;
+};
+
+struct eh_func_list {
+ struct eh_func *head;
+ struct eh_func *tail;
+ int add_default;
+ int count;
+ eh_clean_func_t clean;
+};
+
+struct eh_func_list *init_hook_func_list(struct eh_func_list *list, int defpos);
+void reg_hook_func(struct eh_func_list *list, eh_func_t func, void *extra);
+void reg_hook_func_pos(struct eh_func_list *list, eh_func_t func, void *extra, int pos);
+void unreg_hook_func(struct eh_func_list *list, eh_func_t func, void *extra);
+void free_hook_func_list(struct eh_func_list *list);
+void call_hook_func_noargs(struct eh_func_list *list);
+void call_hook_func_args(struct eh_func_list *list, void *callextra);
+
+#endif /* INCLUDED_eventhooks_h */
sif_used--;
}
-new_user_func_t *nuf_list;
-void **nuf_list_extra;
-unsigned int nuf_size = 0, nuf_used = 0;
+void
+nuf_free_ehf(struct eh_func *ehf)
+{
+ if (ehf->extra != NULL)
+ free(ehf->extra);
+}
+
+DEFINE_EH_FUNC_LIST(nuf_list, EH_ADD_TAIL, nuf_free_ehf);
+
+int
+nuf_wrapper(void *extra, void *callextra)
+{
+ struct funcargs *fa = (struct funcargs *)extra;
+ struct userNode *user = (struct userNode *)callextra;
+
+ ((new_user_func_t)fa->func)(user, fa->extra);
+
+ if (user->dead)
+ return EH_STOP;
+
+ return EH_CONT;
+}
+
+void
+reg_new_user_func_pos(new_user_func_t handler, void *extra, int pos)
+{
+ struct funcargs *fa = malloc(sizeof(struct funcargs));
+
+ fa->func = (void *)handler;
+ fa->extra = extra;
+
+ reg_hook_func_pos(&nuf_list, nuf_wrapper, (void *)fa, pos);
+}
void
reg_new_user_func(new_user_func_t handler, void *extra)
{
- if (nuf_used == nuf_size) {
- if (nuf_size) {
- nuf_size <<= 1;
- nuf_list = realloc(nuf_list, nuf_size*sizeof(new_user_func_t));
- nuf_list_extra = realloc(nuf_list_extra, nuf_size*sizeof(void*));
- } else {
- nuf_size = 8;
- nuf_list = malloc(nuf_size*sizeof(new_user_func_t));
- nuf_list_extra = malloc(nuf_size*sizeof(void*));
- }
- }
- nuf_list[nuf_used] = handler;
- nuf_list_extra[nuf_used++] = extra;
+ reg_new_user_func_pos(handler, extra, EH_ADD_DEFAULT);
}
void
call_new_user_funcs(struct userNode* user)
{
- unsigned int i;
-
- for (i = 0; i < nuf_used && !(user->dead); ++i)
- {
- nuf_list[i](user, nuf_list_extra[i]);
- }
+ call_hook_func_args(&nuf_list, (void *)user);
}
static nick_change_func_t *ncf2_list;
ncf_list_extra[ncf_used++] = extra;
}
-static join_func_t *jf_list;
-static void **jf_list_extra;
-static unsigned int jf_size = 0, jf_used = 0;
+void
+jf_free_ehf(struct eh_func *ehf)
+{
+ if (ehf->extra != NULL)
+ free(ehf->extra);
+}
+
+DEFINE_EH_FUNC_LIST(jf_list, EH_ADD_TAIL, jf_free_ehf);
+
+int
+jf_wrapper(void *extra, void *callextra)
+{
+ struct funcargs *fa = (struct funcargs *)extra;
+ struct modeNode *mNode = (struct modeNode *)callextra;
+ struct userNode *user = mNode->user;
+
+ ((join_func_t)fa->func)(mNode, fa->extra);
+
+ if (user->dead)
+ return EH_STOP;
+
+ return EH_CONT;
+}
+
+void
+reg_join_func_pos(join_func_t handler, void *extra, int pos)
+{
+ struct funcargs *fa = malloc(sizeof(struct funcargs));
+
+ fa->func = (void *)handler;
+ fa->extra = extra;
+
+ reg_hook_func_pos(&jf_list, jf_wrapper, (void *)fa, pos);
+}
void
reg_join_func(join_func_t handler, void *extra)
{
- if (jf_used == jf_size) {
- if (jf_size) {
- jf_size <<= 1;
- jf_list = realloc(jf_list, jf_size*sizeof(join_func_t));
- jf_list_extra = realloc(jf_list_extra, jf_size*sizeof(void*));
- } else {
- jf_size = 8;
- jf_list = malloc(jf_size*sizeof(join_func_t));
- jf_list_extra = malloc(jf_size*sizeof(void*));
- }
- }
- jf_list[jf_used] = handler;
- jf_list_extra[jf_used++] = extra;
+ reg_join_func_pos(handler, extra, EH_ADD_DEFAULT);
+}
+
+void
+call_join_funcs(struct modeNode *mNode)
+{
+ call_hook_func_args(&jf_list, (void *)mNode);
}
int rel_age;
AddChannelUser(struct userNode *user, struct chanNode* channel)
{
struct modeNode *mNode;
- unsigned int n;
mNode = GetUserMode(channel, user);
if (mNode)
irc_join(user, channel);
}
- for (n=0; (n<jf_used) && !user->dead; n++) {
- /* Callbacks return true if they kick or kill the user,
- * and we can continue without removing mNode. */
- if (jf_list[n](mNode, jf_list_extra[n]))
- return NULL;
- }
+ call_join_funcs(mNode);
return mNode;
}
free(slf_list);
free(slf_list_extra);
- free(nuf_list);
- free(nuf_list_extra);
+ free_hook_func_list(&nuf_list);
free(ncf2_list);
free(ncf2_list_extra);
free(duf_list);
free(duf_list_extra);
free(ncf_list);
free(ncf_list_extra);
- free(jf_list);
- free(jf_list_extra);
+ free_hook_func_list(&jf_list);
free(dcf_list);
free(dcf_list_extra);
free(pf_list);
#include "common.h"
#include "dict.h"
+#include "eventhooks.h"
#include "policer.h"
#include "recdb.h"
struct routeList *servers;
};
+/* generic hook function args */
+struct funcargs {
+ void *func;
+ void *extra;
+};
extern struct server *self;
extern dict_t channels;
typedef int (*new_user_func_t) (struct userNode *user, void *extra);
void reg_new_user_func(new_user_func_t handler, void *extra);
+void reg_new_user_func_pos(new_user_func_t handler, void *extra, int pos);
void call_new_user_funcs(struct userNode *user);
typedef void (*del_user_func_t) (struct userNode *user, struct userNode *killer, const char *why, void *extra);
void reg_del_user_func(del_user_func_t handler, void *extra);
typedef void (*new_channel_func_t) (struct chanNode *chan, void *extra);
void reg_new_channel_func(new_channel_func_t handler, void *extra);
typedef int (*join_func_t) (struct modeNode *mNode, void *extra);
+void reg_join_func_pos(join_func_t handler, void *extra, int pos);
void reg_join_func(join_func_t handler, void *extra);
typedef void (*del_channel_func_t) (struct chanNode *chan, void *extra);
void reg_del_channel_func(del_channel_func_t handler, void *extra);
reg_exit_func(snoop_cleanup, NULL);
conf_register_reload(snoop_conf_read);
reg_nick_change_func(snoop_nick_change, NULL);
- reg_join_func(snoop_join, NULL);
+ reg_join_func_pos(snoop_join, NULL, EH_ADD_HEAD);
reg_part_func(snoop_part, NULL);
reg_kick_func(snoop_kick, NULL);
- reg_new_user_func(snoop_new_user, NULL);
+ reg_new_user_func_pos(snoop_new_user, NULL, EH_ADD_HEAD);
reg_del_user_func(snoop_del_user, NULL);
reg_auth_func(snoop_auth, NULL);
reg_channel_mode_func(snoop_channel_mode, NULL);