build.bat can create the image if missing, split the shell into native, posix and win32, clean up the build by moving executables into directories, the bootloader is no longer responsible to resolve drivers, fix ResolvePath, every process gets a copy of a module (dll), the child always inherits the cwd, fix function exports in posix, add unlink and exit to posix, add path translator to win32, first bugcheck.
This commit is contained in:
1 parent
0c7f461c6d
commit
f80e66ecde
38 files changed
+1620
-462
No files matched your search
@@ -0,0 +1,231 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#define NAME_MAX 259
|
||||
|
||||
typedef struct dirent {
|
||||
char d_name[NAME_MAX + 1];
|
||||
unsigned char d_type; // DT_REG or DT_DIR
|
||||
} dirent;
|
||||
|
||||
typedef struct DIR {
|
||||
uint32_t KHandle; // kernel DIR_OBJECT handle
|
||||
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 *file_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 PosixFdInit(void);
|
||||
extern int ClearConsoleScreenBuffer(void* hConsole);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Global handles
|
||||
// ---------------------------------------------------------------------------
|
||||
static int hIn = 0; // stdin
|
||||
static int hOut = 1; // stdout
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Output helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
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; }
|
||||
char rev[12];
|
||||
int j = 0;
|
||||
while (i > 0) rev[j++] = buf[--i];
|
||||
rev[j] = '\0';
|
||||
print(rev);
|
||||
}
|
||||
|
||||
static void printInt(int32_t n) {
|
||||
if (n < 0) { print("-"); n = -n; }
|
||||
printUInt((uint32_t)n);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Line editor
|
||||
// ---------------------------------------------------------------------------
|
||||
#define MAX_CMD 256
|
||||
|
||||
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 char* trim(char* s) {
|
||||
while (*s == ' ') s++;
|
||||
int len = (int)strlen(s);
|
||||
while (len > 0 && s[len - 1] == ' ') len--;
|
||||
s[len] = '\0';
|
||||
return s;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Built-in commands
|
||||
// ---------------------------------------------------------------------------
|
||||
static void cmd_help() {
|
||||
print("Available commands:\n"
|
||||
" help - Show this list\n"
|
||||
" dir [path] - List directory contents\n"
|
||||
" cd <path> - Change directory\n"
|
||||
" type <file> - Display file contents\n"
|
||||
" del <file> - Delete a file\n"
|
||||
" write <file> <txt> - Create a file with text\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') return;
|
||||
|
||||
// Open with O_WRONLY | O_CREAT | O_TRUNC (typical flags: 0x0001 | 0x0040 | 0x0200)
|
||||
int fd = open(filename, 0x0241, 0644);
|
||||
if (fd < 0) return;
|
||||
write(fd, args + i + 1, strlen(args + i + 1));
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void cmd_dir(const char* path) {
|
||||
// If no path is provided, default to current directory
|
||||
const char* target = (path && *path != '\0') ? path : ".";
|
||||
|
||||
DIR* d = opendir(target);
|
||||
if (!d) {
|
||||
print("dir: cannot access '");
|
||||
print(target);
|
||||
print("'\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dirent* entry;
|
||||
while ((entry = readdir(d)) != NULL) {
|
||||
// Filter out the current and parent directory markers
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Display type (Assuming 1=DIR, 2=REG based on common custom POSIX layouts)
|
||||
if (entry->d_type == 1) {
|
||||
print("<DIR> ");
|
||||
} else {
|
||||
print(" ");
|
||||
}
|
||||
|
||||
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) return;
|
||||
char buffer[512];
|
||||
int n;
|
||||
while ((n = read(fd, buffer, 511)) > 0) {
|
||||
buffer[n] = '\0';
|
||||
print(buffer);
|
||||
}
|
||||
close(fd);
|
||||
print("\n");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Run one command.
|
||||
// ---------------------------------------------------------------------------
|
||||
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, "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 (strcmp(cmd, "clear") == 0) {
|
||||
ClearConsoleScreenBuffer(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strncmp(cmd, "cd ", 3) == 0) { chdir(cmd + 3); 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; }
|
||||
|
||||
// --- External Process Execution (No Fork) ---
|
||||
int pid;
|
||||
char *argv[] = {(char*)cmd, NULL};
|
||||
if (posix_spawn(&pid, cmd, NULL, NULL, argv, NULL) == 0) {
|
||||
int status;
|
||||
waitpid(pid, &status, 0);
|
||||
} else {
|
||||
print("shell: error launching\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(const char* args) {
|
||||
PosixFdInit();
|
||||
char lineBuf[MAX_CMD];
|
||||
print("shell: ready\n");
|
||||
|
||||
while (true) {
|
||||
print("> ");
|
||||
readLine(lineBuf, MAX_CMD);
|
||||
if (runCommand(trim(lineBuf))) break;
|
||||
}
|
||||
|
||||
print("shell: goodbye\n");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
Reference in new issue
Block a user