| /* | 
 |  * xmlmodule.c : basic API for dynamic module loading added 2.6.17 | 
 |  * | 
 |  * See Copyright for the status of this software. | 
 |  * | 
 |  * joelwreed@comcast.net | 
 |  * | 
 |  * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html | 
 |  */ | 
 |  | 
 | #define IN_LIBXML | 
 | #include "libxml.h" | 
 |  | 
 | #include <string.h> | 
 | #include <libxml/xmlmemory.h> | 
 | #include <libxml/xmlerror.h> | 
 | #include <libxml/xmlmodule.h> | 
 | #include <libxml/globals.h> | 
 |  | 
 | #ifdef LIBXML_MODULES_ENABLED | 
 |  | 
 | struct _xmlModule { | 
 |     unsigned char *name; | 
 |     void *handle; | 
 | }; | 
 |  | 
 | static void *xmlModulePlatformOpen(const char *name); | 
 | static int xmlModulePlatformClose(void *handle); | 
 | static int xmlModulePlatformSymbol(void *handle, const char *name, void **result); | 
 |  | 
 | /************************************************************************ | 
 |  *									* | 
 |  * 		module memory error handler				* | 
 |  *									* | 
 |  ************************************************************************/ | 
 |  | 
 | /** | 
 |  * xmlModuleErrMemory: | 
 |  * @extra:  extra information | 
 |  * | 
 |  * Handle an out of memory condition | 
 |  */ | 
 | static void | 
 | xmlModuleErrMemory(xmlModulePtr module, const char *extra) | 
 | { | 
 |     const char *name = NULL; | 
 |  | 
 |     if (module != NULL) { | 
 |         name = (const char *) module->name; | 
 |     } | 
 |  | 
 |     __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, | 
 |                     XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra, | 
 |                     name, NULL, 0, 0, | 
 |                     "Memory allocation failed : %s\n", extra); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlModuleOpen: | 
 |  * @name: the module name | 
 |  * @options: a set of xmlModuleOption | 
 |  * | 
 |  * Opens a module/shared library given its name or path | 
 |  * TODO: options are not yet implemented. | 
 |  * | 
 |  * Returns a handle for the module or NULL in case of error | 
 |  */ | 
 | xmlModulePtr | 
 | xmlModuleOpen(const char *name, int options ATTRIBUTE_UNUSED) | 
 | { | 
 |     xmlModulePtr module; | 
 |  | 
 |     module = (xmlModulePtr) xmlMalloc(sizeof(xmlModule)); | 
 |     if (module == NULL) { | 
 |         xmlModuleErrMemory(NULL, "creating module"); | 
 |         return (NULL); | 
 |     } | 
 |  | 
 |     memset(module, 0, sizeof(xmlModule)); | 
 |  | 
 |     module->handle = xmlModulePlatformOpen(name); | 
 |  | 
 |     if (module->handle == NULL) { | 
 |         xmlFree(module); | 
 |         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, | 
 |                         XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0, | 
 |                         name, NULL, 0, 0, "failed to open %s\n", name); | 
 |         return(NULL); | 
 |     } | 
 |  | 
 |     module->name = xmlStrdup((const xmlChar *) name); | 
 |     return (module); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlModuleSymbol: | 
 |  * @module: the module | 
 |  * @name: the name of the symbol | 
 |  * @symbol: the resulting symbol address | 
 |  * | 
 |  * Lookup for a symbol address in the given module | 
 |  * | 
 |  * Returns 0 if the symbol was found, or -1 in case of error | 
 |  */ | 
 | int | 
 | xmlModuleSymbol(xmlModulePtr module, const char *name, void **symbol) | 
 | { | 
 |     int rc = -1; | 
 | 	 | 
 |     if ((NULL == module) || (symbol == NULL)) { | 
 |         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, | 
 |                         XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0, | 
 |                         NULL, NULL, 0, 0, "null parameter\n"); | 
 |         return rc; | 
 |     } | 
 |  | 
 |     rc = xmlModulePlatformSymbol(module->handle, name, symbol); | 
 |  | 
 |     if (rc == -1) { | 
 |         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, | 
 |                         XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0, | 
 |                         name, NULL, 0, 0, | 
 |                         "failed to find symbol: %s\n", | 
 | 			(name == NULL ? "NULL" : name)); | 
 |         return rc; | 
 |     } | 
 |  | 
 |     return rc; | 
 | } | 
 |  | 
 | /** | 
 |  * xmlModuleClose: | 
 |  * @module: the module handle | 
 |  * | 
 |  * The close operations unload the associated module and free the | 
 |  * data associated to the module. | 
 |  * | 
 |  * Returns 0 in case of success, -1 in case of argument error and -2 | 
 |  *         if the module could not be closed/unloaded. | 
 |  */ | 
 | int | 
 | xmlModuleClose(xmlModulePtr module) | 
 | { | 
 |     int rc; | 
 |  | 
 |     if (NULL == module) { | 
 |         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, | 
 |                         XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0, | 
 |                         NULL, NULL, 0, 0, "null module pointer\n"); | 
 |         return -1; | 
 |     } | 
 |  | 
 |     rc = xmlModulePlatformClose(module->handle); | 
 |  | 
 |     if (rc != 0) { | 
 |         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, | 
 |                         XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0, | 
 |                         (const char *) module->name, NULL, 0, 0, | 
 |                         "failed to close: %s\n", module->name); | 
 |         return -2; | 
 |     } | 
 |  | 
 |     rc = xmlModuleFree(module); | 
 |     return (rc); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlModuleFree: | 
 |  * @module: the module handle | 
 |  * | 
 |  * The free operations free the data associated to the module | 
 |  * but does not unload the associated shared library which may still | 
 |  * be in use. | 
 |  * | 
 |  * Returns 0 in case of success, -1 in case of argument error | 
 |  */ | 
 | int | 
 | xmlModuleFree(xmlModulePtr module) | 
 | { | 
 |     if (NULL == module) { | 
 |         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, | 
 |                         XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, NULL, | 
 |                         NULL, NULL, 0, 0, "null module pointer\n"); | 
 |         return -1; | 
 |     } | 
 |  | 
 |     xmlFree(module->name); | 
 |     xmlFree(module); | 
 |  | 
 |     return (0); | 
 | } | 
 |  | 
 | #if defined(HAVE_DLOPEN) && !defined(_WIN32) | 
 | #ifdef HAVE_DLFCN_H | 
 | #include <dlfcn.h> | 
 | #endif | 
 |  | 
 | #ifndef RTLD_GLOBAL            /* For Tru64 UNIX 4.0 */ | 
 | #define RTLD_GLOBAL 0 | 
 | #endif | 
 |  | 
 | /** | 
 |  * xmlModulePlatformOpen: | 
 |  * @name: path to the module | 
 |  * | 
 |  * returns a handle on success, and zero on error. | 
 |  */ | 
 |  | 
 | static void * | 
 | xmlModulePlatformOpen(const char *name) | 
 | { | 
 |     return dlopen(name, RTLD_GLOBAL | RTLD_NOW); | 
 | } | 
 |  | 
 | /* | 
 |  * xmlModulePlatformClose: | 
 |  * @handle: handle to the module | 
 |  * | 
 |  * returns 0 on success, and non-zero on error. | 
 |  */ | 
 |  | 
 | static int | 
 | xmlModulePlatformClose(void *handle) | 
 | { | 
 |     return dlclose(handle); | 
 | } | 
 |  | 
 | /* | 
 |  * xmlModulePlatformSymbol: | 
 |  * http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html | 
 |  * returns 0 on success and the loaded symbol in result, and -1 on error. | 
 |  */ | 
 |  | 
 | static int | 
 | xmlModulePlatformSymbol(void *handle, const char *name, void **symbol) | 
 | { | 
 |     *symbol = dlsym(handle, name); | 
 |     if (dlerror() != NULL) { | 
 | 	return -1; | 
 |     } | 
 |     return 0; | 
 | } | 
 |  | 
 | #else /* ! HAVE_DLOPEN */ | 
 |  | 
 | #ifdef HAVE_SHLLOAD             /* HAVE_SHLLOAD */ | 
 | #ifdef HAVE_DL_H | 
 | #include <dl.h> | 
 | #endif | 
 | /* | 
 |  * xmlModulePlatformOpen: | 
 |  * returns a handle on success, and zero on error. | 
 |  */ | 
 |  | 
 | static void * | 
 | xmlModulePlatformOpen(const char *name) | 
 | { | 
 |     return shl_load(name, BIND_IMMEDIATE, 0L); | 
 | } | 
 |  | 
 | /* | 
 |  * xmlModulePlatformClose: | 
 |  * returns 0 on success, and non-zero on error. | 
 |  */ | 
 |  | 
 | static int | 
 | xmlModulePlatformClose(void *handle) | 
 | { | 
 |     return shl_unload(handle); | 
 | } | 
 |  | 
 | /* | 
 |  * xmlModulePlatformSymbol: | 
 |  * http://docs.hp.com/en/B2355-90683/shl_load.3X.html | 
 |  * returns 0 on success and the loaded symbol in result, and -1 on error. | 
 |  */ | 
 |  | 
 | static int | 
 | xmlModulePlatformSymbol(void *handle, const char *name, void **symbol) | 
 | { | 
 |     int rc; | 
 |  | 
 |     errno = 0; | 
 |     rc = shl_findsym(&handle, name, TYPE_UNDEFINED, symbol); | 
 |     return rc; | 
 | } | 
 |  | 
 | #endif /* HAVE_SHLLOAD */ | 
 | #endif /* ! HAVE_DLOPEN */ | 
 |  | 
 | #ifdef _WIN32 | 
 |  | 
 | #include <windows.h> | 
 |  | 
 | /* | 
 |  * xmlModulePlatformOpen: | 
 |  * returns a handle on success, and zero on error. | 
 |  */ | 
 |  | 
 | static void * | 
 | xmlModulePlatformOpen(const char *name) | 
 | { | 
 |     return LoadLibrary(name); | 
 | } | 
 |  | 
 | /* | 
 |  * xmlModulePlatformClose: | 
 |  * returns 0 on success, and non-zero on error. | 
 |  */ | 
 |  | 
 | static int | 
 | xmlModulePlatformClose(void *handle) | 
 | { | 
 |     int rc; | 
 |  | 
 |     rc = FreeLibrary(handle); | 
 |     return (0 == rc); | 
 | } | 
 |  | 
 | /* | 
 |  * xmlModulePlatformSymbol: | 
 |  * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/getprocaddress.asp | 
 |  * returns 0 on success and the loaded symbol in result, and -1 on error. | 
 |  */ | 
 |  | 
 | static int | 
 | xmlModulePlatformSymbol(void *handle, const char *name, void **symbol) | 
 | { | 
 |     *symbol = GetProcAddress(handle, name); | 
 |     return (NULL == *symbol) ? -1 : 0; | 
 | } | 
 |  | 
 | #endif /* _WIN32 */ | 
 |  | 
 | #ifdef HAVE_BEOS | 
 |  | 
 | #include <kernel/image.h> | 
 |  | 
 | /* | 
 |  * xmlModulePlatformOpen: | 
 |  * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html | 
 |  * returns a handle on success, and zero on error. | 
 |  */ | 
 |  | 
 | static void * | 
 | xmlModulePlatformOpen(const char *name) | 
 | { | 
 |     return (void *) load_add_on(name); | 
 | } | 
 |  | 
 | /* | 
 |  * xmlModulePlatformClose: | 
 |  * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html | 
 |  * returns 0 on success, and non-zero on error. | 
 |  */ | 
 |  | 
 | static int | 
 | xmlModulePlatformClose(void *handle) | 
 | { | 
 |     status_t rc; | 
 |  | 
 |     rc = unload_add_on((image_id) handle); | 
 |  | 
 |     if (rc == B_OK) | 
 |         return 0; | 
 |     else | 
 |         return -1; | 
 | } | 
 |  | 
 | /* | 
 |  * xmlModulePlatformSymbol: | 
 |  * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html | 
 |  * returns 0 on success and the loaded symbol in result, and -1 on error. | 
 |  */ | 
 |  | 
 | static int | 
 | xmlModulePlatformSymbol(void *handle, const char *name, void **symbol) | 
 | { | 
 |     status_t rc; | 
 |  | 
 |     rc = get_image_symbol((image_id) handle, name, B_SYMBOL_TYPE_ANY, symbol); | 
 |  | 
 |     return (rc == B_OK) ? 0 : -1; | 
 | } | 
 |  | 
 | #endif /* HAVE_BEOS */ | 
 |  | 
 | #ifdef HAVE_OS2 | 
 |  | 
 | #include <os2.h> | 
 |  | 
 | /* | 
 |  * xmlModulePlatformOpen: | 
 |  * os2 api info: http://www.edm2.com/os2api/Dos/DosLoadModule.html | 
 |  * returns a handle on success, and zero on error. | 
 |  */ | 
 |  | 
 | static void * | 
 | xmlModulePlatformOpen(const char *name) | 
 | { | 
 |     char errbuf[256]; | 
 |     void *handle; | 
 |     int rc; | 
 |  | 
 |     rc = DosLoadModule(errbuf, sizeof(errbuf) - 1, name, &handle); | 
 |  | 
 |     if (rc) | 
 |         return 0; | 
 |     else | 
 |         return (handle); | 
 | } | 
 |  | 
 | /* | 
 |  * xmlModulePlatformClose: | 
 |  * os2 api info: http://www.edm2.com/os2api/Dos/DosFreeModule.html | 
 |  * returns 0 on success, and non-zero on error. | 
 |  */ | 
 |  | 
 | static int | 
 | xmlModulePlatformClose(void *handle) | 
 | { | 
 |     return DosFreeModule(handle); | 
 | } | 
 |  | 
 | /* | 
 |  * xmlModulePlatformSymbol: | 
 |  * os2 api info: http://www.edm2.com/os2api/Dos/DosQueryProcAddr.html | 
 |  * returns 0 on success and the loaded symbol in result, and -1 on error. | 
 |  */ | 
 |  | 
 | static int | 
 | xmlModulePlatformSymbol(void *handle, const char *name, void **symbol) | 
 | { | 
 |     int rc; | 
 |  | 
 |     rc = DosQueryProcAddr(handle, 0, name, symbol); | 
 |  | 
 |     return (rc == NO_ERROR) ? 0 : -1; | 
 | } | 
 |  | 
 | #endif /* HAVE_OS2 */ | 
 |  | 
 | #define bottom_xmlmodule | 
 | #include "elfgcchack.h" | 
 | #endif /* LIBXML_MODULES_ENABLED */ |