events.c

Go to the documentation of this file.
00001 /* Events functions.
00002  *
00003  * (C) 2004-2013 Anope Team
00004  * Contact us at team@anope.org
00005  *
00006  * Please read COPYING and README for further details.
00007  *
00008  * Based on the original code of Epona by Lara.
00009  * Based on the original code of Services by Andy Church. 
00010  * 
00011  *
00012  */
00013 
00014 #include "modules.h"
00015 #include "language.h"
00016 #include "version.h"
00017 
00018 char *mod_current_evtbuffer = NULL;
00019 
00020 EvtMessageHash *EVENT[MAX_CMD_HASH];
00021 EvtHookHash *EVENTHOOKS[MAX_CMD_HASH];
00022 
00023 EvtMessage *find_event(const char *name)
00024 {
00025     EvtMessage *m;
00026     m = findEventHandler(EVENT, name);
00027     return m;
00028 }
00029 
00030 EvtHook *find_eventhook(const char *name)
00031 {
00032     EvtHook *m;
00033     m = findEventHook(EVENTHOOKS, name);
00034     return m;
00035 }
00036 
00037 void send_event(const char *name, int argc, ...)
00038 {
00039     va_list va;
00040     char *a;
00041     int idx = 0;
00042     char **argv;
00043 
00044     argv = (char **) malloc(sizeof(char *) * argc);
00045     va_start(va, argc);
00046     for (idx = 0; idx < argc; idx++) {
00047         a = va_arg(va, char *);
00048         argv[idx] = sstrdup(a);
00049     }
00050     va_end(va);
00051 
00052     if (debug)
00053         alog("debug: Emitting event \"%s\" (%d args)", name, argc);
00054 
00055     event_process_hook(name, argc, argv);
00056 
00060     for (idx = 0; idx < argc; idx++) {
00061         free(argv[idx]);
00062     }
00063     free(argv);
00064 }
00065 
00066 void eventprintf(char *fmt, ...)
00067 {
00068     va_list args;
00069     char buf[16384];            /* Really huge, to try and avoid truncation */
00070     char *event;
00071 
00072     va_start(args, fmt);
00073     vsnprintf(buf, sizeof(buf), fmt, args);
00074     event = sstrdup(buf);
00075     event_message_process(event);
00076     va_end(args);
00077     if (event) {
00078         free(event);
00079     }
00080     return;
00081 }
00082 
00083 void event_message_process(char *eventbuf)
00084 {
00085     int retVal = 0;
00086     EvtMessage *current = NULL;
00087     char source[64];
00088     char cmd[64];
00089     char buf[512];              /* Longest legal IRC command line */
00090     char *s;
00091     int ac;                     /* Parameters for the command */
00092     char **av;
00093     EvtMessage *evm;
00094 
00095     /* zero out the buffers before we do much else */
00096     *buf = '\0';
00097     *source = '\0';
00098     *cmd = '\0';
00099 
00100     strscpy(buf, eventbuf, sizeof(buf));
00101 
00102     doCleanBuffer((char *) buf);
00103 
00104     /* Split the buffer into pieces. */
00105     if (*buf == ':') {
00106         s = strpbrk(buf, " ");
00107         if (!s)
00108             return;
00109         *s = 0;
00110         while (isspace(*++s));
00111         strscpy(source, buf + 1, sizeof(source));
00112         memmove(buf, s, strlen(s) + 1);
00113     } else {
00114         *source = 0;
00115     }
00116     if (!*buf)
00117         return;
00118     s = strpbrk(buf, " ");
00119     if (s) {
00120         *s = 0;
00121         while (isspace(*++s));
00122     } else
00123         s = buf + strlen(buf);
00124     strscpy(cmd, buf, sizeof(cmd));
00125     ac = split_buf(s, &av, 1);
00126 
00127     /* Do something with the message. */
00128     evm = find_event(cmd);
00129     if (evm) {
00130         char *mod_current_module_name_save = mod_current_module_name;
00131         Module *mod_current_module_save = mod_current_module;
00132         if (evm->func) {
00133             mod_current_module_name = evm->mod_name;
00134             mod_current_module = findModule(evm->mod_name);
00135             retVal = evm->func(source, ac, av);
00136             if (retVal == MOD_CONT) {
00137                 current = evm->next;
00138                 while (current && current->func && retVal == MOD_CONT) {
00139                     mod_current_module_name = current->mod_name;
00140                     mod_current_module = findModule(current->mod_name);
00141                     retVal = current->func(source, ac, av);
00142                     current = current->next;
00143                 }
00144             }
00145             mod_current_module_name = mod_current_module_name_save;
00146             mod_current_module = mod_current_module_save;
00147         }
00148     }
00149     /* Free argument list we created */
00150     free(av);
00151 }
00152 
00153 void event_process_hook(const char *name, int argc, char **argv)
00154 {
00155     int retVal = 0;
00156     EvtHook *current = NULL;
00157     EvtHook *evh;
00158     if (mod_current_evtbuffer) {
00159         free(mod_current_evtbuffer);
00160     }
00161     /* Do something with the message. */
00162     evh = find_eventhook(name);
00163     if (evh) {
00164         if (evh->func) {
00165             char *mod_current_module_name_save = mod_current_module_name;
00166             Module *mod_current_module_save = mod_current_module;
00167             mod_current_module = findModule(evh->mod_name);
00168             mod_current_module_name = evh->mod_name;
00169             retVal = evh->func(argc, argv);
00170             if (retVal == MOD_CONT) {
00171                 current = evh->next;
00172                 while (current && current->func && retVal == MOD_CONT) {
00173                     mod_current_module = findModule(current->mod_name);
00174                     mod_current_module_name = current->mod_name;
00175                     retVal = current->func(argc, argv);
00176                     current = current->next;
00177                 }
00178             }
00179             mod_current_module_name = mod_current_module_name_save;
00180             mod_current_module = mod_current_module_save;
00181         }
00182     }
00183 }
00184 
00191 int displayEventMessage(EvtMessage * evm)
00192 {
00193     EvtMessage *msg = NULL;
00194     int i = 0;
00195     alog("Displaying message list for %s", evm->name);
00196     for (msg = evm; msg; msg = msg->next) {
00197         alog("%d: 0x%p", ++i, (void *) msg);
00198     }
00199     alog("end");
00200     return 0;
00201 }
00202 
00209 int displayEventHook(EvtHook * evh)
00210 {
00211     EvtHook *msg = NULL;
00212     int i = 0;
00213     alog("Displaying message list for %s", evh->name);
00214     for (msg = evh; msg; msg = msg->next) {
00215         alog("%d: 0x%p", ++i, (void *) msg);
00216     }
00217     alog("end");
00218     return 0;
00219 }
00220 
00227 int displayHookFromHash(char *name)
00228 {
00229     EvtHookHash *current = NULL;
00230     int index = 0;
00231     index = CMD_HASH(name);
00232     if (debug > 1) {
00233         alog("debug: trying to display message %s", name);
00234     }
00235     for (current = EVENTHOOKS[index]; current; current = current->next) {
00236         if (stricmp(name, current->name) == 0) {
00237             displayEventHook(current->evh);
00238         }
00239     }
00240     if (debug > 1) {
00241         alog("debug: done displaying message %s", name);
00242     }
00243     return 0;
00244 }
00245 
00252 int displayEvtMessageFromHash(char *name)
00253 {
00254     EvtMessageHash *current = NULL;
00255     int index = 0;
00256     index = CMD_HASH(name);
00257     if (debug > 1) {
00258         alog("debug: trying to display message %s", name);
00259     }
00260     for (current = EVENT[index]; current; current = current->next) {
00261         if (stricmp(name, current->name) == 0) {
00262             displayEventMessage(current->evm);
00263         }
00264     }
00265     if (debug > 1) {
00266         alog("debug: done displaying message %s", name);
00267     }
00268     return 0;
00269 }
00270 
00271 /*******************************************************************************
00272  * Message Functions
00273  *******************************************************************************/
00274 
00281 EvtMessage *createEventHandler(char *name,
00282                                int (*func) (char *source, int ac,
00283                                             char **av))
00284 {
00285     EvtMessage *evm = NULL;
00286     if (!func) {
00287         return NULL;
00288     }
00289     if ((evm = malloc(sizeof(EvtMessage))) == NULL) {
00290         fatal("Out of memory!");
00291     }
00292     evm->name = sstrdup(name);
00293     evm->func = func;
00294     evm->mod_name = NULL;
00295     evm->next = NULL;
00296     return evm;
00297 }
00298 
00305 EvtHook *createEventHook(char *name, int (*func) (int argc, char **argv))
00306 {
00307     EvtHook *evh = NULL;
00308     if (!func) {
00309         return NULL;
00310     }
00311     if ((evh = malloc(sizeof(EvtHook))) == NULL) {
00312         fatal("Out of memory!");
00313     }
00314     evh->name = sstrdup(name);
00315     evh->func = func;
00316     evh->mod_name = NULL;
00317     evh->next = NULL;
00318     return evh;
00319 }
00320 
00328 EvtMessage *findEventHandler(EvtMessageHash * msgEvtTable[],
00329                              const char *name)
00330 {
00331     int idx;
00332     EvtMessageHash *current = NULL;
00333     if (!msgEvtTable || !name) {
00334         return NULL;
00335     }
00336     idx = CMD_HASH(name);
00337 
00338     for (current = msgEvtTable[idx]; current; current = current->next) {
00339         if (stricmp(name, current->name) == 0) {
00340             return current->evm;
00341         }
00342     }
00343     return NULL;
00344 }
00345 
00353 EvtHook *findEventHook(EvtHookHash * hookEvtTable[], const char *name)
00354 {
00355     int idx;
00356     EvtHookHash *current = NULL;
00357     if (!hookEvtTable || !name) {
00358         return NULL;
00359     }
00360     idx = CMD_HASH(name);
00361 
00362     for (current = hookEvtTable[idx]; current; current = current->next) {
00363         if (stricmp(name, current->name) == 0) {
00364             return current->evh;
00365         }
00366     }
00367     return NULL;
00368 }
00369 
00376 int addCoreEventHandler(EvtMessageHash * msgEvtTable[], EvtMessage * evm)
00377 {
00378     if (!msgEvtTable || !evm) {
00379         return MOD_ERR_PARAMS;
00380     }
00381     evm->core = 1;
00382     return addEventHandler(msgEvtTable, evm);
00383 }
00384 
00391 int addEventHandler(EvtMessageHash * msgEvtTable[], EvtMessage * evm)
00392 {
00393     /* We can assume both param's have been checked by this point.. */
00394     int index = 0;
00395     EvtMessageHash *current = NULL;
00396     EvtMessageHash *newHash = NULL;
00397     EvtMessageHash *lastHash = NULL;
00398 
00399     if (!msgEvtTable || !evm) {
00400         return MOD_ERR_PARAMS;
00401     }
00402 
00403     index = CMD_HASH(evm->name);
00404 
00405     for (current = msgEvtTable[index]; current; current = current->next) {
00406         if (stricmp(evm->name, current->name) == 0) {   /* the msg exist's we are a addHead */
00407             evm->next = current->evm;
00408             current->evm = evm;
00409             if (debug)
00410                 alog("debug: existing msg: (0x%p), new msg (0x%p)",
00411                      (void *) evm->next, (void *) evm);
00412             return MOD_ERR_OK;
00413         }
00414         lastHash = current;
00415     }
00416 
00417     if ((newHash = malloc(sizeof(EvtMessageHash))) == NULL) {
00418         fatal("Out of memory");
00419     }
00420     newHash->next = NULL;
00421     newHash->name = sstrdup(evm->name);
00422     newHash->evm = evm;
00423 
00424     if (lastHash == NULL)
00425         msgEvtTable[index] = newHash;
00426     else
00427         lastHash->next = newHash;
00428     return MOD_ERR_OK;
00429 }
00430 
00437 int addEventHook(EvtHookHash * hookEvtTable[], EvtHook * evh)
00438 {
00439     /* We can assume both param's have been checked by this point.. */
00440     int index = 0;
00441     EvtHookHash *current = NULL;
00442     EvtHookHash *newHash = NULL;
00443     EvtHookHash *lastHash = NULL;
00444 
00445     if (!hookEvtTable || !evh) {
00446         return MOD_ERR_PARAMS;
00447     }
00448 
00449     index = CMD_HASH(evh->name);
00450 
00451     for (current = hookEvtTable[index]; current; current = current->next) {
00452         if (stricmp(evh->name, current->name) == 0) {   /* the msg exist's we are a addHead */
00453             evh->next = current->evh;
00454             current->evh = evh;
00455             if (debug)
00456                 alog("debug: existing msg: (0x%p), new msg (0x%p)",
00457                      (void *) evh->next, (void *) evh);
00458             return MOD_ERR_OK;
00459         }
00460         lastHash = current;
00461     }
00462 
00463     if ((newHash = malloc(sizeof(EvtHookHash))) == NULL) {
00464         fatal("Out of memory");
00465     }
00466     newHash->next = NULL;
00467     newHash->name = sstrdup(evh->name);
00468     newHash->evh = evh;
00469 
00470     if (lastHash == NULL)
00471         hookEvtTable[index] = newHash;
00472     else
00473         lastHash->next = newHash;
00474     return MOD_ERR_OK;
00475 }
00476 
00483 int addCoreEventHook(EvtHookHash * hookEvtTable[], EvtHook * evh)
00484 {
00485     if (!hookEvtTable || !evh) {
00486         return MOD_ERR_PARAMS;
00487     }
00488     evh->core = 1;
00489     return addEventHook(hookEvtTable, evh);
00490 }
00491 
00498 int moduleAddEventHandler(EvtMessage * evm)
00499 {
00500     int status;
00501 
00502     if (!evm) {
00503         return MOD_ERR_PARAMS;
00504     }
00505 
00506     if (!mod_current_module) {
00507         return MOD_ERR_UNKNOWN;
00508     }                           /* shouldnt happen */
00509 
00510     evm->core = 0;
00511     if (!evm->mod_name) {
00512         evm->mod_name = sstrdup(mod_current_module->name);
00513     }
00514 
00515     status = addEventHandler(EVENT, evm);
00516     if (debug) {
00517         displayEvtMessageFromHash(evm->name);
00518     }
00519     return status;
00520 }
00521 
00528 int moduleAddEventHook(EvtHook * evh)
00529 {
00530     int status;
00531 
00532     if (!evh) {
00533         return MOD_ERR_PARAMS;
00534     }
00535 
00536     if (!mod_current_module) {
00537         return MOD_ERR_UNKNOWN;
00538     }                           /* shouldnt happen */
00539 
00540     evh->core = 0;
00541     if (!evh->mod_name) {
00542         evh->mod_name = sstrdup(mod_current_module->name);
00543     }
00544 
00545     status = addEventHook(EVENTHOOKS, evh);
00546     if (debug) {
00547         displayHookFromHash(evh->name);
00548     }
00549     return status;
00550 }
00551 
00557 int moduleEventDelHandler(char *name)
00558 {
00559     EvtMessage *evm;
00560     int status;
00561 
00562     if (!mod_current_module) {
00563         return MOD_ERR_UNKNOWN;
00564     }
00565     evm = findEventHandler(EVENT, name);
00566     if (!evm) {
00567         return MOD_ERR_NOEXIST;
00568     }
00569 
00570     status = delEventHandler(EVENT, evm, mod_current_module->name);
00571     if (debug) {
00572         displayEvtMessageFromHash(evm->name);
00573     }
00574     return status;
00575 }
00576 
00582 int moduleEventDelHook(const char *name)
00583 {
00584     EvtHook *evh;
00585     int status;
00586 
00587     if (!mod_current_module) {
00588         return MOD_ERR_UNKNOWN;
00589     }
00590     evh = findEventHook(EVENTHOOKS, name);
00591     if (!evh) {
00592         return MOD_ERR_NOEXIST;
00593     }
00594 
00595     status = delEventHook(EVENTHOOKS, evh, mod_current_module->name);
00596     if (debug) {
00597         displayHookFromHash(evh->name);
00598     }
00599     return status;
00600 }
00601 
00609 int delEventHandler(EvtMessageHash * msgEvtTable[], EvtMessage * evm,
00610                     char *mod_name)
00611 {
00612     int index = 0;
00613     EvtMessageHash *current = NULL;
00614     EvtMessageHash *lastHash = NULL;
00615     EvtMessage *tail = NULL, *last = NULL;
00616 
00617     if (!evm || !msgEvtTable) {
00618         return MOD_ERR_PARAMS;
00619     }
00620 
00621     index = CMD_HASH(evm->name);
00622 
00623     for (current = msgEvtTable[index]; current; current = current->next) {
00624         if (stricmp(evm->name, current->name) == 0) {
00625             if (!lastHash) {
00626                 tail = current->evm;
00627                 if (tail->next) {
00628                     while (tail) {
00629                         if (mod_name && tail->mod_name
00630                             && (stricmp(mod_name, tail->mod_name) == 0)) {
00631                             if (last) {
00632                                 last->next = tail->next;
00633                             } else {
00634                                 current->evm = tail->next;
00635                             }
00636                             return MOD_ERR_OK;
00637                         }
00638                         last = tail;
00639                         tail = tail->next;
00640                     }
00641                 } else {
00642                     msgEvtTable[index] = current->next;
00643                     free(current->name);
00644                     return MOD_ERR_OK;
00645                 }
00646             } else {
00647                 tail = current->evm;
00648                 if (tail->next) {
00649                     while (tail) {
00650                         if (mod_name && tail->mod_name
00651                             && (stricmp(mod_name, tail->mod_name) == 0)) {
00652                             if (last) {
00653                                 last->next = tail->next;
00654                             } else {
00655                                 current->evm = tail->next;
00656                             }
00657                             return MOD_ERR_OK;
00658                         }
00659                         last = tail;
00660                         tail = tail->next;
00661                     }
00662                 } else {
00663                     lastHash->next = current->next;
00664                     free(current->name);
00665                     return MOD_ERR_OK;
00666                 }
00667             }
00668         }
00669         lastHash = current;
00670     }
00671     return MOD_ERR_NOEXIST;
00672 }
00673 
00674 
00682 int delEventHook(EvtHookHash * hookEvtTable[], EvtHook * evh,
00683                  char *mod_name)
00684 {
00685     int index = 0;
00686     EvtHookHash *current = NULL;
00687     EvtHookHash *lastHash = NULL;
00688     EvtHook *tail = NULL, *last = NULL;
00689 
00690     if (!evh || !hookEvtTable) {
00691         return MOD_ERR_PARAMS;
00692     }
00693 
00694     index = CMD_HASH(evh->name);
00695 
00696     for (current = hookEvtTable[index]; current; current = current->next) {
00697         if (stricmp(evh->name, current->name) == 0) {
00698             if (!lastHash) {
00699                 tail = current->evh;
00700                 if (tail->next) {
00701                     while (tail) {
00702                         if (mod_name && tail->mod_name
00703                             && (stricmp(mod_name, tail->mod_name) == 0)) {
00704                             if (last) {
00705                                 last->next = tail->next;
00706                             } else {
00707                                 current->evh = tail->next;
00708                             }
00709                             return MOD_ERR_OK;
00710                         }
00711                         last = tail;
00712                         tail = tail->next;
00713                     }
00714                 } else {
00715                     hookEvtTable[index] = current->next;
00716                     free(current->name);
00717                     return MOD_ERR_OK;
00718                 }
00719             } else {
00720                 tail = current->evh;
00721                 if (tail->next) {
00722                     while (tail) {
00723                         if (mod_name && tail->mod_name
00724                             && (stricmp(mod_name, tail->mod_name) == 0)) {
00725                             if (last) {
00726                                 last->next = tail->next;
00727                             } else {
00728                                 current->evh = tail->next;
00729                             }
00730                             return MOD_ERR_OK;
00731                         }
00732                         last = tail;
00733                         tail = tail->next;
00734                     }
00735                 } else {
00736                     lastHash->next = current->next;
00737                     free(current->name);
00738                     return MOD_ERR_OK;
00739                 }
00740             }
00741         }
00742         lastHash = current;
00743     }
00744     return MOD_ERR_NOEXIST;
00745 }
00746 
00747 
00753 int destroyEventHandler(EvtMessage * evm)
00754 {
00755     if (!evm) {
00756         return MOD_ERR_PARAMS;
00757     }
00758     if (evm->name) {
00759         free(evm->name);
00760     }
00761     evm->func = NULL;
00762     if (evm->mod_name) {
00763         free(evm->mod_name);
00764     }
00765     evm->next = NULL;
00766     return MOD_ERR_OK;
00767 }
00768 
00774 int destroyEventHook(EvtHook * evh)
00775 {
00776     if (!evh) {
00777         return MOD_ERR_PARAMS;
00778     }
00779     if (evh->name) {
00780         free(evh->name);
00781     }
00782     evh->func = NULL;
00783     if (evh->mod_name) {
00784         free(evh->mod_name);
00785     }
00786     evh->next = NULL;
00787     return MOD_ERR_OK;
00788 }