cmd.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. #include "cmd.h"
  2. #include <libc/string.h>
  3. #include <libc/stdio.h>
  4. #include <libc/stddef.h>
  5. #include <libsystem/syscall.h>
  6. #include <libc/string.h>
  7. #include <libc/errno.h>
  8. #include <libc/unistd.h>
  9. #include <libc/stdlib.h>
  10. #include <libc/dirent.h>
  11. #include "cmd_help.h"
  12. // 当前工作目录(在main_loop中初始化)
  13. char *shell_current_path = NULL;
  14. /**
  15. * @brief shell 内建函数的主命令与处理函数的映射表
  16. *
  17. */
  18. struct built_in_cmd_t shell_cmds[] =
  19. {
  20. {"cd", shell_cmd_cd},
  21. {"cat", shell_cmd_cat},
  22. {"exec", shell_cmd_exec},
  23. {"ls", shell_cmd_ls},
  24. {"mkdir", shell_cmd_mkdir},
  25. {"pwd", shell_cmd_pwd},
  26. {"rm", shell_cmd_rm},
  27. {"rmdir", shell_cmd_rmdir},
  28. {"reboot", shell_cmd_reboot},
  29. {"touch", shell_cmd_touch},
  30. {"help", shell_help},
  31. };
  32. // 总共的内建命令数量
  33. const static int total_built_in_cmd_num = sizeof(shell_cmds) / sizeof(struct built_in_cmd_t);
  34. /**
  35. * @brief 寻找对应的主命令编号
  36. *
  37. * @param main_cmd 主命令
  38. * @return int 成功:主命令编号
  39. * 失败: -1
  40. */
  41. int shell_find_cmd(char *main_cmd)
  42. {
  43. for (int i = 0; i < total_built_in_cmd_num; ++i)
  44. {
  45. if (strcmp(main_cmd, shell_cmds[i].name) == 0) // 找到对应的命令号
  46. return i;
  47. }
  48. // 找不到该命令
  49. return -1;
  50. }
  51. /**
  52. * @brief 运行shell内建的命令
  53. *
  54. * @param index 主命令编号
  55. * @param argc 参数数量
  56. * @param argv 参数列表
  57. */
  58. void shell_run_built_in_command(int index, int argc, char **argv)
  59. {
  60. if (index >= total_built_in_cmd_num)
  61. return;
  62. // printf("run built-in command : %s\n", shell_cmds[index].name);
  63. shell_cmds[index].func(argc, argv);
  64. }
  65. /**
  66. * @brief cd命令:进入文件夹
  67. *
  68. * @param argc
  69. * @param argv
  70. * @return int
  71. */
  72. int shell_cmd_cd(int argc, char **argv)
  73. {
  74. int current_dir_len = strlen(shell_current_path);
  75. if (argc < 2)
  76. {
  77. shell_help_cd();
  78. goto done;
  79. }
  80. // 进入当前文件夹
  81. if (!strcmp(".", argv[1]))
  82. goto done;
  83. // 进入父目录
  84. if (!strcmp("..", argv[1]))
  85. {
  86. // 当前已经是根目录
  87. if (!strcmp("/", shell_current_path))
  88. goto done;
  89. // 返回到父目录
  90. int index = current_dir_len - 1;
  91. for (; index > 1; --index)
  92. {
  93. if (shell_current_path[index] == '/')
  94. break;
  95. }
  96. shell_current_path[index] = '\0';
  97. // printf("switch to \" %s \"\n", shell_current_path);
  98. goto done;
  99. }
  100. int dest_len = strlen(argv[1]);
  101. // 路径过长
  102. if (dest_len >= SHELL_CWD_MAX_SIZE - 1)
  103. {
  104. printf("ERROR: Path too long!\n");
  105. goto fail;
  106. }
  107. if (argv[1][0] == '/')
  108. {
  109. // ======进入绝对路径=====
  110. int ec = chdir(argv[1]);
  111. if (ec == -1)
  112. ec = errno;
  113. if (ec == 0)
  114. {
  115. // 获取新的路径字符串
  116. char *new_path = (char *)malloc(dest_len + 2);
  117. memset(new_path, 0, dest_len + 2);
  118. strncpy(new_path, argv[1], dest_len);
  119. // 释放原有的路径字符串的内存空间
  120. free(shell_current_path);
  121. shell_current_path = new_path;
  122. shell_current_path[dest_len] = '\0';
  123. return 0;
  124. }
  125. else
  126. goto fail;
  127. ; // 出错则直接忽略
  128. }
  129. else
  130. {
  131. int dest_offset = 0;
  132. if (dest_len > 2)
  133. {
  134. if (argv[1][0] == '.' && argv[1][1] == '/') // 相对路径
  135. dest_offset = 2;
  136. }
  137. int new_len = current_dir_len + dest_len - dest_offset;
  138. // ======进入相对路径=====
  139. if (new_len >= SHELL_CWD_MAX_SIZE - 1)
  140. {
  141. printf("ERROR: Path too long!\n");
  142. goto fail;
  143. }
  144. // 拼接出新的字符串
  145. char *new_path = (char *)malloc(new_len + 2);
  146. memset(new_path, 0, sizeof(new_path));
  147. strncpy(new_path, shell_current_path, current_dir_len);
  148. if (current_dir_len > 1)
  149. new_path[current_dir_len] = '/';
  150. strcat(new_path, argv[1] + dest_offset);
  151. if (chdir(new_path) == 0) // 成功切换目录
  152. {
  153. free(shell_current_path);
  154. new_path[new_len] = '\0';
  155. shell_current_path = new_path;
  156. goto done;
  157. }
  158. else
  159. {
  160. printf("ERROR: Cannot switch to directory: %s\n", new_path);
  161. goto fail;
  162. }
  163. }
  164. fail:;
  165. done:;
  166. // 释放参数所占的内存
  167. free(argv);
  168. return 0;
  169. }
  170. /**
  171. * @brief 查看文件夹下的文件列表
  172. *
  173. * @param argc
  174. * @param argv
  175. * @return int
  176. */
  177. // todo:
  178. int shell_cmd_ls(int argc, char **argv)
  179. {
  180. struct DIR *dir = opendir(shell_current_path);
  181. if (dir == NULL)
  182. return -1;
  183. struct dirent *buf = NULL;
  184. // printf("dir=%#018lx\n", dir);
  185. while (1)
  186. {
  187. buf = readdir(dir);
  188. if(buf == NULL)
  189. break;
  190. int color = COLOR_WHITE;
  191. if(buf->d_type & VFS_ATTR_DIR)
  192. color = COLOR_YELLOW;
  193. else if(buf->d_type & VFS_ATTR_FILE)
  194. color = COLOR_INDIGO;
  195. char output_buf[256] = {0};
  196. sprintf(output_buf, "%s ", buf->d_name);
  197. put_string(output_buf, color, COLOR_BLACK);
  198. }
  199. printf("\n");
  200. closedir(dir);
  201. return 0;
  202. }
  203. /**
  204. * @brief 显示当前工作目录的命令
  205. *
  206. * @param argc
  207. * @param argv
  208. * @return int
  209. */
  210. int shell_cmd_pwd(int argc, char **argv)
  211. {
  212. if (shell_current_path)
  213. printf("%s\n", shell_current_path);
  214. free(argv);
  215. }
  216. /**
  217. * @brief 查看文件内容的命令
  218. *
  219. * @param argc
  220. * @param argv
  221. * @return int
  222. */
  223. // todo:
  224. int shell_cmd_cat(int argc, char **argv) {}
  225. /**
  226. * @brief 创建空文件的命令
  227. *
  228. * @param argc
  229. * @param argv
  230. * @return int
  231. */
  232. // todo:
  233. int shell_cmd_touch(int argc, char **argv) {}
  234. /**
  235. * @brief 删除命令
  236. *
  237. * @param argc
  238. * @param argv
  239. * @return int
  240. */
  241. // todo:
  242. int shell_cmd_rm(int argc, char **argv) {}
  243. /**
  244. * @brief 创建文件夹的命令
  245. *
  246. * @param argc
  247. * @param argv
  248. * @return int
  249. */
  250. // todo:
  251. int shell_cmd_mkdir(int argc, char **argv) {}
  252. /**
  253. * @brief 删除文件夹的命令
  254. *
  255. * @param argc
  256. * @param argv
  257. * @return int
  258. */
  259. // todo:
  260. int shell_cmd_rmdir(int argc, char **argv) {}
  261. /**
  262. * @brief 执行新的程序的命令
  263. *
  264. * @param argc
  265. * @param argv
  266. * @return int
  267. */
  268. // todo:
  269. int shell_cmd_exec(int argc, char **argv) {}
  270. /**
  271. * @brief 重启命令
  272. *
  273. * @param argc
  274. * @param argv
  275. * @return int
  276. */
  277. // todo:
  278. int shell_cmd_reboot(int argc, char **argv)
  279. {
  280. return syscall_invoke(SYS_REBOOT, 0, 0, 0, 0, 0, 0, 0, 0);
  281. }