shell.c 4.7 KB

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