shell.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. #include "cmd.h"
  2. #include <libKeyboard/keyboard.h>
  3. #include <libc/fcntl.h>
  4. #include <libc/printf.h>
  5. #include <libc/stddef.h>
  6. #include <libc/stdio.h>
  7. #include <libc/stdlib.h>
  8. #include <libc/string.h>
  9. #include <libc/sys/stat.h>
  10. #include <libc/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. current_command_index = count_history - 2;
  120. strcpy(buf, history_commands[current_command_index]);
  121. printf("%s", buf);
  122. put_string(" ", COLOR_BLACK, COLOR_WHITE);
  123. }
  124. /**
  125. * @brief 循环读取每一行
  126. *
  127. * @param fd 键盘文件描述符
  128. * @param buf 输入缓冲区
  129. * @return 读取的字符数
  130. */
  131. int shell_readline(int fd, char *buf)
  132. {
  133. int key = 0;
  134. int count = 0;
  135. while (1)
  136. {
  137. key = keyboard_analyze_keycode(fd);
  138. //向上方向键
  139. if (count_history != 0 && key == 0xc8)
  140. {
  141. // put_string(" ", COLOR_WHITE, COLOR_BLACK);
  142. printf("%c", '\b');
  143. clear_command(count, buf);
  144. count = 0;
  145. //向历史
  146. change_command(buf, 1);
  147. count = strlen(buf);
  148. }
  149. //向下方向键
  150. if (count_history != 0 && key == 0x50)
  151. {
  152. // put_string(" ", COLOR_WHITE, COLOR_BLACK);
  153. printf("%c", '\b');
  154. clear_command(count, buf);
  155. count = 0;
  156. //向现在
  157. change_command(buf, -1);
  158. count = strlen(buf);
  159. }
  160. if (key == '\n')
  161. {
  162. if (count > 0 && current_command_index >= count_history)
  163. {
  164. memset(history_commands[current_command_index - 1], 0,
  165. sizeof(history_commands[current_command_index - 1]));
  166. count_history--;
  167. }
  168. printf("%c", '\b');
  169. return count;
  170. }
  171. if (key && key != 0x50 && key != 0xc8)
  172. {
  173. if (key == '\b')
  174. {
  175. if (count > 0)
  176. {
  177. // 回退去除先前光标
  178. printf("%c", '\b');
  179. // 去除字符
  180. printf("%c", '\b');
  181. buf[--count] = 0;
  182. // 在最后一个字符处加光标
  183. put_string(" ", COLOR_BLACK, COLOR_WHITE);
  184. }
  185. }
  186. else
  187. {
  188. printf("%c", '\b');
  189. buf[count++] = key;
  190. printf("%c", key);
  191. // 在最后一个字符处加光标
  192. put_string(" ", COLOR_BLACK, COLOR_WHITE);
  193. }
  194. if (count > 0 && current_command_index >= count_history)
  195. {
  196. memset(history_commands[count_history], 0, sizeof(history_commands[count_history]));
  197. strcpy(history_commands[count_history], buf);
  198. }
  199. else if (count > 0)
  200. {
  201. memset(history_commands[current_command_index], 0, sizeof(history_commands[current_command_index]));
  202. strcpy(history_commands[current_command_index], buf);
  203. }
  204. }
  205. // 输入缓冲区满了之后,直接返回
  206. if (count >= INPUT_BUFFER_SIZE - 1)
  207. {
  208. printf("%c", '\b');
  209. return count;
  210. }
  211. pause_cpu();
  212. }
  213. }
  214. void print_ascii_logo()
  215. {
  216. printf("\n\n");
  217. printf(" ____ ___ ____ \n");
  218. printf("| _ \\ _ __ __ _ __ _ ___ _ __ / _ \\ / ___| \n");
  219. printf("| | | || '__| / _` | / _` | / _ \\ | '_ \\ | | | |\\___ \\ \n");
  220. printf("| |_| || | | (_| || (_| || (_) || | | || |_| | ___) |\n");
  221. printf("|____/ |_| \\__,_| \\__, | \\___/ |_| |_| \\___/ |____/ \n");
  222. printf(" |___/ \n");
  223. printf("\n\n");
  224. }