/* Copyright (C) 2010 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 "port/sys_internal.h" #include "port/unused.h" #include "port/stdlib.h" /* for malloc, free */ #include "port/stdio.h" /* for snprintf */ #include "port/gettext.h" /* for i18n */ #include "port/string.h" /* for strncpy */ #ifdef HAVE_DLFCN #include /* for dlopen. dlclose functions */ #endif #define INTERNAL_ERRBUF_SIZE 256 struct wolf_library_t { void *handle; /**< the OS handle for the library */ 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; } #else #error Not using DLFCN as shared loader. Port first! #endif *error = WOLF_OK; return l; } wolf_error_t wolf_library_unload( wolf_library_p l ) { int res = 0; if( l == NULL || l->handle == NULL ) { return WOLF_ERR_INVALID_STATE; } res = dlclose( l->handle ); if( res != 0 ) { strncpy( l->errbuf, dlerror( ), INTERNAL_ERRBUF_SIZE ); return WOLF_ERR_INTERNAL; } free( l ); l = NULL; return WOLF_OK; } char *wolf_library_errmsg( const wolf_error_t error, const wolf_library_p library, char *buf, size_t buflen ) { (void)wolf_error_msg( error, buf, buflen ); strncat( buf, " - ", buflen - strlen( buf ) ); if( error == WOLF_ERR_INTERNAL ) { strncat( buf, library->errbuf, buflen - strlen( buf ) ); } return buf; } void *wolf_library_get( const wolf_library_p l, const char *name, wolf_error_t *error ) { void *ret; ret = dlsym( l->handle, name ); *error = WOLF_OK; return ret; }