#include #include #include #include #include #define MAX_CMD 256 #define NAME_MAX 259 typedef struct dirent { char d_name[NAME_MAX + 1]; unsigned char d_type; } dirent; typedef struct DIR { uint32_t KHandle; dirent Current; bool Valid; } DIR; extern int read(int fd, void *buf, size_t count); extern int write(int fd, const void *buf, size_t count); extern int open(const char *pathname, int flags, ...); extern int close(int fd); extern int chdir(const char *path); extern DIR* opendir(const char* path); extern dirent* readdir(DIR* d); extern int closedir(DIR* d); extern int unlink(const char *pathname); extern int posix_spawn(int *pid, const char *path, const void *act, const void *attr, char *const argv[], char *const envp[]); extern int waitpid(int pid, int *status, int options); extern void exit(int status); extern void clearscreen(void); extern void clearkeyboard(void); extern void PosixFdInit(void); static int hIn = 0; static int hOut = 1; static void print(const char* s) { write(hOut, s, strlen(s)); } static void printUInt(uint32_t n) { char buf[12]; int i = 0; if (n == 0) { print("0"); return; } while (n > 0) { buf[i++] = (char)('0' + n % 10); n /= 10; } while (i > 0) { char c[2] = { buf[--i], '\0' }; print(c); } } static void printInt(int32_t n) { if (n < 0) { print("-"); n = -n; } printUInt((uint32_t)n); } static void readLine(char* buf, int len) { int pos = 0; while (true) { char c; if (read(hIn, &c, 1) <= 0) break; if (c == '\r' || c == '\n') { print("\n"); break; } if ((c == '\b' || c == 127) && pos > 0) { pos--; print("\b \b"); continue; } if (c < 0x20 || c == 127) continue; if (pos < len - 1) { buf[pos++] = c; char echo[2] = {c, '\0'}; print(echo); } } buf[pos] = '\0'; } static int splitCommandLine(char* line, char** argv, int maxArgv) { int argc = 0; char* p = line; while (*p && argc < maxArgv - 1) { while (*p == ' ' || *p == '\t') p++; if (!*p) break; if (*p == '"') { p++; argv[argc++] = p; while (*p && *p != '"') p++; if (*p) *p++ = '\0'; } else { argv[argc++] = p; while (*p && *p != ' ' && *p != '\t') p++; if (*p) *p++ = '\0'; } } argv[argc] = NULL; return argc; } static char* trim(char* s) { while (*s == ' ') s++; int len = (int)strlen(s); while (len > 0 && s[len - 1] == ' ') len--; s[len] = '\0'; return s; } static void cmd_help() { print("Available commands:\n" " help - Show this list\n" " dir [path] - List directory contents\n" " cd - Change directory\n" " type - Display file contents\n" " del - Delete a file\n" " write - Create a file with text\n" " clear - Clear the screen\n" " exit - Close the shell\n"); } static void cmd_write(const char* args) { char filename[MAX_CMD]; int i = 0; while (args[i] != ' ' && args[i] != '\0' && i < MAX_CMD - 1) { filename[i] = args[i]; i++; } filename[i] = '\0'; if (args[i] == '\0' || args[i+1] == '\0') { print("write: usage: write \n"); return; } int fd = open(filename, 0x0241, 0644); // O_WRONLY | O_CREAT | O_TRUNC if (fd < 0) { print("write: could not create file\n"); return; } write(fd, args + i + 1, strlen(args + i + 1)); close(fd); print("File written successfully.\n"); } static void cmd_dir(const char* path) { const char* target = (path && *path != '\0') ? path : "."; DIR* d = opendir(target); if (!d) { print("dir: cannot access directory\n"); return; } dirent* entry; while ((entry = readdir(d)) != NULL) { if (entry->d_name[0] == '.') continue; print(entry->d_type == 1 ? " " : " "); print(entry->d_name); print("\n"); } closedir(d); } static void cmd_type(const char* filename) { int fd = open(filename, 0); // O_RDONLY if (fd < 0) { print("type: cannot open file\n"); return; } char buffer[512]; int n; while ((n = read(fd, buffer, 511)) > 0) { buffer[n] = '\0'; print(buffer); } close(fd); print("\n"); } static int runCommand(const char* cmd) { if (!cmd || *cmd == '\0') return 0; if (strcmp(cmd, "exit") == 0) return 1; if (strcmp(cmd, "help") == 0) { cmd_help(); return 0; } if (strcmp(cmd, "clear") == 0) { clearscreen(); return 0; } if (strcmp(cmd, "crash") == 0) { *(int*)0 = 42; return 0; } if (strcmp(cmd, "dir") == 0) { cmd_dir("."); return 0; } if (strncmp(cmd, "dir ", 4) == 0) { cmd_dir(cmd + 4); return 0; } if (strncmp(cmd, "cd ", 3) == 0) { if (chdir(cmd + 3) != 0) print("cd: failed\n"); return 0; } if (strncmp(cmd, "del ", 4) == 0) { unlink(cmd + 4); return 0; } if (strncmp(cmd, "type ", 5) == 0) { cmd_type(cmd + 5); return 0; } if (strncmp(cmd, "write ", 6) == 0) { cmd_write(cmd + 6); return 0; } char cmdBuf[MAX_CMD]; strncpy(cmdBuf, cmd, MAX_CMD - 1); cmdBuf[MAX_CMD - 1] = '\0'; char* argv[32]; int argc = splitCommandLine(cmdBuf, argv, 32); if (argc == 0) return 0; int pid; if (posix_spawn(&pid, argv[0], NULL, NULL, argv, NULL) == 0) { int status; waitpid(pid, &status, 0); clearkeyboard(); } else { print("shell: launch failed\n"); } return 0; } int main(void) { PosixFdInit(); const char* cmdline = SysGetCommandLine(); char lineBuf[MAX_CMD]; print("shell: command line: "); print(cmdline); print("\n"); print("shell: ready\n"); while (true) { print("> "); readLine(lineBuf, MAX_CMD); if (runCommand(trim(lineBuf))) break; } print("shell: goodbye\n"); exit(0); }