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 }