Browse Source

ktpd: ksession_parse_for_completion()

Serj Kalichev 2 years ago
parent
commit
3a12d56765
6 changed files with 79 additions and 41 deletions
  1. 1 1
      bin/klish/klish.c
  2. 1 3
      klish/kpargv.h
  3. 5 2
      klish/ksession.h
  4. 1 9
      klish/ksession/kpargv.c
  5. 58 19
      klish/ksession/ksession_parse.c
  6. 13 7
      klish/ktp/ktpd_session.c

+ 1 - 1
bin/klish/klish.c

@@ -54,7 +54,7 @@ int main(int argc, char **argv)
 	net = faux_net_new();
 	faux_net_set_fd(net, ktp_session_fd(session));
 	msg = faux_msg_new(KTP_MAGIC, KTP_MAJOR, KTP_MINOR);
-	faux_msg_set_cmd(msg, KTP_CMD);
+	faux_msg_set_cmd(msg, KTP_COMPLETION);
 	if (opts->line)
 		faux_msg_add_param(msg, KTP_PARAM_LINE,
 			opts->line, strlen(opts->line));

+ 1 - 3
klish/kpargv.h

@@ -7,6 +7,7 @@
 #define _klish_kpargv_h
 
 #include <faux/list.h>
+#include <faux/argv.h>
 #include <klish/kentry.h>
 
 
@@ -74,9 +75,6 @@ bool_t kpargv_set_purpose(kpargv_t *pargv, kpargv_purpose_e purpose);
 // Last argument
 bool_t kpargv_set_last_arg(kpargv_t *pargv, const char *last_arg);
 const char *kpargv_last_arg(const kpargv_t *pargv);
-// Original line
-bool_t kpargv_set_orig_line(kpargv_t *pargv, const char *orig_line);
-const char *kpargv_orig_line(const kpargv_t *pargv);
 
 // Pargs
 faux_list_t *kpargv_pargs(const kpargv_t *pargv);

+ 5 - 2
klish/ksession.h

@@ -23,9 +23,12 @@ void ksession_free(ksession_t *session);
 const kscheme_t *ksession_scheme(const ksession_t *session);
 kpath_t *ksession_path(const ksession_t *session);
 
-kpargv_t *ksession_parse_line(ksession_t *session, const char *line,
+kpargv_t *ksession_parse_line(ksession_t *session, const faux_argv_t *argv,
 	kpargv_purpose_e purpose);
-faux_list_t *ksession_split_pipes(const char *line);
+faux_list_t *ksession_split_pipes(const char *raw_line);
+kpargv_t *ksession_parse_for_completion(ksession_t *session,
+	const char *raw_line);
+
 
 C_DECL_END
 

+ 1 - 9
klish/ksession/kpargv.c

@@ -20,7 +20,6 @@ struct kpargv_s {
 	bool_t continuable; // Last argument can be expanded
 	kpargv_purpose_e purpose; // Exec/Completion/Help
 	char *last_arg;
-	char *orig_line;
 };
 
 // Status
@@ -47,10 +46,6 @@ KSET(pargv, kpargv_purpose_e, purpose);
 KSET_STR(pargv, last_arg);
 KGET_STR(pargv, last_arg);
 
-// Original line
-KSET_STR(pargv, orig_line);
-KGET_STR(pargv, orig_line);
-
 // Pargs
 KGET(pargv, faux_list_t *, pargs);
 KADD_NESTED(pargv, kparg_t *, pargs);
@@ -102,7 +97,6 @@ kpargv_t *kpargv_new()
 	pargv->continuable = BOOL_FALSE;
 	pargv->purpose = KPURPOSE_EXEC;
 	pargv->last_arg = NULL;
-	pargv->orig_line = NULL;
 
 	// Parsed arguments list
 	pargv->pargs = faux_list_new(FAUX_LIST_UNSORTED, FAUX_LIST_NONUNIQUE,
@@ -124,7 +118,6 @@ void kpargv_free(kpargv_t *pargv)
 		return;
 
 	faux_str_free(pargv->last_arg);
-	faux_str_free(pargv->orig_line);
 
 	faux_list_free(pargv->pargs);
 	faux_list_free(pargv->completions);
@@ -206,10 +199,9 @@ bool_t kpargv_debug(const kpargv_t *pargv)
 	if (!pargv)
 		return BOOL_FALSE;
 
-	printf("Level: %lu, Command: %s, Line '%s': %s\n",
+	printf("Level: %lu, Command: %s, Status: %s\n",
 		kpargv_level(pargv),
 		kpargv_command(pargv) ? kentry_name(kpargv_command(pargv)) : "<none>",
-		kpargv_orig_line(pargv),
 		kpargv_status_str(pargv));
 
 	// Parsed parameters

+ 58 - 19
klish/ksession/ksession_parse.c

@@ -208,10 +208,9 @@ static kpargv_status_e ksession_parse_arg(kentry_t *current_entry,
 }
 
 
-kpargv_t *ksession_parse_line(ksession_t *session, const char *line,
+kpargv_t *ksession_parse_line(ksession_t *session, const faux_argv_t *argv,
 	kpargv_purpose_e purpose)
 {
-	faux_argv_t *argv = NULL;
 	faux_argv_node_t *argv_iter = NULL;
 	kpargv_t *pargv = NULL;
 	kpargv_status_e pstatus = KPARSE_NONE;
@@ -223,19 +222,10 @@ kpargv_t *ksession_parse_line(ksession_t *session, const char *line,
 	assert(session);
 	if (!session)
 		return NULL;
-	assert(line);
-	if (!line)
-		return NULL;
-
-	// Split line to arguments
-	argv = faux_argv_new();
 	assert(argv);
 	if (!argv)
 		return NULL;
-	if (faux_argv_parse(argv, line) < 0) {
-		faux_argv_free(argv);
-		return NULL;
-	}
+
 	argv_iter = faux_argv_iter(argv);
 
 	// Initialize kpargv_t
@@ -243,7 +233,6 @@ kpargv_t *ksession_parse_line(ksession_t *session, const char *line,
 	assert(pargv);
 	kpargv_set_continuable(pargv, faux_argv_is_continuable(argv));
 	kpargv_set_purpose(pargv, purpose);
-	kpargv_set_orig_line(pargv, line);
 
 	// Iterate levels of path from higher to lower. Note the reversed
 	// iterator will be used.
@@ -281,14 +270,12 @@ kpargv_t *ksession_parse_line(ksession_t *session, const char *line,
 	kpargv_set_status(pargv, pstatus);
 	kpargv_set_level(pargv, level_found);
 
-	faux_argv_free(argv);
-
 	return pargv;
 }
 
 
 // Delimeter of commands is '|' (pipe)
-faux_list_t *ksession_split_pipes(const char *line)
+faux_list_t *ksession_split_pipes(const char *raw_line)
 {
 	faux_list_t *list = NULL;
 	faux_argv_t *argv = NULL;
@@ -297,8 +284,8 @@ faux_list_t *ksession_split_pipes(const char *line)
 	const char *delimeter = "|";
 	const char *arg = NULL;
 
-	assert(line);
-	if (!line)
+	assert(raw_line);
+	if (!raw_line)
 		return NULL;
 
 	// Split raw line to arguments
@@ -306,7 +293,7 @@ faux_list_t *ksession_split_pipes(const char *line)
 	assert(argv);
 	if (!argv)
 		return NULL;
-	if (faux_argv_parse(argv, line) < 0) {
+	if (faux_argv_parse(argv, raw_line) < 0) {
 		faux_argv_free(argv);
 		return NULL;
 	}
@@ -357,3 +344,55 @@ faux_list_t *ksession_split_pipes(const char *line)
 
 	return list;
 }
+
+
+// All components except last one must be legal for execution but last
+// component must be parsed for completion.
+kpargv_t *ksession_parse_for_completion(ksession_t *session,
+	const char *raw_line)
+{
+	faux_list_t *split = NULL;
+	faux_list_node_t *iter = NULL;
+	kpargv_t *pargv = NULL;
+
+	assert(session);
+	if (!session)
+		return NULL;
+	assert(raw_line);
+	if (!raw_line)
+		return NULL;
+
+	// Split raw line (with '|') to components
+	split = ksession_split_pipes(raw_line);
+	if (!split || (faux_list_len(split) < 1)) {
+		faux_list_free(split);
+		return NULL;
+	}
+
+	iter = faux_list_head(split);
+	while (iter) {
+		faux_argv_t *argv = (faux_argv_t *)faux_list_data(iter);
+		if (iter == faux_list_tail(split)) { // Last item
+			pargv = ksession_parse_line(session, argv,
+				KPURPOSE_COMPLETION);
+			if (!pargv) {
+				faux_list_free(split);
+				return NULL;
+			}
+		} else { // Non-last item
+			pargv = ksession_parse_line(session, argv,
+				KPURPOSE_EXEC);
+			// All non-last components must be ready for execution
+			if (!pargv || kpargv_status(pargv) != KPARSE_OK) {
+				kpargv_free(pargv);
+				faux_list_free(split);
+				return NULL;
+			}
+		}
+		iter = faux_list_next_node(iter);
+	}
+
+	faux_list_free(split);
+
+	return pargv;
+}

+ 13 - 7
klish/ktp/ktpd_session.c

@@ -63,7 +63,7 @@ static bool_t ktpd_session_process_cmd(ktpd_session_t *session, faux_msg_t *msg)
 {
 	char *line = NULL;
 	faux_msg_t *ack = NULL;
-	kpargv_t *pargv = NULL;
+//	kpargv_t *pargv = NULL;
 	ktp_cmd_e cmd = KTP_CMD_ACK;
 
 	faux_list_t *split = NULL;
@@ -82,7 +82,7 @@ static bool_t ktpd_session_process_cmd(ktpd_session_t *session, faux_msg_t *msg)
 	printf("split %ld\n", split ? (ssize_t)faux_list_len(split) : -1);
 	faux_list_free(split);
 
-	// Parsing
+/*	// Parsing
 	pargv = ksession_parse_line(session->ksession, line, KPURPOSE_EXEC);
 	faux_str_free(line);
 	kpargv_debug(pargv);
@@ -95,7 +95,7 @@ static bool_t ktpd_session_process_cmd(ktpd_session_t *session, faux_msg_t *msg)
 		return BOOL_FALSE;
 	}
 	kpargv_free(pargv);
-
+*/
 	// Send ACK message
 	ack = ktp_msg_preform(cmd, KTP_STATUS_NONE);
 	faux_msg_send_async(ack, session->async);
@@ -122,8 +122,14 @@ static bool_t ktpd_session_process_completion(ktpd_session_t *session, faux_msg_
 	}
 
 	// Parsing
-	pargv = ksession_parse_line(session->ksession, line, KPURPOSE_COMPLETION);
+	pargv = ksession_parse_for_completion(session->ksession, line);
 	faux_str_free(line);
+	if (!pargv) {
+		ktpd_session_send_error(session, cmd, NULL);
+		return BOOL_FALSE;
+	}
+	kpargv_debug(pargv);
+
 	kpargv_free(pargv);
 
 	// Send ACK message
@@ -139,7 +145,7 @@ static bool_t ktpd_session_process_help(ktpd_session_t *session, faux_msg_t *msg
 {
 	char *line = NULL;
 	faux_msg_t *ack = NULL;
-	kpargv_t *pargv = NULL;
+//	kpargv_t *pargv = NULL;
 	ktp_cmd_e cmd = KTP_HELP_ACK;
 
 	assert(session);
@@ -151,11 +157,11 @@ static bool_t ktpd_session_process_help(ktpd_session_t *session, faux_msg_t *msg
 		return BOOL_FALSE;
 	}
 
-	// Parsing
+/*	// Parsing
 	pargv = ksession_parse_line(session->ksession, line, KPURPOSE_HELP);
 	faux_str_free(line);
 	kpargv_free(pargv);
-
+*/
 	// Send ACK message
 	ack = ktp_msg_preform(cmd, KTP_STATUS_NONE);
 	faux_msg_send_async(ack, session->async);