From 6628e983087bd9d91a7c66ab5b8450195edc9800 Mon Sep 17 00:00:00 2001 From: perry.werneck@gmail.com Date: Wed, 3 Apr 2013 12:05:59 +0000 Subject: [PATCH] Implementando carga dinâmica da lib3270 no módulo rexx stand-alone --- src/plugins/rx3270/Makefile.in | 2 +- src/plugins/rx3270/local.cc | 530 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/plugins/rx3270/pluginmain.cc | 7 +++++++ src/plugins/rx3270/rx3270.h | 27 +++++++++++++-------------- src/plugins/rx3270/rxapimain.cc | 48 ------------------------------------------------ src/plugins/rx3270/sample/getversion.rex | 8 ++++++++ 6 files changed, 559 insertions(+), 63 deletions(-) create mode 100644 src/plugins/rx3270/local.cc create mode 100644 src/plugins/rx3270/sample/getversion.rex diff --git a/src/plugins/rx3270/Makefile.in b/src/plugins/rx3270/Makefile.in index ce7afe1..80a0f8f 100644 --- a/src/plugins/rx3270/Makefile.in +++ b/src/plugins/rx3270/Makefile.in @@ -29,7 +29,7 @@ MODULE_NAME=rx3270 DEPENDS=*.h ../../include/*.h ../../include/lib3270/*.h Makefile PLUGIN_SRC=pluginmain.cc -EXTAPI_SRC=rxapimain.cc text.cc typed_routines.cc +EXTAPI_SRC=rxapimain.cc text.cc typed_routines.cc local.cc #---[ Tools ]------------------------------------------------------------------ diff --git a/src/plugins/rx3270/local.cc b/src/plugins/rx3270/local.cc new file mode 100644 index 0000000..d619b37 --- /dev/null +++ b/src/plugins/rx3270/local.cc @@ -0,0 +1,530 @@ +/* + * "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 local.cc e possui - linhas de código. + * + * Contatos: + * + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça) + * + */ + + #include "rx3270.h" + #include + +#if defined WIN32 + #define REXX_DEFAULT_CHARSET "CP1252" +#else + #include + #include + #define REXX_DEFAULT_CHARSET "UTF-8" +#endif + +#ifdef HAVE_SYSLOG + #include + #include +#endif // HAVE_SYSLOG + + +/*--[ Class definition ]-----------------------------------------------------------------------------*/ + + class dynamic : public rx3270 + { + public: + dynamic(); + ~dynamic(); + + const char * get_version(void); + LIB3270_CSTATE get_cstate(void); + int disconnect(void); + int connect(const char *uri, bool wait = true); + int is_connected(void); + int is_ready(void); + + int iterate(void); + int wait(int seconds); + int wait_for_ready(int seconds); + + char * get_text_at(int row, int col, size_t sz); + int cmp_text_at(int row, int col, const char *text); + int set_text_at(int row, int col, const char *str); + + int set_cursor_position(int row, int col); + + void set_toggle(LIB3270_TOGGLE ix, bool value); + + int enter(void); + int pfkey(int key); + int pakey(int key); + + private: + + const char * (*_get_version)(void); + LIB3270_CSTATE (*_get_connection_state)(H3270 *h); + int (*_disconnect)(H3270 *h); + int (*_connect)(H3270 *h,const char *n, int wait); + int (*_is_connected)(H3270 *h); + void (*_main_iterate)(H3270 *h, int wait); + int (*_wait)(H3270 *hSession, int seconds); + int (*_enter)(H3270 *hSession); + int (*_pfkey)(H3270 *hSession, int key); + int (*_pakey)(H3270 *hSession, int key); + int (*_wait_for_ready)(H3270 *hSession, int seconds); + char * (*_get_text_at)(H3270 *h, int row, int col, int len); + int (*_cmp_text_at)(H3270 *h, int row, int col, const char *text); + int (*_set_text_at)(H3270 *h, int row, int col, const unsigned char *str); + int (*_is_ready)(H3270 *h); + int (*_set_cursor_position)(H3270 *h, int row, int col); + void (*_set_toggle)(H3270 *h, LIB3270_TOGGLE ix, int value); + +#ifdef WIN32 + HMODULE hModule +#else + void * hModule; +#endif // WIN32 + + H3270 * hSession; + + }; + +/*--[ Globals ]--------------------------------------------------------------------------------------*/ + + static bool plugin = false; + static rx3270 * defSession = NULL; + +/*--[ Implement ]------------------------------------------------------------------------------------*/ + +rx3270::rx3270() +{ +#ifdef HAVE_ICONV + this->conv2Local = iconv_open(REXX_DEFAULT_CHARSET, "ISO-8859-1"); + this->conv2Host = iconv_open("ISO-8859-1",REXX_DEFAULT_CHARSET); +#endif + + if(!defSession) + defSession = this; +} + +rx3270::~rx3270() +{ +#ifdef HAVE_ICONV + + if(conv2Local != (iconv_t) (-1)) + iconv_close(conv2Local); + + if(conv2Host != (iconv_t) (-1)) + iconv_close(conv2Host); +#endif + + + if(defSession == this) + defSession = NULL; +} + +rx3270 * rx3270::get_default(void) +{ + if(defSession) + return defSession; + + return new dynamic(); +} + +#ifdef WIN32 +static int get_datadir(LPSTR datadir) +{ + HKEY hKey = 0; + unsigned long datalen = strlen(datadir); + + *datadir = 0; + + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\pw3270",0,KEY_QUERY_VALUE,&hKey) == ERROR_SUCCESS) + { + unsigned long datatype; // #defined in winnt.h (predefined types 0-11) + if(RegQueryValueExA(hKey,"datadir",NULL,&datatype,(LPBYTE) datadir,&datalen) != ERROR_SUCCESS) + *datadir = 0; + RegCloseKey(hKey); + } + + return *datadir; +} +#endif // WIN32 + +void rx3270::set_plugin(void) +{ + trace("%s: Rexx API running as plugin",__FUNCTION__); + plugin = true; +} + +extern "C" +{ + +static void loghandler(H3270 *session, const char *module, int rc, const char *fmt, va_list args) +{ +#ifdef HAVE_SYSLOG + openlog(PACKAGE_NAME, LOG_NDELAY, LOG_USER); + vsyslog(LOG_INFO,fmt,args); + closelog(); +#endif // HAVE_SYSLOG +} + +static void tracehandler(H3270 *session, const char *fmt, va_list args) +{ +#ifdef HAVE_SYSLOG + + #define MAX_LOG_LENGTH 200 + + static char line[MAX_LOG_LENGTH+1]; + char temp[MAX_LOG_LENGTH]; + char * ptr; + size_t len = strlen(line); + + vsnprintf(temp,MAX_LOG_LENGTH-len,fmt,args); + + ptr = strchr(temp,'\n'); + if(!ptr) + { + strncat(line,temp,MAX_LOG_LENGTH); + if(strlen(line) >= MAX_LOG_LENGTH) + { + openlog(PACKAGE_NAME, LOG_NDELAY, LOG_USER); + syslog(LOG_INFO,line); + closelog(); + *line = 0; + } + return; + } + + *ptr = 0; + strncat(line,temp,MAX_LOG_LENGTH); + + openlog(PACKAGE_NAME, LOG_NDELAY, LOG_USER); + syslog(LOG_DEBUG,line); + closelog(); + + strncpy(line,ptr+1,MAX_LOG_LENGTH); + +#endif // HAVE_SYSLOG +} + +} + +dynamic::dynamic() +{ + H3270 * (*lib3270_new)(const char *); + void (*set_log_handler)(void (*loghandler)(H3270 *, const char *, int, const char *, va_list)); + void (*set_trace_handler)( void (*handler)(H3270 *session, const char *fmt, va_list args) ); + + struct _call + { + void **entry; + const char * name; + } call[] = + { + { (void **) & lib3270_new, "lib3270_session_new" }, + { (void **) & set_log_handler, "lib3270_set_log_handler" }, + { (void **) & set_trace_handler, "lib3270_set_trace_handler" }, + { (void **) & _get_version, "lib3270_get_version" }, + { (void **) & _get_connection_state, "lib3270_get_connection_state" }, + { (void **) & _disconnect, "lib3270_disconnect" }, + { (void **) & _connect, "lib3270_connect" }, + { (void **) & _is_connected, "lib3270_in_tn3270e" }, + { (void **) & _main_iterate, "lib3270_main_iterate" }, + { (void **) & _wait, "lib3270_wait" }, + { (void **) & _enter, "lib3270_enter" }, + { (void **) & _pfkey, "lib3270_pfkey" }, + { (void **) & _pakey, "lib3270_pakey" }, + { (void **) & _wait_for_ready, "lib3270_wait_for_ready" }, + { (void **) & _get_text_at, "lib3270_get_text_at" }, + { (void **) & _cmp_text_at, "lib3270_cmp_text_at" }, + { (void **) & _set_text_at, "lib3270_set_string_at" }, + { (void **) & _is_ready, "lib3270_is_ready" }, + { (void **) & _set_cursor_position, "lib3270_set_cursor_position" }, + { (void **) & _set_toggle, "lib3270_set_toggle" }, + + }; + +// Load lib3270.dll +#ifdef WIN32 + static const char *dllname = "lib3270.dll." PACKAGE_VERSION; + + int f; + HMODULE kernel; + HANDLE cookie = NULL; + DWORD rc; + HANDLE (*AddDllDirectory)(PCWSTR NewDirectory); + BOOL (*RemoveDllDirectory)(HANDLE Cookie); + UINT errorMode; + char datadir[4096]; + + kernel = LoadLibrary("kernel32.dll"); + AddDllDirectory = (HANDLE (*)(PCWSTR)) GetProcAddress(kernel,"AddDllDirectory"); + RemoveDllDirectory = (BOOL (*)(HANDLE)) GetProcAddress(kernel,"RemoveDllDirectory"); + + // Notify user in case of error loading protocol DLL + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms680621(v=vs.85).aspx + errorMode = SetErrorMode(1); + + memset(datadir,' ',4095); + datadir[4095] = 0; + + if(get_datadir(datadir)) + { + char buffer[4096]; + wchar_t path[4096]; + + mbstowcs(path, datadir, 4095); + trace("Datadir=[%s] AddDllDirectory=%p RemoveDllDirectory=%p\n",datadir,AddDllDirectory,RemoveDllDirectory); + if(AddDllDirectory) + cookie = AddDllDirectory(path); + +#ifdef DEBUG + snprintf(buffer,4096,"%s\\.bin\\Debug\\%s",datadir,dllname); +#else + snprintf(buffer,4096,"%s\\%s",datadir,dllname); +#endif // DEBUG + + hModule = LoadLibrary(buffer); + + trace("%s hModule=%p rc=%d",buffer,hModule,(int) GetLastError()); + + if(hModule == NULL) + { + // Enable DLL error popup and try again with full path + SetErrorMode(0); + hModule = LoadLibraryEx(buffer,NULL,LOAD_LIBRARY_SEARCH_DEFAULT_DIRS|LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR); + } + + rc = GetLastError(); + + trace("%s hModule=%p rc=%d",buffer,hModule,(int) rc); + } + else + { + hModule = LoadLibrary(dllname); + rc = GetLastError(); + } + + SetErrorMode(errorMode); + + trace("%s hModule=%p rc=%d",dllname,hModule,(int) rc); + + if(cookie && RemoveDllDirectory) + RemoveDllDirectory(cookie); + + if(kernel) + FreeLibrary(kernel); + + if(!hModule) + return; + + +#else + dlerror(); + + hModule = dlopen("lib3270.so." PACKAGE_VERSION, RTLD_NOW); + if(!hModule) + { + fprintf(stderr,"Can't load lib3270\n%s\n",dlerror()); + fflush(stderr); + return; + } + +#endif // WIN32 + + // Load entry points + for(unsigned int f = 0; f < (sizeof (call) / sizeof ((call)[0]));f++) + { +#ifdef WIN32 + *call[f].entry = (void *) GetProcAddress(hModule,call[f].name); +#else + *call[f].entry = dlsym(hModule,call[f].name); +#endif // WIN32 + + if(!*call[f].entry) + { +#ifndef WIN32 + fprintf(stderr,"Can't load lib3270::%s\n%s\n",call[f].name,dlerror()); + fflush(stderr); + dlclose(hModule); +#else + #error DLL close +#endif // !WIN32 + hModule = NULL; + return; + } + } + + // Get Session handle, setup base callbacks + set_log_handler(loghandler); + set_trace_handler(tracehandler); + this->hSession = lib3270_new(""); + +} + +dynamic::~dynamic() +{ + static void (*session_free)(void *h); + + if(!hModule) + return; + +#ifdef WIN32 + + session_free = (void (*)(void *h)) GetProcAddress(hModule,"lib3270_session_free"); + + if(session_free) + session_free(hSession); + + FreeLibrary(hModule); + +#else + + session_free = (void (*)(void *h)) dlsym(hModule,"lib3270_session_free"); + + if(session_free) + session_free(hSession); + + dlclose(hModule); + +#endif // WIN32 + +} + +const char * dynamic::get_version(void) +{ + if(!hModule) + return NULL; + return _get_version(); +} + +LIB3270_CSTATE dynamic::get_cstate(void) +{ + if(!hModule) + return (LIB3270_CSTATE) -1; + return _get_connection_state(hSession); +} + +int dynamic::disconnect(void) +{ + if(!hModule) + return -1; + return _disconnect(hSession); +} + +int dynamic::connect(const char *uri, bool wait) +{ + if(!hModule) + return -1; + return _connect(hSession,uri,(int) wait); +} + +int dynamic::is_connected(void) +{ + if(!hModule) + return -1; + return _is_connected(hSession); +} + +int dynamic::is_ready(void) +{ + if(!hModule) + return -1; + return _is_ready(hSession); +} + +int dynamic::iterate(void) +{ + if(!hModule) + return -1; + + _main_iterate(hSession,1); + + return 0; +} + +int dynamic::wait(int seconds) +{ + if(!hModule) + return -1; + return _wait(hSession,seconds); +} + +int dynamic::wait_for_ready(int seconds) +{ + if(!hModule) + return -1; + return _wait_for_ready(hSession,seconds); +} + +char * dynamic::get_text_at(int row, int col, size_t sz) +{ + if(!hModule) + return NULL; + return _get_text_at(hSession,row,col,sz); +} + +int dynamic::cmp_text_at(int row, int col, const char *text) +{ + if(!hModule) + return 0; + return _cmp_text_at(hSession,row,col,text); +} + +int dynamic::set_text_at(int row, int col, const char *str) +{ + if(!hModule) + return -1; + return _set_text_at(hSession,row,col,(const unsigned char *) str); +} + +int dynamic::set_cursor_position(int row, int col) +{ + if(!hModule) + return -1; + return _set_cursor_position(hSession,row,col); +} + +int dynamic::enter(void) +{ + if(!hModule) + return -1; + return _enter(hSession); +} + +int dynamic::pfkey(int key) +{ + if(!hModule) + return -1; + return _pfkey(hSession,key); +} + +int dynamic::pakey(int key) +{ + if(!hModule) + return -1; + return _pakey(hSession,key); +} + +void dynamic::set_toggle(LIB3270_TOGGLE ix, bool value) +{ + if(hModule) + _set_toggle(hSession,ix,(int) value); +} diff --git a/src/plugins/rx3270/pluginmain.cc b/src/plugins/rx3270/pluginmain.cc index cc7091f..28eae41 100644 --- a/src/plugins/rx3270/pluginmain.cc +++ b/src/plugins/rx3270/pluginmain.cc @@ -55,6 +55,8 @@ int set_cursor_position(int row, int col); + void set_toggle(LIB3270_TOGGLE ix, bool value); + int enter(void); int pfkey(int key); int pakey(int key); @@ -176,3 +178,8 @@ { return lib3270_set_cursor_position(hSession,row,col); } + + void plugin::set_toggle(LIB3270_TOGGLE ix, bool value) + { + lib3270_set_toggle(hSession,ix,(int) value); + } diff --git a/src/plugins/rx3270/rx3270.h b/src/plugins/rx3270/rx3270.h index 66e9a3d..3cecfe7 100644 --- a/src/plugins/rx3270/rx3270.h +++ b/src/plugins/rx3270/rx3270.h @@ -101,25 +101,24 @@ virtual const char * get_version(void) = 0; virtual LIB3270_CSTATE get_cstate(void) = 0; - virtual int connect(const char *uri, bool wait = true) = 0; - virtual int disconnect(void) = 0; - virtual int is_connected(void) = 0; - virtual int is_ready(void) = 0; - virtual int iterate(void) = 0; - virtual int wait(int seconds) = 0; - virtual int wait_for_ready(int seconds) = 0; - virtual int set_cursor_position(int row, int col) = 0; - - virtual int enter(void) = 0; - virtual int pfkey(int key) = 0; - virtual int pakey(int key) = 0; + virtual int connect(const char *uri, bool wait = true) = 0; + virtual int disconnect(void) = 0; + virtual int is_connected(void) = 0; + virtual int is_ready(void) = 0; + virtual int iterate(void) = 0; + virtual int wait(int seconds) = 0; + virtual int wait_for_ready(int seconds) = 0; + virtual int set_cursor_position(int row, int col) = 0; + virtual void set_toggle(LIB3270_TOGGLE ix, bool value) = 0; + + virtual int enter(void) = 0; + virtual int pfkey(int key) = 0; + virtual int pakey(int key) = 0; virtual char * get_text_at(int row, int col, size_t sz) = 0; virtual int cmp_text_at(int row, int col, const char *text) = 0; virtual int set_text_at(int row, int col, const char *str) = 0; - - }; #endif // RX3270_H_INCLUDED diff --git a/src/plugins/rx3270/rxapimain.cc b/src/plugins/rx3270/rxapimain.cc index 519c83b..f1de212 100644 --- a/src/plugins/rx3270/rxapimain.cc +++ b/src/plugins/rx3270/rxapimain.cc @@ -41,16 +41,11 @@ #include #if defined WIN32 - - #define REXX_DEFAULT_CHARSET "CP1252" - BOOL WINAPI DllMain(HANDLE hinst, DWORD dwcallpurpose, LPVOID lpvResvd); static int librx3270_loaded(void); static int librx3270_unloaded(void); #else - #define REXX_DEFAULT_CHARSET "UTF-8" - int librx3270_loaded(void) __attribute__((constructor)); int librx3270_unloaded(void) __attribute__((destructor)); #endif @@ -60,10 +55,6 @@ LIB3270_EXPORT RexxRoutineEntry rx3270_functions[]; LIB3270_EXPORT RexxPackageEntry rx3270_package_entry; - - static rx3270 * hSession = NULL; - static bool plugin = false; - /*--[ Implement ]------------------------------------------------------------------------------------*/ #if defined WIN32 @@ -92,8 +83,6 @@ int librx3270_loaded(void) int librx3270_unloaded(void) { - if(hSession) - delete hSession; return 0; } @@ -145,40 +134,3 @@ LIB3270_EXPORT RexxPackageEntry * RexxEntry RexxGetPackage(void) END_EXTERN_C() -rx3270 * rx3270::get_default(void) -{ - return hSession; -} - -rx3270::rx3270() -{ -#ifdef HAVE_ICONV - this->conv2Local = iconv_open(REXX_DEFAULT_CHARSET, "ISO-8859-1"); - this->conv2Host = iconv_open("ISO-8859-1",REXX_DEFAULT_CHARSET); -#endif - - if(!hSession) - hSession = this; -} - -rx3270::~rx3270() -{ -#ifdef HAVE_ICONV - - if(conv2Local != (iconv_t) (-1)) - iconv_close(conv2Local); - - if(conv2Host != (iconv_t) (-1)) - iconv_close(conv2Host); -#endif - - - if(hSession == this) - hSession = NULL; -} - -void rx3270::set_plugin(void) -{ - trace("%s: Rexx API running as plugin",__FUNCTION__); - plugin = true; -} diff --git a/src/plugins/rx3270/sample/getversion.rex b/src/plugins/rx3270/sample/getversion.rex new file mode 100644 index 0000000..d8f4174 --- /dev/null +++ b/src/plugins/rx3270/sample/getversion.rex @@ -0,0 +1,8 @@ + + +say rx3270version() + +return 0 + +::requires "rx3270" library + -- libgit2 0.21.2