shell.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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 "cmd.h"
  9. #define pause_cpu() asm volatile("pause\n\t");
  10. /**
  11. * @brief 循环读取每一行
  12. *
  13. * @param fd 键盘文件描述符
  14. * @param buf 输入缓冲区
  15. * @return 读取的字符数
  16. */
  17. #define INPUT_BUFFER_SIZE 512
  18. int shell_readline(int fd, char *buf);
  19. extern char *shell_current_path;
  20. /**
  21. * @brief 解析shell命令
  22. *
  23. * @param buf 输入缓冲区
  24. * @param argc 返回值:参数数量
  25. * @param argv 返回值:参数列表
  26. * @return int
  27. */
  28. int parse_command(char *buf, int *argc, char ***argv);
  29. /**
  30. * @brief shell主循环
  31. *
  32. * @param kb_fd 键盘文件描述符
  33. */
  34. void main_loop(int kb_fd)
  35. {
  36. unsigned char input_buffer[INPUT_BUFFER_SIZE] = {0};
  37. sbrk(24);
  38. // brk(0x700000000000 + (1<<21));
  39. pid_t pid = fork();
  40. int retval = 0;
  41. for(int i=0;i<10;++i)
  42. printf(" @pid=%d ", pid);
  43. if(pid == 0)
  44. {
  45. int a = 1/0;
  46. }
  47. // 初始化当前工作目录的路径
  48. shell_current_path = (char *)malloc(3);
  49. memset(shell_current_path, 0, 3);
  50. shell_current_path[0] = '/';
  51. shell_current_path[1] = '\0';
  52. // shell命令行的主循环
  53. while (true)
  54. {
  55. int argc = 0;
  56. char **argv;
  57. printf("[DragonOS] %s # ", shell_current_path);
  58. memset(input_buffer, 0, INPUT_BUFFER_SIZE);
  59. // 循环读取每一行到buffer
  60. int count = shell_readline(kb_fd, input_buffer);
  61. if (count)
  62. {
  63. int cmd_num = parse_command(input_buffer, &argc, &argv);
  64. printf("\n");
  65. if (cmd_num >= 0)
  66. shell_run_built_in_command(cmd_num, argc, argv);
  67. }
  68. else
  69. printf("\n");
  70. }
  71. }
  72. int main()
  73. {
  74. // 打开键盘文件
  75. char kb_file_path[] = "/dev/keyboard.dev";
  76. int kb_fd = open(kb_file_path, 0);
  77. // printf("keyboard fd = %d\n", kb_fd);
  78. main_loop(kb_fd);
  79. while (1)
  80. ;
  81. }
  82. /**
  83. * @brief 循环读取每一行
  84. *
  85. * @param fd 键盘文件描述符
  86. * @param buf 输入缓冲区
  87. * @return 读取的字符数
  88. */
  89. int shell_readline(int fd, char *buf)
  90. {
  91. int key = 0;
  92. int count = 0;
  93. while (1)
  94. {
  95. key = keyboard_analyze_keycode(fd);
  96. if (key == '\n')
  97. return count;
  98. if (key)
  99. {
  100. if (key == '\b')
  101. {
  102. if (count > 0)
  103. {
  104. buf[--count] = 0;
  105. printf("%c", '\b');
  106. }
  107. }
  108. else
  109. {
  110. buf[count++] = key;
  111. printf("%c", key);
  112. }
  113. }
  114. // 输入缓冲区满了之后,直接返回
  115. if (count >= INPUT_BUFFER_SIZE - 1)
  116. return count;
  117. pause_cpu();
  118. }
  119. }
  120. /**
  121. * @brief 解析shell命令
  122. *
  123. * @param buf 输入缓冲区
  124. * @param argc 返回值:参数数量
  125. * @param argv 返回值:参数列表
  126. * @return int 主命令的编号
  127. */
  128. int parse_command(char *buf, int *argc, char ***argv)
  129. {
  130. // printf("parse command\n");
  131. int index = 0; // 当前访问的是buf的第几位
  132. // 去除命令前导的空格
  133. while (index < INPUT_BUFFER_SIZE && buf[index] == ' ')
  134. ++index;
  135. // 计算参数数量
  136. for (int i = index; i < (INPUT_BUFFER_SIZE - 1); ++i)
  137. {
  138. // 到达了字符串末尾
  139. if (!buf[i])
  140. break;
  141. if (buf[i] != ' ' && (buf[i + 1] == ' ' || buf[i + 1] == '\0'))
  142. ++(*argc);
  143. }
  144. // printf("\nargc=%d\n", *argc);
  145. // 为指向每个指令的指针分配空间
  146. *argv = (char **)malloc(sizeof(char **) * (*argc));
  147. memset(*argv, 0, sizeof(char **) * (*argc));
  148. // 将每个命令都单独提取出来
  149. for (int i = 0; i < *argc && index < INPUT_BUFFER_SIZE; ++i)
  150. {
  151. // 提取出命令,以空格作为分割
  152. *((*argv) + i) = &buf[index];
  153. while (index < (INPUT_BUFFER_SIZE - 1) && buf[index] && buf[index] != ' ')
  154. ++index;
  155. buf[index++] = '\0';
  156. // 删除命令间多余的空格
  157. while (index < INPUT_BUFFER_SIZE && buf[index] == ' ')
  158. ++index;
  159. // printf("%s\n", (*argv)[i]);
  160. }
  161. // 以第一个命令作为主命令,查找其在命令表中的编号
  162. return shell_find_cmd(**argv);
  163. }