blob: 798ae4673792eb51dec0cc29b1633a2fbd5f5feb [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2004-2006 Intel Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corp. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
/**
* @author Anas Nashif
*/
#ifdef HAVE_CONFIG_H
#include <wsman_config.h>
#endif
#include "stdlib.h"
#include "stdio.h"
#include <string.h>
#ifdef HAVE_DIRENT_H
#include <dirent.h>
#endif
#ifndef WIN32
#include <dlfcn.h>
#endif
#include "u/libu.h"
#include "wsman-plugins.h"
static list_t*
scan_files_in_dir ( const char *dir, int (*select)(const struct dirent *))
{
struct dirent **namelist;
int n;
list_t *files = list_create(LISTCOUNT_T_MAX);
if (0 > (n = scandir (dir, &namelist, 0, alphasort)))
{
return files;
} else {
while (n--)
{
lnode_t *node;
char *tmp = u_strdup(namelist[n]->d_name);
node = lnode_create(tmp);
list_append(files, node );
//debug("plugin file found: %s", namelist[n]->d_name );
u_free(namelist[n]);
}
u_free(namelist);
}
return files;
}
static WsManPlugin*
plugin_new(void)
{
WsManPlugin *self = u_malloc(sizeof(WsManPlugin));
if (self) {
memset(self, 0, sizeof(WsManPlugin));
}
return self ;
}
static void
plugin_free(WsManPlugin *self)
{
message( "Un-loading plugins: %s", self->p_name );
if( self->p_handle && self->cleanup ) {
(*self->cleanup)( self->p_handle, self->data );
}
if(self->p_name)
u_free(self->p_name);
if( self->p_handle )
dlclose( self->p_handle );
}
static WsManPluginError
plugin_init(WsManPlugin *self, const char *p_name)
{
WsManPluginError PluginError = PLUGIN_ERROR_OK ;
self->p_name = u_strdup(p_name) ;
if (NULL != (self->p_handle = dlopen(p_name, RTLD_LAZY))) {
self->init = dlsym(self->p_handle, "init");
self->get_endpoints = dlsym(self->p_handle, "get_endpoints");
if ( ! self->get_endpoints
&& ! self->init)
{
self->init = 0 ;
PluginError = PLUGIN_ERROR_SYMBOLSNOTFOUND ;
}
} else {
PluginError = PLUGIN_ERROR_NOTLOADED ;
}
return PluginError ;
}
static int
load_plugin(WsManPlugin *self, const char *p_name)
{
int retv = -1;
WsManPluginError err = plugin_init(self, p_name);
const char *plugin_err = dlerror();
message("Loading plugin: %s", p_name );
if( NULL == plugin_err )
plugin_err = "";
switch( err )
{
default:
debug( "Unable to load plugin %s. Error: %s", p_name, plugin_err );
break;
case PLUGIN_ERROR_NOTLOADED:
debug( "Unable to load plugin %s. Error: %s", p_name, plugin_err );
break;
case PLUGIN_ERROR_SYMBOLSNOTFOUND:
debug( "Plugin protocol %s unknown Error:%s", p_name, plugin_err );
break;
case PLUGIN_ERROR_INITFAILED:
debug("Unable to start plugin %s", p_name );
break;
case PLUGIN_ERROR_BADPARMS:
debug( "Bad parameters to plugin %s. Error: %s", p_name, plugin_err );
break;
case PLUGIN_ERROR_OK:
retv = 0 ;
break;
}
if( retv < 0 )
debug("Unable to load plugin %s.Error: %s", p_name, plugin_err);
return retv ;
}
static void
free_plugins(list_t * plugin_list)
{
lnode_t *p;
if (plugin_list == NULL) {
return;
}
if (list_isempty(plugin_list)) {
return;
}
p = list_first(plugin_list);
while (p) {
WsManPlugin *plugin = (WsManPlugin *)p->list_data;
plugin_free(plugin);
p = list_next(plugin_list, p);
}
list_destroy_nodes(plugin_list);
list_destroy(plugin_list);
}
static int
select_all_files (const struct dirent *e)
{
return 1;
}
static void
scan_plugins_in_directory ( WsManListenerH *listener,
const char *dir_name)
{
list_t *files = scan_files_in_dir ( dir_name, select_all_files);
lnode_t *node = list_first(files);
listener->plugins = list_create(LISTCOUNT_T_MAX);
while (node != NULL)
{
const char* entry_name;
int retv = -1;
entry_name = (const char*) node->list_data;
node = list_next(files, node);
if ((NULL != entry_name) && strlen (entry_name) > strlen(PLUGIN_EXT)
&& (0 == strcmp (&entry_name[strlen(entry_name)-strlen(PLUGIN_EXT)], PLUGIN_EXT)))
{
char *plugin_path = u_strdup_printf ("%s/%s", dir_name, entry_name);
WsManPlugin *plugin = plugin_new();
if ((NULL != plugin) && (NULL != plugin_path))
{
if (load_plugin(plugin, plugin_path) == 0 )
{
lnode_t *plg = lnode_create (plugin);
list_append (listener->plugins, plg);
retv = 0 ;
}
} else {
error("Out of memory scanning for plugins.");
}
if (plugin_path)
u_free (plugin_path);
if (retv != 0 && (NULL != plugin))
plugin_free(plugin);
}
}
list_destroy_nodes(files);
list_destroy(files);
return;
}
int
wsman_plugins_load(WsManListenerH *listener)
{
char *plugin_dir = iniparser_getstring(listener->config, "server:plugin_dir", PACKAGE_PLUGIN_DIR);
debug("using plugin directory: %s", plugin_dir);
scan_plugins_in_directory(listener, plugin_dir);
return 0;
}
int
wsman_plugins_unload(WsManListenerH *listener)
{
free_plugins(listener->plugins);
// list_destroy(listener->plugins);
return 0;
}