msh.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /*
  2. * RT-Thread module shell implementation.
  3. *
  4. * COPYRIGHT (C) 2013, Shanghai Real-Thread Technology Co., Ltd
  5. *
  6. * This file is part of RT-Thread (http://www.rt-thread.org)
  7. * Maintainer: bernard.xiong <bernard.xiong at gmail.com>
  8. *
  9. * All rights reserved.
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License along
  22. * with this program; if not, write to the Free Software Foundation, Inc.,
  23. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  24. *
  25. * Change Logs:
  26. * Date Author Notes
  27. * 2013-03-30 Bernard the first verion for FinSH
  28. */
  29. #include "msh.h"
  30. #include <finsh.h>
  31. #include <shell.h>
  32. #define RT_FINSH_ARG_MAX 10
  33. typedef int (*cmd_function_t)(int argc, char** argv);
  34. #ifdef FINSH_USING_MSH
  35. #ifdef FINSH_USING_MSH_DEFAULT
  36. static rt_bool_t __msh_state = RT_TRUE;
  37. #else
  38. static rt_bool_t __msh_state = RT_FALSE;
  39. #endif
  40. rt_bool_t msh_is_used(void)
  41. {
  42. return __msh_state;
  43. }
  44. static int msh_exit(int argc, char** argv)
  45. {
  46. /* return to finsh shell mode */
  47. __msh_state = RT_FALSE;
  48. return 0;
  49. }
  50. FINSH_FUNCTION_EXPORT_ALIAS(msh_exit, __cmd_exit, return to RT-Thread shell mode.);
  51. static int msh_enter(void)
  52. {
  53. /* enter module shell mode */
  54. __msh_state = RT_TRUE;
  55. return 0;
  56. }
  57. FINSH_FUNCTION_EXPORT_ALIAS(msh_enter, msh, use module shell);
  58. int msh_help(int argc, char** argv)
  59. {
  60. rt_kprintf("RT-Thread shell commands:\n");
  61. {
  62. struct finsh_syscall *index;
  63. for (index = _syscall_table_begin;
  64. index < _syscall_table_end;
  65. FINSH_NEXT_SYSCALL(index))
  66. {
  67. if (strncmp(index->name, "__cmd_", 6) != 0) continue;
  68. rt_kprintf("%s ", &index->name[6]);
  69. }
  70. }
  71. rt_kprintf("\n");
  72. return 0;
  73. }
  74. FINSH_FUNCTION_EXPORT_ALIAS(msh_help, __cmd_help, "RT-Thread shell help.");
  75. static int msh_split(char* cmd, rt_size_t length, char* argv[RT_FINSH_ARG_MAX])
  76. {
  77. char *ptr;
  78. rt_size_t position;
  79. rt_size_t argc;
  80. ptr = cmd;
  81. position = 0; argc = 0;
  82. while (position < length)
  83. {
  84. /* strip bank and tab */
  85. while ((*ptr == ' ' || *ptr == '\t') && position < length)
  86. {
  87. *ptr = '\0';
  88. ptr ++; position ++;
  89. }
  90. if (position >= length) break;
  91. /* handle string */
  92. if (*ptr == '"')
  93. {
  94. ptr ++; position ++;
  95. argv[argc] = ptr; argc ++;
  96. /* skip this string */
  97. while (*ptr != '"' && position < length)
  98. {
  99. if (*ptr == '\\')
  100. {
  101. if (*(ptr + 1) == '"')
  102. {
  103. ptr ++; position ++;
  104. }
  105. }
  106. ptr ++; position ++;
  107. }
  108. if (position >= length) break;
  109. /* skip '"' */
  110. *ptr = '\0'; ptr ++; position ++;
  111. }
  112. else
  113. {
  114. argv[argc] = ptr;
  115. argc ++;
  116. while ((*ptr != ' ' && *ptr != '\t') && position < length)
  117. {
  118. ptr ++; position ++;
  119. }
  120. if (position >= length) break;
  121. }
  122. }
  123. return argc;
  124. }
  125. static cmd_function_t msh_get_cmd(char *cmd)
  126. {
  127. struct finsh_syscall *index;
  128. cmd_function_t cmd_func = RT_NULL;
  129. for (index = _syscall_table_begin;
  130. index < _syscall_table_end;
  131. FINSH_NEXT_SYSCALL(index))
  132. {
  133. if (strncmp(index->name, "__cmd_", 6) != 0) continue;
  134. if (strcmp(&index->name[6], cmd) == 0)
  135. {
  136. cmd_func = (cmd_function_t)index->func;
  137. break;
  138. }
  139. }
  140. return cmd_func;
  141. }
  142. int msh_exec(char* cmd, rt_size_t length)
  143. {
  144. int argc;
  145. char *argv[RT_FINSH_ARG_MAX];
  146. cmd_function_t cmd_func;
  147. memset(argv, 0x00, sizeof(argv));
  148. argc = msh_split(cmd, length, argv);
  149. if (argc == 0) return -1;
  150. /* get command in internal commands */
  151. cmd_func = msh_get_cmd(argv[0]);
  152. if (cmd_func == RT_NULL)
  153. {
  154. rt_kprintf("%s: command not found\n", argv[0]);
  155. return -1;
  156. }
  157. /* exec this command */
  158. return cmd_func(argc, argv);
  159. }
  160. static int str_common(const char *str1, const char *str2)
  161. {
  162. const char *str = str1;
  163. while ((*str != 0) && (*str2 != 0) && (*str == *str2))
  164. {
  165. str ++;
  166. str2 ++;
  167. }
  168. return (str - str1);
  169. }
  170. void msh_auto_complete(char *prefix)
  171. {
  172. rt_uint16_t func_cnt;
  173. int length, min_length;
  174. const char *name_ptr, *cmd_name;
  175. struct finsh_syscall *index;
  176. func_cnt = 0;
  177. min_length = 0;
  178. name_ptr = RT_NULL;
  179. if (*prefix == '\0')
  180. {
  181. msh_help(0, RT_NULL);
  182. return;
  183. }
  184. /* checks in internal command */
  185. {
  186. for (index = _syscall_table_begin; index < _syscall_table_end; FINSH_NEXT_SYSCALL(index))
  187. {
  188. /* skip finsh shell function */
  189. if (strncmp(index->name, "__cmd_", 6) != 0) continue;
  190. cmd_name = (const char*) &index->name[6];
  191. if (strncmp(prefix, cmd_name, strlen(prefix)) == 0)
  192. {
  193. if (func_cnt == 0)
  194. {
  195. /* set name_ptr */
  196. name_ptr = cmd_name;
  197. /* set initial length */
  198. min_length = strlen(name_ptr);
  199. }
  200. func_cnt ++;
  201. length = str_common(name_ptr, cmd_name);
  202. if (length < min_length)
  203. min_length = length;
  204. rt_kprintf("%s\n", cmd_name);
  205. }
  206. }
  207. }
  208. /* auto complete string */
  209. if (name_ptr != NULL)
  210. {
  211. rt_strncpy(prefix, name_ptr, min_length);
  212. }
  213. return ;
  214. }
  215. #endif