modules.c

Go to the documentation of this file.
00001 
00002 /* Modular support
00003  *
00004  * (C) 2003-2007 Anope Team
00005  * Contact us at info@anope.org
00006  *
00007  * Please read COPYING and README for further details.
00008  *
00009  * Based on the original code of Epona by Lara.
00010  * Based on the original code of Services by Andy Church.
00011  *
00012  * $Id: modules.c 1321 2007-12-27 19:10:36Z geniusdex $
00013  *
00014  */
00015 #include "modules.h"
00016 #include "language.h"
00017 #include "version.h"
00018 
00019 #if defined(USE_MODULES) && !defined(_WIN32)
00020 #include <dlfcn.h>
00021 /* Define these for systems without them */
00022 #ifndef RTLD_NOW
00023 #define RTLD_NOW 0
00024 #endif
00025 #ifndef RTLD_LAZY
00026 #define RTLD_LAZY RTLD_NOW
00027 #endif
00028 #ifndef RTLD_GLOBAL
00029 #define RTLD_GLOBAL 0
00030 #endif
00031 #ifndef RTLD_LOCAL
00032 #define RTLD_LOCAL 0
00033 #endif
00034 #endif
00035 
00036 #ifdef _WIN32
00037 const char *ano_moderr(void);
00038 #endif
00039 
00043 CommandHash *HOSTSERV[MAX_CMD_HASH];
00044 CommandHash *BOTSERV[MAX_CMD_HASH];
00045 CommandHash *MEMOSERV[MAX_CMD_HASH];
00046 CommandHash *NICKSERV[MAX_CMD_HASH];
00047 CommandHash *CHANSERV[MAX_CMD_HASH];
00048 CommandHash *HELPSERV[MAX_CMD_HASH];
00049 CommandHash *OPERSERV[MAX_CMD_HASH];
00050 MessageHash *IRCD[MAX_CMD_HASH];
00051 ModuleHash *MODULE_HASH[MAX_CMD_HASH];
00052 
00053 Module *mod_current_module;
00054 char *mod_current_module_name = NULL;
00055 char *mod_current_buffer = NULL;
00056 User *mod_current_user;
00057 ModuleCallBack *moduleCallBackHead = NULL;
00058 ModuleQueue *mod_operation_queue = NULL;
00059 
00060 int displayCommand(Command * c);
00061 int displayCommandFromHash(CommandHash * cmdTable[], char *name);
00062 int displayMessageFromHash(char *name);
00063 int displayMessage(Message * m);
00064 char *ModuleGetErrStr(int status);
00065 
00066 char *ModuleGetErrStr(int status)
00067 {
00068     const char *module_err_str[] = {
00069         "Module, Okay - No Error",                                             /* MOD_ERR_OK */
00070         "Module Error, Allocating memory",                                     /* MOD_ERR_MEMORY */
00071         "Module Error, Not enough parameters",                                 /* MOD_ERR_PARAMS */
00072         "Module Error, Already loaded",                                        /* MOD_ERR_EXISTS */
00073         "Module Error, File does not exist",                                   /* MOD_ERR_NOEXIST */
00074         "Module Error, No User",                                               /* MOD_ERR_NOUSER */
00075         "Module Error, Error during load time or module returned MOD_STOP",    /* MOD_ERR_NOLOAD */
00076         "Module Error, Unable to unload",                                      /* MOD_ERR_NOUNLOAD */
00077         "Module Error, Incorrect syntax",                                      /* MOD_ERR_SYNTAX */
00078         "Module Error, Unable to delete",                                      /* MOD_ERR_NODELETE */
00079         "Module Error, Unknown Error occuried",                                /* MOD_ERR_UNKOWN */
00080         "Module Error, File I/O Error",                                        /* MOD_ERR_FILE_IO */
00081         "Module Error, No Service found for request",                          /* MOD_ERR_NOSERVICE */
00082         "Module Error, No module name for request"                             /* MOD_ERR_NO_MOD_NAME */
00083     };
00084     return (char *) module_err_str[status];
00085 }
00086 
00092 void modules_init(void)
00093 {
00094 #ifdef USE_MODULES
00095     int idx;
00096     int ret;
00097     Module *m;
00098 
00099     if(nothird) {
00100         return;
00101     }
00102 
00103     for (idx = 0; idx < ModulesNumber; idx++) {
00104         m = findModule(ModulesAutoload[idx]);
00105         if (!m) {
00106             m = createModule(ModulesAutoload[idx]);
00107             mod_current_module = m;
00108             mod_current_user = NULL;
00109             alog("trying to load [%s]", mod_current_module->name);
00110             ret = loadModule(mod_current_module, NULL);
00111             alog("status: [%d][%s]", ret, ModuleGetErrStr(ret));
00112             if (ret != MOD_ERR_OK)
00113                 destroyModule(m);
00114             mod_current_module = NULL;
00115             mod_current_user = NULL;
00116         }
00117     }
00118 #endif
00119 }
00120 
00126 void modules_core_init(int number, char **list)
00127 {
00128     int idx;
00129     Module *m;
00130     int status = 0;
00131     for (idx = 0; idx < number; idx++) {
00132         m = findModule(list[idx]);
00133         if (!m) {
00134             m = createModule(list[idx]);
00135             mod_current_module = m;
00136             mod_current_user = NULL;
00137             status = loadModule(mod_current_module, NULL);
00138             if (debug || status) {
00139                 alog("debug: trying to load core module [%s]",
00140                      mod_current_module->name);
00141                 alog("debug: status: [%d][%s]", status, ModuleGetErrStr(status));
00142                 if (status != MOD_ERR_OK)
00143                     destroyModule(mod_current_module);
00144             }
00145             mod_current_module = NULL;
00146             mod_current_user = NULL;
00147         }
00148     }
00149 }
00153 int encryption_module_init(void) {
00154     int ret = 0;
00155     Module *m;
00156     
00157     m = createModule(EncModule);
00158     mod_current_module = m;
00159     mod_current_user = NULL;
00160     alog("Loading Encryption Module: [%s]", mod_current_module->name);
00161     ret = loadModule(mod_current_module, NULL);
00162     moduleSetType(ENCRYPTION);
00163     alog("status: [%d][%s]", ret, ModuleGetErrStr(ret));
00164     mod_current_module = NULL;
00165     if (ret != MOD_ERR_OK) {
00166         destroyModule(m);
00167     }
00168     return ret;
00169 }
00170 
00174 int protocol_module_init(void)
00175 {
00176     int ret = 0;
00177     Module *m;
00178     
00179     m = createModule(IRCDModule);
00180     mod_current_module = m;
00181     mod_current_user = NULL;
00182     alog("Loading IRCD Protocol Module: [%s]", mod_current_module->name);
00183     ret = loadModule(mod_current_module, NULL);
00184     moduleSetType(PROTOCOL);
00185     alog("status: [%d][%s]", ret, ModuleGetErrStr(ret));
00186     mod_current_module = NULL;
00187     
00188     if (ret == MOD_ERR_OK) {
00189         /* This is really NOT the correct place to do config checks, but
00190          * as we only have the ircd struct filled here, we have to over
00191          * here. -GD
00192          */
00193         if (UseTokens && !(ircd->token)) {
00194             alog("Anope does not support TOKENS for this ircd setting; unsetting UseToken");
00195             UseTokens = 0;
00196         }
00197         
00198         if (UseTS6 && !(ircd->ts6)) {
00199             alog("Chosen IRCd does not support TS6, unsetting UseTS6");
00200             UseTS6 = 0;
00201         }
00202         
00203         /* We can assume the ircd supports TS6 here */
00204         if (UseTS6 && !Numeric) {
00205             alog("UseTS6 requires the setting of Numeric to be enabled.");
00206             ret = -1;
00207         }
00208     } else {
00209         destroyModule(m);
00210     }
00211     
00212     return ret;
00213 }
00214 
00220 void modules_delayed_init(void)
00221 {
00222 #ifdef USE_MODULES
00223     int idx;
00224     int ret;
00225     Module *m;
00226 
00227     if(nothird) {
00228         return;
00229     }
00230 
00231     for (idx = 0; idx < ModulesDelayedNumber; idx++) {
00232         m = findModule(ModulesDelayedAutoload[idx]);
00233         if (!m) {
00234             m = createModule(ModulesDelayedAutoload[idx]);
00235             mod_current_module = m;
00236             mod_current_user = NULL;
00237             alog("trying to load [%s]", mod_current_module->name);
00238             ret = loadModule(mod_current_module, NULL);
00239             alog("status: [%d][%s]", ret, ModuleGetErrStr(ret));
00240             mod_current_module = NULL;
00241             mod_current_user = NULL;
00242             if (ret != MOD_ERR_OK)
00243                 destroyModule(m);
00244         }
00245     }
00246 #endif
00247 }
00248 
00259 void modules_unload_all(boolean fini, boolean unload_proto)
00260 {
00261 #ifdef USE_MODULES
00262     int idx;
00263     ModuleHash *mh, *next;
00264         void (*func) (void);
00265         
00266     for (idx = 0; idx < MAX_CMD_HASH; idx++) {
00267         mh = MODULE_HASH[idx];
00268         while (mh) {
00269             next = mh->next;
00270             if (unload_proto || (mh->m->type != PROTOCOL)) {
00271                 mod_current_module = mh->m;
00272                 if(fini) {
00273                     func = (void (*)(void))ano_modsym(mh->m->handle, "AnopeFini");
00274                     if (func) {
00275                         mod_current_module_name = mh->m->name;
00276                         func();                 /* exec AnopeFini */
00277                         mod_current_module_name = NULL;
00278                     }
00279                 
00280                     if (prepForUnload(mh->m) != MOD_ERR_OK) {
00281                         mh = next;
00282                         continue;
00283                     }
00284                 
00285                     if ((ano_modclose(mh->m->handle)) != 0)
00286                         alog(ano_moderr());
00287                     else
00288                         delModule(mh->m);
00289                 } else {
00290                             delModule(mh->m);
00291                 }
00292             }
00293             mh = next;
00294         }
00295     }
00296 #endif
00297 }
00298 
00304 Module *createModule(char *filename)
00305 {
00306     Module *m;
00307     int i = 0;
00308     if (!filename) {
00309         return NULL;
00310     }
00311     if ((m = malloc(sizeof(Module))) == NULL) {
00312         fatal("Out of memory!");
00313     }
00314 
00315     m->name = sstrdup(filename);        /* Our Name */
00316     m->handle = NULL;           /* Handle */
00317     m->version = NULL;
00318     m->author = NULL;
00319     m->nickHelp = NULL;
00320     m->chanHelp = NULL;
00321     m->memoHelp = NULL;
00322     m->botHelp = NULL;
00323     m->operHelp = NULL;
00324     m->hostHelp = NULL;
00325     m->helpHelp = NULL;
00326 
00327     m->type = THIRD;
00328     for (i = 0; i < NUM_LANGS; i++) {
00329         m->lang[i].argc = 0;
00330     }
00331     return m;                   /* return a nice new module */
00332 }
00333 
00340 int destroyModule(Module * m)
00341 {
00342     int i = 0;
00343     if (!m) {
00344         return MOD_ERR_PARAMS;
00345     }
00346 
00347     mod_current_module = m;
00348     for (i = 0; i < NUM_LANGS; i++) {
00349         moduleDeleteLanguage(i);
00350     }
00351 
00352     if (m->name) {
00353         free(m->name);
00354     }
00355     if (m->filename) {
00356         remove(m->filename);
00357         free(m->filename);
00358     }
00359     m->handle = NULL;
00360     if (m->author) {
00361         free(m->author);
00362     }
00363     if (m->version) {
00364         free(m->version);
00365     }
00366 
00367     /* No need to free our cmd/msg list, as they will always be empty by the module is destroyed */
00368     free(m);
00369     return MOD_ERR_OK;
00370 }
00371 
00377 int addModule(Module * m)
00378 {
00379     int index = 0;
00380     ModuleHash *current = NULL;
00381     ModuleHash *newHash = NULL;
00382     ModuleHash *lastHash = NULL;
00383 
00384     index = CMD_HASH(m->name);
00385 
00386     for (current = MODULE_HASH[index]; current; current = current->next) {
00387         if (stricmp(m->name, current->name) == 0)
00388             return MOD_ERR_EXISTS;
00389         lastHash = current;
00390     }
00391 
00392     if ((newHash = malloc(sizeof(ModuleHash))) == NULL) {
00393         fatal("Out of memory");
00394     }
00395     m->time = time(NULL);
00396     newHash->next = NULL;
00397     newHash->name = sstrdup(m->name);
00398     newHash->m = m;
00399 
00400     if (lastHash == NULL)
00401         MODULE_HASH[index] = newHash;
00402     else
00403         lastHash->next = newHash;
00404     return MOD_ERR_OK;
00405 }
00406 
00412 int delModule(Module * m)
00413 {
00414     int index = 0;
00415     ModuleHash *current = NULL;
00416     ModuleHash *lastHash = NULL;
00417 
00418     if (!m) {
00419         return MOD_ERR_PARAMS;
00420     }
00421 
00422     index = CMD_HASH(m->name);
00423 
00424     for (current = MODULE_HASH[index]; current; current = current->next) {
00425         if (stricmp(m->name, current->name) == 0) {
00426             if (!lastHash) {
00427                 MODULE_HASH[index] = current->next;
00428             } else {
00429                 lastHash->next = current->next;
00430             }
00431             destroyModule(current->m);
00432             free(current->name);
00433             free(current);
00434             return MOD_ERR_OK;
00435         }
00436         lastHash = current;
00437     }
00438     return MOD_ERR_NOEXIST;
00439 }
00440 
00446 Module *findModule(char *name)
00447 {
00448     int idx;
00449     ModuleHash *current = NULL;
00450     if (!name) {
00451         return NULL;
00452     }
00453     idx = CMD_HASH(name);
00454 
00455     for (current = MODULE_HASH[idx]; current; current = current->next) {
00456         if (stricmp(name, current->name) == 0) {
00457             return current->m;
00458         }
00459     }
00460     return NULL;
00461 
00462 }
00463 
00468 int protocolModuleLoaded()
00469 {
00470     int idx = 0;
00471     ModuleHash *current = NULL;
00472 
00473     for (idx = 0; idx != MAX_CMD_HASH; idx++) {
00474         for (current = MODULE_HASH[idx]; current; current = current->next) {
00475             if (current->m->type == PROTOCOL) {
00476                 return 1;
00477             }
00478         }
00479     }
00480     return 0;
00481 }
00482 
00487 int encryptionModuleLoaded()
00488 {
00489     int idx = 0;
00490     ModuleHash *current = NULL;
00491 
00492     for (idx = 0; idx != MAX_CMD_HASH; idx++) {
00493         for (current = MODULE_HASH[idx]; current; current = current->next) {
00494             if (current->m->type == ENCRYPTION) {
00495                 return 1;
00496             }
00497         }
00498     }
00499     return 0;
00500 }
00501 
00511 int moduleCopyFile(char *name, char *output)
00512 {
00513 #ifdef USE_MODULES
00514     int ch;
00515     FILE *source, *target;
00516     int srcfp;
00517     char input[4096];
00518     int len;
00519 
00520     strncpy(input, MODULE_PATH, 4095);  /* Get full path with module extension */
00521     len = strlen(input);
00522     strncat(input, name, 4095 - len);
00523     len = strlen(output);
00524     strncat(input, MODULE_EXT, 4095 - len);
00525 
00526 #ifndef _WIN32
00527     if ((srcfp = mkstemp(output)) == -1)
00528         return MOD_ERR_FILE_IO;
00529 #else
00530     if (!mktemp(output))
00531         return MOD_ERR_FILE_IO;
00532 #endif
00533     
00534     if (debug)
00535         alog("Runtime module location: %s", output);
00536     
00537     /* Linux/UNIX should ignore the b param, why do we still have seperate
00538      * calls for it here? -GD
00539      */
00540 #ifndef _WIN32
00541     if ((source = fopen(input, "r")) == NULL) {
00542 #else
00543     if ((source = fopen(input, "rb")) == NULL) {
00544 #endif
00545         return MOD_ERR_NOEXIST;
00546     }
00547 #ifndef _WIN32
00548     if ((target = fdopen(srcfp, "w")) == NULL) {
00549 #else
00550     if ((target = fopen(output, "wb")) == NULL) {
00551 #endif
00552         return MOD_ERR_FILE_IO;
00553     }
00554     while ((ch = fgetc(source)) != EOF) {
00555         fputc(ch, target);
00556     }
00557     fclose(source);
00558     if (fclose(target) != 0) {
00559         return MOD_ERR_FILE_IO;
00560     }
00561 #endif
00562     return MOD_ERR_OK;
00563 }
00564 
00571 int loadModule(Module * m, User * u)
00572 {
00573 #ifdef USE_MODULES
00574     char buf[4096];
00575     int len;
00576     const char *err;
00577     int (*func) (int, char **);
00578     int (*version)();
00579     int ret = 0;
00580     char *argv[1];
00581     int argc = 0;
00582 
00583     Module *m2;
00584     if (!m || !m->name) {
00585         return MOD_ERR_PARAMS;
00586     }
00587     if (m->handle) {
00588         return MOD_ERR_EXISTS;
00589     }
00590     if ((m2 = findModule(m->name)) != NULL) {
00591         return MOD_ERR_EXISTS;
00592     }
00593     
00594     /* Generate the filename for the temporary copy of the module */
00595     strncpy(buf, MODULE_PATH, 4095);    /* Get full path with module extension */
00596     len = strlen(buf);
00597 #ifndef _WIN32
00598     strncat(buf, "runtime/", 4095 - len);
00599 #else
00600     strncat(buf, "runtime\\", 4095 - len);
00601 #endif
00602     len = strlen(buf);
00603     strncat(buf, m->name, 4095 - len);
00604     len = strlen(buf);
00605     strncat(buf, MODULE_EXT, 4095 - len);
00606     len = strlen(buf);
00607     strncat(buf, ".", 4095 - len);
00608     len = strlen(buf);
00609     strncat(buf, "XXXXXX", 4095 - len);
00610     buf[4095] = '\0';
00611     /* Don't skip return value checking! -GD */
00612     if ((ret = moduleCopyFile(m->name, buf)) != MOD_ERR_OK) {
00613         m->filename = sstrdup(buf);
00614     return ret;
00615     }
00616 
00617     m->filename = sstrdup(buf);
00618     ano_modclearerr();
00619     m->handle = ano_modopen(m->filename);
00620     if ((err = ano_moderr()) != NULL) {
00621         alog(err);
00622         return MOD_ERR_NOLOAD;
00623     }
00624     ano_modclearerr();
00625     func = (int (*)(int, char **))ano_modsym(m->handle, "AnopeInit");
00626     if ((err = ano_moderr()) != NULL) {
00627         ano_modclose(m->handle);        /* If no AnopeInit - it isnt an Anope Module, close it */
00628         return MOD_ERR_NOLOAD;
00629     }
00630     if (func) {
00631     version = (int (*)())ano_modsym(m->handle,"getAnopeBuildVersion");
00632     if (version) {
00633         if (version() >= VERSION_BUILD ) {
00634             if(debug) {
00635                 alog("Module %s compiled against current or newer anope revision %d, this is %d",m->name,version(),VERSION_BUILD);
00636             }
00637         } else {
00638             alog("Module %s is compiled against an old version of anope (%d) current is %d", m->name, version(), VERSION_BUILD);
00639             alog("Rebuild module %s against the current version to resolve this error", m->name);
00640             ano_modclose(m->handle);
00641             ano_modclearerr();
00642             return MOD_ERR_NOLOAD;
00643         }
00644     } else {
00645         ano_modclose(m->handle);
00646         ano_modclearerr();
00647         alog("Module %s is compiled against an older version of anope (unknown)", m->name);
00648         alog("Rebuild module %s against the current version to resolve this error", m->name);
00649         return MOD_ERR_NOLOAD;
00650     }
00651     /* TODO */
00652         mod_current_module_name = m->name;
00653         /* argv[0] is the user if there was one, or NULL if not */
00654         if (u) {
00655             argv[0] = sstrdup(u->nick);
00656         } else {
00657             argv[0] = NULL;
00658         }
00659         argc++;
00660 
00661         ret = func(argc, argv); /* exec AnopeInit */
00662         if (u) {
00663             free(argv[0]);
00664         }
00665         if (m->type == PROTOCOL && protocolModuleLoaded()) {
00666             alog("You cannot load two protocol modules");
00667             ret = MOD_STOP;
00668         } else if (m->type == ENCRYPTION && encryptionModuleLoaded()) {
00669             alog("You cannot load two encryption modules");
00670             ret = MOD_STOP;
00671         }
00672         if (ret == MOD_STOP) {
00673             alog("%s requested unload...", m->name);
00674             unloadModule(m, NULL);
00675             mod_current_module_name = NULL;
00676             return MOD_ERR_NOLOAD;
00677         }
00678 
00679         mod_current_module_name = NULL;
00680     }
00681 
00682     if (u) {
00683         anope_cmd_global(s_OperServ, "%s loaded module %s", u->nick,
00684                          m->name);
00685         notice_lang(s_OperServ, u, OPER_MODULE_LOADED, m->name);
00686     }
00687     addModule(m);
00688     return MOD_ERR_OK;
00689 
00690 #else
00691     return MOD_ERR_NOLOAD;
00692 #endif
00693 }
00694 
00701 int unloadModule(Module * m, User * u)
00702 {
00703 #ifdef USE_MODULES
00704     void (*func) (void);
00705 
00706     if (!m || !m->handle) {
00707         if (u) {
00708             notice_lang(s_OperServ, u, OPER_MODULE_REMOVE_FAIL, m->name);
00709         }
00710         return MOD_ERR_PARAMS;
00711     }
00712 
00713     if (m->type == PROTOCOL) {
00714         if (u) {
00715             notice_lang(s_OperServ, u, OPER_MODULE_NO_UNLOAD);
00716         }
00717         return MOD_ERR_NOUNLOAD;
00718     } else if(m->type == ENCRYPTION) {
00719         if (u) {
00720             notice_lang(s_OperServ, u, OPER_MODULE_NO_UNLOAD);
00721         }
00722         return MOD_ERR_NOUNLOAD;
00723     }
00724 
00725     func = (void (*)(void))ano_modsym(m->handle, "AnopeFini");
00726     if (func) {
00727         mod_current_module_name = m->name;
00728         func();                 /* exec AnopeFini */
00729         mod_current_module_name = NULL;
00730     }
00731 
00732     if (prepForUnload(m) != MOD_ERR_OK) {
00733         return MOD_ERR_UNKNOWN;
00734     }
00735 
00736     if ((ano_modclose(m->handle)) != 0) {
00737         alog(ano_moderr());
00738         if (u) {
00739             notice_lang(s_OperServ, u, OPER_MODULE_REMOVE_FAIL, m->name);
00740         }
00741         return MOD_ERR_NOUNLOAD;
00742     } else {
00743         if (u) {
00744             anope_cmd_global(s_OperServ, "%s unloaded module %s", u->nick,
00745                              m->name);
00746             notice_lang(s_OperServ, u, OPER_MODULE_UNLOADED, m->name);
00747         }
00748         delModule(m);
00749         return MOD_ERR_OK;
00750     }
00751 #else
00752     return MOD_ERR_NOUNLOAD;
00753 #endif
00754 }
00755 
00760 void moduleSetType(MODType type)
00761 {
00762     if ((mod_current_module_name) && (!mod_current_module)) {
00763         mod_current_module = findModule(mod_current_module_name);
00764     }
00765     mod_current_module->type = type;
00766 }
00767 
00775 int prepForUnload(Module * m)
00776 {
00777     int idx;
00778     CommandHash *current = NULL;
00779     MessageHash *mcurrent = NULL;
00780     EvtMessageHash *ecurrent = NULL;
00781     EvtHookHash *ehcurrent = NULL;
00782 
00783     Command *c;
00784     Message *msg;
00785     EvtMessage *eMsg;
00786     EvtHook *eHook;
00787     int status = 0;
00788 
00789     if (!m) {
00790         return MOD_ERR_PARAMS;
00791     }
00792 
00793     /* Kill any active callbacks this module has */
00794     moduleCallBackPrepForUnload(m->name);
00795 
00796     /* Remove any stored data this module has */
00797     moduleDelAllDataMod(m);
00798 
00802     for (idx = 0; idx < MAX_CMD_HASH; idx++) {
00803         for (current = HS_cmdTable[idx]; current; current = current->next) {
00804             for (c = current->c; c; c = c->next) {
00805                 if ((c->mod_name) && (strcmp(c->mod_name, m->name) == 0)) {
00806                     moduleDelCommand(HOSTSERV, c->name);
00807                 }
00808             }
00809         }
00810 
00811         for (current = BS_cmdTable[idx]; current; current = current->next) {
00812             for (c = current->c; c; c = c->next) {
00813                 if ((c->mod_name) && (strcmp(c->mod_name, m->name) == 0)) {
00814                     moduleDelCommand(BOTSERV, c->name);
00815                 }
00816             }
00817         }
00818 
00819         for (current = MS_cmdTable[idx]; current; current = current->next) {
00820             for (c = current->c; c; c = c->next) {
00821                 if ((c->mod_name) && (strcmp(c->mod_name, m->name) == 0)) {
00822                     moduleDelCommand(MEMOSERV, c->name);
00823                 }
00824             }
00825         }
00826 
00827         for (current = NS_cmdTable[idx]; current; current = current->next) {
00828             for (c = current->c; c; c = c->next) {
00829                 if ((c->mod_name) && (strcmp(c->mod_name, m->name) == 0)) {
00830                     moduleDelCommand(NICKSERV, c->name);
00831                 }
00832             }
00833         }
00834 
00835         for (current = CS_cmdTable[idx]; current; current = current->next) {
00836             for (c = current->c; c; c = c->next) {
00837                 if ((c->mod_name) && (strcmp(c->mod_name, m->name) == 0)) {
00838                     moduleDelCommand(CHANSERV, c->name);
00839                 }
00840             }
00841         }
00842 
00843         for (current = HE_cmdTable[idx]; current; current = current->next) {
00844             for (c = current->c; c; c = c->next) {
00845                 if ((c->mod_name) && (strcmp(c->mod_name, m->name) == 0)) {
00846                     moduleDelCommand(HELPSERV, c->name);
00847                 }
00848             }
00849         }
00850 
00851         for (current = OS_cmdTable[idx]; current; current = current->next) {
00852             for (c = current->c; c; c = c->next) {
00853                 if ((c->mod_name) && (stricmp(c->mod_name, m->name) == 0)) {
00854                     moduleDelCommand(OPERSERV, c->name);
00855                 }
00856             }
00857         }
00858 
00859         for (mcurrent = IRCD[idx]; mcurrent; mcurrent = mcurrent->next) {
00860             for (msg = mcurrent->m; msg; msg = msg->next) {
00861                 if ((msg->mod_name)
00862                     && (stricmp(msg->mod_name, m->name) == 0)) {
00863                     moduleDelMessage(msg->name);
00864                 }
00865             }
00866         }
00867 
00868         for (ecurrent = EVENT[idx]; ecurrent; ecurrent = ecurrent->next) {
00869             for (eMsg = ecurrent->evm; eMsg; eMsg = eMsg->next) {
00870                 if ((eMsg->mod_name)
00871                     && (stricmp(eMsg->mod_name, m->name) == 0)) {
00872                     status = delEventHandler(EVENT, eMsg, m->name);
00873                 }
00874             }
00875         }
00876         for (ehcurrent = EVENTHOOKS[idx]; ehcurrent;
00877              ehcurrent = ehcurrent->next) {
00878             for (eHook = ehcurrent->evh; eHook; eHook = eHook->next) {
00879                 if ((eHook->mod_name)
00880                     && (stricmp(eHook->mod_name, m->name) == 0)) {
00881                     status = delEventHook(EVENTHOOKS, eHook, m->name);
00882                 }
00883             }
00884         }
00885 
00886     }
00887     return MOD_ERR_OK;
00888 }
00889 
00890 /*******************************************************************************
00891  * Command Functions
00892  *******************************************************************************/
00905 Command *createCommand(const char *name, int (*func) (User * u),
00906                        int (*has_priv) (User * u), int help_all,
00907                        int help_reg, int help_oper, int help_admin,
00908                        int help_root)
00909 {
00910     Command *c;
00911     if (!name || !*name) {
00912         return NULL;
00913     }
00914 
00915     if ((c = malloc(sizeof(Command))) == NULL) {
00916         fatal("Out of memory!");
00917     }
00918     c->name = sstrdup(name);
00919     c->routine = func;
00920     c->has_priv = has_priv;
00921     c->helpmsg_all = help_all;
00922     c->helpmsg_reg = help_reg;
00923     c->helpmsg_oper = help_oper;
00924     c->helpmsg_admin = help_admin;
00925     c->helpmsg_root = help_root;
00926     c->help_param1 = NULL;
00927     c->help_param2 = NULL;
00928     c->help_param3 = NULL;
00929     c->help_param4 = NULL;
00930     c->next = NULL;
00931     c->mod_name = NULL;
00932     c->service = NULL;
00933     c->all_help = NULL;
00934     c->regular_help = NULL;
00935     c->oper_help = NULL;
00936     c->admin_help = NULL;
00937     c->root_help = NULL;
00938     return c;
00939 }
00940 
00946 int destroyCommand(Command * c)
00947 {
00948     if (!c) {
00949         return MOD_ERR_PARAMS;
00950     }
00951     if (c->core == 1) {
00952         return MOD_ERR_UNKNOWN;
00953     }
00954     if (c->name) {
00955         free(c->name);
00956     }
00957     c->routine = NULL;
00958     c->has_priv = NULL;
00959     c->helpmsg_all = -1;
00960     c->helpmsg_reg = -1;
00961     c->helpmsg_oper = -1;
00962     c->helpmsg_admin = -1;
00963     c->helpmsg_root = -1;
00964     if (c->help_param1) {
00965         free(c->help_param1);
00966     }
00967     if (c->help_param2) {
00968         free(c->help_param2);
00969     }
00970     if (c->help_param3) {
00971         free(c->help_param3);
00972     }
00973     if (c->help_param4) {
00974         free(c->help_param4);
00975     }
00976     if (c->mod_name) {
00977         free(c->mod_name);
00978     }
00979     if (c->service) {
00980         free(c->service);
00981     }
00982     c->next = NULL;
00983     free(c);
00984     return MOD_ERR_OK;
00985 }
00986 
00993 int addCoreCommand(CommandHash * cmdTable[], Command * c)
00994 {
00995     if (!cmdTable || !c) {
00996         return MOD_ERR_PARAMS;
00997     }
00998     c->core = 1;
00999     c->next = NULL;
01000     return addCommand(cmdTable, c, 0);
01001 }
01002 
01012 int moduleAddCommand(CommandHash * cmdTable[], Command * c, int pos)
01013 {
01014     int status;
01015 
01016     if (!cmdTable || !c) {
01017         return MOD_ERR_PARAMS;
01018     }
01019     /* ok, this appears to be a module adding a command from outside of AnopeInit, try to look up its module struct for it */
01020     if ((mod_current_module_name) && (!mod_current_module)) {
01021         mod_current_module = findModule(mod_current_module_name);
01022     }
01023 
01024     if (!mod_current_module) {
01025         return MOD_ERR_UNKNOWN;
01026     }                           /* shouldnt happen */
01027     c->core = 0;
01028     if (!c->mod_name) {
01029         c->mod_name = sstrdup(mod_current_module->name);
01030     }
01031 
01032 
01033     if (cmdTable == HOSTSERV) {
01034         if (s_HostServ) {
01035             c->service = sstrdup(s_HostServ);
01036         } else {
01037             return MOD_ERR_NOSERVICE;
01038         }
01039     } else if (cmdTable == BOTSERV) {
01040         if (s_BotServ) {
01041             c->service = sstrdup(s_BotServ);
01042         } else {
01043             return MOD_ERR_NOSERVICE;
01044         }
01045     } else if (cmdTable == MEMOSERV) {
01046         if (s_MemoServ) {
01047             c->service = sstrdup(s_MemoServ);
01048         } else {
01049             return MOD_ERR_NOSERVICE;
01050         }
01051     } else if (cmdTable == CHANSERV) {
01052         if (s_ChanServ) {
01053             c->service = sstrdup(s_ChanServ);
01054         } else {
01055             return MOD_ERR_NOSERVICE;
01056         }
01057     } else if (cmdTable == NICKSERV) {
01058         if (s_NickServ) {
01059             c->service = sstrdup(s_NickServ);
01060         } else {
01061             return MOD_ERR_NOSERVICE;
01062         }
01063     } else if (cmdTable == HELPSERV) {
01064         if (s_HelpServ) {
01065             c->service = sstrdup(s_HelpServ);
01066         } else {
01067             return MOD_ERR_NOSERVICE;
01068         }
01069     } else if (cmdTable == OPERSERV) {
01070         if (s_OperServ) {
01071             c->service = sstrdup(s_OperServ);
01072         } else {
01073             return MOD_ERR_NOSERVICE;
01074         }
01075     } else
01076         c->service = sstrdup("Unknown");
01077 
01078     if (debug >= 2)
01079         displayCommandFromHash(cmdTable, c->name);
01080     status = addCommand(cmdTable, c, pos);
01081     if (debug >= 2)
01082         displayCommandFromHash(cmdTable, c->name);
01083     if (status != MOD_ERR_OK) {
01084         alog("ERROR! [%d]", status);
01085     }
01086     return status;
01087 }
01088 
01095 int moduleDelCommand(CommandHash * cmdTable[], char *name)
01096 {
01097     Command *c = NULL;
01098     Command *cmd = NULL;
01099     int status = 0;
01100 
01101     if (!mod_current_module) {
01102         return MOD_ERR_UNKNOWN;
01103     }
01104 
01105     c = findCommand(cmdTable, name);
01106     if (!c) {
01107         return MOD_ERR_NOEXIST;
01108     }
01109 
01110 
01111     for (cmd = c; cmd; cmd = cmd->next) {
01112         if (cmd->mod_name
01113             && stricmp(cmd->mod_name, mod_current_module->name) == 0) {
01114             if (debug >= 2) {
01115                 displayCommandFromHash(cmdTable, name);
01116             }
01117             status = delCommand(cmdTable, cmd, mod_current_module->name);
01118             if (debug >= 2) {
01119                 displayCommandFromHash(cmdTable, name);
01120             }
01121         }
01122     }
01123     return status;
01124 }
01125 
01133 int displayCommandFromHash(CommandHash * cmdTable[], char *name)
01134 {
01135     CommandHash *current = NULL;
01136     int index = 0;
01137     index = CMD_HASH(name);
01138     if (debug > 1) {
01139         alog("debug: trying to display command %s", name);
01140     }
01141     for (current = cmdTable[index]; current; current = current->next) {
01142         if (stricmp(name, current->name) == 0) {
01143             displayCommand(current->c);
01144         }
01145     }
01146     if (debug > 1) {
01147         alog("debug: done displaying command %s", name);
01148     }
01149     return 0;
01150 }
01151 
01159 int displayCommand(Command * c)
01160 {
01161     Command *cmd = NULL;
01162     int i = 0;
01163     alog("Displaying command list for %s", c->name);
01164     for (cmd = c; cmd; cmd = cmd->next) {
01165         alog("%d:  0x%p", ++i, (void *) cmd);
01166     }
01167     alog("end");
01168     return 0;
01169 }
01170 
01177 int displayMessageFromHash(char *name)
01178 {
01179     MessageHash *current = NULL;
01180     int index = 0;
01181     index = CMD_HASH(name);
01182     if (debug > 1) {
01183         alog("debug: trying to display message %s", name);
01184     }
01185     for (current = IRCD[index]; current; current = current->next) {
01186         if (stricmp(name, current->name) == 0) {
01187             displayMessage(current->m);
01188         }
01189     }
01190     if (debug > 1) {
01191         alog("debug: done displaying message %s", name);
01192     }
01193     return 0;
01194 }
01195 
01202 int displayMessage(Message * m)
01203 {
01204     Message *msg = NULL;
01205     int i = 0;
01206     alog("Displaying message list for %s", m->name);
01207     for (msg = m; msg; msg = msg->next) {