shell.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. #include "cmd.h"
  2. #include <libKeyboard/keyboard.h>
  3. #include <libc/src/fcntl.h>
  4. #include <libc/src/printf.h>
  5. #include <libc/src/stddef.h>
  6. #include <libc/src/stdio.h>
  7. #include <libc/src/stdlib.h>
  8. #include <libc/src/string.h>
  9. #include <libc/src/sys/stat.h>
  10. #include <libc/src/unistd.h>
  11. #define pause_cpu() asm volatile("pause\n\t");
  12. #define MEM_HISTORY 1024
  13. /**
  14. * @brief 循环读取每一行
  15. *
  16. * @param fd 键盘文件描述符
  17. * @param buf 输入缓冲区
  18. * @return 读取的字符数
  19. */
  20. int shell_readline(int fd, char *buf);
  21. void print_ascii_logo();
  22. extern char *shell_current_path;
  23. //保存的历史命令(瞬时更改)
  24. char history_commands[MEM_HISTORY][INPUT_BUFFER_SIZE];
  25. //真正的历史命令
  26. char real_history_commands[MEM_HISTORY][INPUT_BUFFER_SIZE];
  27. int count_history;
  28. //现在对应的命令
  29. int current_command_index;
  30. /**
  31. * @brief shell主循环
  32. *
  33. * @param kb_fd 键盘文件描述符
  34. */
  35. void main_loop(int kb_fd)
  36. {
  37. count_history = 0;
  38. current_command_index = 0;
  39. unsigned char input_buffer[INPUT_BUFFER_SIZE] = {0};
  40. // 初始化当前工作目录的路径
  41. shell_current_path = (char *)malloc(3);
  42. memset(shell_current_path, 0, 3);
  43. shell_current_path[0] = '/';
  44. shell_current_path[1] = '\0';
  45. // shell命令行的主循环
  46. while (true)
  47. {
  48. int argc = 0;
  49. char **argv;
  50. printf("[DragonOS] %s # ", shell_current_path);
  51. memset(input_buffer, 0, INPUT_BUFFER_SIZE);
  52. //添加初始光标
  53. put_string(" ", COLOR_BLACK, COLOR_WHITE);
  54. // 循环读取每一行到buffer
  55. count_history++;
  56. int count = shell_readline(kb_fd, input_buffer);
  57. if (!count || current_command_index < count_history - 1)
  58. count_history--;
  59. if (count)
  60. {
  61. strcpy(real_history_commands[count_history - 1], input_buffer);
  62. count_history++;
  63. memset(history_commands, 0, sizeof(history_commands));
  64. for (int i = 0; i <= count_history - 2; i++)
  65. strcpy(history_commands[i], real_history_commands[i]);
  66. current_command_index = count_history - 1;
  67. }
  68. if (count)
  69. {
  70. char command_origin[strlen(input_buffer)];
  71. strcpy(command_origin, input_buffer);
  72. int cmd_num = parse_command(input_buffer, &argc, &argv);
  73. printf("\n");
  74. if (cmd_num >= 0)
  75. shell_run_built_in_command(cmd_num, argc, argv);
  76. }
  77. else
  78. printf("\n");
  79. }
  80. }
  81. int main()
  82. {
  83. // 打开键盘文件
  84. char kb_file_path[] = "/dev/char/ps2.kb0";
  85. int kb_fd = open(kb_file_path, 0);
  86. print_ascii_logo();
  87. // printf("before mkdir\n");
  88. // mkdir("/aaac", 0);
  89. // printf("after mkdir\n");
  90. main_loop(kb_fd);
  91. while (1)
  92. ;
  93. }
  94. /**
  95. * @brief 清除缓冲区
  96. *
  97. * @param count 缓冲区大小
  98. * @param buf 缓冲区内容
  99. */
  100. void clear_command(int count, char *buf)
  101. {
  102. for (int i = 0; i < count; i++)
  103. printf("%c", '\b');
  104. memset(buf, 0, sizeof(buf));
  105. }
  106. /**
  107. * @brief 切换命令(写入到缓冲区)
  108. *
  109. * @param buf 缓冲区
  110. * @param type 如果为1,就向上,如果为-1,就向下
  111. */
  112. void change_command(char *buf, int type)
  113. {
  114. current_command_index -= type;
  115. //处理边界
  116. if (current_command_index < 0)
  117. current_command_index++;
  118. if (current_command_index >= count_history - 1)
  119. {
  120. //初始只含一条空历史记录,需单独考虑
  121. if(count_history == 1)
  122. {
  123. //防止出现多条空历史记录
  124. if(current_command_index > 1)
  125. current_command_index = 1;
  126. }
  127. else
  128. current_command_index = count_history - 2;
  129. }
  130. strcpy(buf, history_commands[current_command_index]);
  131. printf("%s", buf);
  132. put_string(" ", COLOR_BLACK, COLOR_WHITE);
  133. }
  134. /**
  135. * @brief 循环读取每一行
  136. *
  137. * @param fd 键盘文件描述符
  138. * @param buf 输入缓冲区
  139. * @return 读取的字符数
  140. */
  141. int shell_readline(int fd, char *buf)
  142. {
  143. int key = 0;
  144. int count = 0;
  145. while (1)
  146. {
  147. key = keyboard_analyze_keycode(fd);
  148. //向上方向键
  149. if (count_history != 0 && key == 0xc8)
  150. {
  151. // put_string(" ", COLOR_WHITE, COLOR_BLACK);
  152. printf("%c", '\b');
  153. clear_command(count, buf);
  154. count = 0;
  155. //向历史
  156. change_command(buf, 1);
  157. count = strlen(buf);
  158. }
  159. //向下方向键
  160. if (count_history != 0 && key == 0x50)
  161. {
  162. // put_string(" ", COLOR_WHITE, COLOR_BLACK);
  163. printf("%c", '\b');
  164. clear_command(count, buf);
  165. count = 0;
  166. //向现在
  167. change_command(buf, -1);
  168. count = strlen(buf);
  169. }
  170. if (key == '\n')
  171. {
  172. if (count > 0 && current_command_index >= count_history)
  173. {
  174. memset(history_commands[current_command_index - 1], 0,
  175. sizeof(history_commands[current_command_index - 1]));
  176. count_history--;
  177. }
  178. printf("%c", '\b');
  179. return count;
  180. }
  181. if (key && key != 0x50 && key != 0xc8)
  182. {
  183. if (key == '\b')
  184. {
  185. if (count > 0)
  186. {
  187. // 回退去除先前光标
  188. printf("%c", '\b');
  189. // 去除字符
  190. printf("%c", '\b');
  191. buf[--count] = 0;
  192. // 在最后一个字符处加光标
  193. put_string(" ", COLOR_BLACK, COLOR_WHITE);
  194. }
  195. }
  196. else
  197. {
  198. printf("%c", '\b');
  199. buf[count++] = key;
  200. printf("%c", key);
  201. // 在最后一个字符处加光标
  202. put_string(" ", COLOR_BLACK, COLOR_WHITE);
  203. }
  204. if (count > 0 && current_command_index >= count_history)
  205. {
  206. memset(history_commands[count_history], 0, sizeof(history_commands[count_history]));
  207. strcpy(history_commands[count_history], buf);
  208. }
  209. else if (count > 0)
  210. {
  211. memset(history_commands[current_command_index], 0, sizeof(history_commands[current_command_index]));
  212. strcpy(history_commands[current_command_index], buf);
  213. }
  214. }
  215. // 输入缓冲区满了之后,直接返回
  216. if (count >= INPUT_BUFFER_SIZE - 1)
  217. {
  218. printf("%c", '\b');
  219. return count;
  220. }
  221. pause_cpu();
  222. }
  223. }
  224. void print_ascii_logo()
  225. {
  226. printf("\n\n");
  227. printf(" ____ ___ ____ \n");
  228. printf("| _ \\ _ __ __ _ __ _ ___ _ __ / _ \\ / ___| \n");
  229. printf("| | | || '__| / _` | / _` | / _ \\ | '_ \\ | | | |\\___ \\ \n");
  230. printf("| |_| || | | (_| || (_| || (_) || | | || |_| | ___) |\n");
  231. printf("|____/ |_| \\__,_| \\__, | \\___/ |_| |_| \\___/ |____/ \n");
  232. printf(" |___/ \n");
  233. printf("\n\n");
  234. }