Browse Source

klishd sends prompt to client. Unfinished

Serj Kalichev 2 years ago
parent
commit
38533ce1bb
5 changed files with 90 additions and 5 deletions
  1. 25 0
      bin/klish/interactive.c
  2. 44 4
      klish/ktp/ktpd_session.c
  3. 19 1
      plugins/klish/misc.c
  4. 1 0
      plugins/klish/plugin_init.c
  5. 1 0
      plugins/klish/private.h

+ 25 - 0
bin/klish/interactive.c

@@ -88,12 +88,33 @@ int klish_interactive_shell(ktp_session_t *ktp, struct options *opts)
 }
 
 
+static bool_t process_prompt_param(tinyrl_t *tinyrl, const faux_msg_t *msg)
+{
+	char *prompt = NULL;
+
+	if (!tinyrl)
+		return BOOL_FALSE;
+	if (!msg)
+		return BOOL_FALSE;
+
+	prompt = faux_msg_get_str_param_by_type(msg, KTP_PARAM_PROMPT);
+	if (prompt) {
+		tinyrl_set_prompt(tinyrl, prompt);
+		faux_str_free(prompt);
+	}
+
+	return BOOL_TRUE;
+}
+
+
 bool_t cmd_ack_cb(ktp_session_t *ktp, const faux_msg_t *msg, void *udata)
 {
 	ctx_t *ctx = (ctx_t *)udata;
 	int rc = -1;
 	faux_error_t *error = NULL;
 
+	process_prompt_param(ctx->tinyrl, msg);
+
 	if (!ktp_session_retcode(ktp, &rc))
 		rc = -1;
 	error = ktp_session_error(ktp);
@@ -230,6 +251,8 @@ bool_t completion_ack_cb(ktp_session_t *ktp, const faux_msg_t *msg, void *udata)
 
 	tinyrl_set_busy(ctx->tinyrl, BOOL_FALSE);
 
+	process_prompt_param(ctx->tinyrl, msg);
+
 	prefix = faux_msg_get_str_param_by_type(msg, KTP_PARAM_PREFIX);
 
 	completions = faux_list_new(FAUX_LIST_UNSORTED, FAUX_LIST_NONUNIQUE,
@@ -330,6 +353,8 @@ bool_t help_ack_cb(ktp_session_t *ktp, const faux_msg_t *msg, void *udata)
 
 	tinyrl_set_busy(ctx->tinyrl, BOOL_FALSE);
 
+	process_prompt_param(ctx->tinyrl, msg);
+
 	help_list = faux_list_new(FAUX_LIST_SORTED, FAUX_LIST_NONUNIQUE,
 		help_compare, help_kcompare, help_free);
 

+ 44 - 4
klish/ktp/ktpd_session.c

@@ -131,6 +131,9 @@ static bool_t ktpd_session_process_cmd(ktpd_session_t *ktpd, faux_msg_t *msg)
 	bool_t dry_run = BOOL_FALSE;
 	uint32_t status = KTP_STATUS_NONE;
 	bool_t ret = BOOL_TRUE;
+	kpath_levels_node_t *iter = NULL;
+	klevel_t *level = NULL;
+	char *prompt = NULL;
 
 	assert(ktpd);
 	assert(msg);
@@ -170,19 +173,56 @@ static bool_t ktpd_session_process_cmd(ktpd_session_t *ktpd, faux_msg_t *msg)
 		status |= KTP_STATUS_EXIT;
 	}
 
+	// Generate prompt
+	iter = kpath_iterr(ksession_path(ktpd->session));
+	while ((level = kpath_eachr(&iter))) {
+		const kentry_t *view = klevel_entry(level);
+		kentry_t *prompt_entry = kentry_nested_by_purpose(view,
+				KENTRY_PURPOSE_PROMPT);
+
+		if (!prompt_entry)
+			continue;
+
+		if (kentry_actions_len(prompt_entry) > 0) {
+			int rc = -1;
+			bool_t res = BOOL_FALSE;
+
+			res = ksession_exec_locally(ktpd->session,
+				prompt_entry, NULL, &rc, &prompt);
+			if (!res || (rc < 0) || !prompt) {
+				if (prompt)
+					faux_str_free(prompt);
+				prompt = NULL;
+			}
+		}
+
+		if (!prompt) {
+			if (kentry_value(prompt_entry))
+				prompt = faux_str_dup(kentry_value(prompt_entry));
+		}
+
+		if (prompt)
+			break;
+	}
+
+	faux_msg_t *ack = ktp_msg_preform(cmd, status);
 	if (rc) {
 		uint8_t retcode8bit = 0;
-		faux_msg_t *ack = ktp_msg_preform(cmd, status);
 		retcode8bit = (uint8_t)(retcode & 0xff);
 		faux_msg_add_param(ack, KTP_PARAM_RETCODE, &retcode8bit, 1);
-		faux_msg_send_async(ack, ktpd->async);
-		faux_msg_free(ack);
 	} else {
+		faux_msg_set_status(ack, KTP_STATUS_ERROR);
 		char *err = faux_error_cstr(error);
-		ktp_send_error(ktpd->async, cmd, err);
+		faux_msg_add_param(ack, KTP_PARAM_ERROR, err, strlen(err));
 		faux_str_free(err);
 		ret = BOOL_FALSE;
 	}
+	if (prompt) {
+		faux_msg_add_param(ack, KTP_PARAM_PROMPT, prompt, strlen(prompt));
+		faux_str_free(prompt);
+	}
+	faux_msg_send_async(ack, ktpd->async);
+	faux_msg_free(ack);
 
 	faux_error_free(error);
 

+ 19 - 1
plugins/klish/misc.c

@@ -46,7 +46,7 @@ int klish_tsym(kcontext_t *context)
 
 
 // Print content of ACTION script
-int klish_print(kcontext_t *context)
+int klish_printl(kcontext_t *context)
 {
 	const kaction_t *action = NULL;
 	const char *script = NULL;
@@ -63,6 +63,24 @@ int klish_print(kcontext_t *context)
 }
 
 
+// Print content of ACTION script. Without additional '/n'
+int klish_print(kcontext_t *context)
+{
+	const kaction_t *action = NULL;
+	const char *script = NULL;
+
+	action = (kaction_t *)faux_list_data(kcontext_action_iter(context));
+
+	script = kaction_script(action);
+	if (faux_str_is_empty(script))
+		script = "";
+
+	printf("%s", script);
+
+	return 0;
+}
+
+
 // Symbol to show current path
 int klish_pwd(kcontext_t *context)
 {

+ 1 - 0
plugins/klish/plugin_init.c

@@ -31,6 +31,7 @@ int kplugin_klish_init(kcontext_t *context)
 		KSYM_USERDEFINED_PERMANENT, KSYM_SYNC));
 	kplugin_add_syms(plugin, ksym_new("tsym", klish_tsym));
 	kplugin_add_syms(plugin, ksym_new("print", klish_print));
+	kplugin_add_syms(plugin, ksym_new("printl", klish_printl));
 	kplugin_add_syms(plugin, ksym_new_ext("pwd", klish_pwd,
 		KSYM_PERMANENT, KSYM_SYNC));
 

+ 1 - 0
plugins/klish/private.h

@@ -15,6 +15,7 @@ C_DECL_BEGIN
 int klish_nop(kcontext_t *context);
 int klish_tsym(kcontext_t *context);
 int klish_print(kcontext_t *context);
+int klish_printl(kcontext_t *context);
 int klish_pwd(kcontext_t *context);
 
 // Navigation