Files
nt-lite/code/shell_native/shell_native.c
T

243 lines
7.8 KiB
C

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include <syscall.h>
#include <io_file.h>
#define MAX_CMD 256
// ---------------------------------------------------------------------------
// Output helpers
// ---------------------------------------------------------------------------
static void print(const char* s) { SysWriteConsole(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("-"); printUInt((uint32_t)-(n + 1) + 1); }
else { printUInt((uint32_t)n); }
}
static uint64_t parseUInt64(const char* s) {
uint64_t v = 0;
while (*s == ' ') s++;
while (*s >= '0' && *s <= '9') v = v * 10 + (uint64_t)(*s++ - '0');
return v;
}
// Parse up to 6 comma-separated uint64 values.
// Returns the number of values actually parsed.
static int parseArgs(const char* line, uint64_t args[6]) {
int count = 0;
while (*line && count < 6) {
args[count++] = parseUInt64(line);
while (*line && *line != ',') line++; // skip to next comma
if (*line == ',') line++; // consume comma
}
return count;
}
static void printUInt64(uint64_t n) {
if (n == 0) { print("0"); return; }
char buf[20]; int i = 0;
while (n > 0) { buf[i++] = (char)('0' + (int)(n % 10)); n /= 10; }
while (i > 0) { char c[2] = { buf[--i], '\0' }; print(c); }
}
// ---------------------------------------------------------------------------
// Line editor
// ---------------------------------------------------------------------------
static void readLine(char* buf, int len) {
int pos = 0;
while (true) {
char c = SysKbReadChar();
if (!c) { SysYield(); continue; }
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"
" debug - Enter debug bucket mode\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> <tx> - Create a file with text\n"
" clear - Clear the screen\n"
" exit - Close the shell\n");
}
static void cmd_debug(void) {
print("Entered debug mode. Type args as: a0,a1,a2,a3,a4,a5\n");
print("Type 'exit' to leave.\n");
char line[MAX_CMD];
while (true) {
print("debug> ");
readLine(line, MAX_CMD);
char* t = trim(line);
if (strcmp(t, "exit") == 0) {
print("Exit debug.\n");
break;
}
if (*t == '\0') continue;
uint64_t args[6] = {0, 0, 0, 0, 0, 0};
parseArgs(t, args);
uint64_t ret = SysCatchAllDebugBucket(args[0], args[1], args[2],
args[3], args[4], args[5]);
printUInt64(ret);
print("\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 <filename> <text>\n"); return; }
uint32_t hFile;
if (SysCreateFile(filename, &hFile) != 0) { print("write: could not create file\n"); return; }
size_t written;
SysWriteFile(hFile, args + i + 1, strlen(args + i + 1), &written);
SysCloseHandle(hFile);
print("File written successfully.\n");
}
static void cmd_dir(const char* path) {
uint32_t hDir;
const char* target = (path && *path != '\0') ? path : ".";
if (SysOpenDir(target, &hDir) != 0) {
print("dir: failed to open directory\n");
return;
}
KDIR_ENTRY ke;
while (SysReadDir(hDir, &ke) == 0) {
// Corrected Attribute Check: 0x10 is the Directory bit in FAT
if (ke.Attr & 0x10) {
print("<DIR> ");
} else {
print(" ");
}
print(ke.Name);
// Optional: print file size for non-directories
if (!(ke.Attr & 0x10)) {
print(" (");
printUInt(ke.FileSize);
print(" bytes)");
}
print("\n");
}
SysCloseHandle(hDir);
}
static void cmd_type(const char* filename) {
uint32_t hFile;
if (SysOpenFile(filename, &hFile) != 0) { print("type: cannot open file\n"); return; }
char buffer[512]; size_t bytesRead;
while (SysReadFile(hFile, buffer, sizeof(buffer) - 1, &bytesRead) == 0 && bytesRead > 0) {
buffer[bytesRead] = '\0'; print(buffer);
}
SysCloseHandle(hFile); print("\n");
}
static bool extractProgramPath(const char* cmdline, char* out, size_t outSize) {
if (!cmdline || !out || outSize == 0) return false;
while (*cmdline == ' ' || *cmdline == '\t') cmdline++;
if (*cmdline == '\0') return false;
size_t pos = 0;
if (*cmdline == '"') {
cmdline++;
while (*cmdline && *cmdline != '"' && pos + 1 < outSize)
out[pos++] = *cmdline++;
} else {
while (*cmdline && *cmdline != ' ' && *cmdline != '\t' && pos + 1 < outSize)
out[pos++] = *cmdline++;
}
out[pos] = '\0';
return pos != 0;
}
// ---------------------------------------------------------------------------
// 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, "clear") == 0) { SysScreenClear(0); return 0; }
if (strcmp(cmd, "crash") == 0) { *(int*)0 = 42; return 0; }
if (strcmp(cmd, "debug") == 0) { cmd_debug(); 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 (SysSetCwd(cmd + 3) != 0) print("cd: failed\n"); return 0; }
if (strncmp(cmd, "del ", 4) == 0) { SysDeleteFile(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 program[MAX_CMD];
if (!extractProgramPath(cmd, program, sizeof(program))) return 0;
uint32_t hProc;
if (SysCreateProcess(program, &hProc, cmd) == 0) {
SysWaitForProcess(hProc);
SysCloseHandle(hProc);
while (SysKbPoll()) (void)SysKbReadChar();
} else { print("shell: launch failed\n"); }
return 0;
}
int main(void) {
const char* cmdline = SysGetPeb()->CommandLine;
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");
SysExitProcess(0);
return 0;
}