/* * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270 * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a * aplicativos mainframe. Registro no INPI sob o nome G3270. * * Copyright (C) <2008> * * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela * Free Software Foundation. * * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para * obter mais detalhes. * * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este * programa; se não, escreva para a Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA, 02111-1307, USA * * Este programa está nomeado como plugin.c e possui 538 linhas de código. * * Contatos: * * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça) * licinio@bb.com.br (Licínio Luis Branco) * kraucer@bb.com.br (Kraucer Fernandes Mazuco) * macmiranda@bb.com.br (Marco Aurélio Caldas Miranda) * */ #include #include #include // #include #include "gui.h" // #include #include /*---[ Structs ]------------------------------------------------------------------------------------------------*/ struct call_parameter { const gchar *name; const gchar *arg; }; /* struct custom_action_call { GtkUIManager *ui; GtkActionGroup **groups; guint n_groups; GKeyFile *conf; } custom_action_call; */ /*---[ Globals ]------------------------------------------------------------------------------------------------*/ #ifdef HAVE_PLUGINS static GSList *plugins = NULL; gchar *plugin_list = NULL; gchar *plugin_path = NULL; #endif /*---[ Implement ]----------------------------------------------------------------------------------------------*/ #ifdef HAVE_PLUGINS static void load_plugin(const gchar *filename) { GModule *handle; Trace("Loading plugin in %s",filename); handle = g_module_open(filename,G_MODULE_BIND_LOCAL); Trace("Handle for %s: %p",filename,handle); if(handle) { PW3270_PLUGIN_VERSION_INFO *info = NULL; if(g_module_symbol(handle, "pw3270_plugin_version_info", (gpointer) &info)) { Trace("%s info: Revision: %d Version: %s Description: \"%s\"",filename,info->rev,info->vrs,info->descr); if(info->rev < PW3270_PLUGIN_REQUIRED_REVISION) { // Incompatible or outdated plugin GtkWidget *dialog; Log("Plugin \"%s\" can't be loaded: Revision: %d Version: %s Description: \"%s\"",filename,info->rev,info->vrs,info->descr); dialog = gtk_message_dialog_new( GTK_WINDOW(topwindow), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _( "The plugin \"%s\" is incompatible or outdated." ), info->descr ? info->descr : filename); gtk_window_set_title(GTK_WINDOW(dialog), _( "Can't load plugin" ) ); gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), _( "It was designed for pw3270 version %s (Revision %d)\nand can't be loaded in current application level." ),info->vrs,info->rev); gtk_dialog_run(GTK_DIALOG (dialog)); gtk_widget_destroy(dialog); g_module_close(handle); return; } } else { Log("Warning: No EXPORT_PW3270_PLUGIN_INFORMATION info on \"%s\"",filename); } plugins = g_slist_append(plugins,handle); } else { Trace("Can't load %s: %s",filename,g_module_error()); Log("Can't load \"%s\": %s",filename,g_module_error()); } } static int scan_for_plugins(const gchar *path) { GDir *dir; const gchar *name; gchar *filename; Trace("Loading plugins in \"%s\"",path); dir = g_dir_open(path,0,NULL); if(!dir) return ENOENT; name = g_dir_read_name(dir); while(name) { filename = g_build_filename(path,name,NULL); if(g_str_has_suffix(filename,G_MODULE_SUFFIX)) load_plugin(filename); g_free(filename); name = g_dir_read_name(dir); } g_dir_close(dir); return 0; } #endif int LoadPlugins(void) { #ifdef HAVE_PLUGINS gchar *path; gchar **list; int f; if(!g_module_supported()) return EINVAL; if(plugin_list) { // Load only defined plugins list = g_strsplit(plugin_list,",",0); if(list) { for(f=0;list[f];f++) { if(g_file_test(list[f],G_FILE_TEST_EXISTS)) { load_plugin(list[f]); } else { GtkWidget *dialog; dialog = gtk_message_dialog_new( GTK_WINDOW(topwindow), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _( "Can't load \"%s\"" ), list[f]); gtk_window_set_title(GTK_WINDOW(dialog), _( "Can't load plugin" ) ); gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), _( "The required plugin file wasn't found" )); gtk_dialog_run(GTK_DIALOG (dialog)); gtk_widget_destroy(dialog); } } g_strfreev(list); } } else { // Scan for all available plugins if(plugin_path) { scan_for_plugins(plugin_path); } else { #if defined( DEBUG ) path = g_build_filename(".","plugins",NULL); scan_for_plugins(path); g_free(path); #elif defined(_WIN32) path = g_build_filename(program_data,"plugins",NULL); scan_for_plugins(path); g_free(path); #elif defined( LIBDIR ) path = g_build_filename(LIBDIR,PACKAGE_NAME,"plugins",NULL); scan_for_plugins(path); g_free(path); #else path = g_build_filename(program_data,"plugins",NULL); scan_for_plugins(path); g_free(path); #endif } } #endif return 0; } void unload(GModule *handle,gpointer arg) { #ifdef HAVE_PLUGINS g_module_close(handle); #endif } int UnloadPlugins(void) { #ifdef HAVE_PLUGINS g_slist_foreach(plugins,(GFunc) unload,NULL); g_slist_free(plugins); plugins = NULL; #endif return 0; } #ifdef HAVE_PLUGINS static void call(GModule *handle, struct call_parameter *arg) { void (*ptr)(GtkWidget *widget, const gchar *arg) = NULL; if(g_module_symbol(handle, arg->name, (gpointer) &ptr)) ptr(topwindow,arg->arg); } static void start_plugin(GModule *handle, struct call_parameter *arg) { void (*ptr)(GtkWidget *widget) = NULL; // Trace("%s::%s: %d",g_module_name(handle),arg->name,g_module_symbol(handle, arg->name, (gpointer) &ptr)); if(g_module_symbol(handle, arg->name, (gpointer) &ptr)) ptr(topwindow); } static void stop_plugin(GModule *handle, gpointer dunno) { void (*ptr)(GtkWidget *widget) = NULL; if(g_module_symbol(handle, "pw3270_plugin_stop", (gpointer) &ptr)) ptr(topwindow); } #endif gboolean StartPlugins(const gchar *startup_script) { #ifdef HAVE_PLUGINS struct call_parameter p = { "pw3270_plugin_start", startup_script }; Trace("Starting plugins with \"%s\"...",startup_script); if(plugins) g_slist_foreach(plugins,(GFunc) start_plugin,&p); if(startup_script) run_script_list(startup_script); #endif return FALSE; } gboolean StopPlugins(void) { #ifdef HAVE_PLUGINS if(plugins) g_slist_foreach(plugins,(GFunc) stop_plugin,0); #endif return FALSE; } void CallPlugins(const gchar *name, const gchar *arg) { #ifdef HAVE_PLUGINS struct call_parameter p = { name, arg }; if(plugins) g_slist_foreach(plugins,(GFunc) call,&p); #endif } gboolean get_symbol_by_name(GModule *module, gpointer *pointer, const gchar *fmt, ...) { gboolean ret = FALSE; #ifdef HAVE_PLUGINS gchar *symbol_name; va_list arg; va_start(arg, fmt); symbol_name = g_strdup_vprintf(fmt,arg); va_end(arg); Trace("Module: %p Symbol: %s",module,symbol_name); if(module) { ret = g_module_symbol(module,symbol_name,pointer); } else { GSList *el = plugins; while(el && !ret) { Trace("el->data: %p",el->data); if(el->data) ret = g_module_symbol((GModule *)el->data,symbol_name,pointer); el = el->next; } } Trace("Symbol(%s): %p Found: %s",symbol_name,*pointer,ret ? "yes" : "no"); g_free(symbol_name); #endif return ret; } GModule * get_plugin_by_name(const gchar *plugin_name) { GModule *ret = NULL; #ifdef HAVE_PLUGINS GSList *el = plugins; while(el && !ret) { GModule *module = (GModule *) el->data; gchar *name = g_path_get_basename(g_module_name(module)); gchar *ptr = strchr(name,'.'); if(ptr) *ptr = 0; if(!g_ascii_strcasecmp(plugin_name,name)) ret = module; g_free(name); el = el->next; } #endif return ret; }