Anope IRC Services  Version 1.8
events.c
Go to the documentation of this file.
1 /* Events functions.
2  *
3  * (C) 2004-2014 Anope Team
4  * Contact us at team@anope.org
5  *
6  * Please read COPYING and README for further details.
7  *
8  * Based on the original code of Epona by Lara.
9  * Based on the original code of Services by Andy Church.
10  *
11  *
12  */
13 
14 #include "modules.h"
15 #include "language.h"
16 #include "version.h"
17 
18 char *mod_current_evtbuffer = NULL;
19 
22 
23 EvtMessage *find_event(const char *name)
24 {
25  EvtMessage *m;
26  m = findEventHandler(EVENT, name);
27  return m;
28 }
29 
30 EvtHook *find_eventhook(const char *name)
31 {
32  EvtHook *m;
33  m = findEventHook(EVENTHOOKS, name);
34  return m;
35 }
36 
37 void send_event(const char *name, int argc, ...)
38 {
39  va_list va;
40  char *a;
41  int idx = 0;
42  char **argv;
43 
44  argv = (char **) malloc(sizeof(char *) * argc);
45  va_start(va, argc);
46  for (idx = 0; idx < argc; idx++) {
47  a = va_arg(va, char *);
48  argv[idx] = sstrdup(a);
49  }
50  va_end(va);
51 
52  if (debug)
53  alog("debug: Emitting event \"%s\" (%d args)", name, argc);
54 
55  event_process_hook(name, argc, argv);
56 
60  for (idx = 0; idx < argc; idx++) {
61  free(argv[idx]);
62  }
63  free(argv);
64 }
65 
66 void eventprintf(char *fmt, ...)
67 {
68  va_list args;
69  char buf[16384]; /* Really huge, to try and avoid truncation */
70  char *event;
71 
72  va_start(args, fmt);
73  vsnprintf(buf, sizeof(buf), fmt, args);
74  event = sstrdup(buf);
75  event_message_process(event);
76  va_end(args);
77  if (event) {
78  free(event);
79  }
80  return;
81 }
82 
83 void event_message_process(char *eventbuf)
84 {
85  int retVal = 0;
86  EvtMessage *current = NULL;
87  char source[64];
88  char cmd[64];
89  char buf[512]; /* Longest legal IRC command line */
90  char *s;
91  int ac; /* Parameters for the command */
92  char **av;
93  EvtMessage *evm;
94 
95  /* zero out the buffers before we do much else */
96  *buf = '\0';
97  *source = '\0';
98  *cmd = '\0';
99 
100  strscpy(buf, eventbuf, sizeof(buf));
101 
102  doCleanBuffer((char *) buf);
103 
104  /* Split the buffer into pieces. */
105  if (*buf == ':') {
106  s = strpbrk(buf, " ");
107  if (!s)
108  return;
109  *s = 0;
110  while (isspace(*++s));
111  strscpy(source, buf + 1, sizeof(source));
112  memmove(buf, s, strlen(s) + 1);
113  } else {
114  *source = 0;
115  }
116  if (!*buf)
117  return;
118  s = strpbrk(buf, " ");
119  if (s) {
120  *s = 0;
121  while (isspace(*++s));
122  } else
123  s = buf + strlen(buf);
124  strscpy(cmd, buf, sizeof(cmd));
125  ac = split_buf(s, &av, 1);
126 
127  /* Do something with the message. */
128  evm = find_event(cmd);
129  if (evm) {
130  char *mod_current_module_name_save = mod_current_module_name;
131  Module *mod_current_module_save = mod_current_module;
132  if (evm->func) {
135  retVal = evm->func(source, ac, av);
136  if (retVal == MOD_CONT) {
137  current = evm->next;
138  while (current && current->func && retVal == MOD_CONT) {
141  retVal = current->func(source, ac, av);
142  current = current->next;
143  }
144  }
145  mod_current_module_name = mod_current_module_name_save;
146  mod_current_module = mod_current_module_save;
147  }
148  }
149  /* Free argument list we created */
150  free(av);
151 }
152 
153 void event_process_hook(const char *name, int argc, char **argv)
154 {
155  int retVal = 0;
156  EvtHook *current = NULL;
157  EvtHook *evh;
158  if (mod_current_evtbuffer) {
159  free(mod_current_evtbuffer);
160  }
161  /* Do something with the message. */
162  evh = find_eventhook(name);
163  if (evh) {
164  if (evh->func) {
165  char *mod_current_module_name_save = mod_current_module_name;
166  Module *mod_current_module_save = mod_current_module;
169  retVal = evh->func(argc, argv);
170  if (retVal == MOD_CONT) {
171  current = evh->next;
172  while (current && current->func && retVal == MOD_CONT) {
175  retVal = current->func(argc, argv);
176  current = current->next;
177  }
178  }
179  mod_current_module_name = mod_current_module_name_save;
180  mod_current_module = mod_current_module_save;
181  }
182  }
183 }
184 
192 {
193  EvtMessage *msg = NULL;
194  int i = 0;
195  alog("Displaying message list for %s", evm->name);
196  for (msg = evm; msg; msg = msg->next) {
197  alog("%d: 0x%p", ++i, (void *) msg);
198  }
199  alog("end");
200  return 0;
201 }
202 
210 {
211  EvtHook *msg = NULL;
212  int i = 0;
213  alog("Displaying message list for %s", evh->name);
214  for (msg = evh; msg; msg = msg->next) {
215  alog("%d: 0x%p", ++i, (void *) msg);
216  }
217  alog("end");
218  return 0;
219 }
220 
227 int displayHookFromHash(char *name)
228 {
229  EvtHookHash *current = NULL;
230  int index = 0;
231  index = CMD_HASH(name);
232  if (debug > 1) {
233  alog("debug: trying to display message %s", name);
234  }
235  for (current = EVENTHOOKS[index]; current; current = current->next) {
236  if (stricmp(name, current->name) == 0) {
237  displayEventHook(current->evh);
238  }
239  }
240  if (debug > 1) {
241  alog("debug: done displaying message %s", name);
242  }
243  return 0;
244 }
245 
253 {
254  EvtMessageHash *current = NULL;
255  int index = 0;
256  index = CMD_HASH(name);
257  if (debug > 1) {
258  alog("debug: trying to display message %s", name);
259  }
260  for (current = EVENT[index]; current; current = current->next) {
261  if (stricmp(name, current->name) == 0) {
262  displayEventMessage(current->evm);
263  }
264  }
265  if (debug > 1) {
266  alog("debug: done displaying message %s", name);
267  }
268  return 0;
269 }
270 
271 /*******************************************************************************
272  * Message Functions
273  *******************************************************************************/
274 
282  int (*func) (char *source, int ac,
283  char **av))
284 {
285  EvtMessage *evm = NULL;
286  if (!func) {
287  return NULL;
288  }
289  if ((evm = malloc(sizeof(EvtMessage))) == NULL) {
290  fatal("Out of memory!");
291  }
292  evm->name = sstrdup(name);
293  evm->func = func;
294  evm->mod_name = NULL;
295  evm->next = NULL;
296  return evm;
297 }
298 
305 EvtHook *createEventHook(char *name, int (*func) (int argc, char **argv))
306 {
307  EvtHook *evh = NULL;
308  if (!func) {
309  return NULL;
310  }
311  if ((evh = malloc(sizeof(EvtHook))) == NULL) {
312  fatal("Out of memory!");
313  }
314  evh->name = sstrdup(name);
315  evh->func = func;
316  evh->mod_name = NULL;
317  evh->next = NULL;
318  return evh;
319 }
320 
329  const char *name)
330 {
331  int idx;
332  EvtMessageHash *current = NULL;
333  if (!msgEvtTable || !name) {
334  return NULL;
335  }
336  idx = CMD_HASH(name);
337 
338  for (current = msgEvtTable[idx]; current; current = current->next) {
339  if (stricmp(name, current->name) == 0) {
340  return current->evm;
341  }
342  }
343  return NULL;
344 }
345 
353 EvtHook *findEventHook(EvtHookHash * hookEvtTable[], const char *name)
354 {
355  int idx;
356  EvtHookHash *current = NULL;
357  if (!hookEvtTable || !name) {
358  return NULL;
359  }
360  idx = CMD_HASH(name);
361 
362  for (current = hookEvtTable[idx]; current; current = current->next) {
363  if (stricmp(name, current->name) == 0) {
364  return current->evh;
365  }
366  }
367  return NULL;
368 }
369 
376 int addCoreEventHandler(EvtMessageHash * msgEvtTable[], EvtMessage * evm)
377 {
378  if (!msgEvtTable || !evm) {
379  return MOD_ERR_PARAMS;
380  }
381  evm->core = 1;
382  return addEventHandler(msgEvtTable, evm);
383 }
384 
391 int addEventHandler(EvtMessageHash * msgEvtTable[], EvtMessage * evm)
392 {
393  /* We can assume both param's have been checked by this point.. */
394  int index = 0;
395  EvtMessageHash *current = NULL;
396  EvtMessageHash *newHash = NULL;
397  EvtMessageHash *lastHash = NULL;
398 
399  if (!msgEvtTable || !evm) {
400  return MOD_ERR_PARAMS;
401  }
402 
403  index = CMD_HASH(evm->name);
404 
405  for (current = msgEvtTable[index]; current; current = current->next) {
406  if (stricmp(evm->name, current->name) == 0) { /* the msg exist's we are a addHead */
407  evm->next = current->evm;
408  current->evm = evm;
409  if (debug)
410  alog("debug: existing msg: (0x%p), new msg (0x%p)",
411  (void *) evm->next, (void *) evm);
412  return MOD_ERR_OK;
413  }
414  lastHash = current;
415  }
416 
417  if ((newHash = malloc(sizeof(EvtMessageHash))) == NULL) {
418  fatal("Out of memory");
419  }
420  newHash->next = NULL;
421  newHash->name = sstrdup(evm->name);
422  newHash->evm = evm;
423 
424  if (lastHash == NULL)
425  msgEvtTable[index] = newHash;
426  else
427  lastHash->next = newHash;
428  return MOD_ERR_OK;
429 }
430 
437 int addEventHook(EvtHookHash * hookEvtTable[], EvtHook * evh)
438 {
439  /* We can assume both param's have been checked by this point.. */
440  int index = 0;
441  EvtHookHash *current = NULL;
442  EvtHookHash *newHash = NULL;
443  EvtHookHash *lastHash = NULL;
444 
445  if (!hookEvtTable || !evh) {
446  return MOD_ERR_PARAMS;
447  }
448 
449  index = CMD_HASH(evh->name);
450 
451  for (current = hookEvtTable[index]; current; current = current->next) {
452  if (stricmp(evh->name, current->name) == 0) { /* the msg exist's we are a addHead */
453  evh->next = current->evh;
454  current->evh = evh;
455  if (debug)
456  alog("debug: existing msg: (0x%p), new msg (0x%p)",
457  (void *) evh->next, (void *) evh);
458  return MOD_ERR_OK;
459  }
460  lastHash = current;
461  }
462 
463  if ((newHash = malloc(sizeof(EvtHookHash))) == NULL) {
464  fatal("Out of memory");
465  }
466  newHash->next = NULL;
467  newHash->name = sstrdup(evh->name);
468  newHash->evh = evh;
469 
470  if (lastHash == NULL)
471  hookEvtTable[index] = newHash;
472  else
473  lastHash->next = newHash;
474  return MOD_ERR_OK;
475 }
476 
483 int addCoreEventHook(EvtHookHash * hookEvtTable[], EvtHook * evh)
484 {
485  if (!hookEvtTable || !evh) {
486  return MOD_ERR_PARAMS;
487  }
488  evh->core = 1;
489  return addEventHook(hookEvtTable, evh);
490 }
491 
499 {
500  int status;
501 
502  if (!evm) {
503  return MOD_ERR_PARAMS;
504  }
505 
506  if (!mod_current_module) {
507  return MOD_ERR_UNKNOWN;
508  } /* shouldnt happen */
509 
510  evm->core = 0;
511  if (!evm->mod_name) {
513  }
514 
515  status = addEventHandler(EVENT, evm);
516  if (debug) {
518  }
519  return status;
520 }
521 
529 {
530  int status;
531 
532  if (!evh) {
533  return MOD_ERR_PARAMS;
534  }
535 
536  if (!mod_current_module) {
537  return MOD_ERR_UNKNOWN;
538  } /* shouldnt happen */
539 
540  evh->core = 0;
541  if (!evh->mod_name) {
543  }
544 
545  status = addEventHook(EVENTHOOKS, evh);
546  if (debug) {
548  }
549  return status;
550 }
551 
557 int moduleEventDelHandler(char *name)
558 {
559  EvtMessage *evm;
560  int status;
561 
562  if (!mod_current_module) {
563  return MOD_ERR_UNKNOWN;
564  }
565  evm = findEventHandler(EVENT, name);
566  if (!evm) {
567  return MOD_ERR_NOEXIST;
568  }
569 
570  status = delEventHandler(EVENT, evm, mod_current_module->name);
571  if (debug) {
573  }
574  destroyEventHandler(evm);
575  return status;
576 }
577 
583 int moduleEventDelHook(const char *name)
584 {
585  EvtHook *evh;
586  int status;
587 
588  if (!mod_current_module) {
589  return MOD_ERR_UNKNOWN;
590  }
591  evh = findEventHook(EVENTHOOKS, name);
592  if (!evh) {
593  return MOD_ERR_NOEXIST;
594  }
595 
596  status = delEventHook(EVENTHOOKS, evh, mod_current_module->name);
597  if (debug) {
599  }
600  destroyEventHook(evh);
601  return status;
602 }
603 
611 int delEventHandler(EvtMessageHash * msgEvtTable[], EvtMessage * evm,
612  char *mod_name)
613 {
614  int index = 0;
615  EvtMessageHash *current = NULL;
616  EvtMessageHash *lastHash = NULL;
617  EvtMessage *tail = NULL, *last = NULL;
618 
619  if (!evm || !msgEvtTable) {
620  return MOD_ERR_PARAMS;
621  }
622 
623  index = CMD_HASH(evm->name);
624 
625  for (current = msgEvtTable[index]; current; current = current->next) {
626  if (stricmp(evm->name, current->name) == 0) {
627  if (!lastHash) {
628  tail = current->evm;
629  if (tail->next) {
630  while (tail) {
631  if (mod_name && tail->mod_name
632  && (stricmp(mod_name, tail->mod_name) == 0)) {
633  if (last) {
634  last->next = tail->next;
635  } else {
636  current->evm = tail->next;
637  }
638  return MOD_ERR_OK;
639  }
640  last = tail;
641  tail = tail->next;
642  }
643  } else {
644  msgEvtTable[index] = current->next;
645  free(current->name);
646  free(current);
647  return MOD_ERR_OK;
648  }
649  } else {
650  tail = current->evm;
651  if (tail->next) {
652  while (tail) {
653  if (mod_name && tail->mod_name
654  && (stricmp(mod_name, tail->mod_name) == 0)) {
655  if (last) {
656  last->next = tail->next;
657  } else {
658  current->evm = tail->next;
659  }
660  return MOD_ERR_OK;
661  }
662  last = tail;
663  tail = tail->next;
664  }
665  } else {
666  lastHash->next = current->next;
667  free(current->name);
668  free(current);
669  return MOD_ERR_OK;
670  }
671  }
672  }
673  lastHash = current;
674  }
675  return MOD_ERR_NOEXIST;
676 }
677 
678 
686 int delEventHook(EvtHookHash * hookEvtTable[], EvtHook * evh,
687  char *mod_name)
688 {
689  int index = 0;
690  EvtHookHash *current = NULL;
691  EvtHookHash *lastHash = NULL;
692  EvtHook *tail = NULL, *last = NULL;
693 
694  if (!evh || !hookEvtTable) {
695  return MOD_ERR_PARAMS;
696  }
697 
698  index = CMD_HASH(evh->name);
699 
700  for (current = hookEvtTable[index]; current; current = current->next) {
701  if (stricmp(evh->name, current->name) == 0) {
702  if (!lastHash) {
703  tail = current->evh;
704  if (tail->next) {
705  while (tail) {
706  if (mod_name && tail->mod_name
707  && (stricmp(mod_name, tail->mod_name) == 0)) {
708  if (last) {
709  last->next = tail->next;
710  } else {
711  current->evh = tail->next;
712  }
713  return MOD_ERR_OK;
714  }
715  last = tail;
716  tail = tail->next;
717  }
718  } else {
719  hookEvtTable[index] = current->next;
720  free(current->name);
721  free(current);
722  return MOD_ERR_OK;
723  }
724  } else {
725  tail = current->evh;
726  if (tail->next) {
727  while (tail) {
728  if (mod_name && tail->mod_name
729  && (stricmp(mod_name, tail->mod_name) == 0)) {
730  if (last) {
731  last->next = tail->next;
732  } else {
733  current->evh = tail->next;
734  }
735  return MOD_ERR_OK;
736  }
737  last = tail;
738  tail = tail->next;
739  }
740  } else {
741  lastHash->next = current->next;
742  free(current->name);
743  free(current);
744  return MOD_ERR_OK;
745  }
746  }
747  }
748  lastHash = current;
749  }
750  return MOD_ERR_NOEXIST;
751 }
752 
753 
760 {
761  if (!evm) {
762  return MOD_ERR_PARAMS;
763  }
764  if (evm->name) {
765  free(evm->name);
766  }
767  evm->func = NULL;
768  if (evm->mod_name) {
769  free(evm->mod_name);
770  }
771  evm->next = NULL;
772  free(evm);
773  return MOD_ERR_OK;
774 }
775 
782 {
783  if (!evh) {
784  return MOD_ERR_PARAMS;
785  }
786  if (evh->name) {
787  free(evh->name);
788  }
789  evh->func = NULL;
790  if (evh->mod_name) {
791  free(evh->mod_name);
792  }
793  evh->next = NULL;
794  free(evh);
795  return MOD_ERR_OK;
796 }
char * mod_current_evtbuffer
Definition: events.c:18
void send_event(const char *name, int argc,...)
Definition: events.c:37
E void doCleanBuffer(char *str)
Definition: misc.c:800
int core
Definition: modules.h:238
int moduleEventDelHandler(char *name)
Definition: events.c:557
static Channel * current
Definition: channels.c:427
int core
Definition: modules.h:252
int delEventHook(EvtHookHash *hookEvtTable[], EvtHook *evh, char *mod_name)
Definition: events.c:686
void event_message_process(char *eventbuf)
Definition: events.c:83
char * mod_name
Definition: modules.h:254
EvtHook * evh
Definition: modules.h:260
void eventprintf(char *fmt,...)
Definition: events.c:66
int delEventHandler(EvtMessageHash *msgEvtTable[], EvtMessage *evm, char *mod_name)
Definition: events.c:611
#define MAX_CMD_HASH
Definition: modules.h:51
int(* func)(char *source, int ac, char **av)
Definition: modules.h:237
EvtHook * next
Definition: modules.h:255
E int stricmp(const char *s1, const char *s2)
Definition: compat.c:58
int displayEventHook(EvtHook *evh)
Definition: events.c:209
char * name
Definition: modules.h:259
EvtMessage * next
Definition: modules.h:240
char * name
Definition: modules.h:244
EvtHookHash * EVENTHOOKS[MAX_CMD_HASH]
Definition: events.c:21
int addCoreEventHook(EvtHookHash *hookEvtTable[], EvtHook *evh)
Definition: events.c:483
char * mod_name
Definition: modules.h:239
EvtMessageHash * next
Definition: modules.h:246
EvtHook * find_eventhook(const char *name)
Definition: events.c:30
E char * strscpy(char *d, const char *s, size_t len)
Definition: db-merger.c:1886
int addEventHook(EvtHookHash *hookEvtTable[], EvtHook *evh)
Definition: events.c:437
int destroyEventHook(EvtHook *evh)
Definition: events.c:781
EvtMessage * find_event(const char *name)
Definition: events.c:23
E char * sstrdup(const char *s)
Definition: memory.c:105
E void E void E void fatal(const char *fmt,...) FORMAT(printf
int moduleAddEventHandler(EvtMessage *evm)
Definition: events.c:498
MDE Module * findModule(char *name)
Definition: modules.c:473
EvtHook * createEventHook(char *name, int(*func)(int argc, char **argv))
Definition: events.c:305
int(* func)(int argc, char **argv)
Definition: modules.h:251
#define MOD_ERR_PARAMS
Definition: modules.h:73
char * name
Definition: modules.h:236
int moduleEventDelHook(const char *name)
Definition: events.c:583
int displayHookFromHash(char *name)
Definition: events.c:227
int addCoreEventHandler(EvtMessageHash *msgEvtTable[], EvtMessage *evm)
Definition: events.c:376
E void alog(const char *fmt,...) FORMAT(printf
#define MOD_ERR_OK
Definition: modules.h:71
#define MOD_ERR_NOEXIST
Definition: modules.h:75
#define MOD_CONT
Definition: modules.h:54
char * name
Definition: modules.h:137
E int debug
Definition: extern.h:775
E int split_buf(char *buf, char ***argv, int colon_special)
Definition: process.c:270
void event_process_hook(const char *name, int argc, char **argv)
Definition: events.c:153
EvtMessageHash * EVENT[MAX_CMD_HASH]
Definition: events.c:20
MDE Module * mod_current_module
Definition: modules.c:52
EvtMessage * createEventHandler(char *name, int(*func)(char *source, int ac, char **av))
Definition: events.c:281
E int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
EvtHookHash * next
Definition: modules.h:261
char * name
Definition: modules.h:253
int addEventHandler(EvtMessageHash *msgEvtTable[], EvtMessage *evm)
Definition: events.c:391
int moduleAddEventHook(EvtHook *evh)
Definition: events.c:528
EvtMessage * findEventHandler(EvtMessageHash *msgEvtTable[], const char *name)
Definition: events.c:328
int destroyEventHandler(EvtMessage *evm)
Definition: events.c:759
#define MOD_ERR_UNKNOWN
Definition: modules.h:81
EvtMessage * evm
Definition: modules.h:245
#define CMD_HASH(x)
Definition: modules.h:50
EvtHook * findEventHook(EvtHookHash *hookEvtTable[], const char *name)
Definition: events.c:353
int displayEvtMessageFromHash(char *name)
Definition: events.c:252
MDE char * mod_current_module_name
Definition: modules.c:53
int displayEventMessage(EvtMessage *evm)
Definition: events.c:191