events.c

Go to the documentation of this file.
00001 /* Events functions.
00002  *
00003  * (C) 2004-2008 Anope Team
00004  * Contact us at info@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         if (evm->func) {
00131             mod_current_module_name = evm->mod_name;
00132             retVal = evm->func(source, ac, av);
00133             mod_current_module_name = NULL;
00134             if (retVal == MOD_CONT) {
00135                 current = evm->next;
00136                 while (current && current->func && retVal == MOD_CONT) {
00137                     mod_current_module_name = current->mod_name;
00138                     retVal = current->func(source, ac, av);
00139                     mod_current_module_name = NULL;
00140                     current = current->next;
00141                 }
00142             }
00143         }
00144     }
00145     /* Free argument list we created */
00146     free(av);
00147 }
00148 
00149 void event_process_hook(const char *name, int argc, char **argv)
00150 {
00151     int retVal = 0;
00152     EvtHook *current = NULL;
00153     EvtHook *evh;
00154     if (mod_current_evtbuffer) {
00155         free(mod_current_evtbuffer);
00156     }
00157     /* Do something with the message. */
00158     evh = find_eventhook(name);
00159     if (evh) {
00160         if (evh->func) {
00161             mod_current_module_name = evh->mod_name;
00162             retVal = evh->func(argc, argv);
00163             mod_current_module_name = NULL;
00164             if (retVal == MOD_CONT) {
00165                 current = evh->next;
00166                 while (current && current->func && retVal == MOD_CONT) {
00167                     mod_current_module_name = current->mod_name;
00168                     retVal = current->func(argc, argv);
00169                     mod_current_module_name = NULL;
00170                     current = current->next;
00171                 }
00172             }
00173         }
00174     }
00175 }
00176 
00183 int displayEventMessage(EvtMessage * evm)
00184 {
00185     EvtMessage *msg = NULL;
00186     int i = 0;
00187     alog("Displaying message list for %s", evm->name);
00188     for (msg = evm; msg; msg = msg->next) {
00189         alog("%d: 0x%p", ++i, (void *) msg);
00190     }
00191     alog("end");
00192     return 0;
00193 }
00194 
00201 int displayEventHook(EvtHook * evh)
00202 {
00203     EvtHook *msg = NULL;
00204     int i = 0;
00205     alog("Displaying message list for %s", evh->name);
00206     for (msg = evh; msg; msg = msg->next) {
00207         alog("%d: 0x%p", ++i, (void *) msg);
00208     }
00209     alog("end");
00210     return 0;
00211 }
00212 
00219 int displayHookFromHash(char *name)
00220 {
00221     EvtHookHash *current = NULL;
00222     int index = 0;
00223     index = CMD_HASH(name);
00224     if (debug > 1) {
00225         alog("debug: trying to display message %s", name);
00226     }
00227     for (current = EVENTHOOKS[index]; current; current = current->next) {
00228         if (stricmp(name, current->name) == 0) {
00229             displayEventHook(current->evh);
00230         }
00231     }
00232     if (debug > 1) {
00233         alog("debug: done displaying message %s", name);
00234     }
00235     return 0;
00236 }
00237 
00244 int displayEvtMessageFromHash(char *name)
00245 {
00246     EvtMessageHash *current = NULL;
00247     int index = 0;
00248     index = CMD_HASH(name);
00249     if (debug > 1) {
00250         alog("debug: trying to display message %s", name);
00251     }
00252     for (current = EVENT[index]; current; current = current->next) {
00253         if (stricmp(name, current->name) == 0) {
00254             displayEventMessage(current->evm);
00255         }
00256     }
00257     if (debug > 1) {
00258         alog("debug: done displaying message %s", name);
00259     }
00260     return 0;
00261 }
00262 
00263 /*******************************************************************************
00264  * Message Functions
00265  *******************************************************************************/
00266 
00273 EvtMessage *createEventHandler(char *name,
00274                                int (*func) (char *source, int ac,
00275                                             char **av))
00276 {
00277     EvtMessage *evm = NULL;
00278     if (!func) {
00279         return NULL;
00280     }
00281     if ((evm = malloc(sizeof(EvtMessage))) == NULL) {
00282         fatal("Out of memory!");
00283     }
00284     evm->name = sstrdup(name);
00285     evm->func = func;
00286     evm->mod_name = NULL;
00287     evm->next = NULL;
00288     return evm;
00289 }
00290 
00297 EvtHook *createEventHook(char *name, int (*func) (int argc, char **argv))
00298 {
00299     EvtHook *evh = NULL;
00300     if (!func) {
00301         return NULL;
00302     }
00303     if ((evh = malloc(sizeof(EvtHook))) == NULL) {
00304         fatal("Out of memory!");
00305     }
00306     evh->name = sstrdup(name);
00307     evh->func = func;
00308     evh->mod_name = NULL;
00309     evh->next = NULL;
00310     return evh;
00311 }
00312 
00320 EvtMessage *findEventHandler(EvtMessageHash * msgEvtTable[],
00321                              const char *name)
00322 {
00323     int idx;
00324     EvtMessageHash *current = NULL;
00325     if (!msgEvtTable || !name) {
00326         return NULL;
00327     }
00328     idx = CMD_HASH(name);
00329 
00330     for (current = msgEvtTable[idx]; current; current = current->next) {
00331         if (stricmp(name, current->name) == 0) {
00332             return current->evm;
00333         }
00334     }
00335     return NULL;
00336 }
00337 
00345 EvtHook *findEventHook(EvtHookHash * hookEvtTable[], const char *name)
00346 {
00347     int idx;
00348     EvtHookHash *current = NULL;
00349     if (!hookEvtTable || !name) {
00350         return NULL;
00351     }
00352     idx = CMD_HASH(name);
00353 
00354     for (current = hookEvtTable[idx]; current; current = current->next) {
00355         if (stricmp(name, current->name) == 0) {
00356             return current->evh;
00357         }
00358     }
00359     return NULL;
00360 }
00361 
00368 int addCoreEventHandler(EvtMessageHash * msgEvtTable[], EvtMessage * evm)
00369 {
00370     if (!msgEvtTable || !evm) {
00371         return MOD_ERR_PARAMS;
00372     }
00373     evm->core = 1;
00374     return addEventHandler(msgEvtTable, evm);
00375 }
00376 
00383 int addEventHandler(EvtMessageHash * msgEvtTable[], EvtMessage * evm)
00384 {
00385     /* We can assume both param's have been checked by this point.. */
00386     int index = 0;
00387     EvtMessageHash *current = NULL;
00388     EvtMessageHash *newHash = NULL;
00389     EvtMessageHash *lastHash = NULL;
00390 
00391     if (!msgEvtTable || !evm) {
00392         return MOD_ERR_PARAMS;
00393     }
00394 
00395     index = CMD_HASH(evm->name);
00396 
00397     for (current = msgEvtTable[index]; current; current = current->next) {
00398         if (stricmp(evm->name, current->name) == 0) {   /* the msg exist's we are a addHead */
00399             evm->next = current->evm;
00400             current->evm = evm;
00401             if (debug)
00402                 alog("debug: existing msg: (0x%p), new msg (0x%p)",
00403                      (void *) evm->next, (void *) evm);
00404             return MOD_ERR_OK;
00405         }
00406         lastHash = current;
00407     }
00408 
00409     if ((newHash = malloc(sizeof(EvtMessageHash))) == NULL) {
00410         fatal("Out of memory");
00411     }
00412     newHash->next = NULL;
00413     newHash->name = sstrdup(evm->name);
00414     newHash->evm = evm;
00415 
00416     if (lastHash == NULL)
00417         msgEvtTable[index] = newHash;
00418     else
00419         lastHash->next = newHash;
00420     return MOD_ERR_OK;
00421 }
00422 
00429 int addEventHook(EvtHookHash * hookEvtTable[], EvtHook * evh)
00430 {
00431     /* We can assume both param's have been checked by this point.. */
00432     int index = 0;
00433     EvtHookHash *current = NULL;
00434     EvtHookHash *newHash = NULL;
00435     EvtHookHash *lastHash = NULL;
00436 
00437     if (!hookEvtTable || !evh) {
00438         return MOD_ERR_PARAMS;
00439     }
00440 
00441     index = CMD_HASH(evh->name);
00442 
00443     for (current = hookEvtTable[index]; current; current = current->next) {
00444         if (stricmp(evh->name, current->name) == 0) {   /* the msg exist's we are a addHead */
00445             evh->next = current->evh;
00446             current->evh = evh;
00447             if (debug)
00448                 alog("debug: existing msg: (0x%p), new msg (0x%p)",
00449                      (void *) evh->next, (void *) evh);
00450             return MOD_ERR_OK;
00451         }
00452         lastHash = current;
00453     }
00454 
00455     if ((newHash = malloc(sizeof(EvtHookHash))) == NULL) {
00456         fatal("Out of memory");
00457     }
00458     newHash->next = NULL;
00459     newHash->name = sstrdup(evh->name);
00460     newHash->evh = evh;
00461 
00462     if (lastHash == NULL)
00463         hookEvtTable[index] = newHash;
00464     else
00465         lastHash->next = newHash;
00466     return MOD_ERR_OK;
00467 }
00468 
00475 int addCoreEventHook(EvtHookHash * hookEvtTable[], EvtHook * evh)
00476 {
00477     if (!hookEvtTable || !evh) {
00478         return MOD_ERR_PARAMS;
00479     }
00480     evh->core = 1;
00481     return addEventHook(hookEvtTable, evh);
00482 }
00483 
00490 int moduleAddEventHandler(EvtMessage * evm)
00491 {
00492     int status;
00493 
00494     if (!evm) {
00495         return MOD_ERR_PARAMS;
00496     }
00497 
00498     /* ok, this appears to be a module adding a message from outside of AnopeInit, try to look up its module struct for it */
00499     if ((mod_current_module_name) && (!mod_current_module)) {
00500         mod_current_module = findModule(mod_current_module_name);
00501     }
00502 
00503     if (!mod_current_module) {
00504         return MOD_ERR_UNKNOWN;
00505     }                           /* shouldnt happen */
00506     evm->core = 0;
00507     if (!evm->mod_name) {
00508         evm->mod_name = sstrdup(mod_current_module->name);
00509     }
00510 
00511     status = addEventHandler(EVENT, evm);
00512     if (debug) {
00513         displayEvtMessageFromHash(evm->name);
00514     }
00515     return status;
00516 }
00517 
00524 int moduleAddEventHook(EvtHook * evh)
00525 {
00526     int status;
00527 
00528     if (!evh) {
00529         return MOD_ERR_PARAMS;
00530     }
00531 
00532     if ((mod_current_module_name) && (!mod_current_module)) {
00533         mod_current_module = findModule(mod_current_module_name);
00534     }
00535 
00536     if (!mod_current_module) {
00537         return MOD_ERR_UNKNOWN;
00538     }                           /* shouldnt happen */
00539     evh->core = 0;
00540     if (!evh->mod_name) {
00541         evh->mod_name = sstrdup(mod_current_module->name);
00542     }
00543 
00544     status = addEventHook(EVENTHOOKS, evh);
00545     if (debug) {
00546         displayHookFromHash(evh->name);
00547     }
00548     return status;
00549 }
00550 
00556 int moduleEventDelHandler(char *name)
00557 {
00558     EvtMessage *evm;
00559     int status;
00560 
00561     if (!mod_current_module) {
00562         return MOD_ERR_UNKNOWN;
00563     }
00564     evm = findEventHandler(EVENT, name);
00565     if (!evm) {
00566         return MOD_ERR_NOEXIST;
00567     }
00568 
00569     status = delEventHandler(EVENT, evm, mod_current_module->name);
00570     if (debug) {
00571         displayEvtMessageFromHash(evm->name);
00572     }
00573     return status;
00574 }
00575 
00581 int moduleEventDelHook(const char *name)
00582 {
00583     EvtHook *evh;
00584     int status;
00585 
00586     if (!mod_current_module) {
00587         return MOD_ERR_UNKNOWN;
00588     }
00589     evh = findEventHook(EVENTHOOKS, name);
00590     if (!evh) {
00591         return MOD_ERR_NOEXIST;
00592     }
00593 
00594     status = delEventHook(EVENTHOOKS, evh, mod_current_module->name);
00595     if (debug) {
00596         displayHookFromHash(evh->name);
00597     }
00598     return status;
00599 }
00600 
00608 int delEventHandler(EvtMessageHash * msgEvtTable[], EvtMessage * evm,
00609                     char *mod_name)
00610 {
00611     int index = 0;
00612     EvtMessageHash *current = NULL;
00613     EvtMessageHash *lastHash = NULL;
00614     EvtMessage *tail = NULL, *last = NULL;
00615 
00616     if (!evm || !msgEvtTable) {
00617         return MOD_ERR_PARAMS;
00618     }
00619 
00620     index = CMD_HASH(evm->name);
00621 
00622     for (current = msgEvtTable[index]; current; current = current->next) {
00623         if (stricmp(evm->name, current->name) == 0) {
00624             if (!lastHash) {
00625                 tail = current->evm;
00626                 if (tail->next) {
00627                     while (tail) {
00628                         if (mod_name && tail->mod_name
00629                             && (stricmp(mod_name, tail->mod_name) == 0)) {
00630                             if (last) {
00631                                 last->next = tail->next;
00632                             } else {
00633                                 current->evm = tail->next;
00634                             }
00635                             return MOD_ERR_OK;
00636                         }
00637                         last = tail;
00638                         tail = tail->next;
00639                     }
00640                 } else {
00641                     msgEvtTable[index] = current->next;
00642                     free(current->name);
00643                     return MOD_ERR_OK;
00644                 }
00645             } else {
00646                 tail = current->evm;
00647                 if (tail->next) {
00648                     while (tail) {
00649                         if (mod_name && tail->mod_name
00650                             && (stricmp(mod_name, tail->mod_name) == 0)) {
00651                             if (last) {
00652                                 last->next = tail->next;
00653                             } else {
00654                                 current->evm = tail->next;
00655                             }
00656                             return MOD_ERR_OK;
00657                         }
00658                         last = tail;
00659                         tail = tail->next;
00660                     }
00661                 } else {
00662                     lastHash->next = current->next;
00663                     free(current->name);
00664                     return MOD_ERR_OK;
00665                 }
00666             }
00667         }
00668         lastHash = current;
00669     }
00670     return MOD_ERR_NOEXIST;
00671 }
00672 
00673 
00681 int delEventHook(EvtHookHash * hookEvtTable[], EvtHook * evh,
00682                  char *mod_name)
00683 {
00684     int index = 0;
00685     EvtHookHash *current = NULL;
00686     EvtHookHash *lastHash = NULL;
00687     EvtHook *tail = NULL, *last = NULL;
00688 
00689     if (!evh || !hookEvtTable) {
00690         return MOD_ERR_PARAMS;
00691     }
00692 
00693     index = CMD_HASH(evh->name);
00694 
00695     for (current = hookEvtTable[index]; current; current = current->next) {
00696         if (stricmp(evh->name, current->name) == 0) {
00697             if (!lastHash) {
00698                 tail = current->evh;
00699                 if (tail->next) {
00700                     while (tail) {
00701                         if (mod_name && tail->mod_name
00702                             && (stricmp(mod_name, tail->mod_name) == 0)) {
00703                             if (last) {
00704                                 last->next = tail->next;
00705                             } else {
00706                                 current->evh = tail->next;
00707                             }
00708                             return MOD_ERR_OK;
00709                         }
00710                         last = tail;
00711                         tail = tail->next;
00712                     }
00713                 } else {
00714                     hookEvtTable[index] = current->next;
00715                     free(current->name);
00716                     return MOD_ERR_OK;
00717                 }
00718             } else {
00719                 tail = current->evh;
00720                 if (tail->next) {
00721                     while (tail) {
00722                         if (mod_name && tail->mod_name
00723                             && (stricmp(mod_name, tail->mod_name) == 0)) {
00724                             if (last) {
00725                                 last->next = tail->next;
00726                             } else {
00727                                 current->evh = tail->next;
00728                             }
00729                             return MOD_ERR_OK;
00730                         }
00731                         last = tail;
00732                         tail = tail->next;
00733                     }
00734                 } else {
00735                     lastHash->next = current->next;
00736                     free(current->name);
00737                     return MOD_ERR_OK;
00738                 }
00739             }
00740         }
00741         lastHash = current;
00742     }
00743     return MOD_ERR_NOEXIST;
00744 }
00745 
00746 
00752 int destroyEventHandler(EvtMessage * evm)
00753 {
00754     if (!evm) {
00755         return MOD_ERR_PARAMS;
00756     }
00757     if (evm->name) {
00758         free(evm->name);
00759     }
00760     evm->func = NULL;
00761     if (evm->mod_name) {
00762         free(evm->mod_name);
00763     }
00764     evm->next = NULL;
00765     return MOD_ERR_OK;
00766 }
00767 
00773 int destroyEventHook(EvtHook * evh)
00774 {
00775     if (!evh) {
00776         return MOD_ERR_PARAMS;
00777     }
00778     if (evh->name) {
00779         free(evh->name);
00780     }
00781     evh->func = NULL;
00782     if (evh->mod_name) {
00783         free(evh->mod_name);
00784     }
00785     evh->next = NULL;
00786     return MOD_ERR_OK;
00787 }

Generated on Sun Oct 5 09:06:55 2008 for Anope by  doxygen 1.5.7.1