fix: Fix some shell weirdness

This commit is contained in:
2026-02-19 23:15:08 +01:00
parent d7b17d9a61
commit 3753ebd4f4
+78 -37
View File
@@ -138,6 +138,11 @@ static void cmd_help() {
zenith::print("Any .elf on the ramdisk is executable.\n"); zenith::print("Any .elf on the ramdisk is executable.\n");
} }
// Check if a string already has a VFS drive prefix (e.g. "0:/")
static bool has_drive_prefix(const char* s) {
return s[0] >= '0' && s[0] <= '9' && s[1] == ':';
}
// ---- Builtin: ls ---- // ---- Builtin: ls ----
static void cmd_ls(const char* arg) { static void cmd_ls(const char* arg) {
@@ -146,24 +151,24 @@ static void cmd_ls(const char* arg) {
// Build the target directory (relative path from root) // Build the target directory (relative path from root)
char dir[128]; char dir[128];
if (*arg) { if (*arg) {
// ls <dir> -- combine cwd and arg if (has_drive_prefix(arg)) {
if (cwd[0]) { // Absolute VFS path: "0:/something"
int i = 0, j = 0; scopy(dir, arg + 3, sizeof(dir));
while (cwd[j] && i < 126) dir[i++] = cwd[j++]; } else if (arg[0] == '/') {
dir[i++] = '/'; // Absolute path from root: "/something"
j = 0; scopy(dir, arg + 1, sizeof(dir));
while (arg[j] && i < 126) dir[i++] = arg[j++]; } else if (cwd[0]) {
dir[i] = '\0'; // Relative path with CWD
scopy(dir, cwd, sizeof(dir));
scat(dir, "/", sizeof(dir));
scat(dir, arg, sizeof(dir));
} else { } else {
int i = 0; // Relative path at root
while (arg[i] && i < 126) { dir[i] = arg[i]; i++; } scopy(dir, arg, sizeof(dir));
dir[i] = '\0';
} }
} else { } else {
// ls with no arg -- use cwd // ls with no arg -- use cwd
int i = 0; scopy(dir, cwd, sizeof(dir));
while (cwd[i] && i < 126) { dir[i] = cwd[i]; i++; }
dir[i] = '\0';
} }
char path[128]; char path[128];
@@ -225,19 +230,48 @@ static void cmd_cd(const char* arg) {
return; return;
} }
// Build target directory path // cd /path -> absolute path from root
if (arg[0] == '/') {
arg++;
if (*arg == '\0') { cwd[0] = '\0'; return; }
char path[128];
build_dir_path(arg, path, sizeof(path));
const char* entries[1];
if (zenith::readdir(path, entries, 1) < 0) {
zenith::print("cd: no such directory: ");
zenith::print(arg);
zenith::putchar('\n');
return;
}
scopy(cwd, arg, sizeof(cwd));
return;
}
// cd 0:/path -> absolute VFS path
if (has_drive_prefix(arg)) {
const char* rel = arg + 3; // skip "0:/"
if (*rel == '\0') { cwd[0] = '\0'; return; }
char path[128];
build_dir_path(rel, path, sizeof(path));
const char* entries[1];
if (zenith::readdir(path, entries, 1) < 0) {
zenith::print("cd: no such directory: ");
zenith::print(arg);
zenith::putchar('\n');
return;
}
scopy(cwd, rel, sizeof(cwd));
return;
}
// Build target directory path (relative to CWD)
char target[128]; char target[128];
if (cwd[0]) { if (cwd[0]) {
int i = 0, j = 0; scopy(target, cwd, sizeof(target));
while (cwd[j] && i < 126) target[i++] = cwd[j++]; scat(target, "/", sizeof(target));
target[i++] = '/'; scat(target, arg, sizeof(target));
j = 0;
while (arg[j] && i < 126) target[i++] = arg[j++];
target[i] = '\0';
} else { } else {
int i = 0; scopy(target, arg, sizeof(target));
while (arg[i] && i < 126) { target[i] = arg[i]; i++; }
target[i] = '\0';
} }
// Validate: try readdir on the target // Validate: try readdir on the target
@@ -253,9 +287,7 @@ static void cmd_cd(const char* arg) {
} }
// Set cwd // Set cwd
int i = 0; scopy(cwd, target, sizeof(cwd));
while (target[i] && i < 126) { cwd[i] = target[i]; i++; }
cwd[i] = '\0';
} }
// ---- Builtin: man ---- // ---- Builtin: man ----
@@ -292,11 +324,6 @@ static bool try_exec(const char* path, const char* args) {
return true; return true;
} }
// Check if a string already has a VFS drive prefix (e.g. "0:/")
static bool has_drive_prefix(const char* s) {
return s[0] >= '0' && s[0] <= '9' && s[1] == ':';
}
// Resolve arguments: expand relative file paths against CWD. // Resolve arguments: expand relative file paths against CWD.
// Tokens that already have a drive prefix (e.g. "0:/foo") are left as-is. // Tokens that already have a drive prefix (e.g. "0:/foo") are left as-is.
// Everything before the first space-delimited token that looks like a path // Everything before the first space-delimited token that looks like a path
@@ -322,12 +349,26 @@ static void resolve_args(const char* args, char* out, int outMax) {
bool resolve = cwd[0] && !has_drive_prefix(tokStart) && tokStart[0] != '-'; bool resolve = cwd[0] && !has_drive_prefix(tokStart) && tokStart[0] != '-';
if (resolve) { if (resolve) {
// Write "0:/<cwd>/<token>" // Build candidate resolved path and check if the file exists
if (o + 3 < outMax) { out[o++] = '0'; out[o++] = ':'; out[o++] = '/'; } char candidate[256];
int r = 0;
candidate[r++] = '0'; candidate[r++] = ':'; candidate[r++] = '/';
int j = 0; int j = 0;
while (cwd[j] && o < outMax - 1) out[o++] = cwd[j++]; while (cwd[j] && r < 255) candidate[r++] = cwd[j++];
if (o < outMax - 1) out[o++] = '/'; if (r < 255) candidate[r++] = '/';
for (int k = 0; k < tokLen && o < outMax - 1; k++) out[o++] = tokStart[k]; for (int k = 0; k < tokLen && r < 255; k++) candidate[r++] = tokStart[k];
candidate[r] = '\0';
// Only use the resolved path if the file actually exists;
// otherwise pass the argument through unchanged (it may be
// a hostname, IP address, URL, or other non-path argument).
int h = zenith::open(candidate);
if (h >= 0) {
zenith::close(h);
for (int k = 0; k < r && o < outMax - 1; k++) out[o++] = candidate[k];
} else {
for (int k = 0; k < tokLen && o < outMax - 1; k++) out[o++] = tokStart[k];
}
} else { } else {
for (int k = 0; k < tokLen && o < outMax - 1; k++) out[o++] = tokStart[k]; for (int k = 0; k < tokLen && o < outMax - 1; k++) out[o++] = tokStart[k];
} }