From 04548e41fa30b4e00357171e3fb5cc20d37e8485 Mon Sep 17 00:00:00 2001 From: perry.werneck@gmail.com Date: Thu, 4 Oct 2012 04:42:19 +0000 Subject: [PATCH] Melhorando plugin hllapi --- src/include/lib3270.h | 2 +- src/include/pw3270/v3270.h | 2 +- src/lib3270/iocalls.c | 3 +++ src/plugins/remotectl/hllapi.c | 28 ++++++++++++++++++---------- src/plugins/remotectl/pipesource.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------ src/plugins/remotectl/remotectl.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------- src/plugins/remotectl/remotectl.h | 25 ++++++++++++++++++++++++- src/pw3270/v3270/oia.c | 2 +- 8 files changed, 294 insertions(+), 93 deletions(-) diff --git a/src/include/lib3270.h b/src/include/lib3270.h index bbc9bbe..3115d75 100644 --- a/src/include/lib3270.h +++ b/src/include/lib3270.h @@ -36,7 +36,7 @@ #include #ifndef ENOTCONN - #define ENOTCONN 107 + #define ENOTCONN 126 #endif // !ENOTCONN #if defined(__GNUC__) diff --git a/src/include/pw3270/v3270.h b/src/include/pw3270/v3270.h index febddef..b826d73 100644 --- a/src/include/pw3270/v3270.h +++ b/src/include/pw3270/v3270.h @@ -186,7 +186,7 @@ LIB3270_EXPORT void v3270_popup_message(GtkWidget *widget, LIB3270_NOTIFY type, const gchar *title, const gchar *message, const gchar *text); LIB3270_EXPORT const gchar * v3270_get_session_name(GtkWidget *widget); LIB3270_EXPORT void v3270_set_session_name(GtkWidget *widget, const gchar *name); - LIB3270_EXPORT int v3270_set_script(GtkWidget *widget, const gchar id, unsigned char on); + LIB3270_EXPORT int v3270_set_script(GtkWidget *widget, const gchar id, gboolean on); LIB3270_EXPORT void v3270_set_scaled_fonts(GtkWidget *widget, gboolean on); LIB3270_EXPORT void v3270_set_host(GtkWidget *widget, const gchar *uri); diff --git a/src/lib3270/iocalls.c b/src/lib3270/iocalls.c index 6f161e4..d4bc22a 100644 --- a/src/lib3270/iocalls.c +++ b/src/lib3270/iocalls.c @@ -726,6 +726,9 @@ LIB3270_EXPORT int lib3270_wait_for_ready(H3270 *hSession, int seconds) { time_t end = time(0)+seconds; + if(hSession->oia_status == LIB3270_STATUS_BLANK) + return 0; + while(time(0) < end) { event_dispatcher(hSession,1); diff --git a/src/plugins/remotectl/hllapi.c b/src/plugins/remotectl/hllapi.c index 23dbd32..aa9f8d6 100644 --- a/src/plugins/remotectl/hllapi.c +++ b/src/plugins/remotectl/hllapi.c @@ -79,7 +79,7 @@ } - static char * run_query(unsigned long func, const char *arg, size_t length, unsigned short *rc) + static char * run_query(unsigned long func, const char *arg, size_t *length, unsigned short *rc) { char *outBuffer = NULL; @@ -93,7 +93,7 @@ else { HLLAPI_DATA *buffer = malloc(HLLAPI_MAXLENGTH+1); - DWORD cbSize = sizeof(HLLAPI_DATA) + length; + DWORD cbSize = sizeof(HLLAPI_DATA) + *length; HLLAPI_DATA *data = malloc(cbSize+1); memset(buffer,0,HLLAPI_MAXLENGTH); @@ -101,10 +101,10 @@ data->id = HLLAPI_REQUEST_ID; data->func = func; data->rc = *rc; - data->len = length; + data->len = *length; - if(arg && length > 0) - memcpy(data->string,arg,length); + if(arg && *length > 0) + memcpy(data->string,arg,*length); memset(buffer,0,HLLAPI_MAXLENGTH); @@ -115,7 +115,8 @@ } else { - *rc = buffer->rc; + *rc = buffer->rc; + *length = buffer->len; trace("buffer->len=%d rc=%d",buffer->len,buffer->rc); @@ -162,6 +163,7 @@ { char * inBuffer = NULL; char * outBuffer = NULL; + size_t szOutBuffer; if(*length < 0 || *length > HLLAPI_MAXLENGTH) { @@ -169,6 +171,8 @@ return 0; } + szOutBuffer = (size_t) *length; + // Copy input argument if(*length) { @@ -187,7 +191,7 @@ *rc = cmd_connect_ps(inBuffer); if(!*rc) { - outBuffer = run_query(*func, inBuffer, *length, rc); + outBuffer = run_query(*func, inBuffer, &szOutBuffer, rc); if(*rc) { trace("Closing pipe rc=%d",*rc); @@ -205,7 +209,7 @@ } else { - outBuffer = run_query(*func, inBuffer, *length, rc); + outBuffer = run_query(*func, inBuffer, &szOutBuffer, rc); CloseHandle(hPipe); hPipe = INVALID_HANDLE_VALUE; } @@ -214,14 +218,18 @@ default: trace("Calling function %d",(int) *func); - outBuffer = run_query(*func, inBuffer, *length, rc); + outBuffer = run_query(*func, inBuffer, &szOutBuffer, rc); } if(*rc) copyString(buffer,length,strerror(*rc)); else if(outBuffer) - copyString(buffer,length,outBuffer); + { + if(szOutBuffer < *length) + *length = szOutBuffer; + copyString(buffer,length,outBuffer); + } if(outBuffer) free(outBuffer); diff --git a/src/plugins/remotectl/pipesource.c b/src/plugins/remotectl/pipesource.c index 05f2729..ebc211b 100644 --- a/src/plugins/remotectl/pipesource.c +++ b/src/plugins/remotectl/pipesource.c @@ -66,7 +66,7 @@ static void wait_for_client(pipe_source *source) { - v3270_set_script(pw3270_get_terminal_widget(NULL),'H',0); + set_active(FALSE); if(ConnectNamedPipe(source->hPipe,&source->overlap)) { popup_lasterror("%s",_( "Error in ConnectNamedPipe" )); @@ -84,7 +84,7 @@ static void wait_for_client(pipe_source *source) // Client is already connected, so signal an event. case ERROR_PIPE_CONNECTED: trace("%s: ERROR_PIPE_CONNECTED",__FUNCTION__); - v3270_set_script(pw3270_get_terminal_widget(NULL),'H',1); + set_active(TRUE); if(SetEvent(source->overlap.hEvent)) break; @@ -137,21 +137,101 @@ static void wait_for_client(pipe_source *source) static void process_input(pipe_source *source, DWORD cbRead) { - HLLAPI_DATA *data = (HLLAPI_DATA *) source->buffer; + HLLAPI_DATA * data = (HLLAPI_DATA *) source->buffer; + QUERY * qry = g_malloc0(sizeof(QUERY)+cbRead+1); - source->buffer[cbRead] = 0; + qry->hPipe = source->hPipe; + qry->text = (const gchar *) (qry+1); if(data->id == 0x01) { - DWORD wrote; - data->rc = run_hllapi(data->func,data->string,data->len,data->rc); - wrote = sizeof(HLLAPI_DATA)+data->len; + // HLLAPI query + qry->cmd = (int) data->func; + qry->pos = (int) data->rc; + qry->length = data->len; + memcpy((gchar *)(qry->text),data->string,qry->length); + } + else + { + qry->cmd = -1; + } + + enqueue_request(qry); + } + + void request_complete(QUERY *qry, int rc, const gchar *text) + { + request_buffer(qry,rc,strlen(text),(const gpointer) text); + } + + void request_status(QUERY *qry, int rc) + { + if(rc) + { + const gchar *msg = strerror(rc); + request_buffer(qry, rc, strlen(msg), (const gpointer) msg); + } + else + { + request_buffer(qry, rc, 0, NULL); + } +/* + HLLAPI_DATA data; + + memset(&data,0,sizeof(data)); + + data.id = 0x01; + data.func = qry->cmd; + data.rc = rc; + + trace("rc=%d",rc); + +#ifdef WIN32 + { + DWORD wrote = sizeof(data); + WriteFile(qry->hPipe,&data,wrote,&wrote,NULL); + } +#endif // WIN32 + + g_free(qry); +*/ + } - trace("%s rc=%d",__FUNCTION__,(int) data->rc); + void request_buffer(QUERY *qry, int rc, size_t szBuffer, const gpointer buffer) + { + size_t sz; + HLLAPI_DATA *data; - WriteFile(source->hPipe,data,wrote,&wrote,NULL); + if(buffer) + { + sz = sizeof(HLLAPI_DATA)+szBuffer; + data = g_malloc0(sz); + data->len = szBuffer; + memcpy(data->string,buffer,szBuffer); + } + else + { + sz = sizeof(HLLAPI_DATA); + data = g_malloc0(sz); } + data->id = 0x01; + data->func = qry->cmd; + data->rc = rc; + + trace("rc=%d data->len=%d",rc,(int) data->len); + +#ifdef WIN32 + { + DWORD wrote = sz; + WriteFile(qry->hPipe,data,wrote,&wrote,NULL); + trace("Wrote=%d len=%d",(int) wrote, (int) sz); + } +#endif // WIN32 + + g_free(data); + g_free(qry); + } static void read_input_pipe(pipe_source *source) @@ -179,9 +259,10 @@ static void wait_for_client(pipe_source *source) case ERROR_BROKEN_PIPE: trace("%s: ERROR_BROKEN_PIPE",__FUNCTION__); + if(!DisconnectNamedPipe(source->hPipe)) { - v3270_set_script(pw3270_get_terminal_widget(NULL),'H',0); + set_active(FALSE); popup_lasterror("%s",_( "Error in DisconnectNamedPipe" )); } else @@ -192,7 +273,7 @@ static void wait_for_client(pipe_source *source) case ERROR_PIPE_NOT_CONNECTED: trace("%s: ERROR_PIPE_NOT_CONNECTED",__FUNCTION__); - v3270_set_script(pw3270_get_terminal_widget(NULL),'H',0); + set_active(FALSE); break; default: @@ -227,7 +308,7 @@ static void wait_for_client(pipe_source *source) if(fSuccess) { trace("Pipe connected (cbRet=%d)",(int) cbRead); - v3270_set_script(pw3270_get_terminal_widget(NULL),'H',1); + set_active(TRUE); ((pipe_source *) source)->state = PIPE_STATE_READ; } else diff --git a/src/plugins/remotectl/remotectl.c b/src/plugins/remotectl/remotectl.c index 8c283cd..79a0448 100644 --- a/src/plugins/remotectl/remotectl.c +++ b/src/plugins/remotectl/remotectl.c @@ -41,7 +41,7 @@ /*--[ Implement ]------------------------------------------------------------------------------------*/ - static const gchar control_char = '@'; + static const gchar control_char = '@'; /*--[ Implement ]------------------------------------------------------------------------------------*/ @@ -137,55 +137,64 @@ #error Nao implementado #endif // WIN32 + + set_active(FALSE); + return 0; } - static int cmd_connectps(H3270 *hSession, unsigned short rc, char *string, unsigned short length) + static void cmd_connectps(QUERY *qry) { g_message("%s","HLLAPI ConnectPS request received"); - return v3270_set_script(pw3270_get_terminal_widget(NULL),'H',1); + request_status(qry,v3270_set_script(pw3270_get_terminal_widget(NULL),'H',TRUE)); } - static int cmd_disconnectps(H3270 *hSession, unsigned short rc, char *string, unsigned short length) + static void cmd_disconnectps(QUERY *qry) { g_message("%s","HLLAPI DisconnectPS request received"); - return 0; + request_status(qry,0); } - static int cmd_getrevision(H3270 *hSession, unsigned short rc, char *string, unsigned short length) + static void cmd_getrevision(QUERY *qry) { - strncpy(string,lib3270_get_revision(),length); - return 0; + request_complete(qry,0,lib3270_get_revision()); } - static int cmd_setcursor(H3270 *hSession, unsigned short rc, char *string, unsigned short length) + static void cmd_setcursor(QUERY *qry) { - if(!lib3270_connected(hSession)) - return ENOTCONN; + int rc = ENOTCONN; - trace("%s: pos=%d row=%d col=%d",__FUNCTION__,rc,rc/80,rc%80); - lib3270_set_cursor_address(hSession,((int) rc) -1); - return 0; + if(lib3270_connected(qry->hSession)) + { + trace("%s: pos=%d row=%d col=%d",__FUNCTION__,rc,rc/80,rc%80); + lib3270_set_cursor_address(qry->hSession,qry->pos -1); + rc = 0; + } + + request_status(qry,rc); } - static int cmd_sendstring(H3270 *hSession, unsigned short dunno, char *buffer, unsigned short length) + static void cmd_sendstring(QUERY *qry) { gchar * text; GError * error = NULL; gsize bytes_read; gsize bytes_written; const gchar * charset; - int rc = -1; - if(!lib3270_connected(hSession)) - return ENOTCONN; + if(!lib3270_connected(qry->hSession)) + { + request_status(qry,ENOTCONN); + return; + } g_get_charset(&charset); - text = g_convert(buffer,length,lib3270_get_charset(hSession),charset,&bytes_read,&bytes_written,&error); + text = g_convert(qry->text,qry->length,lib3270_get_charset(qry->hSession),charset,&bytes_read,&bytes_written,&error); if(text) { - rc = 0; + int rc = 0; + if(strchr(text,control_char)) { // Convert control char @@ -196,7 +205,7 @@ { *(ptr++) = 0; - lib3270_emulate_input(hSession,buffer,-1,0); + lib3270_emulate_input(qry->hSession,buffer,-1,0); switch(*(ptr++)) { @@ -205,112 +214,160 @@ break; case 'E': // Enter - lib3270_enter(hSession); + lib3270_enter(qry->hSession); break; case 'F': // Erase EOF - lib3270_eraseeof(hSession); + lib3270_eraseeof(qry->hSession); break; case '1': // PF1 - lib3270_pfkey(hSession,1); + lib3270_pfkey(qry->hSession,1); break; case '2': // PF2 - lib3270_pfkey(hSession,2); + lib3270_pfkey(qry->hSession,2); break; case '3': // PF3 - lib3270_pfkey(hSession,3); + lib3270_pfkey(qry->hSession,3); break; case '4': // PF4 - lib3270_pfkey(hSession,4); + lib3270_pfkey(qry->hSession,4); break; case '5': // PF5 - lib3270_pfkey(hSession,5); + lib3270_pfkey(qry->hSession,5); break; case '6': // PF6 - lib3270_pfkey(hSession,6); + lib3270_pfkey(qry->hSession,6); break; case '7': // PF7 - lib3270_pfkey(hSession,7); + lib3270_pfkey(qry->hSession,7); break; case '8': // PF8 - lib3270_pfkey(hSession,8); + lib3270_pfkey(qry->hSession,8); break; case '9': // PF9 - lib3270_pfkey(hSession,9); + lib3270_pfkey(qry->hSession,9); break; case 'a': // PF10 - lib3270_pfkey(hSession,10); + lib3270_pfkey(qry->hSession,10); break; case 'b': // PF11 - lib3270_pfkey(hSession,11); + lib3270_pfkey(qry->hSession,11); break; case 'c': // PF12 - lib3270_pfkey(hSession,12); + lib3270_pfkey(qry->hSession,12); break; } } - lib3270_emulate_input(hSession,buffer,-1,0); + lib3270_emulate_input(qry->hSession,buffer,-1,0); } else { - lib3270_emulate_input(hSession,text,strlen(text),0); + lib3270_emulate_input(qry->hSession,text,strlen(text),0); } g_free(text); + + request_status(qry,rc); + + return; } - else + + request_complete(qry, error->code, error->message); + g_error_free(error); + + } + + struct wait + { + QUERY * qry; + time_t end; + }; + + static gboolean do_wait(struct wait *w) + { + if(lib3270_get_program_message(w->qry->hSession) == LIB3270_MESSAGE_NONE) { - strncpy(buffer,error->message,length); - rc = error->code; - g_error_free(error); + request_status(w->qry,0); + return FALSE; } - return rc; + if(time(0) > w->end) + { + trace("%s: TIMEOUT",__FUNCTION__); + request_status(w->qry,ETIMEDOUT); + return FALSE; + } + + return TRUE; } - static int cmd_wait(H3270 *hSession, unsigned short rc, char *text, unsigned short length) + static void cmd_wait(QUERY *qry) { - return lib3270_wait_for_ready(hSession,pw3270_get_integer(pw3270_get_toplevel(),"hllapi","wait",2)); + struct wait *w; + + if(lib3270_get_program_message(qry->hSession) == LIB3270_MESSAGE_NONE) + { + request_status(qry,0); + return; + } + + w = g_malloc0(sizeof(struct wait)); + w->qry = qry; + w->end = time(0)+pw3270_get_integer(pw3270_get_toplevel(),"hllapi","wait",2); + + g_timeout_add_full(G_PRIORITY_DEFAULT, (guint) 300, (GSourceFunc) do_wait, w, g_free); } - static int cmd_copypstostr(H3270 *hSession, unsigned short pos, char *outBuff, unsigned short length) + static void cmd_copypstostr(QUERY *qry) { int rows; int cols; unsigned short * attr; unsigned char * text; int rc; + unsigned char * buffer; + size_t length; - lib3270_get_screen_size(hSession,&rows,&cols); + if(!lib3270_connected(qry->hSession)) + { + request_status(qry,ENOTCONN); + return; + } - if(pos < 1 || (pos+length) >= (rows*cols)) - return EINVAL; + lib3270_get_screen_size(qry->hSession,&rows,&cols); + + if(qry->pos < 1 || (qry->pos+qry->length) >= (rows*cols)) + { + request_status(qry,EINVAL); + return; + } - pos--; + qry->pos--; - attr = g_new0(unsigned short, length+0); - text = g_new0(unsigned char, length+1); + length = (qry->length * sizeof(unsigned short)) + qry->length + 2; + text = buffer = g_malloc0(length+1); + attr = (unsigned short *) (text+qry->length+1); - trace("%s: pos=%d length=%d",__FUNCTION__,pos,length); - rc = lib3270_get_contents(hSession,pos,pos+(length-1),text,attr); + trace("%s: pos=%d length=%d",__FUNCTION__,qry->pos,qry->length); + rc = lib3270_get_contents(qry->hSession,qry->pos,qry->pos+(qry->length-1),text,attr); if(rc) { - strncpy(outBuff,strerror(rc),length); + request_status(qry,rc); } else { @@ -324,44 +381,66 @@ g_get_charset(&charset); - local = g_convert((const gchar *) text,length,charset,lib3270_get_charset(hSession),&bytes_read,&bytes_written,&error); - - g_free(attr); - g_free(text); + local = g_convert((const gchar *) text,-1,charset,lib3270_get_charset(qry->hSession),&bytes_read,&bytes_written,&error); if(!local) { - rc = error->code; - strncpy(outBuff,error->message,length); + request_complete(qry,error->code,error->message); g_error_free(error); } else { - strncpy(outBuff,(const char *) local,length); + strncpy((char *) text,(const char *) local,qry->length); + + trace("response: [%s] len=%d",buffer,length); + request_buffer(qry,0,length,buffer); g_free(local); } } - return rc; + + g_free(buffer); } - int run_hllapi(unsigned long function, char *string, unsigned short length, unsigned short rc) + void enqueue_request(QUERY *qry) { static const struct _cmd { - unsigned long function; - int (*exec)(H3270 *hSession, unsigned short rc, char *string, unsigned short length); + int cmd; + void (*exec)(QUERY *qry); } cmd[] = { { HLLAPI_CMD_CONNECTPS, cmd_connectps }, { HLLAPI_CMD_DISCONNECTPS, cmd_disconnectps }, { HLLAPI_CMD_INPUTSTRING, cmd_sendstring }, - { HLLAPI_CMD_WAIT, cmd_wait }, { HLLAPI_CMD_SETCURSOR, cmd_setcursor }, { HLLAPI_CMD_GETREVISION, cmd_getrevision }, - { HLLAPI_CMD_COPYPSTOSTR, cmd_copypstostr } + { HLLAPI_CMD_COPYPSTOSTR, cmd_copypstostr }, + { HLLAPI_CMD_WAIT, cmd_wait }, }; + int f; + trace("HLLAPI function %d",(int) qry->cmd); + + qry->hSession = lib3270_get_default_session_handle(); + + for(f=0;fcmd) + { + cmd[f].exec(qry); + return; + } + } + + g_warning("Unexpected HLLAPI function %d",(int) qry->cmd); + request_status(qry,EINVAL); + } + +/* + int run_hllapi(unsigned long function, char *string, unsigned short length, unsigned short rc) + { + trace("HLLAPI function %d",(int) function); for(f=0;f #include - int run_hllapi(unsigned long function, char *string, unsigned short length, unsigned short rc); + typedef struct _remotequery + { +#ifdef WIN32 + HANDLE hPipe; /**< Pipe handle (for response) */ +#endif // WIN32 + + H3270 * hSession; /**< 3270 Session */ + int cmd; /**< Command */ + int rc; /**< Response status */ + + int pos; + unsigned short length; /**< Query string length */ + const gchar * text; /**< Query string */ + + } QUERY; + + G_GNUC_INTERNAL void set_active(gboolean on); + G_GNUC_INTERNAL void enqueue_request(QUERY *qry); + G_GNUC_INTERNAL void request_complete(QUERY *qry, int rc, const gchar *text); + G_GNUC_INTERNAL void request_status(QUERY *qry, int rc); + G_GNUC_INTERNAL void request_buffer(QUERY *qry, int rc, size_t sz, const gpointer buffer); + +// int run_hllapi(unsigned long function, char *string, unsigned short length, unsigned short rc); + #ifdef WIN32 diff --git a/src/pw3270/v3270/oia.c b/src/pw3270/v3270/oia.c index 0e2c654..17b74fb 100644 --- a/src/pw3270/v3270/oia.c +++ b/src/pw3270/v3270/oia.c @@ -1087,7 +1087,7 @@ static void release_script(v3270 *widget) widget->script.id = 0; } -LIB3270_EXPORT int v3270_set_script(GtkWidget *widget, const gchar id, unsigned char on) +LIB3270_EXPORT int v3270_set_script(GtkWidget *widget, const gchar id, gboolean on) { v3270 *terminal; g_return_val_if_fail(GTK_IS_V3270(widget),EINVAL); -- libgit2 0.21.2