diff --git a/Changes b/Changes index d458063f5..5734cccc8 100644 --- a/Changes +++ b/Changes @@ -425,3 +425,9 @@ - Added duplicate config entry detection (#0002126) suggested by brain2 - May have a few bugs (easily fixed) - Corrected numerous -Wall warnings +- Fixed a bug with /rehash and classes due to the config parser rewrite +- Modified the module symbol dependency code to do more accurate searching for the module + that contains the necessary symbol (#0002123) suggested by Xuefer. + - Unreal will now prepend the pathname to the module and append the appropriate extension + (.so or .dll) to the end) + - The new module system version is "3.2.3" to allow for backwards compatibility diff --git a/include/h.h b/include/h.h index e6c9d2822..801a665dd 100644 --- a/include/h.h +++ b/include/h.h @@ -639,6 +639,7 @@ extern int place_host_ban(aClient *sptr, int action, char *reason, long time); extern int valid_host(char *host); extern int count_oper_sessions(char *); extern char *unreal_mktemp(char *dir, char *suffix); +extern char *unreal_getpathname(char *filepath, char *path); extern char *unreal_getfilename(char *path); extern int unreal_copyfile(char *src, char *dest); extern time_t unreal_getfilemodtime(char *filename); diff --git a/include/modules.h b/include/modules.h index 95771a893..fcbf636c5 100644 --- a/include/modules.h +++ b/include/modules.h @@ -21,23 +21,24 @@ #ifndef MODULES_H #define MODULES_H #include "types.h" -#define MOD_VERSION "3.2-b5-1" -#define MOD_WE_SUPPORT "3.2-b5*" #define MAXCUSTOMHOOKS 30 #define MAXHOOKTYPES 100 #define MAXCALLBACKS 30 #if defined(_WIN32) + #define MOD_EXTENSION "dll" #define DLLFUNC _declspec(dllexport) #define irc_dlopen(x,y) LoadLibrary(x) #define irc_dlclose FreeLibrary #define irc_dlsym(x,y,z) z = (void *)GetProcAddress(x,y) #define irc_dlerror our_dlerror #elif defined(HPUX) + #define MOD_EXTENSION "so" #define irc_dlopen(x,y) shl_load(x,y,0L) #define irc_dlsym(x,y,z) shl_findsym(x,y,z) #define irc_dlclose shl_unload #define irc_dlerror() strerror(errno) #else + #define MOD_EXTENSION "so" #define irc_dlopen dlopen #define irc_dlclose dlclose #if defined(UNDERSCORE) @@ -381,6 +382,7 @@ struct _Module unsigned char options; unsigned char errorcode; char *tmp_file; + unsigned long mod_sys_version; }; /* * Symbol table diff --git a/src/modules.c b/src/modules.c index d968d4faa..3e8d7c8ac 100644 --- a/src/modules.c +++ b/src/modules.c @@ -62,7 +62,7 @@ Callback *RCallbacks[MAXCALLBACKS]; /* 'Real' callback function, used for callba MODVAR Module *Modules = NULL; MODVAR Versionflag *Versionflags = NULL; -int Module_Depend_Resolve(Module *p); +int Module_Depend_Resolve(Module *p, char *path); Module *Module_make(ModuleHeader *header, #ifdef _WIN32 HMODULE mod @@ -171,6 +171,30 @@ static char retbuf[128]; return retbuf; } +int parse_modsys_version(char *version) +{ + int betaversion, tag; + if (!strcmp(version, "3.2.3")) + return 0x32300; + if (sscanf(version, "3.2-b%d-%d", &betaversion, &tag)) + { + switch (betaversion) + { + case 5: + return 0x320b5; + case 6: + return 0x320b6; + case 7: + return 0x320b7; + case 8: + return 0x320b8; + default: + return 0; + } + } + return 0; +} + /* * Returns an error if insucessful .. yes NULL is OK! */ @@ -189,11 +213,11 @@ char *Module_Create(char *path_) char *Mod_Version; static char errorbuf[1024]; char *path, *tmppath; - ModuleHeader *mod_header; + ModuleHeader *mod_header = NULL; int ret = 0; Module *mod = NULL, **Mod_Handle = NULL; - int betaversion,tag; char *expectedmodversion = our_mod_version(); + long modsys_ver = 0; Debug((DEBUG_DEBUG, "Attempting to load module from %s", path_)); path = path_; @@ -243,14 +267,13 @@ char *Module_Create(char *path_) remove(tmppath); return ("Lacking mod_header->modversion"); } - if (sscanf(mod_header->modversion, "3.2-b%d-%d", &betaversion, &tag)) { - if (betaversion < 5 || betaversion >8) { - snprintf(errorbuf, 1023, "Unsupported version, we support %s, %s is %s", - MOD_WE_SUPPORT, path, mod_header->modversion); - irc_dlclose(Mod); - remove(tmppath); - return(errorbuf); - } + if (!(modsys_ver = parse_modsys_version(mod_header->modversion))) + { + snprintf(errorbuf, 1023, "Unsupported module system version '%s'", + mod_header->modversion); + irc_dlclose(Mod); + remove(tmppath); + return(errorbuf); } if (!mod_header->name || !mod_header->version || !mod_header->description) @@ -267,6 +290,7 @@ char *Module_Create(char *path_) } mod = (Module *)Module_make(mod_header, Mod); mod->tmp_file = strdup(tmppath); + mod->mod_sys_version = modsys_ver; irc_dlsym(Mod, "Mod_Init", Mod_Init); if (!Mod_Init) { @@ -285,7 +309,7 @@ char *Module_Create(char *path_) Module_free(mod); return ("Unable to locate Mod_Load"); } - if (Module_Depend_Resolve(mod) == -1) + if (Module_Depend_Resolve(mod, path) == -1) { Module_free(mod); return ("Dependancy problem"); @@ -296,7 +320,7 @@ char *Module_Create(char *path_) irc_dlsym(Mod, "Mod_Test", Mod_Test); if (Mod_Test) { - if (betaversion >= 8) { + if (mod->mod_sys_version >= 0x320b8) { if ((ret = (*Mod_Test)(&mod->modinfo)) < MOD_SUCCESS) { ircsprintf(errorbuf, "Mod_Test returned %i", ret); @@ -365,6 +389,7 @@ Module *Module_make(ModuleHeader *header, modp->modinfo.size = sizeof(ModuleInfo); modp->modinfo.module_load = 0; modp->modinfo.handle = modp; + return (modp); } @@ -372,7 +397,7 @@ void Init_all_testing_modules(void) { Module *mi, *next; - int betaversion, tag, ret; + int ret; iFP Mod_Init; for (mi = Modules; mi; mi = next) { @@ -380,8 +405,7 @@ void Init_all_testing_modules(void) if (!(mi->flags & MODFLAG_TESTING)) continue; irc_dlsym(mi->dll, "Mod_Init", Mod_Init); - sscanf(mi->header->modversion, "3.2-b%d-%d", &betaversion, &tag); - if (betaversion >= 8) { + if (mi->mod_sys_version >= 0x320b8) { if ((ret = (*Mod_Init)(&mi->modinfo)) < MOD_SUCCESS) { config_error("Error loading %s: Mod_Init returned %i", mi->header->name, ret); @@ -786,15 +810,13 @@ inline void Module_AddAsChild(Module *parent, Module *child) AddListItem(childp, parent->children); } -int Module_Depend_Resolve(Module *p) +int Module_Depend_Resolve(Module *p, char *path) { Mod_SymbolDepTable *d = p->header->symdep; Module *parental = NULL; if (d == NULL) - { return 0; - } #ifndef STATIC_LINKING while (d->pointer) { @@ -806,8 +828,22 @@ int Module_Depend_Resolve(Module *p) *(d->pointer) = Module_SymX(d->symbol, &parental); if (!*(d->pointer)) { - config_progress("Unable to resolve symbol %s, attempting to load %s to find it", d->symbol, d->module); - Module_Create(d->module); + /* If >= 3.2.3 */ + if (p->mod_sys_version >= 0x32300) + { + char tmppath[PATH_MAX], curpath[PATH_MAX]; + + unreal_getpathname(path, curpath); + snprintf(tmppath, PATH_MAX, "%s/%s.%s", curpath, d->module, + MOD_EXTENSION); + config_progress("Unable to resolve symbol %s, attempting to load %s to find it", d->symbol, tmppath); + Module_Create(tmppath); + } + else + { + config_progress("Unable to resolve symbol %s, attempting to load %s to find it", d->symbol, d->module); + Module_Create(d->module); + } *(d->pointer) = Module_SymX(d->symbol, &parental); if (!*(d->pointer)) { config_progress("module dependancy error: cannot resolve symbol %s", diff --git a/src/s_conf.c b/src/s_conf.c index f0442ba8f..3bec5ea95 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -3368,8 +3368,19 @@ int _conf_class(ConfigFile *conf, ConfigEntry *ce) { ConfigEntry *cep; ConfigItem_class *class; + unsigned char isnew = 0; - class = MyMallocEx(sizeof(ConfigItem_class)); + if (!(class = Find_class(ce->ce_vardata))) + { + class = MyMallocEx(sizeof(ConfigItem_class)); + ircstrdup(class->name, ce->ce_vardata); + isnew = 1; + } + else + { + isnew = 0; + class->flag.temporary = 0; + } ircstrdup(class->name, ce->ce_vardata); for (cep = ce->ce_entries; cep; cep = cep->ce_next) @@ -3385,7 +3396,8 @@ int _conf_class(ConfigFile *conf, ConfigEntry *ce) else if (!strcmp(cep->ce_varname, "recvq")) class->recvq = atol(cep->ce_vardata); } - AddListItem(class, conf_class); + if (isnew) + AddListItem(class, conf_class); return 1; } diff --git a/src/support.c b/src/support.c index 9c1b70424..f1df36809 100644 --- a/src/support.c +++ b/src/support.c @@ -1693,6 +1693,32 @@ char *unreal_mktemp(char *dir, char *suffix) return NULL; } +/* Returns the path portion of the given path/file + * in the specified location (must be at least PATH_MAX + * bytes). + */ +char *unreal_getpathname(char *filepath, char *path) +{ + char *end = filepath+strlen(filepath); + + while (*end != '\\' && *end != '/' && end > filepath) + end--; + if (end == filepath) + path = NULL; + else + { + int size = end-filepath; + if (size >= PATH_MAX) + path = NULL; + else + { + memcpy(path, filepath, size); + path[size] = 0; + } + } + return path; +} + /* Returns the filename portion of the given path * The original string is not modified */