Browse Source

hotkey: client gets hotkey parameters

Serj Kalichev 1 year ago
parent
commit
ce3d0fe6e1
5 changed files with 128 additions and 6 deletions
  1. 65 0
      bin/klish/interactive.c
  2. 1 1
      klish/ktp/ktpd_session.c
  3. 1 1
      tinyrl/tinyrl/tinyrl.c
  4. 5 1
      tinyrl/vt100.h
  5. 56 3
      tinyrl/vt100/vt100.c

+ 65 - 0
bin/klish/interactive.c

@@ -20,6 +20,7 @@ typedef struct ctx_s {
 	ktp_session_t *ktp;
 	tinyrl_t *tinyrl;
 	struct options *opts;
+	char *hotkeys[VT100_HOTKEY_MAP_LEN];
 } ctx_t;
 
 
@@ -31,6 +32,7 @@ static bool_t stdin_cb(faux_eloop_t *eloop, faux_eloop_type_e type,
 	void *associated_data, void *user_data);
 static bool_t ktp_sync_auth(ktp_session_t *ktp, int *retcode,
 	faux_error_t *error);
+static void reset_hotkey_table(ctx_t *ctx);
 
 // Keys
 static bool_t tinyrl_key_enter(tinyrl_t *tinyrl, unsigned char key);
@@ -68,6 +70,7 @@ int klish_interactive_shell(ktp_session_t *ktp, struct options *opts)
 	ctx.ktp = ktp;
 	ctx.tinyrl = tinyrl;
 	ctx.opts = opts;
+	faux_bzero(ctx.hotkeys, sizeof(ctx.hotkeys));
 
 	// Now AUTH command is used only for starting hand-shake and getting
 	// prompt from the server. Generally it must be necessary for
@@ -93,6 +96,7 @@ int klish_interactive_shell(ktp_session_t *ktp, struct options *opts)
 
 cleanup:
 	// Cleanup
+	reset_hotkey_table(&ctx);
 	if (tinyrl_busy(tinyrl))
 		faux_error_free(ktp_session_error(ktp));
 	tinyrl_free(tinyrl);
@@ -123,6 +127,65 @@ static bool_t process_prompt_param(tinyrl_t *tinyrl, const faux_msg_t *msg)
 }
 
 
+static void reset_hotkey_table(ctx_t *ctx)
+{
+	size_t i = 0;
+
+	assert(ctx);
+
+	for (i = 0; i < VT100_HOTKEY_MAP_LEN; i++)
+		faux_str_free(ctx->hotkeys[i]);
+	faux_bzero(ctx->hotkeys, sizeof(ctx->hotkeys));
+}
+
+
+static bool_t process_hotkey_param(ctx_t *ctx, const faux_msg_t *msg)
+{
+	faux_list_node_t *iter = NULL;
+	uint32_t param_len = 0;
+	char *param_data = NULL;
+	uint16_t param_type = 0;
+
+	if (!ctx)
+		return BOOL_FALSE;
+	if (!msg)
+		return BOOL_FALSE;
+
+	if (!faux_msg_get_param_by_type(msg, KTP_PARAM_HOTKEY,
+		(void **)&param_data, &param_len))
+		return BOOL_TRUE;
+
+	// If there is HOTKEY parameter then reinitialize whole hotkey table
+	reset_hotkey_table(ctx);
+
+	iter = faux_msg_init_param_iter(msg);
+	while (faux_msg_get_param_each(
+		&iter, &param_type, (void **)&param_data, &param_len)) {
+		char *cmd = NULL;
+		ssize_t code = -1;
+		size_t key_len = 0;
+
+		if (param_len < 3) // <key>'\0'<cmd>
+			continue;
+		if (KTP_PARAM_HOTKEY != param_type)
+			continue;
+		key_len = strlen(param_data); // Length of <key>
+		if (key_len < 1)
+			continue;
+		code = vt100_hotkey_decode(param_data);
+		if ((code < 0) || (code > VT100_HOTKEY_MAP_LEN))
+			continue;
+		cmd = faux_str_dupn(param_data + key_len + 1,
+			param_len - key_len - 1);
+		if (!cmd)
+			continue;
+		ctx->hotkeys[code] = cmd;
+	}
+
+	return BOOL_TRUE;
+}
+
+
 bool_t auth_ack_cb(ktp_session_t *ktp, const faux_msg_t *msg, void *udata)
 {
 	ctx_t *ctx = (ctx_t *)udata;
@@ -130,6 +193,7 @@ bool_t auth_ack_cb(ktp_session_t *ktp, const faux_msg_t *msg, void *udata)
 	faux_error_t *error = NULL;
 
 	process_prompt_param(ctx->tinyrl, msg);
+	process_hotkey_param(ctx, msg);
 
 	if (!ktp_session_retcode(ktp, &rc))
 		rc = -1;
@@ -156,6 +220,7 @@ bool_t cmd_ack_cb(ktp_session_t *ktp, const faux_msg_t *msg, void *udata)
 	faux_error_t *error = NULL;
 
 	process_prompt_param(ctx->tinyrl, msg);
+	process_hotkey_param(ctx, msg);
 
 	if (!ktp_session_retcode(ktp, &rc))
 		rc = -1;

+ 1 - 1
klish/ktp/ktpd_session.c

@@ -175,7 +175,7 @@ static bool_t add_hotkey(faux_msg_t *msg, khotkey_t *hotkey)
 	key = khotkey_key(hotkey);
 	key_s = strlen(key);
 	cmd = khotkey_cmd(hotkey);
-	cmd_s = strlen(key);
+	cmd_s = strlen(cmd);
 
 	whole_str = faux_zmalloc(key_s + 1 + cmd_s);
 	memcpy(whole_str, key, key_s);

+ 1 - 1
tinyrl/tinyrl/tinyrl.c

@@ -469,7 +469,7 @@ bool_t tinyrl_esc_seq(tinyrl_t *tinyrl, const char *esc_seq)
 {
 	bool_t result = BOOL_FALSE;
 
-	switch (vt100_esc_decode(tinyrl->term, esc_seq)) {
+	switch (vt100_esc_decode(esc_seq)) {
 	case VT100_CURSOR_UP:
 		result = tinyrl_key_up(tinyrl, 0);
 		break;

+ 5 - 1
tinyrl/vt100.h

@@ -14,6 +14,9 @@
 typedef struct vt100_s vt100_t;
 
 
+#define VT100_HOTKEY_MAP_LEN 32
+
+
 // Key codes
 #define KEY_NUL	0	// ^@ Null character
 #define KEY_SOH	1	// ^A Start of heading, = console interrupt
@@ -86,7 +89,8 @@ int vt100_ierror(const vt100_t *vt100);
 int vt100_oerror(const vt100_t *vt100);
 int vt100_ieof(const vt100_t *vt100);
 int vt100_getchar(const vt100_t *vt100, unsigned char *c);
-vt100_esc_e vt100_esc_decode(const vt100_t *vt100, const char *esc_seq);
+vt100_esc_e vt100_esc_decode(const char *esc_seq);
+ssize_t vt100_hotkey_decode(const char *hotkey);
 
 void vt100_ding(const vt100_t *vt100);
 void vt100_attr_reset(const vt100_t *vt100);

+ 56 - 3
tinyrl/vt100/vt100.c

@@ -41,6 +41,44 @@ static vt100_decode_t esc_map[] = {
 };
 
 
+// Hotkeys
+const char *hotkey_map[] = {
+	"^@", /* 0 Null character */
+	"^A", /* 1 Start of heading, = console interrupt */
+	"^B", /* 2 Start of text, maintenance mode on HP console */
+	"^C", /* 3 End of text */
+	"^D", /* 4 End of transmission, not the same as ETB */
+	"^E", /* 5 Enquiry, goes with ACK; old HP flow control */
+	"^F", /* 6 Acknowledge, clears ENQ logon hand */
+	"^G", /* 7 Bell, rings the bell... */
+	"^H", /* 8 Backspace, works on HP terminals/computers */
+	"^I", /* 9 Horizontal tab, move to next tab stop */
+	"^J", /* 10 Line Feed */
+	"^K", /* 11 Vertical tab */
+	"^L", /* 12 Form Feed, page eject */
+	"^M", /* 13 Carriage Return*/
+	"^N", /* 14 Shift Out, alternate character set */
+	"^O", /* 15 Shift In, resume defaultn character set */
+	"^P", /* 16 Data link escape */
+	"^Q", /* 17 XON, with XOFF to pause listings; "okay to send". */
+	"^R", /* 18 Device control 2, block-mode flow control */
+	"^S", /* 19 XOFF, with XON is TERM=18 flow control */
+	"^T", /* 20 Device control 4 */
+	"^U", /* 21 Negative acknowledge */
+	"^V", /* 22 Synchronous idle */
+	"^W", /* 23 End transmission block, not the same as EOT */
+	"^X", /* 24 Cancel line, MPE echoes !!! */
+	"^Y", /* 25 End of medium, Control-Y interrupt */
+	"^Z", /* 26 Substitute */
+	"^[", /* 27 Escape, next character is not echoed */
+	"^\\", /* 28 File separator */
+	"^]", /* 29 Group separator */
+	"^^", /* 30 Record separator, block-mode terminator */
+	"^_",  /* 31 Unit separator */
+	NULL
+};
+
+
 vt100_t *vt100_new(FILE *istream, FILE *ostream)
 {
 	vt100_t *vt100 = NULL;
@@ -99,7 +137,7 @@ void vt100_set_ostream(vt100_t *vt100, FILE *ostream)
 }
 
 
-vt100_esc_e vt100_esc_decode(const vt100_t *vt100, const char *esc_seq)
+vt100_esc_e vt100_esc_decode(const char *esc_seq)
 {
 	vt100_esc_e result = VT100_UNKNOWN;
 	unsigned int i = 0;
@@ -111,12 +149,27 @@ vt100_esc_e vt100_esc_decode(const vt100_t *vt100, const char *esc_seq)
 		break;
 	}
 
-	vt100 = vt100; // Happy compiler
-
 	return result;
 }
 
 
+ssize_t vt100_hotkey_decode(const char *hotkey)
+{
+	unsigned int i = 0;
+
+	if (!hotkey)
+		return -1;
+
+	while (hotkey_map[i]) {
+		if (strcmp(hotkey_map[i], hotkey) == 0)
+			return i;
+		i++;
+	}
+
+	return -1;
+}
+
+
 int vt100_printf(const vt100_t *vt100, const char *fmt, ...)
 {
 	va_list args;