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