shell.c 6.0 KB

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