diff --git a/src/protocols/kubernetes/argv.c b/src/protocols/kubernetes/argv.c index 0bff3149..c37595de 100644 --- a/src/protocols/kubernetes/argv.c +++ b/src/protocols/kubernetes/argv.c @@ -125,11 +125,15 @@ static int guac_kubernetes_argv_end_handler(guac_user* user, /* Update color scheme */ case GUAC_KUBERNETES_ARGV_SETTING_COLOR_SCHEME: guac_terminal_apply_color_scheme(terminal, argv->buffer); + guac_client_stream_argv(client, client->socket, "text/plain", + "color-scheme", argv->buffer); break; /* Update font name */ case GUAC_KUBERNETES_ARGV_SETTING_FONT_NAME: guac_terminal_apply_font(terminal, argv->buffer, -1, 0); + guac_client_stream_argv(client, client->socket, "text/plain", + "font-name", argv->buffer); break; /* Update font size */ @@ -140,6 +144,8 @@ static int guac_kubernetes_argv_end_handler(guac_user* user, if (size > 0) { guac_terminal_apply_font(terminal, NULL, size, kubernetes_client->settings->resolution); + guac_client_stream_argv(client, client->socket, "text/plain", + "font-size", argv->buffer); } break; @@ -193,3 +199,26 @@ int guac_kubernetes_argv_handler(guac_user* user, guac_stream* stream, } +void* guac_kubernetes_send_current_argv(guac_user* user, void* data) { + + guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) data; + guac_terminal* terminal = kubernetes_client->term; + + /* Send current color scheme */ + guac_user_stream_argv(user, user->socket, "text/plain", "color-scheme", + terminal->color_scheme); + + /* Send current font name */ + guac_user_stream_argv(user, user->socket, "text/plain", "font-name", + terminal->font_name); + + /* Send current font size */ + char font_size[64]; + sprintf(font_size, "%i", terminal->font_size); + guac_user_stream_argv(user, user->socket, "text/plain", "font-size", + font_size); + + return NULL; + +} + diff --git a/src/protocols/kubernetes/argv.h b/src/protocols/kubernetes/argv.h index da9e11b7..2fc6c1ba 100644 --- a/src/protocols/kubernetes/argv.h +++ b/src/protocols/kubernetes/argv.h @@ -37,5 +37,25 @@ */ guac_user_argv_handler guac_kubernetes_argv_handler; +/** + * Sends the current values of all non-sensitive parameters which may be set + * while the connection is running to the given user. Note that the user + * receiving these values will not necessarily be able to set new values + * themselves if their connection is read-only. This function can be used as + * the callback for guac_client_foreach_user() and guac_client_for_owner() + * + * @param user + * The user that should receive the values of all non-sensitive parameters + * which may be set while the connection is running. + * + * @param data + * The guac_kubernetes_client instance associated with the current + * connection. + * + * @return + * Always NULL. + */ +void* guac_kubernetes_send_current_argv(guac_user* user, void* data); + #endif diff --git a/src/protocols/kubernetes/kubernetes.c b/src/protocols/kubernetes/kubernetes.c index 931f8ca3..7158a989 100644 --- a/src/protocols/kubernetes/kubernetes.c +++ b/src/protocols/kubernetes/kubernetes.c @@ -18,6 +18,8 @@ */ #include "config.h" + +#include "argv.h" #include "client.h" #include "common/recording.h" #include "io.h" @@ -249,6 +251,10 @@ void* guac_kubernetes_client_thread(void* data) { goto fail; } + /* Send current values of exposed arguments to owner only */ + guac_client_for_owner(client, guac_kubernetes_send_current_argv, + kubernetes_client); + /* Set up typescript, if requested */ if (settings->typescript_path != NULL) { guac_terminal_create_typescript(kubernetes_client->term, diff --git a/src/protocols/kubernetes/user.c b/src/protocols/kubernetes/user.c index d1b79a31..d1fcd5da 100644 --- a/src/protocols/kubernetes/user.c +++ b/src/protocols/kubernetes/user.c @@ -74,6 +74,7 @@ int guac_kubernetes_user_join_handler(guac_user* user, int argc, char** argv) { /* If not owner, synchronize with current display */ else { guac_terminal_dup(kubernetes_client->term, user, user->socket); + guac_kubernetes_send_current_argv(user, kubernetes_client); guac_socket_flush(user->socket); } diff --git a/src/protocols/ssh/argv.c b/src/protocols/ssh/argv.c index 8db2b242..d9ce1e75 100644 --- a/src/protocols/ssh/argv.c +++ b/src/protocols/ssh/argv.c @@ -126,11 +126,15 @@ static int guac_ssh_argv_end_handler(guac_user* user, /* Update color scheme */ case GUAC_SSH_ARGV_SETTING_COLOR_SCHEME: guac_terminal_apply_color_scheme(terminal, argv->buffer); + guac_client_stream_argv(client, client->socket, "text/plain", + "color-scheme", argv->buffer); break; /* Update font name */ case GUAC_SSH_ARGV_SETTING_FONT_NAME: guac_terminal_apply_font(terminal, argv->buffer, -1, 0); + guac_client_stream_argv(client, client->socket, "text/plain", + "font-name", argv->buffer); break; /* Update font size */ @@ -141,6 +145,8 @@ static int guac_ssh_argv_end_handler(guac_user* user, if (size > 0) { guac_terminal_apply_font(terminal, NULL, size, ssh_client->settings->resolution); + guac_client_stream_argv(client, client->socket, "text/plain", + "font-size", argv->buffer); } break; @@ -198,3 +204,26 @@ int guac_ssh_argv_handler(guac_user* user, guac_stream* stream, } +void* guac_ssh_send_current_argv(guac_user* user, void* data) { + + guac_ssh_client* ssh_client = (guac_ssh_client*) data; + guac_terminal* terminal = ssh_client->term; + + /* Send current color scheme */ + guac_user_stream_argv(user, user->socket, "text/plain", "color-scheme", + terminal->color_scheme); + + /* Send current font name */ + guac_user_stream_argv(user, user->socket, "text/plain", "font-name", + terminal->font_name); + + /* Send current font size */ + char font_size[64]; + sprintf(font_size, "%i", terminal->font_size); + guac_user_stream_argv(user, user->socket, "text/plain", "font-size", + font_size); + + return NULL; + +} + diff --git a/src/protocols/ssh/argv.h b/src/protocols/ssh/argv.h index 88cf8e97..186e0b5f 100644 --- a/src/protocols/ssh/argv.h +++ b/src/protocols/ssh/argv.h @@ -37,5 +37,24 @@ */ guac_user_argv_handler guac_ssh_argv_handler; +/** + * Sends the current values of all non-sensitive parameters which may be set + * while the connection is running to the given user. Note that the user + * receiving these values will not necessarily be able to set new values + * themselves if their connection is read-only. This function can be used as + * the callback for guac_client_foreach_user() and guac_client_for_owner() + * + * @param user + * The user that should receive the values of all non-sensitive parameters + * which may be set while the connection is running. + * + * @param data + * The guac_ssh_client instance associated with the current connection. + * + * @return + * Always NULL. + */ +void* guac_ssh_send_current_argv(guac_user* user, void* data); + #endif diff --git a/src/protocols/ssh/ssh.c b/src/protocols/ssh/ssh.c index 138de6b9..89572050 100644 --- a/src/protocols/ssh/ssh.c +++ b/src/protocols/ssh/ssh.c @@ -19,6 +19,7 @@ #include "config.h" +#include "argv.h" #include "common/recording.h" #include "common-ssh/sftp.h" #include "common-ssh/ssh.h" @@ -234,6 +235,9 @@ void* ssh_client_thread(void* data) { return NULL; } + /* Send current values of exposed arguments to owner only */ + guac_client_for_owner(client, guac_ssh_send_current_argv, ssh_client); + /* Set up typescript, if requested */ if (settings->typescript_path != NULL) { guac_terminal_create_typescript(ssh_client->term, diff --git a/src/protocols/ssh/user.c b/src/protocols/ssh/user.c index 76a2a963..8ea30a4c 100644 --- a/src/protocols/ssh/user.c +++ b/src/protocols/ssh/user.c @@ -74,6 +74,7 @@ int guac_ssh_user_join_handler(guac_user* user, int argc, char** argv) { /* If not owner, synchronize with current display */ else { guac_terminal_dup(ssh_client->term, user, user->socket); + guac_ssh_send_current_argv(user, ssh_client); guac_socket_flush(user->socket); } diff --git a/src/protocols/telnet/argv.c b/src/protocols/telnet/argv.c index 450c7f35..37564a60 100644 --- a/src/protocols/telnet/argv.c +++ b/src/protocols/telnet/argv.c @@ -125,11 +125,15 @@ static int guac_telnet_argv_end_handler(guac_user* user, /* Update color scheme */ case GUAC_TELNET_ARGV_SETTING_COLOR_SCHEME: guac_terminal_apply_color_scheme(terminal, argv->buffer); + guac_client_stream_argv(client, client->socket, "text/plain", + "color-scheme", argv->buffer); break; /* Update font name */ case GUAC_TELNET_ARGV_SETTING_FONT_NAME: guac_terminal_apply_font(terminal, argv->buffer, -1, 0); + guac_client_stream_argv(client, client->socket, "text/plain", + "font-name", argv->buffer); break; /* Update font size */ @@ -140,6 +144,8 @@ static int guac_telnet_argv_end_handler(guac_user* user, if (size > 0) { guac_terminal_apply_font(terminal, NULL, size, telnet_client->settings->resolution); + guac_client_stream_argv(client, client->socket, "text/plain", + "font-size", argv->buffer); } break; @@ -194,3 +200,26 @@ int guac_telnet_argv_handler(guac_user* user, guac_stream* stream, } +void* guac_telnet_send_current_argv(guac_user* user, void* data) { + + guac_telnet_client* telnet_client = (guac_telnet_client*) data; + guac_terminal* terminal = telnet_client->term; + + /* Send current color scheme */ + guac_user_stream_argv(user, user->socket, "text/plain", "color-scheme", + terminal->color_scheme); + + /* Send current font name */ + guac_user_stream_argv(user, user->socket, "text/plain", "font-name", + terminal->font_name); + + /* Send current font size */ + char font_size[64]; + sprintf(font_size, "%i", terminal->font_size); + guac_user_stream_argv(user, user->socket, "text/plain", "font-size", + font_size); + + return NULL; + +} + diff --git a/src/protocols/telnet/argv.h b/src/protocols/telnet/argv.h index aa13dda9..e362e14a 100644 --- a/src/protocols/telnet/argv.h +++ b/src/protocols/telnet/argv.h @@ -37,5 +37,24 @@ */ guac_user_argv_handler guac_telnet_argv_handler; +/** + * Sends the current values of all non-sensitive parameters which may be set + * while the connection is running to the given user. Note that the user + * receiving these values will not necessarily be able to set new values + * themselves if their connection is read-only. This function can be used as + * the callback for guac_client_foreach_user() and guac_client_for_owner() + * + * @param user + * The user that should receive the values of all non-sensitive parameters + * which may be set while the connection is running. + * + * @param data + * The guac_telnet_client instance associated with the current connection. + * + * @return + * Always NULL. + */ +void* guac_telnet_send_current_argv(guac_user* user, void* data); + #endif diff --git a/src/protocols/telnet/telnet.c b/src/protocols/telnet/telnet.c index d8fc5e09..5a5ca303 100644 --- a/src/protocols/telnet/telnet.c +++ b/src/protocols/telnet/telnet.c @@ -18,6 +18,8 @@ */ #include "config.h" + +#include "argv.h" #include "common/recording.h" #include "telnet.h" #include "terminal/terminal.h" @@ -580,6 +582,10 @@ void* guac_telnet_client_thread(void* data) { return NULL; } + /* Send current values of exposed arguments to owner only */ + guac_client_for_owner(client, guac_telnet_send_current_argv, + telnet_client); + /* Set up typescript, if requested */ if (settings->typescript_path != NULL) { guac_terminal_create_typescript(telnet_client->term, diff --git a/src/protocols/telnet/user.c b/src/protocols/telnet/user.c index 5c15283b..63408cca 100644 --- a/src/protocols/telnet/user.c +++ b/src/protocols/telnet/user.c @@ -73,6 +73,7 @@ int guac_telnet_user_join_handler(guac_user* user, int argc, char** argv) { /* If not owner, synchronize with current display */ else { guac_terminal_dup(telnet_client->term, user, user->socket); + guac_telnet_send_current_argv(user, telnet_client); guac_socket_flush(user->socket); } diff --git a/src/terminal/color-scheme.c b/src/terminal/color-scheme.c index f4300196..5df181fa 100644 --- a/src/terminal/color-scheme.c +++ b/src/terminal/color-scheme.c @@ -196,6 +196,23 @@ void guac_terminal_parse_color_scheme(guac_client* client, guac_terminal_color* background, guac_terminal_color (*palette)[256]) { + /* Special cases. */ + if (color_scheme[0] == '\0') { + /* guac_terminal_parse_color_scheme defaults to gray-black */ + } + else if (strcmp(color_scheme, GUAC_TERMINAL_SCHEME_GRAY_BLACK) == 0) { + color_scheme = "foreground:color7;background:color0"; + } + else if (strcmp(color_scheme, GUAC_TERMINAL_SCHEME_BLACK_WHITE) == 0) { + color_scheme = "foreground:color0;background:color15"; + } + else if (strcmp(color_scheme, GUAC_TERMINAL_SCHEME_GREEN_BLACK) == 0) { + color_scheme = "foreground:color2;background:color0"; + } + else if (strcmp(color_scheme, GUAC_TERMINAL_SCHEME_WHITE_BLACK) == 0) { + color_scheme = "foreground:color15;background:color0"; + } + /* Set default gray-black color scheme and initial palette. */ *foreground = GUAC_TERMINAL_INITIAL_PALETTE[GUAC_TERMINAL_COLOR_GRAY]; *background = GUAC_TERMINAL_INITIAL_PALETTE[GUAC_TERMINAL_COLOR_BLACK]; diff --git a/src/terminal/terminal.c b/src/terminal/terminal.c index 7ddcb2f1..b76a6ea8 100644 --- a/src/terminal/terminal.c +++ b/src/terminal/terminal.c @@ -327,23 +327,6 @@ guac_terminal* guac_terminal_create(guac_client* client, guac_terminal_color (*default_palette)[256] = (guac_terminal_color(*)[256]) malloc(sizeof(guac_terminal_color[256])); - /* Special cases. */ - if (color_scheme == NULL || color_scheme[0] == '\0') { - /* guac_terminal_parse_color_scheme defaults to gray-black */ - } - else if (strcmp(color_scheme, GUAC_TERMINAL_SCHEME_GRAY_BLACK) == 0) { - color_scheme = "foreground:color7;background:color0"; - } - else if (strcmp(color_scheme, GUAC_TERMINAL_SCHEME_BLACK_WHITE) == 0) { - color_scheme = "foreground:color0;background:color15"; - } - else if (strcmp(color_scheme, GUAC_TERMINAL_SCHEME_GREEN_BLACK) == 0) { - color_scheme = "foreground:color2;background:color0"; - } - else if (strcmp(color_scheme, GUAC_TERMINAL_SCHEME_WHITE_BLACK) == 0) { - color_scheme = "foreground:color15;background:color0"; - } - guac_terminal_parse_color_scheme(client, color_scheme, &default_char.attributes.foreground, &default_char.attributes.background, @@ -360,6 +343,11 @@ guac_terminal* guac_terminal_create(guac_client* client, term->upload_path_handler = NULL; term->file_download_handler = NULL; + /* Copy initially-provided color scheme and font details */ + term->color_scheme = strdup(color_scheme); + term->font_name = strdup(font_name); + term->font_size = font_size; + /* Set size of available screen area */ term->outer_width = width; term->outer_height = height; @@ -529,6 +517,10 @@ void guac_terminal_free(guac_terminal* term) { /* Free scrollbar */ guac_terminal_scrollbar_free(term->scrollbar); + /* Free copies of font and color scheme information */ + free((char*) term->color_scheme); + free((char*) term->font_name); + /* Free the terminal itself */ free(term); @@ -1973,6 +1965,16 @@ void guac_terminal_apply_color_scheme(guac_terminal* terminal, terminal->term_height - 1, terminal->term_width - 1); + /* Acquire exclusive access to terminal */ + guac_terminal_lock(terminal); + + /* Update stored copy of color scheme */ + free((char*) terminal->color_scheme); + terminal->color_scheme = strdup(color_scheme); + + /* Release terminal */ + guac_terminal_unlock(terminal); + guac_terminal_notify(terminal); } @@ -1997,6 +1999,20 @@ void guac_terminal_apply_font(guac_terminal* terminal, const char* font_name, terminal->term_height - 1, terminal->term_width - 1); + /* Acquire exclusive access to terminal */ + guac_terminal_lock(terminal); + + /* Update stored copy of font name, if changed */ + if (font_name != NULL) + terminal->font_name = strdup(font_name); + + /* Update stored copy of font size, if changed */ + if (font_size != -1) + terminal->font_size = font_size; + + /* Release terminal */ + guac_terminal_unlock(terminal); + guac_terminal_notify(terminal); } diff --git a/src/terminal/terminal/color-scheme.h b/src/terminal/terminal/color-scheme.h index 962d820d..5417ce1c 100644 --- a/src/terminal/terminal/color-scheme.h +++ b/src/terminal/terminal/color-scheme.h @@ -72,9 +72,15 @@ * The client that the terminal is connected to. * * @param color_scheme - * A semicolon-separated list of name-value pairs, i.e. - * ": [; : [; ...]]". - * For example, "color2: rgb:cc/33/22; background: color5". + * The name of a pre-defined color scheme (one of the + * names defined by the GUAC_TERMINAL_SCHEME_* constants), or + * semicolon-separated list of name-value pairs, i.e. ": [; + * : [; ...]]". For example, "color2: rgb:cc/33/22; + * background: color5". + * + * If blank, the default scheme of GUAC_TERMINAL_SCHEME_GRAY_BLACK will be + * used. If invalid, a warning will be logged, and + * GUAC_TERMINAL_SCHEME_GRAY_BLACK will be used. * * @param[out] foreground * Parsed foreground color. diff --git a/src/terminal/terminal/terminal.h b/src/terminal/terminal/terminal.h index 28e69357..4185837f 100644 --- a/src/terminal/terminal/terminal.h +++ b/src/terminal/terminal/terminal.h @@ -506,6 +506,25 @@ struct guac_terminal { */ guac_common_clipboard* clipboard; + /** + * The name of the font to use when rendering glyphs, as requested at + * creation time or via guac_terminal_apply_font(). + */ + const char* font_name; + + /** + * The size of each glyph, in points, as requested at creation time or via + * guac_terminal_apply_font(). + */ + int font_size; + + /** + * The name of the color scheme to use, as requested at creation time or + * via guac_terminal_apply_color_scheme(). This string must be in the + * format accepted by guac_terminal_parse_color_scheme(). + */ + const char* color_scheme; + /** * ASCII character to send when backspace is pressed. */ @@ -574,11 +593,8 @@ struct guac_terminal { * The height of the terminal, in pixels. * * @param color_scheme - * The name of the color scheme to use. This string must be one of the - * names defined by the GUAC_TERMINAL_SCHEME_* constants. If blank or NULL, - * the default scheme of GUAC_TERMINAL_SCHEME_GRAY_BLACK will be used. If - * invalid, a warning will be logged, and the terminal will fall back on - * GUAC_TERMINAL_SCHEME_GRAY_BLACK. + * The name of the color scheme to use. This string must be in the format + * accepted by guac_terminal_parse_color_scheme(). * * @param backspace * The integer ASCII code to send when backspace is pressed in