console-client: Support an alternate string escape mode
This mode is intended to avoid the behavior of witholding any characters
from the console-server. It sends the entire buffer regardless of
matching the escape sequence, however it will immediately terminate
after seeing a full escape sequence and sending the remaining buffered
content.
Tested:
Ran obmc-console-client with no arguments and ensured the ssh-like
escape sequence still worked. Then ran `obmc-console-client -e esc`,
typed a bunch of text into the console followed by esc and watched
the console exit as expected.
Change-Id: I780719d6e2402f93bba81beb8c09e1c661471e22
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/console-client.c b/console-client.c
index 57ca206..3f3f519 100644
--- a/console-client.c
+++ b/console-client.c
@@ -15,6 +15,7 @@
*/
#include <err.h>
+#include <getopt.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
@@ -36,12 +37,18 @@
enum esc_type {
ESC_TYPE_SSH,
+ ESC_TYPE_STR,
};
struct ssh_esc_state {
uint8_t state;
};
+struct str_esc_state {
+ const uint8_t *str;
+ size_t pos;
+};
+
struct console_client {
int console_sd;
int fd_in;
@@ -51,6 +58,7 @@
enum esc_type esc_type;
union {
struct ssh_esc_state ssh;
+ struct str_esc_state str;
} esc_state;
};
@@ -95,6 +103,30 @@
return rc < 0 ? PROCESS_ERR : PROCESS_OK;
}
+static enum process_rc process_str_tty(
+ struct console_client *client, const uint8_t *buf, size_t len)
+{
+ struct str_esc_state *esc_state = &client->esc_state.str;
+ enum process_rc prc = PROCESS_OK;
+ size_t i;
+
+ for (i = 0; i < len; ++i) {
+ if (buf[i] == esc_state->str[esc_state->pos])
+ esc_state->pos++;
+ else
+ esc_state->pos = 0;
+
+ if (esc_state->str[esc_state->pos] == '\0') {
+ prc = PROCESS_EXIT;
+ break;
+ }
+ }
+
+ if (write_buf_to_fd(client->console_sd, buf, i) < 0)
+ return PROCESS_ERR;
+ return prc;
+}
+
static enum process_rc process_tty(struct console_client *client)
{
uint8_t buf[4096];
@@ -110,6 +142,8 @@
{
case ESC_TYPE_SSH:
return process_ssh_tty(client, buf, len);
+ case ESC_TYPE_STR:
+ return process_str_tty(client, buf, len);
default:
return PROCESS_ERR;
}
@@ -201,7 +235,7 @@
close(client->console_sd);
}
-int main(void)
+int main(int argc, char *argv[])
{
struct console_client _client, *client;
struct pollfd pollfds[2];
@@ -212,6 +246,29 @@
memset(client, 0, sizeof(*client));
client->esc_type = ESC_TYPE_SSH;
+ for (;;) {
+ rc = getopt(argc, argv, "e:");
+ if (rc == -1)
+ break;
+
+ switch (rc) {
+ case 'e':
+ if (optarg[0] == '\0') {
+ fprintf(stderr, "Escape str cannot be empty\n");
+ return EXIT_FAILURE;
+ }
+ client->esc_type = ESC_TYPE_STR;
+ client->esc_state.str.str = (const uint8_t*)optarg;
+ break;
+ default:
+ fprintf(stderr,
+ "Usage: %s "
+ "[-e <escape sequence>]\n",
+ argv[0]);
+ return EXIT_FAILURE;
+ }
+ }
+
rc = client_init(client);
if (rc)
return EXIT_FAILURE;