/* Copyright (C) 2008 Andreas Baumann This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "library/loader.h" #include "errors.h" #include "port/sys_internal.h" #include "port/stdlib.h" /* for malloc, free */ #include "port/stdio.h" /* for snprintf */ #include "port/string.h" /* for strncpy */ #include "i18n/gettext.h" /* for i18n */ /* check for type of dynamic loading interface */ #if !defined _WIN32 #if !defined HAVE_DLFCN #error Unkown dynamic loading interface on this platform, port first. #endif #endif #if defined HAVE_DLFCN #include /* for dlopen. dlclose functions */ #if defined NEEDS_LINK_H //#include #endif #endif #if defined _WIN32 #define WIN32_MEAN_AND_LEAN #include #endif #define INTERNAL_ERRBUF_SIZE 256 struct wolf_library_t { #if defined HAVE_DLFCN void *handle; /**< the OS handle for a library */ #endif #if defined _WIN32 HMODULE handle; /**< the windows handle for a library */ #endif char errbuf[INTERNAL_ERRBUF_SIZE]; /**< internal buffer to hold the error message * we get with dlerror */ }; wolf_library_p wolf_library_load( const char *name, wolf_error_t *error ) { wolf_library_p l; int flags = 0; l = (struct wolf_library_t *)malloc( sizeof ( struct wolf_library_t ) ); if( l == NULL ) { *error = WOLF_ERR_OUT_OF_MEMORY; return NULL; } #if defined HAVE_DLFCN /* TODO: Apache has a flags variable and a direct parameter version, find out why.. * also make up our mind how many flags we should "leak" to the application layer */ flags = RTLD_NOW | RTLD_LOCAL; l->handle = dlopen( name, flags ); if( l->handle == NULL ) { strncpy( l->errbuf, dlerror( ), INTERNAL_ERRBUF_SIZE ); *error = WOLF_ERR_INTERNAL; return l; } #endif /* defined HAVE_DLFCN */ #if defined _WIN32 l->handle = LoadLibrary( name ); if( l->handle == NULL ) { wolf_system_error_msg( l->errbuf, INTERNAL_ERRBUF_SIZE ); *error = WOLF_ERR_INTERNAL; return l; } #endif /* defined _WIN32 */ *error = WOLF_OK; return l; } wolf_error_t wolf_library_unload( wolf_library_p l ) { #if !defined _WIN32 int res = 0; #else BOOL res = FALSE; #endif if( l == NULL ) { return WOLF_OK; } if( l->handle == NULL ) { return WOLF_ERR_INVALID_STATE; } #if defined HAVE_DLFCN res = dlclose( l->handle ); if( res != 0 ) { strncpy( l->errbuf, dlerror( ), INTERNAL_ERRBUF_SIZE ); return WOLF_ERR_INTERNAL; } #endif /* defined HAVE_DLFCN */ #if defined _WIN32 res = FreeLibrary( l->handle ); if( !res ) { wolf_system_error_msg( l->errbuf, INTERNAL_ERRBUF_SIZE ); return WOLF_ERR_INTERNAL; } #endif /* defined _WIN32 */ free( l ); l = NULL; return WOLF_OK; } char *wolf_library_error_msg( const wolf_library_p library, char *buf, size_t buflen ) { strncpy( buf, library->errbuf, buflen ); return buf; } WOLF_LIBRARY_FUNCPTR wolf_library_get( const wolf_library_p l, const char *name, wolf_error_t *error ) { WOLF_LIBRARY_FUNCPTR ret; #if !defined _WIN32 WOLF_LIBRARY_DLERROR_CONST char *err = NULL; #endif /* !defined _WIN32 */ #if defined HAVE_DLFCN /* clear error state before calling dlsym, so that calling dlsym * can return a NULL as value of a symbol */ (void)dlerror( ); ret = dlsym( l->handle, name ); err = dlerror( ); if( err != NULL ) { strncpy( l->errbuf, err, INTERNAL_ERRBUF_SIZE ); *error = WOLF_ERR_INTERNAL; return ret; } #endif /* defined HAVE_DLFCN */ #if defined _WIN32 ret = GetProcAddress( l->handle, name ); if( ret == NULL ) { wolf_system_error_msg( l->errbuf, INTERNAL_ERRBUF_SIZE ); *error = WOLF_ERR_INTERNAL; return ret; } #endif /* defined _WIN32 */ *error = WOLF_OK; return ret; }