GUAC-1452: Echo to pipe stream if open (buffered).
This commit is contained in:
parent
01edd8ccd8
commit
ff557a7f01
@ -1731,3 +1731,80 @@ int guac_terminal_next_tab(guac_terminal* term, int column) {
|
||||
return tabstop;
|
||||
}
|
||||
|
||||
void guac_terminal_pipe_stream_open(guac_terminal* term, const char* name) {
|
||||
|
||||
guac_client* client = term->client;
|
||||
guac_socket* socket = client->socket;
|
||||
|
||||
/* Close existing stream, if any */
|
||||
guac_terminal_pipe_stream_close(term);
|
||||
|
||||
/* Allocate and assign new pipe stream */
|
||||
term->pipe_stream = guac_client_alloc_stream(client);
|
||||
term->pipe_buffer_length = 0;
|
||||
|
||||
/* Open new pipe stream */
|
||||
guac_protocol_send_pipe(socket, term->pipe_stream, "text/plain", name);
|
||||
|
||||
/* Log redirect at debug level */
|
||||
guac_client_log(client, GUAC_LOG_DEBUG,
|
||||
"Terminal output now redirected to pipe '%s'.", name);
|
||||
|
||||
}
|
||||
|
||||
void guac_terminal_pipe_stream_write(guac_terminal* term, char c) {
|
||||
|
||||
/* Append byte to buffer only if pipe is open */
|
||||
if (term->pipe_stream != NULL) {
|
||||
|
||||
/* Flush buffer if no space is available */
|
||||
if (term->pipe_buffer_length == sizeof(term->pipe_buffer))
|
||||
guac_terminal_pipe_stream_flush(term);
|
||||
|
||||
/* Append single byte to buffer */
|
||||
term->pipe_buffer[term->pipe_buffer_length++] = c;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void guac_terminal_pipe_stream_flush(guac_terminal* term) {
|
||||
|
||||
guac_client* client = term->client;
|
||||
guac_socket* socket = client->socket;
|
||||
guac_stream* pipe_stream = term->pipe_stream;
|
||||
|
||||
/* Write blob if data exists in buffer */
|
||||
if (pipe_stream != NULL && term->pipe_buffer_length > 0) {
|
||||
guac_protocol_send_blob(socket, pipe_stream,
|
||||
term->pipe_buffer, term->pipe_buffer_length);
|
||||
term->pipe_buffer_length = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void guac_terminal_pipe_stream_close(guac_terminal* term) {
|
||||
|
||||
guac_client* client = term->client;
|
||||
guac_socket* socket = client->socket;
|
||||
guac_stream* pipe_stream = term->pipe_stream;
|
||||
|
||||
/* Close any existing pipe */
|
||||
if (pipe_stream != NULL) {
|
||||
|
||||
/* Write end of stream */
|
||||
guac_terminal_pipe_stream_flush(term);
|
||||
guac_protocol_send_end(socket, pipe_stream);
|
||||
|
||||
/* Destroy stream */
|
||||
guac_client_free_stream(client, pipe_stream);
|
||||
term->pipe_stream = NULL;
|
||||
|
||||
/* Log redirect at debug level */
|
||||
guac_client_log(client, GUAC_LOG_DEBUG,
|
||||
"Terminal output now redirected to display.");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -156,6 +156,19 @@ struct guac_terminal {
|
||||
*/
|
||||
guac_stream* pipe_stream;
|
||||
|
||||
/**
|
||||
* Buffer of data pending write to the pipe_stream. Data within this buffer
|
||||
* will be flushed to the pipe_stream when either (1) the buffer is full
|
||||
* and another character needs to be written or (2) the pipe_stream is
|
||||
* closed.
|
||||
*/
|
||||
char pipe_buffer[6048];
|
||||
|
||||
/**
|
||||
* The number of bytes currently stored within the pipe_buffer.
|
||||
*/
|
||||
int pipe_buffer_length;
|
||||
|
||||
/**
|
||||
* Graphical representation of the current scroll state.
|
||||
*/
|
||||
@ -663,5 +676,58 @@ void guac_terminal_clear_tabs(guac_terminal* term);
|
||||
*/
|
||||
int guac_terminal_next_tab(guac_terminal* term, int column);
|
||||
|
||||
/**
|
||||
* Opens a new pipe stream, redirecting all output from the given terminal to
|
||||
* that pipe stream. If a pipe stream is already open, that pipe stream will
|
||||
* be flushed and closed prior to opening the new pipe stream.
|
||||
*
|
||||
* @param term
|
||||
* The terminal which should redirect output to a new pipe stream having
|
||||
* the given name.
|
||||
*
|
||||
* @param name
|
||||
* The name of the pipe stream to open.
|
||||
*/
|
||||
void guac_terminal_pipe_stream_open(guac_terminal* term, const char* name);
|
||||
|
||||
/**
|
||||
* Writes a single byte of data to the pipe stream currently open and
|
||||
* associated with the given terminal. The pipe stream must already have been
|
||||
* opened via guac_terminal_pipe_stream_open(). If no pipe stream is currently
|
||||
* open, this function has no effect. Data written through this function may
|
||||
* be buffered.
|
||||
*
|
||||
* @param term
|
||||
* The terminal whose currently-open pipe stream should be written to.
|
||||
*
|
||||
* @param c
|
||||
* The byte of data to write to the pipe stream.
|
||||
*/
|
||||
void guac_terminal_pipe_stream_write(guac_terminal* term, char c);
|
||||
|
||||
/**
|
||||
* Flushes any data currently buffered for the currently-open pipe stream
|
||||
* associated with the given terminal. The pipe stream must already have been
|
||||
* opened via guac_terminal_pipe_stream_open(). If no pipe stream is currently
|
||||
* open or no data is in the buffer, this function has no effect.
|
||||
*
|
||||
* @param term
|
||||
* The terminal whose pipe stream buffer should be flushed.
|
||||
*/
|
||||
void guac_terminal_pipe_stream_flush(guac_terminal* term);
|
||||
|
||||
/**
|
||||
* Closes the currently-open pipe stream associated with the given terminal,
|
||||
* redirecting all output back to the terminal display. Any data currently
|
||||
* buffered for output to the pipe stream will be flushed prior to closure. The
|
||||
* pipe stream must already have been opened via
|
||||
* guac_terminal_pipe_stream_open(). If no pipe stream is currently open, this
|
||||
* function has no effect.
|
||||
*
|
||||
* @param term
|
||||
* The terminal whose currently-open pipe stream should be closed.
|
||||
*/
|
||||
void guac_terminal_pipe_stream_close(guac_terminal* term);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -59,6 +59,12 @@ int guac_terminal_echo(guac_terminal* term, unsigned char c) {
|
||||
|
||||
const int* char_mapping = term->char_mapping[term->active_char_set];
|
||||
|
||||
/* Echo to pipe stream if open and not starting an ESC sequence */
|
||||
if (term->pipe_stream != NULL && c != 0x1B) {
|
||||
guac_terminal_pipe_stream_write(term, c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If using non-Unicode mapping, just map straight bytes */
|
||||
if (char_mapping != NULL) {
|
||||
codepoint = c;
|
||||
@ -940,9 +946,6 @@ int guac_terminal_download(guac_terminal* term, unsigned char c) {
|
||||
|
||||
int guac_terminal_open_pipe_stream(guac_terminal* term, unsigned char c) {
|
||||
|
||||
guac_client* client = term->client;
|
||||
guac_socket* socket = client->socket;
|
||||
|
||||
static char stream_name[2048];
|
||||
static int length = 0;
|
||||
|
||||
@ -951,25 +954,14 @@ int guac_terminal_open_pipe_stream(guac_terminal* term, unsigned char c) {
|
||||
|
||||
/* End stream name string */
|
||||
stream_name[length++] = '\0';
|
||||
term->char_handler = guac_terminal_echo;
|
||||
length = 0;
|
||||
|
||||
/* Close existing stream, if any */
|
||||
if (term->pipe_stream != NULL) {
|
||||
guac_protocol_send_end(socket, term->pipe_stream);
|
||||
guac_client_free_stream(client, term->pipe_stream);
|
||||
}
|
||||
|
||||
/* Allocate and assign new pipe stream */
|
||||
term->pipe_stream = guac_client_alloc_stream(client);
|
||||
|
||||
/* Open new pipe stream */
|
||||
guac_protocol_send_pipe(socket, term->pipe_stream,
|
||||
"text/plain", stream_name);
|
||||
guac_terminal_pipe_stream_open(term, stream_name);
|
||||
|
||||
/* Return to echo mode */
|
||||
term->char_handler = guac_terminal_echo;
|
||||
|
||||
/* Log redirect at debug level */
|
||||
guac_client_log(client, GUAC_LOG_DEBUG,
|
||||
"Terminal output now redirected to pipe '%s'.", stream_name);
|
||||
}
|
||||
|
||||
/* Otherwise, store character within stream name */
|
||||
@ -982,26 +974,14 @@ int guac_terminal_open_pipe_stream(guac_terminal* term, unsigned char c) {
|
||||
|
||||
int guac_terminal_close_pipe_stream(guac_terminal* term, unsigned char c) {
|
||||
|
||||
guac_client* client = term->client;
|
||||
guac_socket* socket = client->socket;
|
||||
|
||||
/* Handle closure on ECMA-48 ST (String Terminator) */
|
||||
if (c == 0x9C || c == 0x5C || c == 0x07) {
|
||||
term->char_handler = guac_terminal_echo;
|
||||
|
||||
/* Close any existing pipe */
|
||||
if (term->pipe_stream != NULL) {
|
||||
guac_protocol_send_end(socket, term->pipe_stream);
|
||||
guac_client_free_stream(client, term->pipe_stream);
|
||||
term->pipe_stream = NULL;
|
||||
guac_client_log(client, GUAC_LOG_DEBUG,
|
||||
"Terminal output now redirected to display.");
|
||||
}
|
||||
guac_terminal_pipe_stream_close(term);
|
||||
|
||||
/* Warn if OSC is inappropriate */
|
||||
else
|
||||
guac_client_log(client, GUAC_LOG_DEBUG,
|
||||
"Cannot handle pipe close OSC - no open pipe exists.");
|
||||
/* Return to echo mode */
|
||||
term->char_handler = guac_terminal_echo;
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user