refactor: improve on scrolling experience in lunaix console
[lunaix-os.git] / lunaix-os / kernel / demos / simple_sh.c
1 #include <lunaix/fctrl.h>
2 #include <lunaix/foptions.h>
3 #include <lunaix/lunistd.h>
4 #include <lunaix/proc.h>
5 #include <lunaix/status.h>
6
7 #include <klibc/string.h>
8 #include <ulibc/stdio.h>
9
10 char pwd[512];
11
12 /*
13     Simple shell - (actually this is not even a shell)
14     It just to make the testing more easy.
15 */
16
17 void
18 parse_cmdline(char* line, char** cmd, char** arg_part)
19 {
20     strrtrim(line);
21     line = strltrim_safe(line);
22     int l = 0;
23     char c = 0;
24     while ((c = line[l])) {
25         if (c == ' ') {
26             line[l++] = 0;
27             break;
28         }
29         l++;
30     }
31     *cmd = line;
32     *arg_part = strltrim_safe(line + l);
33 }
34
35 void
36 sh_printerr()
37 {
38     int errno = geterrno();
39     switch (errno) {
40         case ENOTDIR:
41             printf("Error: Not a directory\n");
42             break;
43         case ENOENT:
44             printf("Error: No such file or directory\n");
45             break;
46         case EINVAL:
47             printf("Error: Invalid parameter or operation\n");
48             break;
49         case ENOTSUP:
50             printf("Error: Not supported\n");
51             break;
52         case EROFS:
53             printf("Error: File system is read only\n");
54             break;
55         case ENOMEM:
56             printf("Error: Out of memory\n");
57             break;
58         default:
59             printf("Error: Fail to open (%d)\n", errno);
60             break;
61     }
62 }
63
64 void
65 sh_main()
66 {
67     char buf[512];
68     char *cmd, *argpart;
69
70     printf("\n Simple shell. Use <PG_UP> or <PG_DOWN> to scroll.\n\n");
71
72     while (1) {
73         getcwd(pwd, 512);
74         printf("%s$ ", pwd);
75         size_t sz = read(stdin, buf, 512);
76         if (sz < 0) {
77             printf("fail to read user input (%d)\n", geterrno());
78             return;
79         }
80         buf[sz - 1] = '\0';
81         parse_cmdline(buf, &cmd, &argpart);
82         if (cmd[0] == 0) {
83             goto cont;
84         }
85         if (streq(cmd, "cd")) {
86             if (chdir(argpart) < 0) {
87                 sh_printerr();
88             }
89         } else if (streq(cmd, "ls")) {
90             int fd = open(argpart, 0);
91             if (fd < 0) {
92                 sh_printerr();
93             } else {
94                 struct dirent ent = { .d_offset = 0 };
95                 int status;
96                 while ((status = readdir(fd, &ent)) == 1) {
97                     printf(" %s\n", ent.d_name);
98                 }
99
100                 if (status < 0)
101                     sh_printerr();
102
103                 close(fd);
104             }
105         } else {
106             printf("unknow command");
107         }
108     cont:
109         printf("\n");
110     }
111 }