1 /*
2  * Copyright (c) 2018 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <ctype.h>
8 #include <stdlib.h>
9 #include <zephyr/sys/atomic.h>
10 #include <zephyr/shell/shell.h>
11 #if defined(CONFIG_SHELL_BACKEND_DUMMY)
12 #include <zephyr/shell/shell_dummy.h>
13 #endif
14 #include "shell_ops.h"
15 #include "shell_help.h"
16 #include "shell_utils.h"
17 #include "shell_vt100.h"
18 #include "shell_wildcard.h"
19 
20 /* 2 == 1 char for cmd + 1 char for '\0' */
21 #if (CONFIG_SHELL_CMD_BUFF_SIZE < 2)
22 	#error too small CONFIG_SHELL_CMD_BUFF_SIZE
23 #endif
24 
25 #if (CONFIG_SHELL_PRINTF_BUFF_SIZE < 1)
26 	#error too small SHELL_PRINTF_BUFF_SIZE
27 #endif
28 
29 #define SHELL_MSG_CMD_NOT_FOUND		": command not found"
30 #define SHELL_MSG_BACKEND_NOT_ACTIVE	\
31 	"WARNING: A print request was detected on not active shell backend.\n"
32 #define SHELL_MSG_TOO_MANY_ARGS		"Too many arguments in the command.\n"
33 #define SHELL_INIT_OPTION_PRINTER	(NULL)
34 #define SHELL_TX_MTX_TIMEOUT_MS		50
35 
36 #define SHELL_THREAD_PRIORITY \
37 	COND_CODE_1(CONFIG_SHELL_THREAD_PRIORITY_OVERRIDE, \
38 			(CONFIG_SHELL_THREAD_PRIORITY), (K_LOWEST_APPLICATION_THREAD_PRIO))
39 
40 BUILD_ASSERT(SHELL_THREAD_PRIORITY >=
41 		  K_HIGHEST_APPLICATION_THREAD_PRIO
42 		&& SHELL_THREAD_PRIORITY <= K_LOWEST_APPLICATION_THREAD_PRIO,
43 		  "Invalid range for thread priority");
44 
receive_state_change(const struct shell * sh,enum shell_receive_state state)45 static inline void receive_state_change(const struct shell *sh,
46 					enum shell_receive_state state)
47 {
48 	sh->ctx->receive_state = state;
49 }
50 
cmd_buffer_clear(const struct shell * sh)51 static void cmd_buffer_clear(const struct shell *sh)
52 {
53 	sh->ctx->cmd_buff[0] = '\0'; /* clear command buffer */
54 	sh->ctx->cmd_buff_pos = 0;
55 	sh->ctx->cmd_buff_len = 0;
56 }
57 
shell_internal_help_print(const struct shell * sh)58 static void shell_internal_help_print(const struct shell *sh)
59 {
60 	if (!IS_ENABLED(CONFIG_SHELL_HELP)) {
61 		return;
62 	}
63 
64 	z_shell_help_cmd_print(sh, &sh->ctx->active_cmd);
65 	z_shell_help_subcmd_print(sh, &sh->ctx->active_cmd,
66 				  "Subcommands:\n");
67 }
68 
69 /**
70  * @brief Prints error message on wrong argument count.
71  *	  Optionally, printing help on wrong argument count.
72  *
73  * @param[in] shell	  Pointer to the shell instance.
74  * @param[in] arg_cnt_ok  Flag indicating valid number of arguments.
75  *
76  * @return 0		  if check passed
77  * @return -EINVAL	  if wrong argument count
78  */
cmd_precheck(const struct shell * sh,bool arg_cnt_ok)79 static int cmd_precheck(const struct shell *sh,
80 			bool arg_cnt_ok)
81 {
82 	if (!arg_cnt_ok) {
83 		z_shell_fprintf(sh, SHELL_ERROR,
84 				"%s: wrong parameter count\n",
85 				sh->ctx->active_cmd.syntax);
86 
87 		if (IS_ENABLED(CONFIG_SHELL_HELP_ON_WRONG_ARGUMENT_COUNT)) {
88 			shell_internal_help_print(sh);
89 		}
90 
91 		return -EINVAL;
92 	}
93 
94 	return 0;
95 }
96 
state_set(const struct shell * sh,enum shell_state state)97 static inline void state_set(const struct shell *sh, enum shell_state state)
98 {
99 	sh->ctx->state = state;
100 
101 	if (state == SHELL_STATE_ACTIVE && !sh->ctx->bypass) {
102 		cmd_buffer_clear(sh);
103 		if (z_flag_print_noinit_get(sh)) {
104 			z_shell_fprintf(sh, SHELL_WARNING, "%s",
105 					SHELL_MSG_BACKEND_NOT_ACTIVE);
106 			z_flag_print_noinit_set(sh, false);
107 		}
108 		z_shell_print_prompt_and_cmd(sh);
109 	}
110 }
111 
state_get(const struct shell * sh)112 static inline enum shell_state state_get(const struct shell *sh)
113 {
114 	return sh->ctx->state;
115 }
116 
117 static inline const struct shell_static_entry *
selected_cmd_get(const struct shell * sh)118 selected_cmd_get(const struct shell *sh)
119 {
120 	if (IS_ENABLED(CONFIG_SHELL_CMDS_SELECT)
121 	    || (CONFIG_SHELL_CMD_ROOT[0] != 0)) {
122 		return sh->ctx->selected_cmd;
123 	}
124 
125 	return NULL;
126 }
127 
tab_item_print(const struct shell * sh,const char * option,uint16_t longest_option)128 static void tab_item_print(const struct shell *sh, const char *option,
129 			   uint16_t longest_option)
130 {
131 	static const char *tab = "  ";
132 	uint16_t columns;
133 	uint16_t diff;
134 
135 	/* Function initialization has been requested. */
136 	if (option == NULL) {
137 		sh->ctx->vt100_ctx.printed_cmd = 0;
138 		return;
139 	}
140 
141 	longest_option += z_shell_strlen(tab);
142 
143 	columns = (sh->ctx->vt100_ctx.cons.terminal_wid
144 			- z_shell_strlen(tab)) / longest_option;
145 	__ASSERT_NO_MSG(columns != 0);
146 	diff = longest_option - z_shell_strlen(option);
147 
148 	if (sh->ctx->vt100_ctx.printed_cmd++ % columns == 0U) {
149 		z_shell_fprintf(sh, SHELL_OPTION, "\n%s%s", tab, option);
150 	} else {
151 		z_shell_fprintf(sh, SHELL_OPTION, "%s", option);
152 	}
153 
154 	z_shell_op_cursor_horiz_move(sh, diff);
155 }
156 
history_init(const struct shell * sh)157 static void history_init(const struct shell *sh)
158 {
159 	if (!IS_ENABLED(CONFIG_SHELL_HISTORY)) {
160 		return;
161 	}
162 
163 	z_shell_history_init(sh->history);
164 }
165 
history_purge(const struct shell * sh)166 static void history_purge(const struct shell *sh)
167 {
168 	if (!IS_ENABLED(CONFIG_SHELL_HISTORY)) {
169 		return;
170 	}
171 
172 	z_shell_history_purge(sh->history);
173 }
174 
history_mode_exit(const struct shell * sh)175 static void history_mode_exit(const struct shell *sh)
176 {
177 	if (!IS_ENABLED(CONFIG_SHELL_HISTORY)) {
178 		return;
179 	}
180 
181 	z_flag_history_exit_set(sh, false);
182 	z_shell_history_mode_exit(sh->history);
183 }
184 
history_put(const struct shell * sh,uint8_t * line,size_t length)185 static void history_put(const struct shell *sh, uint8_t *line, size_t length)
186 {
187 	if (!IS_ENABLED(CONFIG_SHELL_HISTORY)) {
188 		return;
189 	}
190 
191 	z_shell_history_put(sh->history, line, length);
192 }
193 
history_handle(const struct shell * sh,bool up)194 static void history_handle(const struct shell *sh, bool up)
195 {
196 	bool history_mode;
197 	uint16_t len;
198 
199 	/*optional feature */
200 	if (!IS_ENABLED(CONFIG_SHELL_HISTORY)) {
201 		return;
202 	}
203 
204 	/* Checking if history process has been stopped */
205 	if (z_flag_history_exit_get(sh)) {
206 		z_flag_history_exit_set(sh, false);
207 		z_shell_history_mode_exit(sh->history);
208 	}
209 
210 	/* Backup command if history is entered */
211 	if (!z_shell_history_active(sh->history)) {
212 		if (up) {
213 			uint16_t cmd_len = z_shell_strlen(sh->ctx->cmd_buff);
214 
215 			if (cmd_len) {
216 				strcpy(sh->ctx->temp_buff,
217 				       sh->ctx->cmd_buff);
218 			} else {
219 				sh->ctx->temp_buff[0] = '\0';
220 			}
221 		} else {
222 			/* Pressing 'down' not in history mode has no effect. */
223 			return;
224 		}
225 	}
226 
227 	/* Start by checking if history is not empty. */
228 	history_mode = z_shell_history_get(sh->history, up,
229 					   sh->ctx->cmd_buff, &len);
230 
231 	/* On exiting history mode print backed up command. */
232 	if (!history_mode) {
233 		strcpy(sh->ctx->cmd_buff, sh->ctx->temp_buff);
234 		len = z_shell_strlen(sh->ctx->cmd_buff);
235 	}
236 
237 	z_shell_op_cursor_home_move(sh);
238 	z_clear_eos(sh);
239 	z_shell_print_cmd(sh);
240 	sh->ctx->cmd_buff_pos = len;
241 	sh->ctx->cmd_buff_len = len;
242 	z_shell_op_cond_next_line(sh);
243 }
244 
completion_space_get(const struct shell * sh)245 static inline uint16_t completion_space_get(const struct shell *sh)
246 {
247 	uint16_t space = (CONFIG_SHELL_CMD_BUFF_SIZE - 1) -
248 			sh->ctx->cmd_buff_len;
249 	return space;
250 }
251 
252 /* Prepare arguments and return number of space available for completion. */
tab_prepare(const struct shell * sh,const struct shell_static_entry ** cmd,const char *** argv,size_t * argc,size_t * complete_arg_idx,struct shell_static_entry * d_entry)253 static bool tab_prepare(const struct shell *sh,
254 			const struct shell_static_entry **cmd,
255 			const char ***argv, size_t *argc,
256 			size_t *complete_arg_idx,
257 			struct shell_static_entry *d_entry)
258 {
259 	uint16_t compl_space = completion_space_get(sh);
260 	size_t search_argc;
261 
262 	if (compl_space == 0U) {
263 		return false;
264 	}
265 
266 	/* Copy command from its beginning to cursor position. */
267 	memcpy(sh->ctx->temp_buff, sh->ctx->cmd_buff,
268 			sh->ctx->cmd_buff_pos);
269 	sh->ctx->temp_buff[sh->ctx->cmd_buff_pos] = '\0';
270 
271 	/* Create argument list. */
272 	(void)z_shell_make_argv(argc, *argv, sh->ctx->temp_buff,
273 				CONFIG_SHELL_ARGC_MAX);
274 
275 	if (*argc > CONFIG_SHELL_ARGC_MAX) {
276 		return false;
277 	}
278 
279 	/* terminate arguments with NULL */
280 	(*argv)[*argc] = NULL;
281 
282 	if ((IS_ENABLED(CONFIG_SHELL_CMDS_SELECT) || (CONFIG_SHELL_CMD_ROOT[0] != 0))
283 	    && (*argc > 0) &&
284 	    (strcmp("select", (*argv)[0]) == 0) &&
285 	    !z_shell_in_select_mode(sh)) {
286 		*argv = *argv + 1;
287 		*argc = *argc - 1;
288 	}
289 
290 	/* If last command is not completed (followed by space) it is treated
291 	 * as uncompleted one.
292 	 */
293 	int space = (sh->ctx->cmd_buff_pos > 0) ?
294 		     isspace((int)sh->ctx->cmd_buff[sh->ctx->cmd_buff_pos - 1]) : 0;
295 
296 	/* root command completion */
297 	if ((*argc == 0) || ((space == 0) && (*argc == 1))) {
298 		*complete_arg_idx = Z_SHELL_CMD_ROOT_LVL;
299 		*cmd = selected_cmd_get(sh);
300 		return true;
301 	}
302 
303 	search_argc = space ? *argc : *argc - 1;
304 
305 	*cmd = z_shell_get_last_command(selected_cmd_get(sh), search_argc,
306 					*argv, complete_arg_idx,	d_entry,
307 					false);
308 
309 	/* if search_argc == 0 (empty command line) shell_get_last_command will
310 	 * return NULL tab is allowed, otherwise not.
311 	 */
312 	if ((*cmd == NULL) && (search_argc != 0)) {
313 		return false;
314 	}
315 
316 	return true;
317 }
318 
is_completion_candidate(const char * candidate,const char * str,size_t len)319 static inline bool is_completion_candidate(const char *candidate,
320 					   const char *str, size_t len)
321 {
322 	return (strncmp(candidate, str, len) == 0) ? true : false;
323 }
324 
find_completion_candidates(const struct shell * sh,const struct shell_static_entry * cmd,const char * incompl_cmd,size_t * first_idx,size_t * cnt,uint16_t * longest)325 static void find_completion_candidates(const struct shell *sh,
326 				       const struct shell_static_entry *cmd,
327 				       const char *incompl_cmd,
328 				       size_t *first_idx, size_t *cnt,
329 				       uint16_t *longest)
330 {
331 	const struct shell_static_entry *candidate;
332 	struct shell_static_entry dloc;
333 	size_t incompl_cmd_len;
334 	size_t idx = 0;
335 
336 	incompl_cmd_len = z_shell_strlen(incompl_cmd);
337 	*longest = 0U;
338 	*cnt = 0;
339 
340 	while ((candidate = z_shell_cmd_get(cmd, idx, &dloc)) != NULL) {
341 		bool is_candidate;
342 		is_candidate = is_completion_candidate(candidate->syntax,
343 						incompl_cmd, incompl_cmd_len);
344 		if (is_candidate) {
345 			*longest = Z_MAX(strlen(candidate->syntax), *longest);
346 			if (*cnt == 0) {
347 				*first_idx = idx;
348 			}
349 			(*cnt)++;
350 		}
351 
352 		idx++;
353 	}
354 }
355 
autocomplete(const struct shell * sh,const struct shell_static_entry * cmd,const char * arg,size_t subcmd_idx)356 static void autocomplete(const struct shell *sh,
357 			 const struct shell_static_entry *cmd,
358 			 const char *arg,
359 			 size_t subcmd_idx)
360 {
361 	const struct shell_static_entry *match;
362 	uint16_t cmd_len;
363 	uint16_t arg_len = z_shell_strlen(arg);
364 
365 	/* sh->ctx->active_cmd can be safely used outside of command context
366 	 * to save stack
367 	 */
368 	match = z_shell_cmd_get(cmd, subcmd_idx, &sh->ctx->active_cmd);
369 	__ASSERT_NO_MSG(match != NULL);
370 	cmd_len = z_shell_strlen(match->syntax);
371 
372 	if (!IS_ENABLED(CONFIG_SHELL_TAB_AUTOCOMPLETION)) {
373 		/* Add a space if the Tab button is pressed when command is
374 		 * complete.
375 		 */
376 		if (cmd_len == arg_len) {
377 			z_shell_op_char_insert(sh, ' ');
378 		}
379 		return;
380 	}
381 
382 	/* no exact match found */
383 	if (cmd_len != arg_len) {
384 		z_shell_op_completion_insert(sh,
385 					     match->syntax + arg_len,
386 					     cmd_len - arg_len);
387 	}
388 
389 	/* Next character in the buffer is not 'space'. */
390 	if (isspace((int) sh->ctx->cmd_buff[
391 					sh->ctx->cmd_buff_pos]) == 0) {
392 		if (z_flag_insert_mode_get(sh)) {
393 			z_flag_insert_mode_set(sh, false);
394 			z_shell_op_char_insert(sh, ' ');
395 			z_flag_insert_mode_set(sh, true);
396 		} else {
397 			z_shell_op_char_insert(sh, ' ');
398 		}
399 	} else {
400 		/*  case:
401 		 * | | -> cursor
402 		 * cons_name $: valid_cmd valid_sub_cmd| |argument  <tab>
403 		 */
404 		z_shell_op_cursor_move(sh, 1);
405 		/* result:
406 		 * cons_name $: valid_cmd valid_sub_cmd |a|rgument
407 		 */
408 	}
409 }
410 
str_common(const char * s1,const char * s2,size_t n)411 static size_t str_common(const char *s1, const char *s2, size_t n)
412 {
413 	size_t common = 0;
414 
415 	while ((n > 0) && (*s1 == *s2) && (*s1 != '\0')) {
416 		s1++;
417 		s2++;
418 		n--;
419 		common++;
420 	}
421 
422 	return common;
423 }
424 
tab_options_print(const struct shell * sh,const struct shell_static_entry * cmd,const char * str,size_t first,size_t cnt,uint16_t longest)425 static void tab_options_print(const struct shell *sh,
426 			      const struct shell_static_entry *cmd,
427 			      const char *str, size_t first, size_t cnt,
428 			      uint16_t longest)
429 {
430 	const struct shell_static_entry *match;
431 	size_t str_len = z_shell_strlen(str);
432 	size_t idx = first;
433 
434 	/* Printing all matching commands (options). */
435 	tab_item_print(sh, SHELL_INIT_OPTION_PRINTER, longest);
436 
437 	while (cnt) {
438 		/* sh->ctx->active_cmd can be safely used outside of command
439 		 * context to save stack
440 		 */
441 		match = z_shell_cmd_get(cmd, idx, &sh->ctx->active_cmd);
442 		__ASSERT_NO_MSG(match != NULL);
443 		idx++;
444 		if (str && match->syntax &&
445 		    !is_completion_candidate(match->syntax, str, str_len)) {
446 			continue;
447 		}
448 
449 		tab_item_print(sh, match->syntax, longest);
450 		cnt--;
451 	}
452 
453 	z_cursor_next_line_move(sh);
454 	z_shell_print_prompt_and_cmd(sh);
455 }
456 
common_beginning_find(const struct shell * sh,const struct shell_static_entry * cmd,const char ** str,size_t first,size_t cnt,uint16_t arg_len)457 static uint16_t common_beginning_find(const struct shell *sh,
458 				   const struct shell_static_entry *cmd,
459 				   const char **str,
460 				   size_t first, size_t cnt, uint16_t arg_len)
461 {
462 	struct shell_static_entry dynamic_entry;
463 	const struct shell_static_entry *match;
464 	uint16_t common = UINT16_MAX;
465 	size_t idx = first + 1;
466 
467 	__ASSERT_NO_MSG(cnt > 1);
468 
469 	match = z_shell_cmd_get(cmd, first, &dynamic_entry);
470 	__ASSERT_NO_MSG(match);
471 	strncpy(sh->ctx->temp_buff, match->syntax,
472 			sizeof(sh->ctx->temp_buff) - 1);
473 
474 	*str = match->syntax;
475 
476 	while (cnt > 1) {
477 		struct shell_static_entry dynamic_entry2;
478 		const struct shell_static_entry *match2;
479 		int curr_common;
480 
481 		match2 = z_shell_cmd_get(cmd, idx++, &dynamic_entry2);
482 		if (match2 == NULL) {
483 			break;
484 		}
485 
486 		curr_common = str_common(sh->ctx->temp_buff, match2->syntax,
487 					 UINT16_MAX);
488 		if ((arg_len == 0U) || (curr_common >= arg_len)) {
489 			--cnt;
490 			common = (curr_common < common) ? curr_common : common;
491 		}
492 	}
493 
494 	return common;
495 }
496 
partial_autocomplete(const struct shell * sh,const struct shell_static_entry * cmd,const char * arg,size_t first,size_t cnt)497 static void partial_autocomplete(const struct shell *sh,
498 				 const struct shell_static_entry *cmd,
499 				 const char *arg,
500 				 size_t first, size_t cnt)
501 {
502 	const char *completion;
503 	uint16_t arg_len = z_shell_strlen(arg);
504 	uint16_t common = common_beginning_find(sh, cmd, &completion, first,
505 					     cnt, arg_len);
506 
507 	if (!IS_ENABLED(CONFIG_SHELL_TAB_AUTOCOMPLETION)) {
508 		return;
509 	}
510 
511 	if (common) {
512 		z_shell_op_completion_insert(sh, &completion[arg_len],
513 					     common - arg_len);
514 	}
515 }
516 
exec_cmd(const struct shell * sh,size_t argc,const char ** argv,const struct shell_static_entry * help_entry)517 static int exec_cmd(const struct shell *sh, size_t argc, const char **argv,
518 		    const struct shell_static_entry *help_entry)
519 {
520 	int ret_val = 0;
521 
522 	if (sh->ctx->active_cmd.handler == NULL) {
523 		if ((help_entry != NULL) && IS_ENABLED(CONFIG_SHELL_HELP)) {
524 			if (help_entry->help == NULL) {
525 				return -ENOEXEC;
526 			}
527 			if (help_entry->help != sh->ctx->active_cmd.help) {
528 				sh->ctx->active_cmd = *help_entry;
529 			}
530 			shell_internal_help_print(sh);
531 			return SHELL_CMD_HELP_PRINTED;
532 		} else {
533 			if (IS_ENABLED(CONFIG_SHELL_MSG_SPECIFY_SUBCOMMAND)) {
534 				z_shell_fprintf(sh, SHELL_ERROR,
535 						SHELL_MSG_SPECIFY_SUBCOMMAND);
536 			}
537 			return -ENOEXEC;
538 		}
539 	}
540 
541 	if (sh->ctx->active_cmd.args.mandatory) {
542 		uint32_t mand = sh->ctx->active_cmd.args.mandatory;
543 		uint8_t opt8 = sh->ctx->active_cmd.args.optional;
544 		uint32_t opt = (opt8 == SHELL_OPT_ARG_CHECK_SKIP) ?
545 				UINT16_MAX : opt8;
546 		const bool in_range = IN_RANGE(argc, mand, mand + opt);
547 
548 		/* Check if argc is within allowed range */
549 		ret_val = cmd_precheck(sh, in_range);
550 	}
551 
552 	if (!ret_val) {
553 #if CONFIG_SHELL_GETOPT
554 		getopt_init();
555 #endif
556 
557 		z_flag_cmd_ctx_set(sh, true);
558 		/* Unlock thread mutex in case command would like to borrow
559 		 * shell context to other thread to avoid mutex deadlock.
560 		 */
561 		k_mutex_unlock(&sh->ctx->wr_mtx);
562 		ret_val = sh->ctx->active_cmd.handler(sh, argc,
563 							 (char **)argv);
564 		/* Bring back mutex to shell thread. */
565 		k_mutex_lock(&sh->ctx->wr_mtx, K_FOREVER);
566 		z_flag_cmd_ctx_set(sh, false);
567 	}
568 
569 	return ret_val;
570 }
571 
active_cmd_prepare(const struct shell_static_entry * entry,struct shell_static_entry * active_cmd,struct shell_static_entry * help_entry,size_t * lvl,size_t * handler_lvl,size_t * args_left)572 static void active_cmd_prepare(const struct shell_static_entry *entry,
573 				struct shell_static_entry *active_cmd,
574 				struct shell_static_entry *help_entry,
575 				size_t *lvl, size_t *handler_lvl,
576 				size_t *args_left)
577 {
578 	if (entry->handler) {
579 		*handler_lvl = *lvl;
580 		*active_cmd = *entry;
581 		/* If command is final handler and it has a raw optional argument,
582 		 * then set remaining arguments to mandatory - 1 so after processing mandatory
583 		 * args, handler is passed remaining raw string
584 		 */
585 		if ((entry->subcmd == NULL)
586 		    && entry->args.optional == SHELL_OPT_ARG_RAW) {
587 			*args_left = entry->args.mandatory - 1;
588 		}
589 	}
590 	if (entry->help) {
591 		*help_entry = *entry;
592 	}
593 }
594 
wildcard_check_report(const struct shell * sh,bool found,const struct shell_static_entry * entry)595 static bool wildcard_check_report(const struct shell *sh, bool found,
596 				  const struct shell_static_entry *entry)
597 {
598 	/* An error occurred, fnmatch  argument cannot be followed by argument
599 	 * with a handler to avoid multiple function calls.
600 	 */
601 	if (IS_ENABLED(CONFIG_SHELL_WILDCARD) && found && entry->handler) {
602 		z_shell_op_cursor_end_move(sh);
603 		z_shell_op_cond_next_line(sh);
604 
605 		z_shell_fprintf(sh, SHELL_ERROR,
606 			"Error: requested multiple function executions\n");
607 		return false;
608 	}
609 
610 	return true;
611 }
612 
613 /* Function is analyzing the command buffer to find matching commands. Next, it
614  * invokes the  last recognized command which has a handler and passes the rest
615  * of command buffer as arguments.
616  *
617  * By default command buffer is parsed and spaces are treated by arguments
618  * separators. Complex arguments are provided in quotation marks with quotation
619  * marks escaped within the argument. Argument parser is removing quotation
620  * marks at argument boundary as well as escape characters within the argument.
621  * However, it is possible to indicate that command shall treat remaining part
622  * of command buffer as the last argument without parsing. This can be used for
623  * commands which expects whole command buffer to be passed directly to
624  * the command handler without any preprocessing.
625  * Because of that feature, command buffer is processed argument by argument and
626  * decision on further processing is based on currently processed command.
627  */
execute(const struct shell * sh)628 static int execute(const struct shell *sh)
629 {
630 	struct shell_static_entry dloc; /* Memory for dynamic commands. */
631 	const char *argv[CONFIG_SHELL_ARGC_MAX + 1] = {0}; /* +1 reserved for NULL */
632 	const struct shell_static_entry *parent = selected_cmd_get(sh);
633 	const struct shell_static_entry *entry = NULL;
634 	struct shell_static_entry help_entry;
635 	size_t cmd_lvl = 0;
636 	size_t cmd_with_handler_lvl = 0;
637 	bool wildcard_found = false;
638 	size_t argc = 0, args_left = SIZE_MAX;
639 	char quote;
640 	const char **argvp;
641 	char *cmd_buf = sh->ctx->cmd_buff;
642 	bool has_last_handler = false;
643 
644 	z_shell_op_cursor_end_move(sh);
645 	if (!z_shell_cursor_in_empty_line(sh)) {
646 		z_cursor_next_line_move(sh);
647 	}
648 
649 	memset(&sh->ctx->active_cmd, 0, sizeof(sh->ctx->active_cmd));
650 
651 	if (IS_ENABLED(CONFIG_SHELL_HISTORY)) {
652 		z_shell_cmd_trim(sh);
653 		history_put(sh, sh->ctx->cmd_buff,
654 			    sh->ctx->cmd_buff_len);
655 	}
656 
657 	if (IS_ENABLED(CONFIG_SHELL_WILDCARD)) {
658 		z_shell_wildcard_prepare(sh);
659 	}
660 
661 	/* Parent present means we are in select mode. */
662 	if (parent != NULL) {
663 		argv[0] = parent->syntax;
664 		argv[1] = cmd_buf;
665 		argvp = &argv[1];
666 		active_cmd_prepare(parent, &sh->ctx->active_cmd, &help_entry,
667 				   &cmd_lvl, &cmd_with_handler_lvl, &args_left);
668 		cmd_lvl++;
669 	} else {
670 		help_entry.help = NULL;
671 		argvp = &argv[0];
672 	}
673 
674 	/* Below loop is analyzing subcommands of found root command. */
675 	while ((argc != 1) && (cmd_lvl < CONFIG_SHELL_ARGC_MAX)
676 		&& args_left > 0) {
677 		quote = z_shell_make_argv(&argc, argvp, cmd_buf, 2);
678 		cmd_buf = (char *)argvp[1];
679 
680 		if (argc == 0) {
681 			return -ENOEXEC;
682 		} else if ((argc == 1) && (quote != 0)) {
683 			z_shell_fprintf(sh, SHELL_ERROR,
684 					"not terminated: %c\n", quote);
685 			return -ENOEXEC;
686 		}
687 
688 		if (IS_ENABLED(CONFIG_SHELL_HELP) && (cmd_lvl > 0) &&
689 		    z_shell_help_request(argvp[0])) {
690 			/* Command called with help option so it makes no sense
691 			 * to search deeper commands.
692 			 */
693 			if (help_entry.help) {
694 				sh->ctx->active_cmd = help_entry;
695 				shell_internal_help_print(sh);
696 				return SHELL_CMD_HELP_PRINTED;
697 			}
698 
699 			if (IS_ENABLED(CONFIG_SHELL_MSG_SPECIFY_SUBCOMMAND)) {
700 				z_shell_fprintf(sh, SHELL_ERROR,
701 						SHELL_MSG_SPECIFY_SUBCOMMAND);
702 			}
703 			return -ENOEXEC;
704 		}
705 
706 		if (IS_ENABLED(CONFIG_SHELL_WILDCARD) && (cmd_lvl > 0)) {
707 			enum shell_wildcard_status status;
708 
709 			status = z_shell_wildcard_process(sh, entry,
710 							  argvp[0]);
711 			/* Wildcard character found but there is no matching
712 			 * command.
713 			 */
714 			if (status == SHELL_WILDCARD_CMD_NO_MATCH_FOUND) {
715 				break;
716 			}
717 
718 			/* Wildcard character was not found function can process
719 			 * argument.
720 			 */
721 			if (status != SHELL_WILDCARD_NOT_FOUND) {
722 				++cmd_lvl;
723 				wildcard_found = true;
724 				continue;
725 			}
726 		}
727 
728 		if (has_last_handler == false) {
729 			entry = z_shell_find_cmd(parent, argvp[0], &dloc);
730 		}
731 
732 		argvp++;
733 		args_left--;
734 		if (entry) {
735 			if (wildcard_check_report(sh, wildcard_found, entry)
736 				== false) {
737 				return -ENOEXEC;
738 			}
739 
740 			active_cmd_prepare(entry, &sh->ctx->active_cmd,
741 					  &help_entry, &cmd_lvl,
742 					  &cmd_with_handler_lvl, &args_left);
743 			parent = entry;
744 		} else {
745 			if (IS_ENABLED(CONFIG_SHELL_MSG_CMD_NOT_FOUND) &&
746 				cmd_lvl == 0 &&
747 				(!z_shell_in_select_mode(sh) ||
748 				 sh->ctx->selected_cmd->handler == NULL)) {
749 				z_shell_fprintf(sh, SHELL_ERROR,
750 						"%s%s\n", argv[0],
751 						SHELL_MSG_CMD_NOT_FOUND);
752 			}
753 
754 			/* last handler found - no need to search commands in
755 			 * the next iteration.
756 			 */
757 			has_last_handler = true;
758 		}
759 
760 		if (args_left || (argc == 2)) {
761 			cmd_lvl++;
762 		}
763 
764 	}
765 
766 	if ((cmd_lvl >= CONFIG_SHELL_ARGC_MAX) && (argc == 2)) {
767 		/* argc == 2 indicates that when command string was parsed
768 		 * there was more characters remaining. It means that number of
769 		 * arguments exceeds the limit.
770 		 */
771 		z_shell_fprintf(sh, SHELL_ERROR, "%s\n",
772 				SHELL_MSG_TOO_MANY_ARGS);
773 		return -ENOEXEC;
774 	}
775 
776 	if (IS_ENABLED(CONFIG_SHELL_WILDCARD) && wildcard_found) {
777 		z_shell_wildcard_finalize(sh);
778 		/* cmd_buffer has been overwritten by function finalize function
779 		 * with all expanded commands. Hence shell_make_argv needs to
780 		 * be called again.
781 		 */
782 		(void)z_shell_make_argv(&cmd_lvl,
783 					&argv[selected_cmd_get(sh) ? 1 : 0],
784 					sh->ctx->cmd_buff,
785 					CONFIG_SHELL_ARGC_MAX);
786 
787 		if (selected_cmd_get(sh)) {
788 			/* Apart from what is in the command buffer, there is
789 			 * a selected command.
790 			 */
791 			cmd_lvl++;
792 		}
793 	}
794 
795 	/* If a command was found */
796 	if (parent != NULL) {
797 		/* If the found command uses a raw optional argument and
798 		 * we have a remaining unprocessed non-null string,
799 		 * then increment command level so handler receives raw string
800 		 */
801 		if (parent->args.optional == SHELL_OPT_ARG_RAW && argv[cmd_lvl] != NULL) {
802 			cmd_lvl++;
803 		}
804 	}
805 
806 	/* Executing the deepest found handler. */
807 	return exec_cmd(sh, cmd_lvl - cmd_with_handler_lvl,
808 			&argv[cmd_with_handler_lvl], &help_entry);
809 }
810 
tab_handle(const struct shell * sh)811 static void tab_handle(const struct shell *sh)
812 {
813 	const char *__argv[CONFIG_SHELL_ARGC_MAX + 1];
814 	/* d_entry - placeholder for dynamic command */
815 	struct shell_static_entry d_entry;
816 	const struct shell_static_entry *cmd;
817 	const char **argv = __argv;
818 	size_t first = 0;
819 	size_t arg_idx;
820 	uint16_t longest;
821 	size_t argc;
822 	size_t cnt;
823 
824 	bool tab_possible = tab_prepare(sh, &cmd, &argv, &argc, &arg_idx,
825 					&d_entry);
826 
827 	if (tab_possible == false) {
828 		return;
829 	}
830 
831 	find_completion_candidates(sh, cmd, argv[arg_idx], &first, &cnt,
832 				   &longest);
833 
834 	if (cnt == 1) {
835 		/* Autocompletion.*/
836 		autocomplete(sh, cmd, argv[arg_idx], first);
837 	} else if (cnt > 1) {
838 		tab_options_print(sh, cmd, argv[arg_idx], first, cnt,
839 				  longest);
840 		partial_autocomplete(sh, cmd, argv[arg_idx], first, cnt);
841 	}
842 }
843 
alt_metakeys_handle(const struct shell * sh,char data)844 static void alt_metakeys_handle(const struct shell *sh, char data)
845 {
846 	/* Optional feature */
847 	if (!IS_ENABLED(CONFIG_SHELL_METAKEYS)) {
848 		return;
849 	}
850 	if (data == SHELL_VT100_ASCII_ALT_B) {
851 		z_shell_op_cursor_word_move(sh, -1);
852 	} else if (data == SHELL_VT100_ASCII_ALT_F) {
853 		z_shell_op_cursor_word_move(sh, 1);
854 	} else if (data == SHELL_VT100_ASCII_ALT_R &&
855 		   IS_ENABLED(CONFIG_SHELL_CMDS_SELECT)) {
856 		if (selected_cmd_get(sh) != NULL) {
857 			z_shell_cmd_line_erase(sh);
858 			z_shell_fprintf(sh, SHELL_WARNING,
859 					"Restored default root commands\n");
860 			if (CONFIG_SHELL_CMD_ROOT[0]) {
861 				sh->ctx->selected_cmd = root_cmd_find(CONFIG_SHELL_CMD_ROOT);
862 			} else {
863 				sh->ctx->selected_cmd = NULL;
864 			}
865 			z_shell_print_prompt_and_cmd(sh);
866 		}
867 	}
868 }
869 
ctrl_metakeys_handle(const struct shell * sh,char data)870 static void ctrl_metakeys_handle(const struct shell *sh, char data)
871 {
872 	/* Optional feature */
873 	if (!IS_ENABLED(CONFIG_SHELL_METAKEYS)) {
874 		return;
875 	}
876 
877 	switch (data) {
878 	case SHELL_VT100_ASCII_CTRL_A: /* CTRL + A */
879 		z_shell_op_cursor_home_move(sh);
880 		break;
881 
882 	case SHELL_VT100_ASCII_CTRL_B: /* CTRL + B */
883 		z_shell_op_left_arrow(sh);
884 		break;
885 
886 	case SHELL_VT100_ASCII_CTRL_C: /* CTRL + C */
887 		z_shell_op_cursor_end_move(sh);
888 		if (!z_shell_cursor_in_empty_line(sh)) {
889 			z_cursor_next_line_move(sh);
890 		}
891 		z_flag_history_exit_set(sh, true);
892 		state_set(sh, SHELL_STATE_ACTIVE);
893 		break;
894 
895 	case SHELL_VT100_ASCII_CTRL_D: /* CTRL + D */
896 		z_shell_op_char_delete(sh);
897 		break;
898 
899 	case SHELL_VT100_ASCII_CTRL_E: /* CTRL + E */
900 		z_shell_op_cursor_end_move(sh);
901 		break;
902 
903 	case SHELL_VT100_ASCII_CTRL_F: /* CTRL + F */
904 		z_shell_op_right_arrow(sh);
905 		break;
906 
907 	case SHELL_VT100_ASCII_CTRL_K: /* CTRL + K */
908 		z_shell_op_delete_from_cursor(sh);
909 		break;
910 
911 	case SHELL_VT100_ASCII_CTRL_L: /* CTRL + L */
912 		Z_SHELL_VT100_CMD(sh, SHELL_VT100_CURSORHOME);
913 		Z_SHELL_VT100_CMD(sh, SHELL_VT100_CLEARSCREEN);
914 		z_shell_print_prompt_and_cmd(sh);
915 		break;
916 
917 	case SHELL_VT100_ASCII_CTRL_N: /* CTRL + N */
918 		history_handle(sh, false);
919 		break;
920 
921 	case SHELL_VT100_ASCII_CTRL_P: /* CTRL + P */
922 		history_handle(sh, true);
923 		break;
924 
925 	case SHELL_VT100_ASCII_CTRL_U: /* CTRL + U */
926 		z_shell_op_cursor_home_move(sh);
927 		cmd_buffer_clear(sh);
928 		z_flag_history_exit_set(sh, true);
929 		z_clear_eos(sh);
930 		break;
931 
932 	case SHELL_VT100_ASCII_CTRL_W: /* CTRL + W */
933 		z_shell_op_word_remove(sh);
934 		z_flag_history_exit_set(sh, true);
935 		break;
936 
937 	default:
938 		break;
939 	}
940 }
941 
942 /* Functions returns true if new line character shall be processed */
process_nl(const struct shell * sh,uint8_t data)943 static bool process_nl(const struct shell *sh, uint8_t data)
944 {
945 	if ((data != '\r') && (data != '\n')) {
946 		z_flag_last_nl_set(sh, 0);
947 		return false;
948 	}
949 
950 	if ((z_flag_last_nl_get(sh) == 0U) ||
951 	    (data == z_flag_last_nl_get(sh))) {
952 		z_flag_last_nl_set(sh, data);
953 		return true;
954 	}
955 
956 	return false;
957 }
958 
959 #define SHELL_ASCII_MAX_CHAR (127u)
ascii_filter(const char data)960 static inline int ascii_filter(const char data)
961 {
962 	if (IS_ENABLED(CONFIG_SHELL_ASCII_FILTER)) {
963 		return (uint8_t) data > SHELL_ASCII_MAX_CHAR ? -EINVAL : 0;
964 	} else {
965 		return 0;
966 	}
967 }
968 
state_collect(const struct shell * sh)969 static void state_collect(const struct shell *sh)
970 {
971 	size_t count = 0;
972 	char data;
973 
974 	while (true) {
975 		shell_bypass_cb_t bypass = sh->ctx->bypass;
976 
977 		if (bypass) {
978 #if defined(CONFIG_SHELL_BACKEND_RTT) && defined(CONFIG_SEGGER_RTT_BUFFER_SIZE_DOWN)
979 			uint8_t buf[CONFIG_SEGGER_RTT_BUFFER_SIZE_DOWN];
980 #else
981 			uint8_t buf[16];
982 #endif
983 
984 			(void)sh->iface->api->read(sh->iface, buf,
985 							sizeof(buf), &count);
986 			if (count) {
987 				z_flag_cmd_ctx_set(sh, true);
988 				bypass(sh, buf, count);
989 				z_flag_cmd_ctx_set(sh, false);
990 				/* Check if bypass mode ended. */
991 				if (!(volatile shell_bypass_cb_t *)sh->ctx->bypass) {
992 					state_set(sh, SHELL_STATE_ACTIVE);
993 				} else {
994 					continue;
995 				}
996 			}
997 
998 			return;
999 		}
1000 
1001 		(void)sh->iface->api->read(sh->iface, &data,
1002 					      sizeof(data), &count);
1003 		if (count == 0) {
1004 			return;
1005 		}
1006 
1007 		if (ascii_filter(data) != 0) {
1008 			continue;
1009 		}
1010 
1011 		switch (sh->ctx->receive_state) {
1012 		case SHELL_RECEIVE_DEFAULT:
1013 			if (process_nl(sh, data)) {
1014 				if (!sh->ctx->cmd_buff_len) {
1015 					history_mode_exit(sh);
1016 					z_cursor_next_line_move(sh);
1017 				} else {
1018 					/* Command execution */
1019 					sh->ctx->ret_val = execute(sh);
1020 				}
1021 				/* Function responsible for printing prompt
1022 				 * on received NL.
1023 				 */
1024 				state_set(sh, SHELL_STATE_ACTIVE);
1025 				continue;
1026 			}
1027 
1028 			switch (data) {
1029 			case SHELL_VT100_ASCII_ESC: /* ESCAPE */
1030 				receive_state_change(sh, SHELL_RECEIVE_ESC);
1031 				break;
1032 
1033 			case '\0':
1034 				break;
1035 
1036 			case '\t': /* TAB */
1037 				if (z_flag_echo_get(sh) &&
1038 				    IS_ENABLED(CONFIG_SHELL_TAB)) {
1039 					/* If the Tab key is pressed, "history
1040 					 * mode" must be terminated because
1041 					 * tab and history handlers are sharing
1042 					 * the same array: temp_buff.
1043 					 */
1044 					z_flag_history_exit_set(sh, true);
1045 					tab_handle(sh);
1046 				}
1047 				break;
1048 
1049 			case SHELL_VT100_ASCII_BSPACE: /* BACKSPACE */
1050 				if (z_flag_echo_get(sh)) {
1051 					z_flag_history_exit_set(sh, true);
1052 					z_shell_op_char_backspace(sh);
1053 				}
1054 				break;
1055 
1056 			case SHELL_VT100_ASCII_DEL: /* DELETE */
1057 				if (z_flag_echo_get(sh)) {
1058 					z_flag_history_exit_set(sh, true);
1059 					if (z_flag_mode_delete_get(sh)) {
1060 						z_shell_op_char_backspace(sh);
1061 
1062 					} else {
1063 						z_shell_op_char_delete(sh);
1064 					}
1065 				}
1066 				break;
1067 
1068 			default:
1069 				if (isprint((int) data) != 0) {
1070 					z_flag_history_exit_set(sh, true);
1071 					z_shell_op_char_insert(sh, data);
1072 				} else if (z_flag_echo_get(sh)) {
1073 					ctrl_metakeys_handle(sh, data);
1074 				}
1075 				break;
1076 			}
1077 			break;
1078 
1079 		case SHELL_RECEIVE_ESC:
1080 			if (data == '[') {
1081 				receive_state_change(sh,
1082 						SHELL_RECEIVE_ESC_SEQ);
1083 				break;
1084 			} else if (z_flag_echo_get(sh)) {
1085 				alt_metakeys_handle(sh, data);
1086 			}
1087 			receive_state_change(sh, SHELL_RECEIVE_DEFAULT);
1088 			break;
1089 
1090 		case SHELL_RECEIVE_ESC_SEQ:
1091 			receive_state_change(sh, SHELL_RECEIVE_DEFAULT);
1092 
1093 			if (!z_flag_echo_get(sh)) {
1094 				continue;
1095 			}
1096 
1097 			switch (data) {
1098 			case 'A': /* UP arrow */
1099 				history_handle(sh, true);
1100 				break;
1101 
1102 			case 'B': /* DOWN arrow */
1103 				history_handle(sh, false);
1104 				break;
1105 
1106 			case 'C': /* RIGHT arrow */
1107 				z_shell_op_right_arrow(sh);
1108 				break;
1109 
1110 			case 'D': /* LEFT arrow */
1111 				z_shell_op_left_arrow(sh);
1112 				break;
1113 
1114 			case '4': /* END Button in ESC[n~ mode */
1115 				receive_state_change(sh,
1116 						SHELL_RECEIVE_TILDE_EXP);
1117 				__fallthrough;
1118 			case 'F': /* END Button in VT100 mode */
1119 				z_shell_op_cursor_end_move(sh);
1120 				break;
1121 
1122 			case '1': /* HOME Button in ESC[n~ mode */
1123 				receive_state_change(sh,
1124 						SHELL_RECEIVE_TILDE_EXP);
1125 				__fallthrough;
1126 			case 'H': /* HOME Button in VT100 mode */
1127 				z_shell_op_cursor_home_move(sh);
1128 				break;
1129 
1130 			case '2': /* INSERT Button in ESC[n~ mode */
1131 				receive_state_change(sh,
1132 						SHELL_RECEIVE_TILDE_EXP);
1133 				__fallthrough;
1134 			case 'L': {/* INSERT Button in VT100 mode */
1135 				bool status = z_flag_insert_mode_get(sh);
1136 
1137 				z_flag_insert_mode_set(sh, !status);
1138 				break;
1139 			}
1140 
1141 			case '3':/* DELETE Button in ESC[n~ mode */
1142 				receive_state_change(sh,
1143 						SHELL_RECEIVE_TILDE_EXP);
1144 				if (z_flag_echo_get(sh)) {
1145 					z_shell_op_char_delete(sh);
1146 				}
1147 				break;
1148 
1149 			default:
1150 				break;
1151 			}
1152 			break;
1153 
1154 		case SHELL_RECEIVE_TILDE_EXP:
1155 			receive_state_change(sh, SHELL_RECEIVE_DEFAULT);
1156 			break;
1157 
1158 		default:
1159 			receive_state_change(sh, SHELL_RECEIVE_DEFAULT);
1160 			break;
1161 		}
1162 
1163 		z_transport_buffer_flush(sh);
1164 	}
1165 }
1166 
transport_evt_handler(enum shell_transport_evt evt_type,void * ctx)1167 static void transport_evt_handler(enum shell_transport_evt evt_type, void *ctx)
1168 {
1169 	struct shell *sh = (struct shell *)ctx;
1170 	struct k_poll_signal *signal;
1171 
1172 	signal = (evt_type == SHELL_TRANSPORT_EVT_RX_RDY) ?
1173 			&sh->ctx->signals[SHELL_SIGNAL_RXRDY] :
1174 			&sh->ctx->signals[SHELL_SIGNAL_TXDONE];
1175 	k_poll_signal_raise(signal, 0);
1176 }
1177 
shell_log_process(const struct shell * sh)1178 static void shell_log_process(const struct shell *sh)
1179 {
1180 	bool processed = false;
1181 	int signaled = 0;
1182 	int result;
1183 
1184 	do {
1185 		if (!IS_ENABLED(CONFIG_LOG_MODE_IMMEDIATE)) {
1186 			z_shell_cmd_line_erase(sh);
1187 
1188 			processed = z_shell_log_backend_process(
1189 					sh->log_backend);
1190 		}
1191 
1192 		struct k_poll_signal *signal =
1193 			&sh->ctx->signals[SHELL_SIGNAL_RXRDY];
1194 
1195 		z_shell_print_prompt_and_cmd(sh);
1196 
1197 		/* Arbitrary delay added to ensure that prompt is
1198 		 * readable and can be used to enter further commands.
1199 		 */
1200 		if (sh->ctx->cmd_buff_len) {
1201 			k_sleep(K_MSEC(15));
1202 		}
1203 
1204 		k_poll_signal_check(signal, &signaled, &result);
1205 
1206 	} while (processed && !signaled);
1207 }
1208 
instance_init(const struct shell * sh,const void * transport_config,struct shell_backend_config_flags cfg_flags)1209 static int instance_init(const struct shell *sh,
1210 			 const void *transport_config,
1211 			 struct shell_backend_config_flags cfg_flags)
1212 {
1213 	__ASSERT_NO_MSG((sh->shell_flag == SHELL_FLAG_CRLF_DEFAULT) ||
1214 			(sh->shell_flag == SHELL_FLAG_OLF_CRLF));
1215 
1216 	memset(sh->ctx, 0, sizeof(*sh->ctx));
1217 	if (CONFIG_SHELL_CMD_ROOT[0]) {
1218 		sh->ctx->selected_cmd = root_cmd_find(CONFIG_SHELL_CMD_ROOT);
1219 	}
1220 
1221 	history_init(sh);
1222 
1223 	k_mutex_init(&sh->ctx->wr_mtx);
1224 
1225 	for (int i = 0; i < SHELL_SIGNALS; i++) {
1226 		k_poll_signal_init(&sh->ctx->signals[i]);
1227 		k_poll_event_init(&sh->ctx->events[i],
1228 				  K_POLL_TYPE_SIGNAL,
1229 				  K_POLL_MODE_NOTIFY_ONLY,
1230 				  &sh->ctx->signals[i]);
1231 	}
1232 
1233 	if (IS_ENABLED(CONFIG_SHELL_STATS)) {
1234 		sh->stats->log_lost_cnt = 0;
1235 	}
1236 
1237 	z_flag_tx_rdy_set(sh, true);
1238 
1239 	sh->ctx->vt100_ctx.cons.terminal_wid =
1240 					CONFIG_SHELL_DEFAULT_TERMINAL_WIDTH;
1241 	sh->ctx->vt100_ctx.cons.terminal_hei =
1242 					CONFIG_SHELL_DEFAULT_TERMINAL_HEIGHT;
1243 
1244 #if defined(CONFIG_SHELL_PROMPT_CHANGE) && CONFIG_SHELL_PROMPT_CHANGE
1245 	shell_prompt_change(sh, sh->default_prompt);
1246 #else
1247 	sh->ctx->prompt = sh->default_prompt;
1248 	sh->ctx->vt100_ctx.cons.name_len = z_shell_strlen(sh->ctx->prompt);
1249 #endif
1250 
1251 	/* Configure backend according to enabled shell features and backend
1252 	 * specific settings.
1253 	 */
1254 	cfg_flags.obscure     &= IS_ENABLED(CONFIG_SHELL_START_OBSCURED);
1255 	cfg_flags.use_colors  &= IS_ENABLED(CONFIG_SHELL_VT100_COLORS);
1256 	cfg_flags.use_vt100   &= IS_ENABLED(CONFIG_SHELL_VT100_COMMANDS);
1257 	cfg_flags.echo        &= IS_ENABLED(CONFIG_SHELL_ECHO_STATUS);
1258 	cfg_flags.mode_delete &= IS_ENABLED(CONFIG_SHELL_BACKSPACE_MODE_DELETE);
1259 	sh->ctx->cfg.flags = cfg_flags;
1260 
1261 	int ret = sh->iface->api->init(sh->iface, transport_config,
1262 				       transport_evt_handler,
1263 				       (void *)sh);
1264 	if (ret == 0) {
1265 		state_set(sh, SHELL_STATE_INITIALIZED);
1266 	}
1267 
1268 	return ret;
1269 }
1270 
instance_uninit(const struct shell * sh)1271 static int instance_uninit(const struct shell *sh)
1272 {
1273 	__ASSERT_NO_MSG(sh);
1274 	__ASSERT_NO_MSG(sh->ctx && sh->iface);
1275 
1276 	int err;
1277 
1278 	if (z_flag_processing_get(sh)) {
1279 		return -EBUSY;
1280 	}
1281 
1282 	if (IS_ENABLED(CONFIG_SHELL_LOG_BACKEND)) {
1283 		/* todo purge log queue */
1284 		z_shell_log_backend_disable(sh->log_backend);
1285 	}
1286 
1287 	err = sh->iface->api->uninit(sh->iface);
1288 	if (err != 0) {
1289 		return err;
1290 	}
1291 
1292 	history_purge(sh);
1293 	state_set(sh, SHELL_STATE_UNINITIALIZED);
1294 
1295 	return 0;
1296 }
1297 
1298 typedef void (*shell_signal_handler_t)(const struct shell *sh);
1299 
shell_signal_handle(const struct shell * sh,enum shell_signal sig_idx,shell_signal_handler_t handler)1300 static void shell_signal_handle(const struct shell *sh,
1301 				enum shell_signal sig_idx,
1302 				shell_signal_handler_t handler)
1303 {
1304 	struct k_poll_signal *sig = &sh->ctx->signals[sig_idx];
1305 	int set;
1306 	int res;
1307 
1308 	k_poll_signal_check(sig, &set, &res);
1309 
1310 	if (set) {
1311 		k_poll_signal_reset(sig);
1312 		handler(sh);
1313 	}
1314 }
1315 
kill_handler(const struct shell * sh)1316 static void kill_handler(const struct shell *sh)
1317 {
1318 	int err = instance_uninit(sh);
1319 
1320 	if (sh->ctx->uninit_cb) {
1321 		sh->ctx->uninit_cb(sh, err);
1322 	}
1323 
1324 	sh->ctx->tid = NULL;
1325 	k_thread_abort(k_current_get());
1326 
1327 	CODE_UNREACHABLE;
1328 }
1329 
shell_thread(void * shell_handle,void * arg_log_backend,void * arg_log_level)1330 void shell_thread(void *shell_handle, void *arg_log_backend,
1331 		  void *arg_log_level)
1332 {
1333 	struct shell *sh = shell_handle;
1334 	int err;
1335 
1336 	z_flag_handle_log_set(sh, (bool)arg_log_backend);
1337 	sh->ctx->log_level = POINTER_TO_UINT(arg_log_level);
1338 
1339 	err = sh->iface->api->enable(sh->iface, false);
1340 	if (err != 0) {
1341 		return;
1342 	}
1343 
1344 	if (IS_ENABLED(CONFIG_SHELL_AUTOSTART)) {
1345 		/* Enable shell and print prompt. */
1346 		err = shell_start(sh);
1347 		if (err != 0) {
1348 			return;
1349 		}
1350 	}
1351 
1352 	while (true) {
1353 		/* waiting for all signals except SHELL_SIGNAL_TXDONE */
1354 		err = k_poll(sh->ctx->events, SHELL_SIGNAL_TXDONE,
1355 			     K_FOREVER);
1356 
1357 		if (err != 0) {
1358 			if (k_mutex_lock(&sh->ctx->wr_mtx, K_MSEC(SHELL_TX_MTX_TIMEOUT_MS)) != 0) {
1359 				return;
1360 			}
1361 			z_shell_fprintf(sh, SHELL_ERROR,
1362 					"Shell thread error: %d", err);
1363 			k_mutex_unlock(&sh->ctx->wr_mtx);
1364 			return;
1365 		}
1366 
1367 		k_mutex_lock(&sh->ctx->wr_mtx, K_FOREVER);
1368 
1369 		shell_signal_handle(sh, SHELL_SIGNAL_KILL, kill_handler);
1370 		shell_signal_handle(sh, SHELL_SIGNAL_RXRDY, shell_process);
1371 		if (IS_ENABLED(CONFIG_SHELL_LOG_BACKEND)) {
1372 			shell_signal_handle(sh, SHELL_SIGNAL_LOG_MSG,
1373 					    shell_log_process);
1374 		}
1375 
1376 		if (sh->iface->api->update) {
1377 			sh->iface->api->update(sh->iface);
1378 		}
1379 
1380 		k_mutex_unlock(&sh->ctx->wr_mtx);
1381 	}
1382 }
1383 
shell_init(const struct shell * sh,const void * transport_config,struct shell_backend_config_flags cfg_flags,bool log_backend,uint32_t init_log_level)1384 int shell_init(const struct shell *sh, const void *transport_config,
1385 	       struct shell_backend_config_flags cfg_flags,
1386 	       bool log_backend, uint32_t init_log_level)
1387 {
1388 	__ASSERT_NO_MSG(sh);
1389 	__ASSERT_NO_MSG(sh->ctx && sh->iface && sh->default_prompt);
1390 
1391 	if (sh->ctx->tid) {
1392 		return -EALREADY;
1393 	}
1394 
1395 	int err = instance_init(sh, transport_config, cfg_flags);
1396 
1397 	if (err != 0) {
1398 		return err;
1399 	}
1400 
1401 	k_tid_t tid = k_thread_create(sh->thread,
1402 				  sh->stack, CONFIG_SHELL_STACK_SIZE,
1403 				  shell_thread, (void *)sh, (void *)log_backend,
1404 				  UINT_TO_POINTER(init_log_level),
1405 				  SHELL_THREAD_PRIORITY, 0, K_NO_WAIT);
1406 
1407 	sh->ctx->tid = tid;
1408 	k_thread_name_set(tid, sh->name);
1409 
1410 	return 0;
1411 }
1412 
shell_uninit(const struct shell * sh,shell_uninit_cb_t cb)1413 void shell_uninit(const struct shell *sh, shell_uninit_cb_t cb)
1414 {
1415 	__ASSERT_NO_MSG(sh);
1416 
1417 	if (IS_ENABLED(CONFIG_MULTITHREADING)) {
1418 		struct k_poll_signal *signal =
1419 				&sh->ctx->signals[SHELL_SIGNAL_KILL];
1420 
1421 		sh->ctx->uninit_cb = cb;
1422 		/* signal kill message */
1423 		(void)k_poll_signal_raise(signal, 0);
1424 
1425 		return;
1426 	}
1427 
1428 	int err = instance_uninit(sh);
1429 
1430 	if (cb) {
1431 		cb(sh, err);
1432 	} else {
1433 		__ASSERT_NO_MSG(0);
1434 	}
1435 }
1436 
shell_start(const struct shell * sh)1437 int shell_start(const struct shell *sh)
1438 {
1439 	__ASSERT_NO_MSG(sh);
1440 	__ASSERT_NO_MSG(sh->ctx && sh->iface && sh->default_prompt);
1441 
1442 	if (state_get(sh) != SHELL_STATE_INITIALIZED) {
1443 		return -ENOTSUP;
1444 	}
1445 
1446 	if (IS_ENABLED(CONFIG_SHELL_LOG_BACKEND) && z_flag_handle_log_get(sh)
1447 	    && !z_flag_obscure_get(sh)) {
1448 		z_shell_log_backend_enable(sh->log_backend, (void *)sh, sh->ctx->log_level);
1449 	}
1450 
1451 	if (k_mutex_lock(&sh->ctx->wr_mtx, K_MSEC(SHELL_TX_MTX_TIMEOUT_MS)) != 0) {
1452 		return -EBUSY;
1453 	}
1454 
1455 	if (IS_ENABLED(CONFIG_SHELL_VT100_COLORS)) {
1456 		z_shell_vt100_color_set(sh, SHELL_NORMAL);
1457 	}
1458 
1459 	/* print new line before printing the prompt to clear the line
1460 	 * vt100 are not used here for compatibility reasons
1461 	 */
1462 	z_cursor_next_line_move(sh);
1463 	state_set(sh, SHELL_STATE_ACTIVE);
1464 
1465 	/*
1466 	 * If the shell is stopped with the shell_stop function, its backend remains active
1467 	 * and continues to buffer incoming data. As a result, when the shell is resumed,
1468 	 * all buffered data is processed, which may lead to the execution of commands
1469 	 * received while the shell was stopped.
1470 	 */
1471 	z_shell_backend_rx_buffer_flush(sh);
1472 
1473 	k_mutex_unlock(&sh->ctx->wr_mtx);
1474 
1475 	return 0;
1476 }
1477 
shell_stop(const struct shell * sh)1478 int shell_stop(const struct shell *sh)
1479 {
1480 	__ASSERT_NO_MSG(sh);
1481 	__ASSERT_NO_MSG(sh->ctx);
1482 
1483 	enum shell_state state = state_get(sh);
1484 
1485 	if ((state == SHELL_STATE_INITIALIZED) ||
1486 	    (state == SHELL_STATE_UNINITIALIZED)) {
1487 		return -ENOTSUP;
1488 	}
1489 
1490 	state_set(sh, SHELL_STATE_INITIALIZED);
1491 
1492 	if (IS_ENABLED(CONFIG_SHELL_LOG_BACKEND)) {
1493 		z_shell_log_backend_disable(sh->log_backend);
1494 	}
1495 
1496 	return 0;
1497 }
1498 
shell_process(const struct shell * sh)1499 void shell_process(const struct shell *sh)
1500 {
1501 	__ASSERT_NO_MSG(sh);
1502 	__ASSERT_NO_MSG(sh->ctx);
1503 
1504 	/* atomically set the processing flag */
1505 	z_flag_processing_set(sh, true);
1506 
1507 	switch (sh->ctx->state) {
1508 	case SHELL_STATE_UNINITIALIZED:
1509 	case SHELL_STATE_INITIALIZED:
1510 		/* Console initialized but not started. */
1511 		break;
1512 
1513 	case SHELL_STATE_ACTIVE:
1514 		state_collect(sh);
1515 		break;
1516 	default:
1517 		break;
1518 	}
1519 
1520 	/* atomically clear the processing flag */
1521 	z_flag_processing_set(sh, false);
1522 }
1523 
shell_backend_get_by_name(const char * backend_name)1524 const struct shell *shell_backend_get_by_name(const char *backend_name)
1525 {
1526 	STRUCT_SECTION_FOREACH(shell, backend) {
1527 		if (strcmp(backend_name, backend->name) == 0) {
1528 			return backend;
1529 		}
1530 	}
1531 
1532 	return NULL;
1533 }
1534 
1535 /* This function mustn't be used from shell context to avoid deadlock.
1536  * However it can be used in shell command handlers.
1537  */
shell_vfprintf(const struct shell * sh,enum shell_vt100_color color,const char * fmt,va_list args)1538 void shell_vfprintf(const struct shell *sh, enum shell_vt100_color color,
1539 		   const char *fmt, va_list args)
1540 {
1541 	__ASSERT_NO_MSG(sh);
1542 	__ASSERT(!k_is_in_isr(), "Thread context required.");
1543 	__ASSERT_NO_MSG(sh->ctx);
1544 	__ASSERT_NO_MSG(z_flag_cmd_ctx_get(sh) ||
1545 			(k_current_get() != sh->ctx->tid));
1546 	__ASSERT_NO_MSG(sh->fprintf_ctx);
1547 	__ASSERT_NO_MSG(fmt);
1548 
1549 	/* Sending a message to a non-active shell leads to a dead lock. */
1550 	if (state_get(sh) != SHELL_STATE_ACTIVE) {
1551 		z_flag_print_noinit_set(sh, true);
1552 		return;
1553 	}
1554 
1555 	if (k_mutex_lock(&sh->ctx->wr_mtx, K_MSEC(SHELL_TX_MTX_TIMEOUT_MS)) != 0) {
1556 		return;
1557 	}
1558 
1559 	if (!z_flag_cmd_ctx_get(sh) && !sh->ctx->bypass && z_flag_use_vt100_get(sh)) {
1560 		z_shell_cmd_line_erase(sh);
1561 	}
1562 	z_shell_vfprintf(sh, color, fmt, args);
1563 	if (!z_flag_cmd_ctx_get(sh) && !sh->ctx->bypass && z_flag_use_vt100_get(sh)) {
1564 		z_shell_print_prompt_and_cmd(sh);
1565 	}
1566 	z_transport_buffer_flush(sh);
1567 
1568 	k_mutex_unlock(&sh->ctx->wr_mtx);
1569 }
1570 
1571 /* These functions mustn't be used from shell context to avoid deadlock:
1572  * - shell_fprintf_impl
1573  * - shell_fprintf_info
1574  * - shell_fprintf_normal
1575  * - shell_fprintf_warn
1576  * - shell_fprintf_error
1577  * However, they can be used in shell command handlers.
1578  */
shell_fprintf_impl(const struct shell * sh,enum shell_vt100_color color,const char * fmt,...)1579 void shell_fprintf_impl(const struct shell *sh, enum shell_vt100_color color,
1580 		   const char *fmt, ...)
1581 {
1582 	va_list args;
1583 
1584 	va_start(args, fmt);
1585 	shell_vfprintf(sh, color, fmt, args);
1586 	va_end(args);
1587 }
1588 
shell_fprintf_info(const struct shell * sh,const char * fmt,...)1589 void shell_fprintf_info(const struct shell *sh, const char *fmt, ...)
1590 {
1591 	va_list args;
1592 
1593 	va_start(args, fmt);
1594 	shell_vfprintf(sh, SHELL_INFO, fmt, args);
1595 	va_end(args);
1596 }
1597 
shell_fprintf_normal(const struct shell * sh,const char * fmt,...)1598 void shell_fprintf_normal(const struct shell *sh, const char *fmt, ...)
1599 {
1600 	va_list args;
1601 
1602 	va_start(args, fmt);
1603 	shell_vfprintf(sh, SHELL_NORMAL, fmt, args);
1604 	va_end(args);
1605 }
1606 
shell_fprintf_warn(const struct shell * sh,const char * fmt,...)1607 void shell_fprintf_warn(const struct shell *sh, const char *fmt, ...)
1608 {
1609 	va_list args;
1610 
1611 	va_start(args, fmt);
1612 	shell_vfprintf(sh, SHELL_WARNING, fmt, args);
1613 	va_end(args);
1614 }
1615 
shell_fprintf_error(const struct shell * sh,const char * fmt,...)1616 void shell_fprintf_error(const struct shell *sh, const char *fmt, ...)
1617 {
1618 	va_list args;
1619 
1620 	va_start(args, fmt);
1621 	shell_vfprintf(sh, SHELL_ERROR, fmt, args);
1622 	va_end(args);
1623 }
1624 
shell_hexdump_line(const struct shell * sh,unsigned int offset,const uint8_t * data,size_t len)1625 void shell_hexdump_line(const struct shell *sh, unsigned int offset,
1626 			const uint8_t *data, size_t len)
1627 {
1628 	__ASSERT_NO_MSG(sh);
1629 
1630 	int i;
1631 
1632 	shell_fprintf_normal(sh, "%08X: ", offset);
1633 
1634 	for (i = 0; i < SHELL_HEXDUMP_BYTES_IN_LINE; i++) {
1635 		if (i > 0 && !(i % 8)) {
1636 			shell_fprintf_normal(sh, " ");
1637 		}
1638 
1639 		if (i < len) {
1640 			shell_fprintf_normal(sh, "%02x ",
1641 					     data[i] & 0xFF);
1642 		} else {
1643 			shell_fprintf_normal(sh, "   ");
1644 		}
1645 	}
1646 
1647 	shell_fprintf_normal(sh, "|");
1648 
1649 	for (i = 0; i < SHELL_HEXDUMP_BYTES_IN_LINE; i++) {
1650 		if (i > 0 && !(i % 8)) {
1651 			shell_fprintf_normal(sh, " ");
1652 		}
1653 
1654 		if (i < len) {
1655 			char c = data[i];
1656 
1657 			shell_fprintf_normal(sh, "%c",
1658 					     isprint((int)c) != 0 ? c : '.');
1659 		} else {
1660 			shell_fprintf_normal(sh, " ");
1661 		}
1662 	}
1663 
1664 	shell_print(sh, "|");
1665 }
1666 
shell_hexdump(const struct shell * sh,const uint8_t * data,size_t len)1667 void shell_hexdump(const struct shell *sh, const uint8_t *data, size_t len)
1668 {
1669 	__ASSERT_NO_MSG(sh);
1670 
1671 	const uint8_t *p = data;
1672 	size_t line_len;
1673 
1674 	while (len) {
1675 		line_len = MIN(len, SHELL_HEXDUMP_BYTES_IN_LINE);
1676 
1677 		shell_hexdump_line(sh, p - data, p, line_len);
1678 
1679 		len -= line_len;
1680 		p += line_len;
1681 	}
1682 }
1683 
shell_prompt_change(const struct shell * sh,const char * prompt)1684 int shell_prompt_change(const struct shell *sh, const char *prompt)
1685 {
1686 #if defined(CONFIG_SHELL_PROMPT_CHANGE) && CONFIG_SHELL_PROMPT_CHANGE
1687 	__ASSERT_NO_MSG(sh);
1688 
1689 	if (prompt == NULL) {
1690 		return -EINVAL;
1691 	}
1692 
1693 	size_t prompt_length = z_shell_strlen(prompt);
1694 
1695 	if (k_mutex_lock(&sh->ctx->wr_mtx, K_MSEC(SHELL_TX_MTX_TIMEOUT_MS)) != 0) {
1696 		return -EBUSY;
1697 	}
1698 
1699 	if ((prompt_length + 1 > CONFIG_SHELL_PROMPT_BUFF_SIZE) || (prompt_length == 0)) {
1700 		k_mutex_unlock(&sh->ctx->wr_mtx);
1701 		return -EINVAL;
1702 	}
1703 
1704 	strcpy(sh->ctx->prompt, prompt);
1705 
1706 	sh->ctx->vt100_ctx.cons.name_len = prompt_length;
1707 
1708 	k_mutex_unlock(&sh->ctx->wr_mtx);
1709 
1710 	return 0;
1711 #else
1712 	return -EPERM;
1713 #endif
1714 }
1715 
shell_help(const struct shell * sh)1716 void shell_help(const struct shell *sh)
1717 {
1718 	if (k_mutex_lock(&sh->ctx->wr_mtx, K_MSEC(SHELL_TX_MTX_TIMEOUT_MS)) != 0) {
1719 		return;
1720 	}
1721 	shell_internal_help_print(sh);
1722 	k_mutex_unlock(&sh->ctx->wr_mtx);
1723 }
1724 
shell_execute_cmd(const struct shell * sh,const char * cmd)1725 int shell_execute_cmd(const struct shell *sh, const char *cmd)
1726 {
1727 	uint16_t cmd_len = z_shell_strlen(cmd);
1728 	int ret_val;
1729 
1730 	if (cmd == NULL) {
1731 		return -ENOEXEC;
1732 	}
1733 
1734 	if (cmd_len > (CONFIG_SHELL_CMD_BUFF_SIZE - 1)) {
1735 		return -ENOMEM;
1736 	}
1737 
1738 	if (sh == NULL) {
1739 #if defined(CONFIG_SHELL_BACKEND_DUMMY)
1740 		sh = shell_backend_dummy_get_ptr();
1741 #else
1742 		return -EINVAL;
1743 #endif
1744 	}
1745 
1746 	__ASSERT(!z_flag_cmd_ctx_get(sh), "Function cannot be called"
1747 					  " from command context");
1748 
1749 	strcpy(sh->ctx->cmd_buff, cmd);
1750 	sh->ctx->cmd_buff_len = cmd_len;
1751 	sh->ctx->cmd_buff_pos = cmd_len;
1752 
1753 	if (k_mutex_lock(&sh->ctx->wr_mtx, K_MSEC(SHELL_TX_MTX_TIMEOUT_MS)) != 0) {
1754 		return -ENOEXEC;
1755 	}
1756 	ret_val = execute(sh);
1757 	k_mutex_unlock(&sh->ctx->wr_mtx);
1758 
1759 	cmd_buffer_clear(sh);
1760 
1761 	return ret_val;
1762 }
1763 
shell_insert_mode_set(const struct shell * sh,bool val)1764 int shell_insert_mode_set(const struct shell *sh, bool val)
1765 {
1766 	if (sh == NULL) {
1767 		return -EINVAL;
1768 	}
1769 
1770 	return (int)z_flag_insert_mode_set(sh, val);
1771 }
1772 
shell_use_colors_set(const struct shell * sh,bool val)1773 int shell_use_colors_set(const struct shell *sh, bool val)
1774 {
1775 	if (sh == NULL) {
1776 		return -EINVAL;
1777 	}
1778 
1779 	return (int)z_flag_use_colors_set(sh, val);
1780 }
1781 
shell_use_vt100_set(const struct shell * sh,bool val)1782 int shell_use_vt100_set(const struct shell *sh, bool val)
1783 {
1784 	if (sh == NULL) {
1785 		return -EINVAL;
1786 	}
1787 
1788 	return (int)z_flag_use_vt100_set(sh, val);
1789 }
1790 
shell_get_return_value(const struct shell * sh)1791 int shell_get_return_value(const struct shell *sh)
1792 {
1793 	if (sh == NULL) {
1794 		return -EINVAL;
1795 	}
1796 
1797 	return z_shell_get_return_value(sh);
1798 }
1799 
shell_echo_set(const struct shell * sh,bool val)1800 int shell_echo_set(const struct shell *sh, bool val)
1801 {
1802 	if (sh == NULL) {
1803 		return -EINVAL;
1804 	}
1805 
1806 	return (int)z_flag_echo_set(sh, val);
1807 }
1808 
shell_obscure_set(const struct shell * sh,bool val)1809 int shell_obscure_set(const struct shell *sh, bool val)
1810 {
1811 	if (sh == NULL) {
1812 		return -EINVAL;
1813 	}
1814 
1815 	return (int)z_flag_obscure_set(sh, val);
1816 }
1817 
shell_mode_delete_set(const struct shell * sh,bool val)1818 int shell_mode_delete_set(const struct shell *sh, bool val)
1819 {
1820 	if (sh == NULL) {
1821 		return -EINVAL;
1822 	}
1823 
1824 	return (int)z_flag_mode_delete_set(sh, val);
1825 }
1826 
shell_set_bypass(const struct shell * sh,shell_bypass_cb_t bypass)1827 void shell_set_bypass(const struct shell *sh, shell_bypass_cb_t bypass)
1828 {
1829 	__ASSERT_NO_MSG(sh);
1830 
1831 	sh->ctx->bypass = bypass;
1832 
1833 	if (bypass == NULL) {
1834 		cmd_buffer_clear(sh);
1835 	}
1836 }
1837 
shell_ready(const struct shell * sh)1838 bool shell_ready(const struct shell *sh)
1839 {
1840 	__ASSERT_NO_MSG(sh);
1841 
1842 	return state_get(sh) ==	SHELL_STATE_ACTIVE;
1843 }
1844 
cmd_help(const struct shell * sh,size_t argc,char ** argv)1845 static int cmd_help(const struct shell *sh, size_t argc, char **argv)
1846 {
1847 	ARG_UNUSED(argc);
1848 	ARG_UNUSED(argv);
1849 
1850 #if defined(CONFIG_SHELL_TAB)
1851 	shell_print(sh, "Please press the <Tab> button to see all available "
1852 			   "commands.");
1853 #endif
1854 
1855 #if defined(CONFIG_SHELL_TAB_AUTOCOMPLETION)
1856 	shell_print(sh,
1857 		"You can also use the <Tab> button to prompt or auto-complete"
1858 		" all commands or its subcommands.");
1859 #endif
1860 
1861 #if defined(CONFIG_SHELL_HELP)
1862 	shell_print(sh,
1863 		"You can try to call commands with <-h> or <--help> parameter"
1864 		" for more information.");
1865 #endif
1866 
1867 #if defined(CONFIG_SHELL_METAKEYS)
1868 	shell_print(sh,
1869 		"\nShell supports following meta-keys:\n"
1870 		"  Ctrl + (a key from: abcdefklnpuw)\n"
1871 		"  Alt  + (a key from: bf)\n"
1872 		"Please refer to shell documentation for more details.");
1873 #endif
1874 
1875 	if (IS_ENABLED(CONFIG_SHELL_HELP)) {
1876 		/* For NULL argument function will print all root commands */
1877 		z_shell_help_subcmd_print(sh, NULL,
1878 					 "\nAvailable commands:\n");
1879 	} else {
1880 		const struct shell_static_entry *entry;
1881 		size_t idx = 0;
1882 
1883 		shell_print(sh, "\nAvailable commands:");
1884 		while ((entry = z_shell_cmd_get(NULL, idx++, NULL)) != NULL) {
1885 			shell_print(sh, "  %s", entry->syntax);
1886 		}
1887 	}
1888 
1889 	return 0;
1890 }
1891 
1892 SHELL_CMD_ARG_REGISTER(help, NULL, "Prints the help message.", cmd_help, 1, 0);
1893