GUACAMOLE-860: [WIP] TN5250 adjustments.

This commit is contained in:
Nick Couchman 2019-08-03 17:15:02 -04:00
parent 22fe81913f
commit 30ec3be924
16 changed files with 431 additions and 308 deletions

View File

@ -30,50 +30,50 @@
#include <string.h> #include <string.h>
/** /**
* All telnet connection settings which may be updated by unprivileged users * All tn5250 connection settings which may be updated by unprivileged users
* through "argv" streams. * through "argv" streams.
*/ */
typedef enum guac_telnet_argv_setting { typedef enum guac_tn5250_argv_setting {
/** /**
* The color scheme of the terminal. * The color scheme of the terminal.
*/ */
GUAC_TELNET_ARGV_SETTING_COLOR_SCHEME, GUAC_TN5250_ARGV_SETTING_COLOR_SCHEME,
/** /**
* The name of the font family used by the terminal. * The name of the font family used by the terminal.
*/ */
GUAC_TELNET_ARGV_SETTING_FONT_NAME, GUAC_TN5250_ARGV_SETTING_FONT_NAME,
/** /**
* The size of the font used by the terminal, in points. * The size of the font used by the terminal, in points.
*/ */
GUAC_TELNET_ARGV_SETTING_FONT_SIZE GUAC_TN5250_ARGV_SETTING_FONT_SIZE
} guac_telnet_argv_setting; } guac_tn5250_argv_setting;
/** /**
* The value or current status of a connection parameter received over an * The value or current status of a connection parameter received over an
* "argv" stream. * "argv" stream.
*/ */
typedef struct guac_telnet_argv { typedef struct guac_tn5250_argv {
/** /**
* The specific setting being updated. * The specific setting being updated.
*/ */
guac_telnet_argv_setting setting; guac_tn5250_argv_setting setting;
/** /**
* Buffer space for containing the received argument value. * Buffer space for containing the received argument value.
*/ */
char buffer[GUAC_TELNET_ARGV_MAX_LENGTH]; char buffer[GUAC_TN5250_ARGV_MAX_LENGTH];
/** /**
* The number of bytes received so far. * The number of bytes received so far.
*/ */
int length; int length;
} guac_telnet_argv; } guac_tn5250_argv;
/** /**
* Handler for "blob" instructions which appends the data from received blobs * Handler for "blob" instructions which appends the data from received blobs
@ -81,10 +81,10 @@ typedef struct guac_telnet_argv {
* *
* @see guac_user_blob_handler * @see guac_user_blob_handler
*/ */
static int guac_telnet_argv_blob_handler(guac_user* user, static int guac_tn5250_argv_blob_handler(guac_user* user,
guac_stream* stream, void* data, int length) { guac_stream* stream, void* data, int length) {
guac_telnet_argv* argv = (guac_telnet_argv*) stream->data; guac_tn5250_argv* argv = (guac_tn5250_argv*) stream->data;
/* Calculate buffer size remaining, including space for null terminator, /* Calculate buffer size remaining, including space for null terminator,
* adjusting received length accordingly */ * adjusting received length accordingly */
@ -106,40 +106,40 @@ static int guac_telnet_argv_blob_handler(guac_user* user,
* *
* @see guac_user_end_handler * @see guac_user_end_handler
*/ */
static int guac_telnet_argv_end_handler(guac_user* user, static int guac_tn5250_argv_end_handler(guac_user* user,
guac_stream* stream) { guac_stream* stream) {
int size; int size;
guac_client* client = user->client; guac_client* client = user->client;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
guac_terminal* terminal = telnet_client->term; guac_terminal* terminal = tn5250_client->term;
/* Append null terminator to value */ /* Append null terminator to value */
guac_telnet_argv* argv = (guac_telnet_argv*) stream->data; guac_tn5250_argv* argv = (guac_tn5250_argv*) stream->data;
argv->buffer[argv->length] = '\0'; argv->buffer[argv->length] = '\0';
/* Apply changes to chosen setting */ /* Apply changes to chosen setting */
switch (argv->setting) { switch (argv->setting) {
/* Update color scheme */ /* Update color scheme */
case GUAC_TELNET_ARGV_SETTING_COLOR_SCHEME: case GUAC_TN5250_ARGV_SETTING_COLOR_SCHEME:
guac_terminal_apply_color_scheme(terminal, argv->buffer); guac_terminal_apply_color_scheme(terminal, argv->buffer);
break; break;
/* Update font name */ /* Update font name */
case GUAC_TELNET_ARGV_SETTING_FONT_NAME: case GUAC_TN5250_ARGV_SETTING_FONT_NAME:
guac_terminal_apply_font(terminal, argv->buffer, -1, 0); guac_terminal_apply_font(terminal, argv->buffer, -1, 0);
break; break;
/* Update font size */ /* Update font size */
case GUAC_TELNET_ARGV_SETTING_FONT_SIZE: case GUAC_TN5250_ARGV_SETTING_FONT_SIZE:
/* Update only if font size is sane */ /* Update only if font size is sane */
size = atoi(argv->buffer); size = atoi(argv->buffer);
if (size > 0) { if (size > 0) {
guac_terminal_apply_font(terminal, NULL, size, guac_terminal_apply_font(terminal, NULL, size,
telnet_client->settings->resolution); tn5250_client->settings->resolution);
} }
break; break;
@ -147,8 +147,8 @@ static int guac_telnet_argv_end_handler(guac_user* user,
} }
/* Update terminal window size if connected */ /* Update terminal window size if connected */
if (telnet_client->telnet != NULL && telnet_client->naws_enabled) if (tn5250_client->tn5250 != NULL && tn5250_client->naws_enabled)
guac_telnet_send_naws(telnet_client->telnet, terminal->term_width, guac_tn5250_send_naws(tn5250_client->tn5250, terminal->term_width,
terminal->term_height); terminal->term_height);
free(argv); free(argv);
@ -156,18 +156,18 @@ static int guac_telnet_argv_end_handler(guac_user* user,
} }
int guac_telnet_argv_handler(guac_user* user, guac_stream* stream, int guac_tn5250_argv_handler(guac_user* user, guac_stream* stream,
char* mimetype, char* name) { char* mimetype, char* name) {
guac_telnet_argv_setting setting; guac_tn5250_argv_setting setting;
/* Allow users to update the color scheme and font details */ /* Allow users to update the color scheme and font details */
if (strcmp(name, "color-scheme") == 0) if (strcmp(name, "color-scheme") == 0)
setting = GUAC_TELNET_ARGV_SETTING_COLOR_SCHEME; setting = GUAC_TN5250_ARGV_SETTING_COLOR_SCHEME;
else if (strcmp(name, "font-name") == 0) else if (strcmp(name, "font-name") == 0)
setting = GUAC_TELNET_ARGV_SETTING_FONT_NAME; setting = GUAC_TN5250_ARGV_SETTING_FONT_NAME;
else if (strcmp(name, "font-size") == 0) else if (strcmp(name, "font-size") == 0)
setting = GUAC_TELNET_ARGV_SETTING_FONT_SIZE; setting = GUAC_TN5250_ARGV_SETTING_FONT_SIZE;
/* No other connection parameters may be updated */ /* No other connection parameters may be updated */
else { else {
@ -177,13 +177,13 @@ int guac_telnet_argv_handler(guac_user* user, guac_stream* stream,
return 0; return 0;
} }
guac_telnet_argv* argv = malloc(sizeof(guac_telnet_argv)); guac_tn5250_argv* argv = malloc(sizeof(guac_tn5250_argv));
argv->setting = setting; argv->setting = setting;
argv->length = 0; argv->length = 0;
/* Prepare stream to receive argument value */ /* Prepare stream to receive argument value */
stream->blob_handler = guac_telnet_argv_blob_handler; stream->blob_handler = guac_tn5250_argv_blob_handler;
stream->end_handler = guac_telnet_argv_end_handler; stream->end_handler = guac_tn5250_argv_end_handler;
stream->data = argv; stream->data = argv;
/* Signal stream is ready */ /* Signal stream is ready */

View File

@ -18,8 +18,8 @@
*/ */
#ifndef GUAC_TELNET_ARGV_H #ifndef GUAC_TN5250_ARGV_H
#define GUAC_TELNET_ARGV_H #define GUAC_TN5250_ARGV_H
#include "config.h" #include "config.h"
@ -29,13 +29,13 @@
* The maximum number of bytes to allow for any argument value received via an * The maximum number of bytes to allow for any argument value received via an
* argv stream, including null terminator. * argv stream, including null terminator.
*/ */
#define GUAC_TELNET_ARGV_MAX_LENGTH 16384 #define GUAC_TN5250_ARGV_MAX_LENGTH 16384
/** /**
* Handles an incoming stream from a Guacamole "argv" instruction, updating the * Handles an incoming stream from a Guacamole "argv" instruction, updating the
* given connection parameter if that parameter is allowed to be updated. * given connection parameter if that parameter is allowed to be updated.
*/ */
guac_user_argv_handler guac_telnet_argv_handler; guac_user_argv_handler guac_tn5250_argv_handler;
#endif #endif

View File

@ -21,7 +21,7 @@
#include "client.h" #include "client.h"
#include "common/recording.h" #include "common/recording.h"
#include "settings.h" #include "settings.h"
#include "telnet.h" #include "tn5250.h"
#include "terminal/terminal.h" #include "terminal/terminal.h"
#include "user.h" #include "user.h"
@ -36,23 +36,23 @@
int guac_client_init(guac_client* client) { int guac_client_init(guac_client* client) {
/* Set client args */ /* Set client args */
client->args = GUAC_TELNET_CLIENT_ARGS; client->args = GUAC_TN5250_CLIENT_ARGS;
/* Allocate client instance data */ /* Allocate client instance data */
guac_telnet_client* telnet_client = calloc(1, sizeof(guac_telnet_client)); guac_tn5250_client* tn5250_client = calloc(1, sizeof(guac_tn5250_client));
client->data = telnet_client; client->data = tn5250_client;
/* Init clipboard */ /* Init clipboard */
telnet_client->clipboard = guac_common_clipboard_alloc(GUAC_TELNET_CLIPBOARD_MAX_LENGTH); tn5250_client->clipboard = guac_common_clipboard_alloc(GUAC_TN5250_CLIPBOARD_MAX_LENGTH);
/* Init telnet client */ /* Init tn5250 client */
telnet_client->socket_fd = -1; tn5250_client->socket_fd = -1;
telnet_client->naws_enabled = 0; tn5250_client->naws_enabled = 0;
telnet_client->echo_enabled = 1; tn5250_client->echo_enabled = 1;
/* Set handlers */ /* Set handlers */
client->join_handler = guac_telnet_user_join_handler; client->join_handler = guac_tn5250_user_join_handler;
client->free_handler = guac_telnet_client_free_handler; client->free_handler = guac_tn5250_client_free_handler;
/* Set locale and warn if not UTF-8 */ /* Set locale and warn if not UTF-8 */
setlocale(LC_CTYPE, ""); setlocale(LC_CTYPE, "");
@ -67,33 +67,33 @@ int guac_client_init(guac_client* client) {
} }
int guac_telnet_client_free_handler(guac_client* client) { int guac_tn5250_client_free_handler(guac_client* client) {
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
/* Close telnet connection */ /* Close tn5250 connection */
if (telnet_client->socket_fd != -1) if (tn5250_client->socket_fd != -1)
close(telnet_client->socket_fd); close(tn5250_client->socket_fd);
/* Clean up recording, if in progress */ /* Clean up recording, if in progress */
if (telnet_client->recording != NULL) if (tn5250_client->recording != NULL)
guac_common_recording_free(telnet_client->recording); guac_common_recording_free(tn5250_client->recording);
/* Kill terminal */ /* Kill terminal */
guac_terminal_free(telnet_client->term); guac_terminal_free(tn5250_client->term);
/* Wait for and free telnet session, if connected */ /* Wait for and free tn5250 session, if connected */
if (telnet_client->telnet != NULL) { if (tn5250_client->telnet != NULL) {
pthread_join(telnet_client->client_thread, NULL); pthread_join(tn5250_client->client_thread, NULL);
telnet_free(telnet_client->telnet); telnet_free(tn5250_client->telnet);
} }
/* Free settings */ /* Free settings */
if (telnet_client->settings != NULL) if (tn5250_client->settings != NULL)
guac_telnet_settings_free(telnet_client->settings); guac_tn5250_settings_free(tn5250_client->settings);
guac_common_clipboard_free(telnet_client->clipboard); guac_common_clipboard_free(tn5250_client->clipboard);
free(telnet_client); free(tn5250_client);
return 0; return 0;
} }

View File

@ -17,8 +17,8 @@
* under the License. * under the License.
*/ */
#ifndef GUAC_TELNET__CLIENT_H #ifndef GUAC_TN5250_CLIENT_H
#define GUAC_TELNET__CLIENT_H #define GUAC_TN5250_CLIENT_H
#include "config.h" #include "config.h"
#include "terminal/terminal.h" #include "terminal/terminal.h"
@ -32,13 +32,13 @@
/** /**
* The maximum number of bytes to allow within the clipboard. * The maximum number of bytes to allow within the clipboard.
*/ */
#define GUAC_TELNET_CLIPBOARD_MAX_LENGTH 262144 #define GUAC_TN5250_CLIPBOARD_MAX_LENGTH 262144
/** /**
* Free handler. Required by libguac and called when the guac_client is * Free handler. Required by libguac and called when the guac_client is
* disconnected and must be cleaned up. * disconnected and must be cleaned up.
*/ */
guac_client_free_handler guac_telnet_client_free_handler; guac_client_free_handler guac_tn5250_client_free_handler;
#endif #endif

View File

@ -20,40 +20,40 @@
#include "config.h" #include "config.h"
#include "clipboard.h" #include "clipboard.h"
#include "common/clipboard.h" #include "common/clipboard.h"
#include "telnet.h" #include "tn5250.h"
#include "terminal/terminal.h" #include "terminal/terminal.h"
#include <guacamole/client.h> #include <guacamole/client.h>
#include <guacamole/stream.h> #include <guacamole/stream.h>
#include <guacamole/user.h> #include <guacamole/user.h>
int guac_telnet_clipboard_handler(guac_user* user, guac_stream* stream, int guac_tn5250_clipboard_handler(guac_user* user, guac_stream* stream,
char* mimetype) { char* mimetype) {
/* Clear clipboard and prepare for new data */ /* Clear clipboard and prepare for new data */
guac_client* client = user->client; guac_client* client = user->client;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
guac_common_clipboard_reset(telnet_client->clipboard, mimetype); guac_common_clipboard_reset(tn5250_client->clipboard, mimetype);
/* Set handlers for clipboard stream */ /* Set handlers for clipboard stream */
stream->blob_handler = guac_telnet_clipboard_blob_handler; stream->blob_handler = guac_tn5250_clipboard_blob_handler;
stream->end_handler = guac_telnet_clipboard_end_handler; stream->end_handler = guac_tn5250_clipboard_end_handler;
return 0; return 0;
} }
int guac_telnet_clipboard_blob_handler(guac_user* user, guac_stream* stream, int guac_tn5250_clipboard_blob_handler(guac_user* user, guac_stream* stream,
void* data, int length) { void* data, int length) {
/* Append new data */ /* Append new data */
guac_client* client = user->client; guac_client* client = user->client;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
guac_common_clipboard_append(telnet_client->clipboard, data, length); guac_common_clipboard_append(tn5250_client->clipboard, data, length);
return 0; return 0;
} }
int guac_telnet_clipboard_end_handler(guac_user* user, guac_stream* stream) { int guac_tn5250_clipboard_end_handler(guac_user* user, guac_stream* stream) {
/* Nothing to do - clipboard is implemented within client */ /* Nothing to do - clipboard is implemented within client */

View File

@ -17,8 +17,8 @@
* under the License. * under the License.
*/ */
#ifndef GUAC_TELNET_CLIPBOARD_H #ifndef GUAC_TN5250_CLIPBOARD_H
#define GUAC_TELNET_CLIPBOARD_H #define GUAC_TN5250_CLIPBOARD_H
#include "config.h" #include "config.h"
@ -27,17 +27,17 @@
/** /**
* Handler for inbound clipboard streams. * Handler for inbound clipboard streams.
*/ */
guac_user_clipboard_handler guac_telnet_clipboard_handler; guac_user_clipboard_handler guac_tn5250_clipboard_handler;
/** /**
* Handler for data received along clipboard streams. * Handler for data received along clipboard streams.
*/ */
guac_user_blob_handler guac_telnet_clipboard_blob_handler; guac_user_blob_handler guac_tn5250_clipboard_blob_handler;
/** /**
* Handler for end-of-stream related to clipboard. * Handler for end-of-stream related to clipboard.
*/ */
guac_user_end_handler guac_telnet_clipboard_end_handler; guac_user_end_handler guac_tn5250_clipboard_end_handler;
#endif #endif

View File

@ -21,7 +21,7 @@
#include "common/recording.h" #include "common/recording.h"
#include "input.h" #include "input.h"
#include "terminal/terminal.h" #include "terminal/terminal.h"
#include "telnet.h" #include "tn5250.h"
#include <guacamole/client.h> #include <guacamole/client.h>
#include <guacamole/user.h> #include <guacamole/user.h>
@ -32,20 +32,20 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
int guac_telnet_user_mouse_handler(guac_user* user, int x, int y, int mask) { int guac_tn5250_user_mouse_handler(guac_user* user, int x, int y, int mask) {
guac_client* client = user->client; guac_client* client = user->client;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
guac_telnet_settings* settings = telnet_client->settings; guac_tn5250_settings* settings = tn5250_client->settings;
guac_terminal* term = telnet_client->term; guac_terminal* term = tn5250_client->term;
/* Skip if terminal not yet ready */ /* Skip if terminal not yet ready */
if (term == NULL) if (term == NULL)
return 0; return 0;
/* Report mouse position within recording */ /* Report mouse position within recording */
if (telnet_client->recording != NULL) if (tn5250_client->recording != NULL)
guac_common_recording_report_mouse(telnet_client->recording, x, y, guac_common_recording_report_mouse(tn5250_client->recording, x, y,
mask); mask);
/* Send mouse if not searching for password or username */ /* Send mouse if not searching for password or username */
@ -56,16 +56,16 @@ int guac_telnet_user_mouse_handler(guac_user* user, int x, int y, int mask) {
} }
int guac_telnet_user_key_handler(guac_user* user, int keysym, int pressed) { int guac_tn5250_user_key_handler(guac_user* user, int keysym, int pressed) {
guac_client* client = user->client; guac_client* client = user->client;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
guac_telnet_settings* settings = telnet_client->settings; guac_tn5250_settings* settings = tn5250_client->settings;
guac_terminal* term = telnet_client->term; guac_terminal* term = tn5250_client->term;
/* Report key state within recording */ /* Report key state within recording */
if (telnet_client->recording != NULL) if (tn5250_client->recording != NULL)
guac_common_recording_report_key(telnet_client->recording, guac_common_recording_report_key(tn5250_client->recording,
keysym, pressed); keysym, pressed);
/* Skip if terminal not yet ready */ /* Skip if terminal not yet ready */
@ -104,7 +104,7 @@ int guac_telnet_user_key_handler(guac_user* user, int keysym, int pressed) {
)) { )) {
/* Send IAC BRK */ /* Send IAC BRK */
telnet_iac(telnet_client->telnet, TELNET_BREAK); telnet_iac(tn5250_client->telnet, TELNET_BREAK);
return 0; return 0;
} }
@ -116,12 +116,12 @@ int guac_telnet_user_key_handler(guac_user* user, int keysym, int pressed) {
} }
int guac_telnet_user_size_handler(guac_user* user, int width, int height) { int guac_tn5250_user_size_handler(guac_user* user, int width, int height) {
/* Get terminal */ /* Get terminal */
guac_client* client = user->client; guac_client* client = user->client;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
guac_terminal* terminal = telnet_client->term; guac_terminal* terminal = tn5250_client->term;
/* Skip if terminal not yet ready */ /* Skip if terminal not yet ready */
if (terminal == NULL) if (terminal == NULL)
@ -131,8 +131,8 @@ int guac_telnet_user_size_handler(guac_user* user, int width, int height) {
guac_terminal_resize(terminal, width, height); guac_terminal_resize(terminal, width, height);
/* Update terminal window size if connected */ /* Update terminal window size if connected */
if (telnet_client->telnet != NULL && telnet_client->naws_enabled) if (tn5250_client->telnet != NULL && tn5250_client->naws_enabled)
guac_telnet_send_naws(telnet_client->telnet, terminal->term_width, guac_tn5250_send_naws(tn5250_client->telnet, terminal->term_width,
terminal->term_height); terminal->term_height);
return 0; return 0;

View File

@ -17,8 +17,8 @@
* under the License. * under the License.
*/ */
#ifndef GUAC_TELNET_INPUT_H #ifndef GUAC_TN5250_INPUT_H
#define GUAC_TELNET_INPUT_H #define GUAC_TN5250_INPUT_H
#include "config.h" #include "config.h"
@ -28,19 +28,19 @@
* Handler for key events. Required by libguac and called whenever key events * Handler for key events. Required by libguac and called whenever key events
* are received. * are received.
*/ */
guac_user_key_handler guac_telnet_user_key_handler; guac_user_key_handler guac_tn5250_user_key_handler;
/** /**
* Handler for mouse events. Required by libguac and called whenever mouse * Handler for mouse events. Required by libguac and called whenever mouse
* events are received. * events are received.
*/ */
guac_user_mouse_handler guac_telnet_user_mouse_handler; guac_user_mouse_handler guac_tn5250_user_mouse_handler;
/** /**
* Handler for size events. Required by libguac and called whenever the remote * Handler for size events. Required by libguac and called whenever the remote
* display (window) is resized. * display (window) is resized.
*/ */
guac_user_size_handler guac_telnet_user_size_handler; guac_user_size_handler guac_tn5250_user_size_handler;
#endif #endif

View File

@ -19,7 +19,7 @@
#include "config.h" #include "config.h"
#include "pipe.h" #include "pipe.h"
#include "telnet.h" #include "tn5250.h"
#include "terminal/terminal.h" #include "terminal/terminal.h"
#include <guacamole/protocol.h> #include <guacamole/protocol.h>
@ -28,15 +28,15 @@
#include <string.h> #include <string.h>
int guac_telnet_pipe_handler(guac_user* user, guac_stream* stream, int guac_tn5250_pipe_handler(guac_user* user, guac_stream* stream,
char* mimetype, char* name) { char* mimetype, char* name) {
guac_client* client = user->client; guac_client* client = user->client;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
/* Redirect STDIN if pipe has required name */ /* Redirect STDIN if pipe has required name */
if (strcmp(name, GUAC_TELNET_STDIN_PIPE_NAME) == 0) { if (strcmp(name, GUAC_TN5250_STDIN_PIPE_NAME) == 0) {
guac_terminal_send_stream(telnet_client->term, user, stream); guac_terminal_send_stream(tn5250_client->term, user, stream);
return 0; return 0;
} }

View File

@ -18,8 +18,8 @@
*/ */
#ifndef GUAC_TELNET_PIPE_H #ifndef GUAC_TN5250_PIPE_H
#define GUAC_TELNET_PIPE_H #define GUAC_TN5250_PIPE_H
#include "config.h" #include "config.h"
@ -29,14 +29,14 @@
* The name reserved for the inbound pipe stream which forces the terminal * The name reserved for the inbound pipe stream which forces the terminal
* emulator's STDIN to be received from the pipe. * emulator's STDIN to be received from the pipe.
*/ */
#define GUAC_TELNET_STDIN_PIPE_NAME "STDIN" #define GUAC_TN5250_STDIN_PIPE_NAME "STDIN"
/** /**
* Handles an incoming stream from a Guacamole "pipe" instruction. If the pipe * Handles an incoming stream from a Guacamole "pipe" instruction. If the pipe
* is named "STDIN", the the contents of the pipe stream are redirected to * is named "STDIN", the the contents of the pipe stream are redirected to
* STDIN of the terminal emulator for as long as the pipe is open. * STDIN of the terminal emulator for as long as the pipe is open.
*/ */
guac_user_pipe_handler guac_telnet_pipe_handler; guac_user_pipe_handler guac_tn5250_pipe_handler;
#endif #endif

View File

@ -33,6 +33,7 @@
const char* GUAC_TN5250_CLIENT_ARGS[] = { const char* GUAC_TN5250_CLIENT_ARGS[] = {
"hostname", "hostname",
"port", "port",
"ssl",
"username", "username",
"username-regex", "username-regex",
"password", "password",
@ -60,7 +61,7 @@ const char* GUAC_TN5250_CLIENT_ARGS[] = {
NULL NULL
}; };
enum TELNET_ARGS_IDX { enum TN5250_ARGS_IDX {
/** /**
* The hostname to connect to. Required. * The hostname to connect to. Required.
@ -71,6 +72,11 @@ enum TELNET_ARGS_IDX {
* The port to connect to. Optional. * The port to connect to. Optional.
*/ */
IDX_PORT, IDX_PORT,
/**
* Whether or not to use SSL. Optional.
*/
IDX_SSL,
/** /**
* The name of the user to login as. Optional. * The name of the user to login as. Optional.
@ -232,13 +238,13 @@ enum TELNET_ARGS_IDX {
*/ */
IDX_DISABLE_PASTE, IDX_DISABLE_PASTE,
TELNET_ARGS_COUNT TN5250_ARGS_COUNT
}; };
/** /**
* Compiles the given regular expression, returning NULL if compilation fails * Compiles the given regular expression, returning NULL if compilation fails
* or of the given regular expression is NULL. The returned regex_t must be * or of the given regular expression is NULL. The returned regex_t must be
* freed with regfree() AND free(), or with guac_telnet_regex_free(). * freed with regfree() AND free(), or with guac_tn5250_regex_free().
* *
* @param user * @param user
* The user who provided the setting associated with the given regex * The user who provided the setting associated with the given regex
@ -251,7 +257,7 @@ enum TELNET_ARGS_IDX {
* The compiled regular expression, or NULL if compilation fails or NULL * The compiled regular expression, or NULL if compilation fails or NULL
* was originally provided for the pattern. * was originally provided for the pattern.
*/ */
static regex_t* guac_telnet_compile_regex(guac_user* user, char* pattern) { static regex_t* guac_tn5250_compile_regex(guac_user* user, char* pattern) {
/* Nothing to compile if no pattern provided */ /* Nothing to compile if no pattern provided */
if (pattern == NULL) if (pattern == NULL)
@ -275,7 +281,7 @@ static regex_t* guac_telnet_compile_regex(guac_user* user, char* pattern) {
return regex; return regex;
} }
void guac_telnet_regex_free(regex_t** regex) { void guac_tn5250_regex_free(regex_t** regex) {
if (*regex != NULL) { if (*regex != NULL) {
regfree(*regex); regfree(*regex);
free(*regex); free(*regex);
@ -283,100 +289,100 @@ void guac_telnet_regex_free(regex_t** regex) {
} }
} }
guac_telnet_settings* guac_telnet_parse_args(guac_user* user, guac_tn5250_settings* guac_tn5250_parse_args(guac_user* user,
int argc, const char** argv) { int argc, const char** argv) {
/* Validate arg count */ /* Validate arg count */
if (argc != TELNET_ARGS_COUNT) { if (argc != TN5250_ARGS_COUNT) {
guac_user_log(user, GUAC_LOG_WARNING, "Incorrect number of connection " guac_user_log(user, GUAC_LOG_WARNING, "Incorrect number of connection "
"parameters provided: expected %i, got %i.", "parameters provided: expected %i, got %i.",
TELNET_ARGS_COUNT, argc); TN5250_ARGS_COUNT, argc);
return NULL; return NULL;
} }
guac_telnet_settings* settings = calloc(1, sizeof(guac_telnet_settings)); guac_tn5250_settings* settings = calloc(1, sizeof(guac_tn5250_settings));
/* Read parameters */ /* Read hostname */
settings->hostname = settings->hostname =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_HOSTNAME, ""); IDX_HOSTNAME, "");
/* Read username */ /* Read username */
settings->username = settings->username =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_USERNAME, NULL); IDX_USERNAME, NULL);
/* Read username regex only if username is specified */ /* Read username regex only if username is specified */
if (settings->username != NULL) { if (settings->username != NULL) {
settings->username_regex = guac_telnet_compile_regex(user, settings->username_regex = guac_tn5250_compile_regex(user,
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_USERNAME_REGEX, GUAC_TELNET_DEFAULT_USERNAME_REGEX)); IDX_USERNAME_REGEX, GUAC_TN5250_DEFAULT_USERNAME_REGEX));
} }
/* Read password */ /* Read password */
settings->password = settings->password =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_PASSWORD, NULL); IDX_PASSWORD, NULL);
/* Read password regex only if password is specified */ /* Read password regex only if password is specified */
if (settings->password != NULL) { if (settings->password != NULL) {
settings->password_regex = guac_telnet_compile_regex(user, settings->password_regex = guac_tn5250_compile_regex(user,
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_PASSWORD_REGEX, GUAC_TELNET_DEFAULT_PASSWORD_REGEX)); IDX_PASSWORD_REGEX, GUAC_TN5250_DEFAULT_PASSWORD_REGEX));
} }
/* Read optional login success detection regex */ /* Read optional login success detection regex */
settings->login_success_regex = guac_telnet_compile_regex(user, settings->login_success_regex = guac_tn5250_compile_regex(user,
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_LOGIN_SUCCESS_REGEX, NULL)); IDX_LOGIN_SUCCESS_REGEX, NULL));
/* Read optional login failure detection regex */ /* Read optional login failure detection regex */
settings->login_failure_regex = guac_telnet_compile_regex(user, settings->login_failure_regex = guac_tn5250_compile_regex(user,
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_LOGIN_FAILURE_REGEX, NULL)); IDX_LOGIN_FAILURE_REGEX, NULL));
/* Both login success and login failure regexes must be provided if either /* Both login success and login failure regexes must be provided if either
* is present at all */ * is present at all */
if (settings->login_success_regex != NULL if (settings->login_success_regex != NULL
&& settings->login_failure_regex == NULL) { && settings->login_failure_regex == NULL) {
guac_telnet_regex_free(&settings->login_success_regex); guac_tn5250_regex_free(&settings->login_success_regex);
guac_user_log(user, GUAC_LOG_WARNING, "Ignoring provided value for " guac_user_log(user, GUAC_LOG_WARNING, "Ignoring provided value for "
"\"%s\" as \"%s\" must also be provided.", "\"%s\" as \"%s\" must also be provided.",
GUAC_TELNET_CLIENT_ARGS[IDX_LOGIN_SUCCESS_REGEX], GUAC_TN5250_CLIENT_ARGS[IDX_LOGIN_SUCCESS_REGEX],
GUAC_TELNET_CLIENT_ARGS[IDX_LOGIN_FAILURE_REGEX]); GUAC_TN5250_CLIENT_ARGS[IDX_LOGIN_FAILURE_REGEX]);
} }
else if (settings->login_failure_regex != NULL else if (settings->login_failure_regex != NULL
&& settings->login_success_regex == NULL) { && settings->login_success_regex == NULL) {
guac_telnet_regex_free(&settings->login_failure_regex); guac_tn5250_regex_free(&settings->login_failure_regex);
guac_user_log(user, GUAC_LOG_WARNING, "Ignoring provided value for " guac_user_log(user, GUAC_LOG_WARNING, "Ignoring provided value for "
"\"%s\" as \"%s\" must also be provided.", "\"%s\" as \"%s\" must also be provided.",
GUAC_TELNET_CLIENT_ARGS[IDX_LOGIN_FAILURE_REGEX], GUAC_TN5250_CLIENT_ARGS[IDX_LOGIN_FAILURE_REGEX],
GUAC_TELNET_CLIENT_ARGS[IDX_LOGIN_SUCCESS_REGEX]); GUAC_TN5250_CLIENT_ARGS[IDX_LOGIN_SUCCESS_REGEX]);
} }
/* Read-only mode */ /* Read-only mode */
settings->read_only = settings->read_only =
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_boolean(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_READ_ONLY, false); IDX_READ_ONLY, false);
/* Read maximum scrollback size */ /* Read maximum scrollback size */
settings->max_scrollback = settings->max_scrollback =
guac_user_parse_args_int(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_int(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_SCROLLBACK, GUAC_TELNET_DEFAULT_MAX_SCROLLBACK); IDX_SCROLLBACK, GUAC_TN5250_DEFAULT_MAX_SCROLLBACK);
/* Read font name */ /* Read font name */
settings->font_name = settings->font_name =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_FONT_NAME, GUAC_TELNET_DEFAULT_FONT_NAME); IDX_FONT_NAME, GUAC_TN5250_DEFAULT_FONT_NAME);
/* Read font size */ /* Read font size */
settings->font_size = settings->font_size =
guac_user_parse_args_int(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_int(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_FONT_SIZE, GUAC_TELNET_DEFAULT_FONT_SIZE); IDX_FONT_SIZE, GUAC_TN5250_DEFAULT_FONT_SIZE);
/* Copy requested color scheme */ /* Copy requested color scheme */
settings->color_scheme = settings->color_scheme =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_COLOR_SCHEME, ""); IDX_COLOR_SCHEME, "");
/* Pull width/height/resolution directly from user */ /* Pull width/height/resolution directly from user */
@ -384,74 +390,84 @@ guac_telnet_settings* guac_telnet_parse_args(guac_user* user,
settings->height = user->info.optimal_height; settings->height = user->info.optimal_height;
settings->resolution = user->info.optimal_resolution; settings->resolution = user->info.optimal_resolution;
/* Read SSL */
settings->ssl =
guac_user_parse_args_boolean(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_SSL, false);
int defualt_port = GUAC_TN5250_DEFAULT_PORT;
if (settings->ssl)
default_port = GUAC_TN5250_DEFAULT_SSL_PORT;
/* Read port */ /* Read port */
settings->port = settings->port =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_PORT, GUAC_TELNET_DEFAULT_PORT); IDX_PORT, defualt_port);
/* Read typescript path */ /* Read typescript path */
settings->typescript_path = settings->typescript_path =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_TYPESCRIPT_PATH, NULL); IDX_TYPESCRIPT_PATH, NULL);
/* Read typescript name */ /* Read typescript name */
settings->typescript_name = settings->typescript_name =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_TYPESCRIPT_NAME, GUAC_TELNET_DEFAULT_TYPESCRIPT_NAME); IDX_TYPESCRIPT_NAME, GUAC_TN5250_DEFAULT_TYPESCRIPT_NAME);
/* Parse path creation flag */ /* Parse path creation flag */
settings->create_typescript_path = settings->create_typescript_path =
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_boolean(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_CREATE_TYPESCRIPT_PATH, false); IDX_CREATE_TYPESCRIPT_PATH, false);
/* Read recording path */ /* Read recording path */
settings->recording_path = settings->recording_path =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_RECORDING_PATH, NULL); IDX_RECORDING_PATH, NULL);
/* Read recording name */ /* Read recording name */
settings->recording_name = settings->recording_name =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_RECORDING_NAME, GUAC_TELNET_DEFAULT_RECORDING_NAME); IDX_RECORDING_NAME, GUAC_TN5250_DEFAULT_RECORDING_NAME);
/* Parse output exclusion flag */ /* Parse output exclusion flag */
settings->recording_exclude_output = settings->recording_exclude_output =
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_boolean(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_RECORDING_EXCLUDE_OUTPUT, false); IDX_RECORDING_EXCLUDE_OUTPUT, false);
/* Parse mouse exclusion flag */ /* Parse mouse exclusion flag */
settings->recording_exclude_mouse = settings->recording_exclude_mouse =
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_boolean(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_RECORDING_EXCLUDE_MOUSE, false); IDX_RECORDING_EXCLUDE_MOUSE, false);
/* Parse key event inclusion flag */ /* Parse key event inclusion flag */
settings->recording_include_keys = settings->recording_include_keys =
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_boolean(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_RECORDING_INCLUDE_KEYS, false); IDX_RECORDING_INCLUDE_KEYS, false);
/* Parse path creation flag */ /* Parse path creation flag */
settings->create_recording_path = settings->create_recording_path =
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_boolean(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_CREATE_RECORDING_PATH, false); IDX_CREATE_RECORDING_PATH, false);
/* Parse backspace key code */ /* Parse backspace key code */
settings->backspace = settings->backspace =
guac_user_parse_args_int(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_int(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_BACKSPACE, 127); IDX_BACKSPACE, 127);
/* Read terminal emulator type. */ /* Read terminal emulator type. */
settings->terminal_type = settings->terminal_type =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_TERMINAL_TYPE, "linux"); IDX_TERMINAL_TYPE, "linux");
/* Parse clipboard copy disable flag */ /* Parse clipboard copy disable flag */
settings->disable_copy = settings->disable_copy =
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_boolean(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_DISABLE_COPY, false); IDX_DISABLE_COPY, false);
/* Parse clipboard paste disable flag */ /* Parse clipboard paste disable flag */
settings->disable_paste = settings->disable_paste =
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, guac_user_parse_args_boolean(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_DISABLE_PASTE, false); IDX_DISABLE_PASTE, false);
/* Parsing was successful */ /* Parsing was successful */
@ -459,7 +475,7 @@ guac_telnet_settings* guac_telnet_parse_args(guac_user* user,
} }
void guac_telnet_settings_free(guac_telnet_settings* settings) { void guac_tn5250_settings_free(guac_tn5250_settings* settings) {
/* Free network connection information */ /* Free network connection information */
free(settings->hostname); free(settings->hostname);
@ -470,10 +486,10 @@ void guac_telnet_settings_free(guac_telnet_settings* settings) {
free(settings->password); free(settings->password);
/* Free various regexes */ /* Free various regexes */
guac_telnet_regex_free(&settings->username_regex); guac_tn5250_regex_free(&settings->username_regex);
guac_telnet_regex_free(&settings->password_regex); guac_tn5250_regex_free(&settings->password_regex);
guac_telnet_regex_free(&settings->login_success_regex); guac_tn5250_regex_free(&settings->login_success_regex);
guac_telnet_regex_free(&settings->login_failure_regex); guac_tn5250_regex_free(&settings->login_failure_regex);
/* Free display preferences */ /* Free display preferences */
free(settings->font_name); free(settings->font_name);

View File

@ -31,63 +31,170 @@
/** /**
* The name of the font to use for the terminal if no name is specified. * The name of the font to use for the terminal if no name is specified.
*/ */
#define GUAC_TELNET_DEFAULT_FONT_NAME "monospace" #define GUAC_TN5250_DEFAULT_FONT_NAME "monospace"
/** /**
* The size of the font to use for the terminal if no font size is specified, * The size of the font to use for the terminal if no font size is specified,
* in points. * in points.
*/ */
#define GUAC_TELNET_DEFAULT_FONT_SIZE 12 #define GUAC_TN5250_DEFAULT_FONT_SIZE 12
/** /**
* The port to connect to when initiating any telnet connection, if no other * The port to connect to when initiating a 5250 telnet connection, if no other
* port is specified. * port is specified.
*/ */
#define GUAC_TELNET_DEFAULT_PORT "23" #define GUAC_TN5250_DEFAULT_PORT "23"
/**
* The port to connect to when initiating a 5250 telnet connection over SSL,
* if no other port is specified.
*/
#define GUAC_TN5250_DEFAULT_SSL_PORT "992"
/** /**
* The filename to use for the typescript, if not specified. * The filename to use for the typescript, if not specified.
*/ */
#define GUAC_TELNET_DEFAULT_TYPESCRIPT_NAME "typescript" #define GUAC_TN5250_DEFAULT_TYPESCRIPT_NAME "typescript"
/** /**
* The filename to use for the screen recording, if not specified. * The filename to use for the screen recording, if not specified.
*/ */
#define GUAC_TELNET_DEFAULT_RECORDING_NAME "recording" #define GUAC_TN5250_DEFAULT_RECORDING_NAME "recording"
/** /**
* The regular expression to use when searching for the username/login prompt * The regular expression to use when searching for the username/login prompt
* if no other regular expression is specified. * if no other regular expression is specified.
*/ */
#define GUAC_TELNET_DEFAULT_USERNAME_REGEX "[Ll]ogin:" #define GUAC_TN5250_DEFAULT_USERNAME_REGEX "[Ll]ogin:"
/** /**
* The regular expression to use when searching for the password prompt if no * The regular expression to use when searching for the password prompt if no
* other regular expression is specified. * other regular expression is specified.
*/ */
#define GUAC_TELNET_DEFAULT_PASSWORD_REGEX "[Pp]assword:" #define GUAC_TN5250_DEFAULT_PASSWORD_REGEX "[Pp]assword:"
/** /**
* The default maximum scrollback size in rows. * The default maximum scrollback size in rows.
*/ */
#define GUAC_TELNET_DEFAULT_MAX_SCROLLBACK 1000 #define GUAC_TN5250_DEFAULT_MAX_SCROLLBACK 1000
/** /**
* Settings for the telnet connection. The values for this structure are parsed * The available terminal types for TN5250 connections. These are defined
* from the arguments given during the Guacamole protocol handshake using the * in RFC-1205, Section 2.
* guac_telnet_parse_args() function.
*/ */
typedef struct guac_telnet_settings { typedef enum guac_tn5250_terminal_types {
/**
* IBM-3179-2, 24 x 80 color display
*/
IBM_3179_2,
/** /**
* The hostname of the telnet server to connect to. * IBM-3180-2, 27 x 132 monochrome display
*/
IBM_3180_2,
/**
* IBM-3196-A1, 24 x 80 monochrome display
*/
IBM_3196_A1,
/**
* IBM-3477-FC, 27 x 132 color display
*/
IBM_3477_FC,
/**
* IBM-3477-FG, 27 x 132 monochrome display
*/
IBM_3477_FG,
/**
* IBM-5251-11, 24 x 80 monochrome display
*/
IBM_5251_11,
/**
* IBM-5291-1, 24 x 80 monochrome display
*/
IBM_5291_1,
/**
* IBM-5292-2, 24 x 80 color display
*/
IBM_5292_2,
/**
* IBM-5555-B01, 24 x 80 Double-Byte Character Set (DBCS)
*/
IBM_5555_B01,
/**
* IBM-5555-C01, 24 x 80 Double-Byte Character Set color display
*/
IBM_5555_C01
} guac_tn5250_terminal_type;
typedef struct __guac_tn5250_terminal_params {
/**
* The type of terminal, as defined in RFC-1205
*/
guac_tn5250_terminal_type terminal;
/**
* The number of rows in the terminal
*/
int rows;
/**
* The number of columns in the terminal
*/
int cols;
/**
* True if the terminal supports color, false if only monochrome.
*/
bool color;
} __guac_tn5250_terminal_params;
__guac_tn5250_terminal_params __guac_tn5250_terminals[] = {
{IBM_3179_2, 24, 80, true },
{IBM_3180_2, 27, 132, false},
{IBM_3196_A1, 24, 80, false},
{IBM_3477_FC, 27, 132, true },
{IBM_3477_FG, 27, 132, false},
{IBM_5251_11, 24, 80, false},
{IBM_5291_1, 24, 80, false},
{IBM_5292_2, 24, 80, true },
{IBM_5555_B01, 24, 80, false},
{IBM_5555_C01, 24, 80, true },
{NULL, -1, -1, false}
}
/**
* Settings for the TN5250 connection. The values for this structure are parsed
* from the arguments given during the Guacamole protocol handshake using the
* guac_tn5250_parse_args() function.
*/
typedef struct guac_tn5250_settings {
/**
* The hostname of the TN5250 server to connect to.
*/ */
char* hostname; char* hostname;
/** /**
* The port of the telnet server to connect to. * The port of the TN5250 server to connect to.
*/ */
char* port; char* port;
/**
* Whether or not to use SSL.
*/
bool ssl;
/** /**
* The name of the user to login as, if any. If no username is specified, * The name of the user to login as, if any. If no username is specified,
@ -246,7 +353,7 @@ typedef struct guac_telnet_settings {
bool recording_include_keys; bool recording_include_keys;
/** /**
* The ASCII code, as an integer, that the telnet client will use when the * The ASCII code, as an integer, that the 5250 client will use when the
* backspace key is pressed. By default, this is 127, ASCII delete, if * backspace key is pressed. By default, this is 127, ASCII delete, if
* not specified in the client settings. * not specified in the client settings.
*/ */
@ -255,9 +362,9 @@ typedef struct guac_telnet_settings {
/** /**
* The terminal emulator type that is passed to the remote system. * The terminal emulator type that is passed to the remote system.
*/ */
char* terminal_type; guac_tn5250_terminal_type terminal_type;
} guac_telnet_settings; } guac_tn5250_settings;
/** /**
* Parses all given args, storing them in a newly-allocated settings object. If * Parses all given args, storing them in a newly-allocated settings object. If
@ -275,10 +382,10 @@ typedef struct guac_telnet_settings {
* *
* @return * @return
* A newly-allocated settings object which must be freed with * A newly-allocated settings object which must be freed with
* guac_telnet_settings_free() when no longer needed. If the arguments fail * guac_tn5250_settings_free() when no longer needed. If the arguments fail
* to parse, NULL is returned. * to parse, NULL is returned.
*/ */
guac_telnet_settings* guac_telnet_parse_args(guac_user* user, guac_tn5250_settings* guac_tn5250_parse_args(guac_user* user,
int argc, const char** argv); int argc, const char** argv);
/** /**
@ -289,21 +396,21 @@ guac_telnet_settings* guac_telnet_parse_args(guac_user* user,
* @param regex * @param regex
* The address of the pointer to the regex that should be freed. * The address of the pointer to the regex that should be freed.
*/ */
void guac_telnet_regex_free(regex_t** regex); void guac_tn5250_regex_free(regex_t** regex);
/** /**
* Frees the given guac_telnet_settings object, having been previously * Frees the given guac_tn5250_settings object, having been previously
* allocated via guac_telnet_parse_args(). * allocated via guac_tn5250_parse_args().
* *
* @param settings * @param settings
* The settings object to free. * The settings object to free.
*/ */
void guac_telnet_settings_free(guac_telnet_settings* settings); void guac_tn5250_settings_free(guac_tn5250_settings* settings);
/** /**
* NULL-terminated array of accepted client args. * NULL-terminated array of accepted client args.
*/ */
extern const char* GUAC_TELNET_CLIENT_ARGS[]; extern const char* GUAC_TN5250_CLIENT_ARGS[];
#endif #endif

View File

@ -88,13 +88,13 @@ static int __guac_telnet_write_all(int fd, const char* buffer, int size) {
* sent after the value is sent. * sent after the value is sent.
* *
* @param client * @param client
* The guac_client associated with the telnet session. * The guac_client associated with the tn5250 session.
* *
* @param regex * @param regex
* The regex to search for within the given line buffer. * The regex to search for within the given line buffer.
* *
* @param value * @param value
* The string value to send through STDIN of the telnet session if a * The string value to send through STDIN of the tn5250 session if a
* match is found, or NULL if no value should be sent. * match is found, or NULL if no value should be sent.
* *
* @param line_buffer * @param line_buffer
@ -103,18 +103,18 @@ static int __guac_telnet_write_all(int fd, const char* buffer, int size) {
* @return * @return
* true if a match is found, false otherwise. * true if a match is found, false otherwise.
*/ */
static bool guac_telnet_regex_exec(guac_client* client, regex_t* regex, static bool guac_tn5250_regex_exec(guac_client* client, regex_t* regex,
const char* value, const char* line_buffer) { const char* value, const char* line_buffer) {
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
/* Send value upon match */ /* Send value upon match */
if (regexec(regex, line_buffer, 0, NULL, 0) == 0) { if (regexec(regex, line_buffer, 0, NULL, 0) == 0) {
/* Send value */ /* Send value */
if (value != NULL) { if (value != NULL) {
guac_terminal_send_string(telnet_client->term, value); guac_terminal_send_string(tn5250_client->term, value);
guac_terminal_send_string(telnet_client->term, "\x0D"); guac_terminal_send_string(tn5250_client->term, "\x0D");
} }
/* Stop searching for prompt */ /* Stop searching for prompt */
@ -134,60 +134,60 @@ static bool guac_telnet_regex_exec(guac_client* client, regex_t* regex,
* completed, this function has no effect. * completed, this function has no effect.
* *
* @param client * @param client
* The guac_client associated with the telnet session. * The guac_client associated with the tn5250 session.
* *
* @param line_buffer * @param line_buffer
* The line of character data to test. * The line of character data to test.
*/ */
static void guac_telnet_search_line(guac_client* client, const char* line_buffer) { static void guac_tn5250_search_line(guac_client* client, const char* line_buffer) {
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
guac_telnet_settings* settings = telnet_client->settings; guac_tn5250_settings* settings = tn5250_client->settings;
/* Continue search for username prompt */ /* Continue search for username prompt */
if (settings->username_regex != NULL) { if (settings->username_regex != NULL) {
if (guac_telnet_regex_exec(client, settings->username_regex, if (guac_tn5250_regex_exec(client, settings->username_regex,
settings->username, line_buffer)) { settings->username, line_buffer)) {
guac_client_log(client, GUAC_LOG_DEBUG, "Username sent"); guac_client_log(client, GUAC_LOG_DEBUG, "Username sent");
guac_telnet_regex_free(&settings->username_regex); guac_tn5250_regex_free(&settings->username_regex);
} }
} }
/* Continue search for password prompt */ /* Continue search for password prompt */
if (settings->password_regex != NULL) { if (settings->password_regex != NULL) {
if (guac_telnet_regex_exec(client, settings->password_regex, if (guac_tn5250_regex_exec(client, settings->password_regex,
settings->password, line_buffer)) { settings->password, line_buffer)) {
guac_client_log(client, GUAC_LOG_DEBUG, "Password sent"); guac_client_log(client, GUAC_LOG_DEBUG, "Password sent");
/* Do not continue searching for username/password once password is sent */ /* Do not continue searching for username/password once password is sent */
guac_telnet_regex_free(&settings->username_regex); guac_tn5250_regex_free(&settings->username_regex);
guac_telnet_regex_free(&settings->password_regex); guac_tn5250_regex_free(&settings->password_regex);
} }
} }
/* Continue search for login success */ /* Continue search for login success */
if (settings->login_success_regex != NULL) { if (settings->login_success_regex != NULL) {
if (guac_telnet_regex_exec(client, settings->login_success_regex, if (guac_tn5250_regex_exec(client, settings->login_success_regex,
NULL, line_buffer)) { NULL, line_buffer)) {
/* Allow terminal to render now that login has been deemed successful */ /* Allow terminal to render now that login has been deemed successful */
guac_client_log(client, GUAC_LOG_DEBUG, "Login successful"); guac_client_log(client, GUAC_LOG_DEBUG, "Login successful");
guac_terminal_start(telnet_client->term); guac_terminal_start(tn5250_client->term);
/* Stop all searches */ /* Stop all searches */
guac_telnet_regex_free(&settings->username_regex); guac_tn5250_regex_free(&settings->username_regex);
guac_telnet_regex_free(&settings->password_regex); guac_tn5250_regex_free(&settings->password_regex);
guac_telnet_regex_free(&settings->login_success_regex); guac_tn5250_regex_free(&settings->login_success_regex);
guac_telnet_regex_free(&settings->login_failure_regex); guac_tn5250_regex_free(&settings->login_failure_regex);
} }
} }
/* Continue search for login failure */ /* Continue search for login failure */
if (settings->login_failure_regex != NULL) { if (settings->login_failure_regex != NULL) {
if (guac_telnet_regex_exec(client, settings->login_failure_regex, if (guac_tn5250_regex_exec(client, settings->login_failure_regex,
NULL, line_buffer)) { NULL, line_buffer)) {
/* Advise that login has failed and connection should be closed */ /* Advise that login has failed and connection should be closed */
@ -196,10 +196,10 @@ static void guac_telnet_search_line(guac_client* client, const char* line_buffer
"Login failed"); "Login failed");
/* Stop all searches */ /* Stop all searches */
guac_telnet_regex_free(&settings->username_regex); guac_tn5250_regex_free(&settings->username_regex);
guac_telnet_regex_free(&settings->password_regex); guac_tn5250_regex_free(&settings->password_regex);
guac_telnet_regex_free(&settings->login_success_regex); guac_tn5250_regex_free(&settings->login_success_regex);
guac_telnet_regex_free(&settings->login_failure_regex); guac_tn5250_regex_free(&settings->login_failure_regex);
} }
} }
@ -214,7 +214,7 @@ static void guac_telnet_search_line(guac_client* client, const char* line_buffer
* have completed, this function has no effect. * have completed, this function has no effect.
* *
* @param client * @param client
* The guac_client associated with the telnet session. * The guac_client associated with the tn5250 session.
* *
* @param buffer * @param buffer
* The buffer of received data to search through. * The buffer of received data to search through.
@ -222,7 +222,7 @@ static void guac_telnet_search_line(guac_client* client, const char* line_buffer
* @param size * @param size
* The size of the given buffer, in bytes. * The size of the given buffer, in bytes.
*/ */
static void guac_telnet_search(guac_client* client, const char* buffer, int size) { static void guac_tn5250_search(guac_client* client, const char* buffer, int size) {
static char line_buffer[1024] = {0}; static char line_buffer[1024] = {0};
static int length = 0; static int length = 0;
@ -237,7 +237,7 @@ static void guac_telnet_search(guac_client* client, const char* buffer, int size
if (c == '\n') { if (c == '\n') {
if (length > 0) { if (length > 0) {
line_buffer[length] = '\0'; line_buffer[length] = '\0';
guac_telnet_search_line(client, line_buffer); guac_tn5250_search_line(client, line_buffer);
length = 0; length = 0;
} }
} }
@ -252,7 +252,7 @@ static void guac_telnet_search(guac_client* client, const char* buffer, int size
/* Attempt pattern match if an unfinished line remains (may be a prompt) */ /* Attempt pattern match if an unfinished line remains (may be a prompt) */
if (length > 0) { if (length > 0) {
line_buffer[length] = '\0'; line_buffer[length] = '\0';
guac_telnet_search_line(client, line_buffer); guac_tn5250_search_line(client, line_buffer);
} }
} }
@ -262,23 +262,23 @@ static void guac_telnet_search(guac_client* client, const char* buffer, int size
* telnet_init() and will be called for every event fired by libtelnet, * telnet_init() and will be called for every event fired by libtelnet,
* including feature enable/disable and receipt/transmission of data. * including feature enable/disable and receipt/transmission of data.
*/ */
static void __guac_telnet_event_handler(telnet_t* telnet, telnet_event_t* event, void* data) { static void __guac_tn5250_event_handler(telnet_t* telnet, telnet_event_t* event, void* data) {
guac_client* client = (guac_client*) data; guac_client* client = (guac_client*) data;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
guac_telnet_settings* settings = telnet_client->settings; guac_tn5250_settings* settings = tn5250_client->settings;
switch (event->type) { switch (event->type) {
/* Terminal output received */ /* Terminal output received */
case TELNET_EV_DATA: case TELNET_EV_DATA:
guac_terminal_write(telnet_client->term, event->data.buffer, event->data.size); guac_terminal_write(tn5250_client->term, event->data.buffer, event->data.size);
guac_telnet_search(client, event->data.buffer, event->data.size); guac_tn5250_search(client, event->data.buffer, event->data.size);
break; break;
/* Data destined for remote end */ /* Data destined for remote end */
case TELNET_EV_SEND: case TELNET_EV_SEND:
if (__guac_telnet_write_all(telnet_client->socket_fd, event->data.buffer, event->data.size) if (__guac_tn5250_write_all(tn5250_client->socket_fd, event->data.buffer, event->data.size)
!= event->data.size) != event->data.size)
guac_client_stop(client); guac_client_stop(client);
break; break;
@ -286,27 +286,27 @@ static void __guac_telnet_event_handler(telnet_t* telnet, telnet_event_t* event,
/* Remote feature enabled */ /* Remote feature enabled */
case TELNET_EV_WILL: case TELNET_EV_WILL:
if (event->neg.telopt == TELNET_TELOPT_ECHO) if (event->neg.telopt == TELNET_TELOPT_ECHO)
telnet_client->echo_enabled = 0; /* Disable local echo, as remote will echo */ tn5250_client->echo_enabled = 0; /* Disable local echo, as remote will echo */
break; break;
/* Remote feature disabled */ /* Remote feature disabled */
case TELNET_EV_WONT: case TELNET_EV_WONT:
if (event->neg.telopt == TELNET_TELOPT_ECHO) if (event->neg.telopt == TELNET_TELOPT_ECHO)
telnet_client->echo_enabled = 1; /* Enable local echo, as remote won't echo */ tn5250_client->echo_enabled = 1; /* Enable local echo, as remote won't echo */
break; break;
/* Local feature enable */ /* Local feature enable */
case TELNET_EV_DO: case TELNET_EV_DO:
if (event->neg.telopt == TELNET_TELOPT_NAWS) { if (event->neg.telopt == TELNET_TELOPT_NAWS) {
telnet_client->naws_enabled = 1; tn5250_client->naws_enabled = 1;
guac_telnet_send_naws(telnet, telnet_client->term->term_width, telnet_client->term->term_height); guac_tn5250_send_naws(telnet, tn5250_client->term->term_width, tn5250_client->term->term_height);
} }
break; break;
/* Terminal type request */ /* Terminal type request */
case TELNET_EV_TTYPE: case TELNET_EV_TTYPE:
if (event->ttype.cmd == TELNET_TTYPE_SEND) if (event->ttype.cmd == TELNET_TTYPE_SEND)
telnet_ttype_is(telnet_client->telnet, settings->terminal_type); tn5250_ttype_is(tn5250_client->telnet, settings->terminal_type);
break; break;
/* Environment request */ /* Environment request */
@ -314,7 +314,7 @@ static void __guac_telnet_event_handler(telnet_t* telnet, telnet_event_t* event,
/* Only send USER if entire environment was requested */ /* Only send USER if entire environment was requested */
if (event->environ.size == 0) if (event->environ.size == 0)
guac_telnet_send_user(telnet, settings->username); guac_tn5250_send_user(telnet, settings->username);
break; break;
@ -345,19 +345,19 @@ static void __guac_telnet_event_handler(telnet_t* telnet, telnet_event_t* event,
* @param data The current guac_client instance. * @param data The current guac_client instance.
* @return Always NULL. * @return Always NULL.
*/ */
static void* __guac_telnet_input_thread(void* data) { static void* __guac_tn5250_input_thread(void* data) {
guac_client* client = (guac_client*) data; guac_client* client = (guac_client*) data;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
char buffer[8192]; char buffer[8192];
int bytes_read; int bytes_read;
/* Write all data read */ /* Write all data read */
while ((bytes_read = guac_terminal_read_stdin(telnet_client->term, buffer, sizeof(buffer))) > 0) { while ((bytes_read = guac_terminal_read_stdin(tn5250_client->term, buffer, sizeof(buffer))) > 0) {
telnet_send(telnet_client->telnet, buffer, bytes_read); telnet_send(tn5250_client->telnet, buffer, bytes_read);
if (telnet_client->echo_enabled) if (tn5250_client->echo_enabled)
guac_terminal_write(telnet_client->term, buffer, bytes_read); guac_terminal_write(tn5250_client->term, buffer, bytes_read);
} }
return NULL; return NULL;
@ -372,7 +372,7 @@ static void* __guac_telnet_input_thread(void* data) {
* @return The connected telnet instance, if successful, or NULL if the * @return The connected telnet instance, if successful, or NULL if the
* connection fails for any reason. * connection fails for any reason.
*/ */
static telnet_t* __guac_telnet_create_session(guac_client* client) { static telnet_t* __guac_tn5250_create_session(guac_client* client) {
int retval; int retval;
@ -383,8 +383,8 @@ static telnet_t* __guac_telnet_create_session(guac_client* client) {
char connected_address[1024]; char connected_address[1024];
char connected_port[64]; char connected_port[64];
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
guac_telnet_settings* settings = telnet_client->settings; guac_tn5250_settings* settings = tn5250_client->settings;
struct addrinfo hints = { struct addrinfo hints = {
.ai_family = AF_UNSPEC, .ai_family = AF_UNSPEC,
@ -458,7 +458,7 @@ static telnet_t* __guac_telnet_create_session(guac_client* client) {
} }
/* Save file descriptor */ /* Save file descriptor */
telnet_client->socket_fd = fd; tn5250_client->socket_fd = fd;
return telnet; return telnet;
@ -471,7 +471,7 @@ static telnet_t* __guac_telnet_create_session(guac_client* client) {
* @param telnet The telnet connection to use. * @param telnet The telnet connection to use.
* @param value The value to send. * @param value The value to send.
*/ */
static void __guac_telnet_send_uint16(telnet_t* telnet, uint16_t value) { static void __guac_tn5250_send_uint16(telnet_t* telnet, uint16_t value) {
unsigned char buffer[2]; unsigned char buffer[2];
buffer[0] = (value >> 8) & 0xFF; buffer[0] = (value >> 8) & 0xFF;
@ -487,32 +487,32 @@ static void __guac_telnet_send_uint16(telnet_t* telnet, uint16_t value) {
* @param telnet The telnet connection to use. * @param telnet The telnet connection to use.
* @param value The value to send. * @param value The value to send.
*/ */
static void __guac_telnet_send_uint8(telnet_t* telnet, uint8_t value) { static void __guac_tn5250_send_uint8(telnet_t* telnet, uint8_t value) {
telnet_send(telnet, (char*) (&value), 1); telnet_send(telnet, (char*) (&value), 1);
} }
void guac_telnet_send_naws(telnet_t* telnet, uint16_t width, uint16_t height) { void guac_tn5250_send_naws(telnet_t* telnet, uint16_t width, uint16_t height) {
telnet_begin_sb(telnet, TELNET_TELOPT_NAWS); telnet_begin_sb(telnet, TELNET_TELOPT_NAWS);
__guac_telnet_send_uint16(telnet, width); __guac_tn5250_send_uint16(telnet, width);
__guac_telnet_send_uint16(telnet, height); __guac_tn5250_send_uint16(telnet, height);
telnet_finish_sb(telnet); telnet_finish_sb(telnet);
} }
void guac_telnet_send_user(telnet_t* telnet, const char* username) { void guac_tn5250_send_user(telnet_t* telnet, const char* username) {
/* IAC SB NEW-ENVIRON IS */ /* IAC SB NEW-ENVIRON IS */
telnet_begin_sb(telnet, TELNET_TELOPT_NEW_ENVIRON); telnet_begin_sb(telnet, TELNET_TELOPT_NEW_ENVIRON);
__guac_telnet_send_uint8(telnet, TELNET_ENVIRON_IS); __guac_tn5250_send_uint8(telnet, TELNET_ENVIRON_IS);
/* Only send username if defined */ /* Only send username if defined */
if (username != NULL) { if (username != NULL) {
/* VAR "USER" */ /* VAR "USER" */
__guac_telnet_send_uint8(telnet, TELNET_ENVIRON_VAR); __guac_tn5250_send_uint8(telnet, TELNET_ENVIRON_VAR);
telnet_send(telnet, "USER", 4); telnet_send(telnet, "USER", 4);
/* VALUE username */ /* VALUE username */
__guac_telnet_send_uint8(telnet, TELNET_ENVIRON_VALUE); __guac_tn5250_send_uint8(telnet, TELNET_ENVIRON_VALUE);
telnet_send(telnet, username, strlen(username)); telnet_send(telnet, username, strlen(username));
} }
@ -531,7 +531,7 @@ void guac_telnet_send_user(telnet_t* telnet, const char* username) {
* @return A value greater than zero on success, zero on timeout, and * @return A value greater than zero on success, zero on timeout, and
* less than zero on error. * less than zero on error.
*/ */
static int __guac_telnet_wait(int socket_fd) { static int __guac_tn5250_wait(int socket_fd) {
/* Build array of file descriptors */ /* Build array of file descriptors */
struct pollfd fds[] = {{ struct pollfd fds[] = {{
@ -545,11 +545,11 @@ static int __guac_telnet_wait(int socket_fd) {
} }
void* guac_telnet_client_thread(void* data) { void* guac_tn5250_client_thread(void* data) {
guac_client* client = (guac_client*) data; guac_client* client = (guac_client*) data;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
guac_telnet_settings* settings = telnet_client->settings; guac_tn5250_settings* settings = tn5250_client->settings;
pthread_t input_thread; pthread_t input_thread;
char buffer[8192]; char buffer[8192];
@ -557,7 +557,7 @@ void* guac_telnet_client_thread(void* data) {
/* Set up screen recording, if requested */ /* Set up screen recording, if requested */
if (settings->recording_path != NULL) { if (settings->recording_path != NULL) {
telnet_client->recording = guac_common_recording_create(client, tn5250_client->recording = guac_common_recording_create(client,
settings->recording_path, settings->recording_path,
settings->recording_name, settings->recording_name,
settings->create_recording_path, settings->create_recording_path,
@ -567,14 +567,14 @@ void* guac_telnet_client_thread(void* data) {
} }
/* Create terminal */ /* Create terminal */
telnet_client->term = guac_terminal_create(client, tn5250_client->term = guac_terminal_create(client,
telnet_client->clipboard, settings->disable_copy, tn5250_client->clipboard, settings->disable_copy,
settings->max_scrollback, settings->font_name, settings->font_size, settings->max_scrollback, settings->font_name, settings->font_size,
settings->resolution, settings->width, settings->height, settings->resolution, settings->width, settings->height,
settings->color_scheme, settings->backspace); settings->color_scheme, settings->backspace);
/* Fail if terminal init failed */ /* Fail if terminal init failed */
if (telnet_client->term == NULL) { if (tn5250_client->term == NULL) {
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
"Terminal initialization failed"); "Terminal initialization failed");
return NULL; return NULL;
@ -582,46 +582,46 @@ void* guac_telnet_client_thread(void* data) {
/* Set up typescript, if requested */ /* Set up typescript, if requested */
if (settings->typescript_path != NULL) { if (settings->typescript_path != NULL) {
guac_terminal_create_typescript(telnet_client->term, guac_terminal_create_typescript(tn5250_client->term,
settings->typescript_path, settings->typescript_path,
settings->typescript_name, settings->typescript_name,
settings->create_typescript_path); settings->create_typescript_path);
} }
/* Open telnet session */ /* Open telnet session */
telnet_client->telnet = __guac_telnet_create_session(client); tn5250_client->telnet = __guac_tn5250_create_session(client);
if (telnet_client->telnet == NULL) { if (tn5250_client->telnet == NULL) {
/* Already aborted within __guac_telnet_create_session() */ /* Already aborted within __guac_tn5250_create_session() */
return NULL; return NULL;
} }
/* Logged in */ /* Logged in */
guac_client_log(client, GUAC_LOG_INFO, "Telnet connection successful."); guac_client_log(client, GUAC_LOG_INFO, "TN5250 connection successful.");
/* Allow terminal to render if login success/failure detection is not /* Allow terminal to render if login success/failure detection is not
* enabled */ * enabled */
if (settings->login_success_regex == NULL if (settings->login_success_regex == NULL
&& settings->login_failure_regex == NULL) && settings->login_failure_regex == NULL)
guac_terminal_start(telnet_client->term); guac_terminal_start(tn5250_client->term);
/* Start input thread */ /* Start input thread */
if (pthread_create(&(input_thread), NULL, __guac_telnet_input_thread, (void*) client)) { if (pthread_create(&(input_thread), NULL, __guac_tn5250_input_thread, (void*) client)) {
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to start input thread"); guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to start input thread");
return NULL; return NULL;
} }
/* While data available, write to terminal */ /* While data available, write to terminal */
while ((wait_result = __guac_telnet_wait(telnet_client->socket_fd)) >= 0) { while ((wait_result = __guac_tn5250_wait(tn5250_client->socket_fd)) >= 0) {
/* Resume waiting of no data available */ /* Resume waiting of no data available */
if (wait_result == 0) if (wait_result == 0)
continue; continue;
int bytes_read = read(telnet_client->socket_fd, buffer, sizeof(buffer)); int bytes_read = read(tn5250_client->socket_fd, buffer, sizeof(buffer));
if (bytes_read <= 0) if (bytes_read <= 0)
break; break;
telnet_recv(telnet_client->telnet, buffer, bytes_read); telnet_recv(tn5250_client->telnet, buffer, bytes_read);
} }
@ -629,7 +629,7 @@ void* guac_telnet_client_thread(void* data) {
guac_client_stop(client); guac_client_stop(client);
pthread_join(input_thread, NULL); pthread_join(input_thread, NULL);
guac_client_log(client, GUAC_LOG_INFO, "Telnet connection ended."); guac_client_log(client, GUAC_LOG_INFO, "TN5250 connection ended.");
return NULL; return NULL;
} }

View File

@ -33,12 +33,12 @@
/** /**
* Telnet-specific client data. * Telnet-specific client data.
*/ */
typedef struct guac_telnet_client { typedef struct guac_tn5250_client {
/** /**
* Telnet connection settings. * Telnet connection settings.
*/ */
guac_telnet_settings* settings; guac_tn5250_settings* settings;
/** /**
* The telnet client thread. * The telnet client thread.
@ -83,24 +83,24 @@ typedef struct guac_telnet_client {
*/ */
guac_common_recording* recording; guac_common_recording* recording;
} guac_telnet_client; } guac_tn5250_client;
/** /**
* Main telnet client thread, handling transfer of telnet output to STDOUT. * Main tn5250 client thread, handling transfer of tn5250 output to STDOUT.
*/ */
void* guac_telnet_client_thread(void* data); void* guac_tn5250_client_thread(void* data);
/** /**
* Send a telnet NAWS message indicating the given terminal window dimensions * Send a telnet NAWS message indicating the given terminal window dimensions
* in characters. * in characters.
*/ */
void guac_telnet_send_naws(telnet_t* telnet, uint16_t width, uint16_t height); void guac_tn5250_send_naws(telnet_t* telnet, uint16_t width, uint16_t height);
/** /**
* Sends the given username by setting the remote USER environment variable * Sends the given username by setting the remote USER environment variable
* using the telnet NEW-ENVIRON option. * using the tn5250 NEW-ENVIRON option.
*/ */
void guac_telnet_send_user(telnet_t* telnet, const char* username); void guac_tn5250_send_user(telnet_t* telnet, const char* username);
#endif #endif

View File

@ -35,13 +35,13 @@
#include <pthread.h> #include <pthread.h>
#include <string.h> #include <string.h>
int guac_telnet_user_join_handler(guac_user* user, int argc, char** argv) { int guac_tn5250_user_join_handler(guac_user* user, int argc, char** argv) {
guac_client* client = user->client; guac_client* client = user->client;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
/* Parse provided arguments */ /* Parse provided arguments */
guac_telnet_settings* settings = guac_telnet_parse_args(user, guac_tn5250_settings* settings = guac_tn5250_parse_args(user,
argc, (const char**) argv); argc, (const char**) argv);
/* Fail if settings cannot be parsed */ /* Fail if settings cannot be parsed */
@ -54,17 +54,17 @@ int guac_telnet_user_join_handler(guac_user* user, int argc, char** argv) {
/* Store settings at user level */ /* Store settings at user level */
user->data = settings; user->data = settings;
/* Connect via telnet if owner */ /* Connect via tn5250 if owner */
if (user->owner) { if (user->owner) {
/* Store owner's settings at client level */ /* Store owner's settings at client level */
telnet_client->settings = settings; tn5250_client->settings = settings;
/* Start client thread */ /* Start client thread */
if (pthread_create(&(telnet_client->client_thread), NULL, if (pthread_create(&(tn5250_client->client_thread), NULL,
guac_telnet_client_thread, (void*) client)) { guac_tn5250_client_thread, (void*) client)) {
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
"Unable to start telnet client thread"); "Unable to start tn5250 client thread");
return 1; return 1;
} }
@ -72,7 +72,7 @@ int guac_telnet_user_join_handler(guac_user* user, int argc, char** argv) {
/* If not owner, synchronize with current display */ /* If not owner, synchronize with current display */
else { else {
guac_terminal_dup(telnet_client->term, user, user->socket); guac_terminal_dup(tn5250_client->term, user, user->socket);
guac_socket_flush(user->socket); guac_socket_flush(user->socket);
} }
@ -80,21 +80,21 @@ int guac_telnet_user_join_handler(guac_user* user, int argc, char** argv) {
if (!settings->read_only) { if (!settings->read_only) {
/* General mouse/keyboard events */ /* General mouse/keyboard events */
user->key_handler = guac_telnet_user_key_handler; user->key_handler = guac_tn5250_user_key_handler;
user->mouse_handler = guac_telnet_user_mouse_handler; user->mouse_handler = guac_tn5250_user_mouse_handler;
/* Inbound (client to server) clipboard transfer */ /* Inbound (client to server) clipboard transfer */
if (!settings->disable_paste) if (!settings->disable_paste)
user->clipboard_handler = guac_telnet_clipboard_handler; user->clipboard_handler = guac_tn5250_clipboard_handler;
/* STDIN redirection */ /* STDIN redirection */
user->pipe_handler = guac_telnet_pipe_handler; user->pipe_handler = guac_tn5250_pipe_handler;
/* Updates to connection parameters */ /* Updates to connection parameters */
user->argv_handler = guac_telnet_argv_handler; user->argv_handler = guac_tn5250_argv_handler;
/* Display size change events */ /* Display size change events */
user->size_handler = guac_telnet_user_size_handler; user->size_handler = guac_tn5250_user_size_handler;
} }
@ -102,18 +102,18 @@ int guac_telnet_user_join_handler(guac_user* user, int argc, char** argv) {
} }
int guac_telnet_user_leave_handler(guac_user* user) { int guac_tn5250_user_leave_handler(guac_user* user) {
guac_telnet_client* telnet_client = guac_tn5250_client* tn5250_client =
(guac_telnet_client*) user->client->data; (guac_tn5250_client*) user->client->data;
/* Update shared cursor state */ /* Update shared cursor state */
guac_common_cursor_remove_user(telnet_client->term->cursor, user); guac_common_cursor_remove_user(tn5250_client->term->cursor, user);
/* Free settings if not owner (owner settings will be freed with client) */ /* Free settings if not owner (owner settings will be freed with client) */
if (!user->owner) { if (!user->owner) {
guac_telnet_settings* settings = (guac_telnet_settings*) user->data; guac_tn5250_settings* settings = (guac_tn5250_settings*) user->data;
guac_telnet_settings_free(settings); guac_tn5250_settings_free(settings);
} }
return 0; return 0;

View File

@ -27,12 +27,12 @@
/** /**
* Handler for joining users. * Handler for joining users.
*/ */
guac_user_join_handler guac_telnet_user_join_handler; guac_user_join_handler guac_tn5250_user_join_handler;
/** /**
* Handler for leaving users. * Handler for leaving users.
*/ */
guac_user_leave_handler guac_telnet_user_leave_handler; guac_user_leave_handler guac_tn5250_user_leave_handler;
#endif #endif