feat: add cwd tracking to kernel, remove shell hack, update system utilities to use getcwd, fix tcc libc stub, fix nonexistent directory issue
This commit is contained in:
@@ -12,10 +12,13 @@
|
|||||||
#include <Memory/HHDM.hpp>
|
#include <Memory/HHDM.hpp>
|
||||||
#include <Memory/Paging.hpp>
|
#include <Memory/Paging.hpp>
|
||||||
#include <Libraries/Memory.hpp>
|
#include <Libraries/Memory.hpp>
|
||||||
|
#include "Path.hpp"
|
||||||
|
|
||||||
namespace Montauk {
|
namespace Montauk {
|
||||||
static int Sys_Open(const char* path) {
|
static int Sys_Open(const char* path) {
|
||||||
return Fs::Vfs::VfsOpen(path);
|
char resolved[256];
|
||||||
|
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||||
|
return Fs::Vfs::VfsOpen(resolved);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int Sys_Read(int handle, uint8_t* buffer, uint64_t offset, uint64_t size) {
|
static int Sys_Read(int handle, uint8_t* buffer, uint64_t offset, uint64_t size) {
|
||||||
@@ -31,11 +34,14 @@ namespace Montauk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int Sys_ReadDir(const char* path, const char** outNames, int maxEntries) {
|
static int Sys_ReadDir(const char* path, const char** outNames, int maxEntries) {
|
||||||
|
char resolved[256];
|
||||||
|
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||||
|
|
||||||
// Get entries from VFS into a kernel-local array
|
// Get entries from VFS into a kernel-local array
|
||||||
const char* kernelNames[256];
|
const char* kernelNames[256];
|
||||||
int max = maxEntries;
|
int max = maxEntries;
|
||||||
if (max > 256) max = 256;
|
if (max > 256) max = 256;
|
||||||
int count = Fs::Vfs::VfsReadDir(path, kernelNames, max);
|
int count = Fs::Vfs::VfsReadDir(resolved, kernelNames, max);
|
||||||
if (count <= 0) return count;
|
if (count <= 0) return count;
|
||||||
|
|
||||||
// Allocate a user-accessible page for string data via process heap
|
// Allocate a user-accessible page for string data via process heap
|
||||||
@@ -70,19 +76,29 @@ namespace Montauk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int Sys_FCreate(const char* path) {
|
static int Sys_FCreate(const char* path) {
|
||||||
return Fs::Vfs::VfsCreate(path);
|
char resolved[256];
|
||||||
|
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||||
|
return Fs::Vfs::VfsCreate(resolved);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int Sys_FDelete(const char* path) {
|
static int Sys_FDelete(const char* path) {
|
||||||
return Fs::Vfs::VfsDelete(path);
|
char resolved[256];
|
||||||
|
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||||
|
return Fs::Vfs::VfsDelete(resolved);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int Sys_FMkdir(const char* path) {
|
static int Sys_FMkdir(const char* path) {
|
||||||
return Fs::Vfs::VfsMkdir(path);
|
char resolved[256];
|
||||||
|
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||||
|
return Fs::Vfs::VfsMkdir(resolved);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int Sys_FRename(const char* oldPath, const char* newPath) {
|
static int Sys_FRename(const char* oldPath, const char* newPath) {
|
||||||
return Fs::Vfs::VfsRename(oldPath, newPath);
|
char resolvedOld[256];
|
||||||
|
char resolvedNew[256];
|
||||||
|
if (!ResolveProcessPath(oldPath, resolvedOld, sizeof(resolvedOld))) return -1;
|
||||||
|
if (!ResolveProcessPath(newPath, resolvedNew, sizeof(resolvedNew))) return -1;
|
||||||
|
return Fs::Vfs::VfsRename(resolvedOld, resolvedNew);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int Sys_DriveList(int* outDrives, int maxEntries) {
|
static int Sys_DriveList(int* outDrives, int maxEntries) {
|
||||||
|
|||||||
@@ -11,11 +11,15 @@
|
|||||||
|
|
||||||
#include "Syscall.hpp"
|
#include "Syscall.hpp"
|
||||||
#include "Common.hpp"
|
#include "Common.hpp"
|
||||||
|
#include "Path.hpp"
|
||||||
|
|
||||||
namespace Montauk {
|
namespace Montauk {
|
||||||
|
|
||||||
static int Sys_SpawnRedir(const char* path, const char* args) {
|
static int Sys_SpawnRedir(const char* path, const char* args) {
|
||||||
int childPid = Sched::Spawn(path, args);
|
char resolved[256];
|
||||||
|
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||||
|
|
||||||
|
int childPid = Sched::Spawn(resolved, args);
|
||||||
if (childPid < 0) return -1;
|
if (childPid < 0) return -1;
|
||||||
|
|
||||||
auto* child = Sched::GetProcessByPid(childPid);
|
auto* child = Sched::GetProcessByPid(childPid);
|
||||||
|
|||||||
@@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
* Path.hpp
|
||||||
|
* Per-process working-directory path resolution helpers
|
||||||
|
* Copyright (c) 2026 Daniel Hammer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <cstddef>
|
||||||
|
#include <Sched/Scheduler.hpp>
|
||||||
|
#include <Libraries/Memory.hpp>
|
||||||
|
|
||||||
|
namespace Montauk {
|
||||||
|
|
||||||
|
static int ParseDrivePrefix(const char* path, int* outPrefixLen = nullptr) {
|
||||||
|
if (path == nullptr || path[0] < '0' || path[0] > '9') return -1;
|
||||||
|
|
||||||
|
int drive = 0;
|
||||||
|
int i = 0;
|
||||||
|
while (path[i] >= '0' && path[i] <= '9') {
|
||||||
|
drive = drive * 10 + (path[i] - '0');
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path[i] != ':') return -1;
|
||||||
|
if (outPrefixLen) *outPrefixLen = i + 1;
|
||||||
|
return drive;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int WriteDriveRoot(char* out, int outMax, int drive) {
|
||||||
|
if (out == nullptr || outMax < 4 || drive < 0) return -1;
|
||||||
|
|
||||||
|
char digits[12];
|
||||||
|
int digitCount = 0;
|
||||||
|
do {
|
||||||
|
digits[digitCount++] = (char)('0' + (drive % 10));
|
||||||
|
drive /= 10;
|
||||||
|
} while (drive > 0 && digitCount < (int)sizeof(digits));
|
||||||
|
|
||||||
|
if (digitCount + 2 >= outMax) return -1;
|
||||||
|
|
||||||
|
int len = 0;
|
||||||
|
for (int i = digitCount - 1; i >= 0; i--) out[len++] = digits[i];
|
||||||
|
out[len++] = ':';
|
||||||
|
out[len++] = '/';
|
||||||
|
out[len] = '\0';
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool AppendPathSegment(char* out, int outMax, int& len, int rootLen,
|
||||||
|
int* segmentBases, int& segmentCount,
|
||||||
|
const char* segment, int segmentLen) {
|
||||||
|
if (segmentLen <= 0) return true;
|
||||||
|
if (segmentLen == 1 && segment[0] == '.') return true;
|
||||||
|
|
||||||
|
if (segmentLen == 2 && segment[0] == '.' && segment[1] == '.') {
|
||||||
|
if (segmentCount > 0) {
|
||||||
|
len = segmentBases[--segmentCount];
|
||||||
|
out[len] = '\0';
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (segmentCount >= 64) return false;
|
||||||
|
|
||||||
|
int baseLen = len;
|
||||||
|
if (len > rootLen) {
|
||||||
|
if (len >= outMax - 1) return false;
|
||||||
|
out[len++] = '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len + segmentLen >= outMax) return false;
|
||||||
|
memcpy(out + len, segment, (std::size_t)segmentLen);
|
||||||
|
len += segmentLen;
|
||||||
|
out[len] = '\0';
|
||||||
|
segmentBases[segmentCount++] = baseLen;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool NormalizePathInto(char* out, int outMax, int& len, int rootLen,
|
||||||
|
int* segmentBases, int& segmentCount,
|
||||||
|
const char* path) {
|
||||||
|
const char* segmentStart = path;
|
||||||
|
for (const char* p = path;; ++p) {
|
||||||
|
if (*p == '/' || *p == '\0') {
|
||||||
|
if (!AppendPathSegment(out, outMax, len, rootLen, segmentBases,
|
||||||
|
segmentCount, segmentStart, (int)(p - segmentStart))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (*p == '\0') break;
|
||||||
|
segmentStart = p + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ResolvePathAgainst(const char* cwd, const char* path, char* out, int outMax) {
|
||||||
|
if (cwd == nullptr || path == nullptr || out == nullptr || outMax < 4 || path[0] == '\0') return false;
|
||||||
|
|
||||||
|
int drive = -1;
|
||||||
|
int inputPrefixLen = 0;
|
||||||
|
const char* remainder = path;
|
||||||
|
bool useCwdBase = false;
|
||||||
|
|
||||||
|
drive = ParseDrivePrefix(path, &inputPrefixLen);
|
||||||
|
if (drive >= 0) {
|
||||||
|
remainder = path + inputPrefixLen;
|
||||||
|
if (*remainder == '/') remainder++;
|
||||||
|
} else if (path[0] == '/') {
|
||||||
|
drive = ParseDrivePrefix(cwd);
|
||||||
|
if (drive < 0) return false;
|
||||||
|
remainder = path + 1;
|
||||||
|
} else {
|
||||||
|
drive = ParseDrivePrefix(cwd);
|
||||||
|
if (drive < 0) return false;
|
||||||
|
useCwdBase = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int segmentBases[64];
|
||||||
|
int segmentCount = 0;
|
||||||
|
int len = WriteDriveRoot(out, outMax, drive);
|
||||||
|
if (len < 0) return false;
|
||||||
|
int rootLen = len;
|
||||||
|
|
||||||
|
if (useCwdBase) {
|
||||||
|
int cwdPrefixLen = 0;
|
||||||
|
if (ParseDrivePrefix(cwd, &cwdPrefixLen) < 0) return false;
|
||||||
|
|
||||||
|
const char* cwdRemainder = cwd + cwdPrefixLen;
|
||||||
|
if (*cwdRemainder == '/') cwdRemainder++;
|
||||||
|
if (!NormalizePathInto(out, outMax, len, rootLen, segmentBases, segmentCount, cwdRemainder)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NormalizePathInto(out, outMax, len, rootLen, segmentBases, segmentCount, remainder);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ResolveProcessPath(const char* path, char* out, int outMax) {
|
||||||
|
auto* proc = Sched::GetCurrentProcessPtr();
|
||||||
|
const char* cwd = (proc && proc->cwd[0]) ? proc->cwd : "0:/";
|
||||||
|
return ResolvePathAgainst(cwd, path, out, outMax);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,9 +11,11 @@
|
|||||||
#include <Memory/Paging.hpp>
|
#include <Memory/Paging.hpp>
|
||||||
#include <Memory/PageFrameAllocator.hpp>
|
#include <Memory/PageFrameAllocator.hpp>
|
||||||
#include <Memory/HHDM.hpp>
|
#include <Memory/HHDM.hpp>
|
||||||
|
#include <Fs/Vfs.hpp>
|
||||||
|
|
||||||
#include "Syscall.hpp"
|
#include "Syscall.hpp"
|
||||||
#include "WinServer.hpp"
|
#include "WinServer.hpp"
|
||||||
|
#include "Path.hpp"
|
||||||
|
|
||||||
namespace Montauk {
|
namespace Montauk {
|
||||||
static void Sys_Exit(int exitCode) {
|
static void Sys_Exit(int exitCode) {
|
||||||
@@ -38,8 +40,11 @@ namespace Montauk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int Sys_Spawn(const char* path, const char* args) {
|
static int Sys_Spawn(const char* path, const char* args) {
|
||||||
|
char resolved[256];
|
||||||
|
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||||
|
|
||||||
auto* parent = Sched::GetCurrentProcessPtr();
|
auto* parent = Sched::GetCurrentProcessPtr();
|
||||||
int childPid = Sched::Spawn(path, args);
|
int childPid = Sched::Spawn(resolved, args);
|
||||||
if (childPid < 0) return childPid;
|
if (childPid < 0) return childPid;
|
||||||
|
|
||||||
// Inherit I/O redirection: if the parent is redirected, the child
|
// Inherit I/O redirection: if the parent is redirected, the child
|
||||||
@@ -120,4 +125,46 @@ namespace Montauk {
|
|||||||
buf[i] = '\0';
|
buf[i] = '\0';
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int Sys_GetCwd(char* buf, uint64_t maxLen) {
|
||||||
|
auto* proc = Sched::GetCurrentProcessPtr();
|
||||||
|
if (proc == nullptr || buf == nullptr || maxLen == 0) return -1;
|
||||||
|
|
||||||
|
const char* cwd = proc->cwd[0] ? proc->cwd : "0:/";
|
||||||
|
int i = 0;
|
||||||
|
for (; i < (int)maxLen - 1 && cwd[i]; i++) buf[i] = cwd[i];
|
||||||
|
buf[i] = '\0';
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Sys_Chdir(const char* path) {
|
||||||
|
auto* proc = Sched::GetCurrentProcessPtr();
|
||||||
|
if (proc == nullptr || path == nullptr) return -1;
|
||||||
|
|
||||||
|
char resolved[256];
|
||||||
|
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||||
|
|
||||||
|
bool isDriveRoot = false;
|
||||||
|
{
|
||||||
|
int prefixLen = 0;
|
||||||
|
if (ParseDrivePrefix(resolved, &prefixLen) >= 0 &&
|
||||||
|
resolved[prefixLen] == '/' && resolved[prefixLen + 1] == '\0') {
|
||||||
|
isDriveRoot = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDriveRoot) {
|
||||||
|
const char* entries[1];
|
||||||
|
if (Fs::Vfs::VfsReadDir(resolved, entries, 1) < 0) return -1;
|
||||||
|
} else {
|
||||||
|
int handle = Fs::Vfs::VfsOpen(resolved);
|
||||||
|
if (handle < 0) return -1;
|
||||||
|
Fs::Vfs::VfsClose(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (; i < 255 && resolved[i]; i++) proc->cwd[i] = resolved[i];
|
||||||
|
proc->cwd[i] = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
@@ -347,6 +347,12 @@ namespace Montauk {
|
|||||||
case SYS_GETUSER:
|
case SYS_GETUSER:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return Sys_GetUser((char*)frame->arg1, frame->arg2);
|
return Sys_GetUser((char*)frame->arg1, frame->arg2);
|
||||||
|
case SYS_GETCWD:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
|
return Sys_GetCwd((char*)frame->arg1, frame->arg2);
|
||||||
|
case SYS_CHDIR:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
|
return Sys_Chdir((const char*)frame->arg1);
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,6 +184,8 @@ namespace Montauk {
|
|||||||
|
|
||||||
/* Filesystem.hpp */
|
/* Filesystem.hpp */
|
||||||
static constexpr uint64_t SYS_FRENAME = 94;
|
static constexpr uint64_t SYS_FRENAME = 94;
|
||||||
|
static constexpr uint64_t SYS_GETCWD = 95;
|
||||||
|
static constexpr uint64_t SYS_CHDIR = 96;
|
||||||
|
|
||||||
static constexpr int SOCK_TCP = 1;
|
static constexpr int SOCK_TCP = 1;
|
||||||
static constexpr int SOCK_UDP = 2;
|
static constexpr int SOCK_UDP = 2;
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ namespace Sched {
|
|||||||
processTable[i].heapNext = 0;
|
processTable[i].heapNext = 0;
|
||||||
processTable[i].args[0] = '\0';
|
processTable[i].args[0] = '\0';
|
||||||
processTable[i].user[0] = '\0';
|
processTable[i].user[0] = '\0';
|
||||||
|
processTable[i].cwd[0] = '\0';
|
||||||
processTable[i].runningOnCpu = -1;
|
processTable[i].runningOnCpu = -1;
|
||||||
processTable[i].killPending = false;
|
processTable[i].killPending = false;
|
||||||
processTable[i].waitingForPid = -1;
|
processTable[i].waitingForPid = -1;
|
||||||
@@ -301,6 +302,23 @@ namespace Sched {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto* cpu = Smp::GetCurrentCpuData();
|
||||||
|
int parentSlot = cpu->currentSlot;
|
||||||
|
if (parentSlot >= 0 && processTable[parentSlot].cwd[0]) {
|
||||||
|
int i = 0;
|
||||||
|
for (; i < 255 && processTable[parentSlot].cwd[i]; i++) {
|
||||||
|
proc.cwd[i] = processTable[parentSlot].cwd[i];
|
||||||
|
}
|
||||||
|
proc.cwd[i] = '\0';
|
||||||
|
} else {
|
||||||
|
proc.cwd[0] = '0';
|
||||||
|
proc.cwd[1] = ':';
|
||||||
|
proc.cwd[2] = '/';
|
||||||
|
proc.cwd[3] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
proc.redirected = false;
|
proc.redirected = false;
|
||||||
proc.parentPid = -1;
|
proc.parentPid = -1;
|
||||||
proc.outBuf = nullptr;
|
proc.outBuf = nullptr;
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ namespace Sched {
|
|||||||
uint64_t heapNext; // Simple bump allocator for user heap
|
uint64_t heapNext; // Simple bump allocator for user heap
|
||||||
char args[256]; // Command-line arguments (set by parent via Spawn)
|
char args[256]; // Command-line arguments (set by parent via Spawn)
|
||||||
char user[32]; // Owner user name (inherited from parent on spawn)
|
char user[32]; // Owner user name (inherited from parent on spawn)
|
||||||
|
char cwd[256]; // Absolute current working directory
|
||||||
|
|
||||||
int runningOnCpu; // CPU index running this process (-1 if not running)
|
int runningOnCpu; // CPU index running this process (-1 if not running)
|
||||||
bool killPending = false; // Set by Sys_Kill when target is running on another CPU
|
bool killPending = false; // Set by Sys_Kill when target is running on another CPU
|
||||||
|
|||||||
@@ -123,6 +123,9 @@ namespace Montauk {
|
|||||||
// User management
|
// User management
|
||||||
static constexpr uint64_t SYS_SETUSER = 92;
|
static constexpr uint64_t SYS_SETUSER = 92;
|
||||||
static constexpr uint64_t SYS_GETUSER = 93;
|
static constexpr uint64_t SYS_GETUSER = 93;
|
||||||
|
static constexpr uint64_t SYS_FRENAME = 94;
|
||||||
|
static constexpr uint64_t SYS_GETCWD = 95;
|
||||||
|
static constexpr uint64_t SYS_CHDIR = 96;
|
||||||
|
|
||||||
// Audio control commands (for SYS_AUDIOCTL)
|
// Audio control commands (for SYS_AUDIOCTL)
|
||||||
static constexpr int AUDIO_CTL_SET_VOLUME = 0;
|
static constexpr int AUDIO_CTL_SET_VOLUME = 0;
|
||||||
|
|||||||
@@ -97,6 +97,8 @@ extern "C" {
|
|||||||
#define MTK_SYS_AUDIOCTL 83
|
#define MTK_SYS_AUDIOCTL 83
|
||||||
#define MTK_SYS_SETTZ 90
|
#define MTK_SYS_SETTZ 90
|
||||||
#define MTK_SYS_GETTZ 91
|
#define MTK_SYS_GETTZ 91
|
||||||
|
#define MTK_SYS_GETCWD 95
|
||||||
|
#define MTK_SYS_CHDIR 96
|
||||||
|
|
||||||
#define MTK_SOCK_TCP 1
|
#define MTK_SOCK_TCP 1
|
||||||
#define MTK_SOCK_UDP 2
|
#define MTK_SOCK_UDP 2
|
||||||
@@ -318,6 +320,14 @@ static inline int mtk_getargs(char *buf, unsigned long max_len) {
|
|||||||
return (int)_mtk_syscall2(MTK_SYS_GETARGS, (long)buf, (long)max_len);
|
return (int)_mtk_syscall2(MTK_SYS_GETARGS, (long)buf, (long)max_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int mtk_chdir(const char *path) {
|
||||||
|
return (int)_mtk_syscall1(MTK_SYS_CHDIR, (long)path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int mtk_getcwd(char *buf, unsigned long max_len) {
|
||||||
|
return (int)_mtk_syscall2(MTK_SYS_GETCWD, (long)buf, (long)max_len);
|
||||||
|
}
|
||||||
|
|
||||||
/* ====================================================================
|
/* ====================================================================
|
||||||
Console I/O
|
Console I/O
|
||||||
==================================================================== */
|
==================================================================== */
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ int read(int fd, void *buf, size_t count);
|
|||||||
int write(int fd, const void *buf, size_t count);
|
int write(int fd, const void *buf, size_t count);
|
||||||
int close(int fd);
|
int close(int fd);
|
||||||
long lseek(int fd, long offset, int whence);
|
long lseek(int fd, long offset, int whence);
|
||||||
|
int chdir(const char *path);
|
||||||
|
char *getcwd(char *buf, size_t size);
|
||||||
|
|
||||||
unsigned int sleep(unsigned int seconds);
|
unsigned int sleep(unsigned int seconds);
|
||||||
|
|
||||||
|
|||||||
@@ -120,6 +120,12 @@ namespace montauk {
|
|||||||
inline int spawn(const char* path, const char* args = nullptr) {
|
inline int spawn(const char* path, const char* args = nullptr) {
|
||||||
return (int)syscall2(Montauk::SYS_SPAWN, (uint64_t)path, (uint64_t)args);
|
return (int)syscall2(Montauk::SYS_SPAWN, (uint64_t)path, (uint64_t)args);
|
||||||
}
|
}
|
||||||
|
inline int chdir(const char* path) {
|
||||||
|
return (int)syscall1(Montauk::SYS_CHDIR, (uint64_t)path);
|
||||||
|
}
|
||||||
|
inline int getcwd(char* buf, uint64_t maxLen) {
|
||||||
|
return (int)syscall2(Montauk::SYS_GETCWD, (uint64_t)buf, maxLen);
|
||||||
|
}
|
||||||
|
|
||||||
// Console
|
// Console
|
||||||
inline void print(const char* text) { syscall1(Montauk::SYS_PRINT, (uint64_t)text); }
|
inline void print(const char* text) { syscall1(Montauk::SYS_PRINT, (uint64_t)text); }
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
/* ========================================================================
|
/* ========================================================================
|
||||||
@@ -96,6 +97,8 @@ static inline long _zos_syscall4(long nr, long a1, long a2, long a3, long a4) {
|
|||||||
#define SYS_FDELETE 77
|
#define SYS_FDELETE 77
|
||||||
#define SYS_FMKDIR 78
|
#define SYS_FMKDIR 78
|
||||||
#define SYS_FRENAME 94
|
#define SYS_FRENAME 94
|
||||||
|
#define SYS_GETCWD 95
|
||||||
|
#define SYS_CHDIR 96
|
||||||
|
|
||||||
/* ========================================================================
|
/* ========================================================================
|
||||||
errno
|
errno
|
||||||
@@ -1395,6 +1398,30 @@ long lseek(int fd, long offset, int whence) {
|
|||||||
return (long)newpos;
|
return (long)newpos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int chdir(const char *path) {
|
||||||
|
if (path == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((int)_zos_syscall1(SYS_CHDIR, (long)path) < 0) {
|
||||||
|
errno = ENOENT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *getcwd(char *buf, size_t size) {
|
||||||
|
if (buf == NULL || size == 0) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if ((int)_zos_syscall2(SYS_GETCWD, (long)buf, (long)size) < 0) {
|
||||||
|
errno = ERANGE;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
/* ========================================================================
|
/* ========================================================================
|
||||||
sys/stat.h functions
|
sys/stat.h functions
|
||||||
======================================================================== */
|
======================================================================== */
|
||||||
|
|||||||
Binary file not shown.
@@ -11,22 +11,16 @@ extern "C" void _start() {
|
|||||||
char args[256];
|
char args[256];
|
||||||
montauk::getargs((char *)&args, 256);
|
montauk::getargs((char *)&args, 256);
|
||||||
|
|
||||||
if (*args) {
|
const char* path = montauk::skip_spaces((const char *)&args);
|
||||||
const char* arg = montauk::skip_spaces((const char *)&args);
|
if (*path == '\0') {
|
||||||
|
|
||||||
if (*arg != '\0') {
|
|
||||||
int fd = montauk::open(arg);
|
|
||||||
if (fd < 0) {
|
|
||||||
montauk::print("file not found\n");
|
|
||||||
} else {
|
|
||||||
montauk::close(fd);
|
|
||||||
montauk::fdelete(arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
montauk::print("usage: rm [file]\n");
|
montauk::print("usage: rm [file]\n");
|
||||||
montauk::exit(-1);
|
montauk::exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (montauk::fdelete(path) < 0) {
|
||||||
|
montauk::print("rm: failed to remove file\n");
|
||||||
|
montauk::exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
montauk::exit(0);
|
montauk::exit(0);
|
||||||
}
|
}
|
||||||
+26
-148
@@ -6,6 +6,21 @@
|
|||||||
|
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
|
|
||||||
|
static void print_ls_entry(const char* entry) {
|
||||||
|
int len = slen(entry);
|
||||||
|
bool hadTrailingSlash = len > 0 && entry[len - 1] == '/';
|
||||||
|
|
||||||
|
while (len > 0 && entry[len - 1] == '/') len--;
|
||||||
|
|
||||||
|
int base = 0;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
if (entry[i] == '/') base = i + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = base; i < len; i++) montauk::putchar(entry[i]);
|
||||||
|
if (hadTrailingSlash) montauk::putchar('/');
|
||||||
|
}
|
||||||
|
|
||||||
// ---- help ----
|
// ---- help ----
|
||||||
|
|
||||||
void cmd_help() {
|
void cmd_help() {
|
||||||
@@ -67,28 +82,9 @@ void cmd_help() {
|
|||||||
void cmd_ls(const char* arg) {
|
void cmd_ls(const char* arg) {
|
||||||
arg = skip_spaces(arg);
|
arg = skip_spaces(arg);
|
||||||
|
|
||||||
char dir[128];
|
|
||||||
int drive = current_drive;
|
|
||||||
if (*arg) {
|
|
||||||
if (has_drive_prefix(arg)) {
|
|
||||||
drive = parse_drive_prefix(arg);
|
|
||||||
int plen = drive_prefix_len(arg);
|
|
||||||
scopy(dir, arg + plen + 1, sizeof(dir));
|
|
||||||
} else if (arg[0] == '/') {
|
|
||||||
scopy(dir, arg + 1, sizeof(dir));
|
|
||||||
} else if (cwd[0]) {
|
|
||||||
scopy(dir, cwd, sizeof(dir));
|
|
||||||
scat(dir, "/", sizeof(dir));
|
|
||||||
scat(dir, arg, sizeof(dir));
|
|
||||||
} else {
|
|
||||||
scopy(dir, arg, sizeof(dir));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
scopy(dir, cwd, sizeof(dir));
|
|
||||||
}
|
|
||||||
|
|
||||||
char path[128];
|
char path[128];
|
||||||
build_drive_path(drive, dir, path, sizeof(path));
|
if (*arg) scopy(path, arg, sizeof(path));
|
||||||
|
else scopy(path, ".", sizeof(path));
|
||||||
|
|
||||||
const char* entries[64];
|
const char* entries[64];
|
||||||
int count = montauk::readdir(path, entries, 64);
|
int count = montauk::readdir(path, entries, 64);
|
||||||
@@ -97,16 +93,9 @@ void cmd_ls(const char* arg) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int prefixLen = 0;
|
|
||||||
if (dir[0]) prefixLen = slen(dir) + 1;
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
montauk::print(" ");
|
montauk::print(" ");
|
||||||
if (prefixLen > 0 && starts_with(entries[i], dir)) {
|
print_ls_entry(entries[i]);
|
||||||
montauk::print(entries[i] + prefixLen);
|
|
||||||
} else {
|
|
||||||
montauk::print(entries[i]);
|
|
||||||
}
|
|
||||||
montauk::putchar('\n');
|
montauk::putchar('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,141 +105,30 @@ void cmd_ls(const char* arg) {
|
|||||||
bool switch_drive(int drive) {
|
bool switch_drive(int drive) {
|
||||||
char path[8];
|
char path[8];
|
||||||
build_drive_path(drive, "", path, sizeof(path));
|
build_drive_path(drive, "", path, sizeof(path));
|
||||||
const char* entries[1];
|
if (montauk::chdir(path) < 0) return false;
|
||||||
if (montauk::readdir(path, entries, 1) < 0) return false;
|
sync_cwd();
|
||||||
current_drive = drive;
|
|
||||||
cwd[0] = '\0';
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cmd_cd(const char* arg) {
|
int cmd_cd(const char* arg) {
|
||||||
arg = skip_spaces(arg);
|
arg = skip_spaces(arg);
|
||||||
|
|
||||||
// cd with no argument -> go to home directory (or root if no session)
|
|
||||||
if (*arg == '\0') {
|
|
||||||
if (session_home[0] && has_drive_prefix(session_home)) {
|
|
||||||
int drive = parse_drive_prefix(session_home);
|
|
||||||
int plen = drive_prefix_len(session_home);
|
|
||||||
const char* rel = session_home + plen;
|
|
||||||
if (*rel == '/') rel++;
|
|
||||||
current_drive = drive;
|
|
||||||
if (*rel) scopy(cwd, rel, sizeof(cwd));
|
|
||||||
else cwd[0] = '\0';
|
|
||||||
} else {
|
|
||||||
cwd[0] = '\0';
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// cd / -> go to root
|
|
||||||
if (streq(arg, "/")) {
|
|
||||||
cwd[0] = '\0';
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Strip trailing slashes from argument
|
|
||||||
static char argBuf[128];
|
|
||||||
int aLen = 0;
|
|
||||||
while (arg[aLen] && aLen < 127) { argBuf[aLen] = arg[aLen]; aLen++; }
|
|
||||||
argBuf[aLen] = '\0';
|
|
||||||
while (aLen > 0 && argBuf[aLen - 1] == '/') argBuf[--aLen] = '\0';
|
|
||||||
arg = argBuf;
|
|
||||||
|
|
||||||
if (*arg == '\0') {
|
|
||||||
cwd[0] = '\0';
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// cd .. -> go up one level
|
|
||||||
if (streq(arg, "..")) {
|
|
||||||
int len = slen(cwd);
|
|
||||||
int last = -1;
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
if (cwd[i] == '/') last = i;
|
|
||||||
}
|
|
||||||
if (last >= 0) {
|
|
||||||
cwd[last] = '\0';
|
|
||||||
} else {
|
|
||||||
cwd[0] = '\0';
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// cd /path -> absolute path from root
|
|
||||||
if (arg[0] == '/') {
|
|
||||||
arg++;
|
|
||||||
if (*arg == '\0') { cwd[0] = '\0'; return 0; }
|
|
||||||
char path[128];
|
|
||||||
build_dir_path(arg, path, sizeof(path));
|
|
||||||
const char* entries[1];
|
|
||||||
if (montauk::readdir(path, entries, 1) < 0) {
|
|
||||||
montauk::print("cd: no such directory: ");
|
|
||||||
montauk::print(arg);
|
|
||||||
montauk::putchar('\n');
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
scopy(cwd, arg, sizeof(cwd));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// cd N:/ or cd N:/path -> switch drive
|
|
||||||
if (has_drive_prefix(arg)) {
|
|
||||||
int drive = parse_drive_prefix(arg);
|
|
||||||
int plen = drive_prefix_len(arg);
|
|
||||||
const char* rel = arg + plen;
|
|
||||||
if (*rel == '/') rel++;
|
|
||||||
|
|
||||||
char rootPath[8];
|
|
||||||
build_drive_path(drive, "", rootPath, sizeof(rootPath));
|
|
||||||
const char* rootEntries[1];
|
|
||||||
if (montauk::readdir(rootPath, rootEntries, 1) < 0) {
|
|
||||||
montauk::print("cd: no such drive: ");
|
|
||||||
montauk::print(arg);
|
|
||||||
montauk::putchar('\n');
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*rel != '\0') {
|
|
||||||
char path[128];
|
|
||||||
build_drive_path(drive, rel, path, sizeof(path));
|
|
||||||
const char* entries[1];
|
|
||||||
if (montauk::readdir(path, entries, 1) < 0) {
|
|
||||||
montauk::print("cd: no such directory: ");
|
|
||||||
montauk::print(arg);
|
|
||||||
montauk::putchar('\n');
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
current_drive = drive;
|
|
||||||
scopy(cwd, rel, sizeof(cwd));
|
|
||||||
} else {
|
|
||||||
current_drive = drive;
|
|
||||||
cwd[0] = '\0';
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Relative path
|
|
||||||
char target[128];
|
char target[128];
|
||||||
if (cwd[0]) {
|
if (*arg == '\0') {
|
||||||
scopy(target, cwd, sizeof(target));
|
if (session_home[0]) scopy(target, session_home, sizeof(target));
|
||||||
scat(target, "/", sizeof(target));
|
else scopy(target, "/", sizeof(target));
|
||||||
scat(target, arg, sizeof(target));
|
|
||||||
} else {
|
} else {
|
||||||
scopy(target, arg, sizeof(target));
|
scopy(target, arg, sizeof(target));
|
||||||
}
|
}
|
||||||
|
|
||||||
char path[128];
|
if (montauk::chdir(target) < 0) {
|
||||||
build_dir_path(target, path, sizeof(path));
|
|
||||||
const char* entries[1];
|
|
||||||
int count = montauk::readdir(path, entries, 1);
|
|
||||||
if (count < 0) {
|
|
||||||
montauk::print("cd: no such directory: ");
|
montauk::print("cd: no such directory: ");
|
||||||
montauk::print(arg);
|
montauk::print(target);
|
||||||
montauk::putchar('\n');
|
montauk::putchar('\n');
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
scopy(cwd, target, sizeof(cwd));
|
sync_cwd();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-65
@@ -36,81 +36,29 @@ static void build_cwd_path(const char* name, char* out, int outMax) {
|
|||||||
scat(out, name, outMax);
|
scat(out, name, outMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Resolve arguments: expand relative file paths against CWD ----
|
|
||||||
|
|
||||||
static void resolve_args(const char* args, char* out, int outMax) {
|
|
||||||
if (!args || !args[0]) { out[0] = '\0'; return; }
|
|
||||||
|
|
||||||
int o = 0;
|
|
||||||
const char* p = args;
|
|
||||||
|
|
||||||
while (*p && o < outMax - 1) {
|
|
||||||
while (*p == ' ' && o < outMax - 1) { out[o++] = *p++; }
|
|
||||||
if (!*p) break;
|
|
||||||
|
|
||||||
const char* tokStart = p;
|
|
||||||
int tokLen = 0;
|
|
||||||
while (p[tokLen] && p[tokLen] != ' ') tokLen++;
|
|
||||||
|
|
||||||
bool resolve = (cwd[0] || current_drive != 0) && !has_drive_prefix(tokStart) && tokStart[0] != '-';
|
|
||||||
|
|
||||||
if (resolve) {
|
|
||||||
char candidate[256];
|
|
||||||
int r = 0;
|
|
||||||
if (current_drive >= 10) candidate[r++] = '0' + current_drive / 10;
|
|
||||||
candidate[r++] = '0' + current_drive % 10;
|
|
||||||
candidate[r++] = ':'; candidate[r++] = '/';
|
|
||||||
int j = 0;
|
|
||||||
while (cwd[j] && r < 255) candidate[r++] = cwd[j++];
|
|
||||||
if (cwd[0] && r < 255) candidate[r++] = '/';
|
|
||||||
|
|
||||||
// Strip leading "./" from token
|
|
||||||
int skip = 0;
|
|
||||||
if (tokLen >= 2 && tokStart[0] == '.' && tokStart[1] == '/') skip = 2;
|
|
||||||
|
|
||||||
for (int k = skip; k < tokLen && r < 255; k++) candidate[r++] = tokStart[k];
|
|
||||||
candidate[r] = '\0';
|
|
||||||
|
|
||||||
int h = montauk::open(candidate);
|
|
||||||
if (h >= 0) {
|
|
||||||
montauk::close(h);
|
|
||||||
for (int k = 0; k < r && o < outMax - 1; k++) out[o++] = candidate[k];
|
|
||||||
} else {
|
|
||||||
bool looksLikeFile = false;
|
|
||||||
for (int k = 0; k < tokLen; k++) {
|
|
||||||
if (tokStart[k] == '.') { looksLikeFile = true; break; }
|
|
||||||
}
|
|
||||||
if (looksLikeFile) {
|
|
||||||
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 {
|
|
||||||
for (int k = 0; k < tokLen && o < outMax - 1; k++) out[o++] = tokStart[k];
|
|
||||||
}
|
|
||||||
|
|
||||||
p = tokStart + tokLen;
|
|
||||||
}
|
|
||||||
out[o] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- Search and execute an external command ----
|
// ---- Search and execute an external command ----
|
||||||
|
|
||||||
int exec_external(const char* cmd, const char* args) {
|
int exec_external(const char* cmd, const char* args) {
|
||||||
char path[256];
|
char path[256];
|
||||||
|
const char* finalArgs = (args && args[0]) ? args : nullptr;
|
||||||
char resolvedArgs[512];
|
|
||||||
resolve_args(args, resolvedArgs, sizeof(resolvedArgs));
|
|
||||||
const char* finalArgs = resolvedArgs[0] ? resolvedArgs : nullptr;
|
|
||||||
|
|
||||||
// Strip leading "./" from command name
|
// Strip leading "./" from command name
|
||||||
const char* name = cmd;
|
const char* name = cmd;
|
||||||
if (name[0] == '.' && name[1] == '/') name += 2;
|
if (name[0] == '.' && name[1] == '/') name += 2;
|
||||||
|
|
||||||
// 0. If cmd has a drive prefix (absolute path), try it directly
|
// 0. Direct paths are resolved by the kernel against the process CWD.
|
||||||
if (has_drive_prefix(cmd)) {
|
bool hasSlash = false;
|
||||||
|
for (int i = 0; cmd[i]; i++) {
|
||||||
|
if (cmd[i] == '/') {
|
||||||
|
hasSlash = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (has_drive_prefix(cmd) || cmd[0] == '/' || cmd[0] == '.' || hasSlash) {
|
||||||
if (try_exec(cmd, finalArgs)) return 0;
|
if (try_exec(cmd, finalArgs)) return 0;
|
||||||
|
scopy(path, cmd, sizeof(path));
|
||||||
|
scat(path, ".elf", sizeof(path));
|
||||||
|
if (try_exec(path, finalArgs)) return 0;
|
||||||
montauk::print(cmd);
|
montauk::print(cmd);
|
||||||
montauk::print(": not found\n");
|
montauk::print(": not found\n");
|
||||||
return 127;
|
return 127;
|
||||||
|
|||||||
@@ -14,6 +14,28 @@ int last_exit = 0;
|
|||||||
char session_user[32] = "";
|
char session_user[32] = "";
|
||||||
char session_home[64] = "";
|
char session_home[64] = "";
|
||||||
|
|
||||||
|
void sync_cwd() {
|
||||||
|
char abs[128];
|
||||||
|
if (montauk::getcwd(abs, sizeof(abs)) < 0) {
|
||||||
|
current_drive = 0;
|
||||||
|
cwd[0] = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int drive = parse_drive_prefix(abs);
|
||||||
|
if (drive < 0) {
|
||||||
|
current_drive = 0;
|
||||||
|
cwd[0] = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_drive = drive;
|
||||||
|
int plen = drive_prefix_len(abs);
|
||||||
|
const char* rel = abs + plen;
|
||||||
|
if (*rel == '/') rel++;
|
||||||
|
scopy(cwd, rel, sizeof(cwd));
|
||||||
|
}
|
||||||
|
|
||||||
// ---- Session info (read once at startup) ----
|
// ---- Session info (read once at startup) ----
|
||||||
|
|
||||||
void read_session() {
|
void read_session() {
|
||||||
@@ -165,6 +187,7 @@ static int process_command(const char* line) {
|
|||||||
if (streq(cmd, "false")) { return 1; }
|
if (streq(cmd, "false")) { return 1; }
|
||||||
|
|
||||||
if (streq(cmd, "pwd")) {
|
if (streq(cmd, "pwd")) {
|
||||||
|
sync_cwd();
|
||||||
char path[128];
|
char path[128];
|
||||||
build_dir_path(cwd, path, sizeof(path));
|
build_dir_path(cwd, path, sizeof(path));
|
||||||
montauk::print(path);
|
montauk::print(path);
|
||||||
@@ -202,6 +225,7 @@ static int process_command(const char* line) {
|
|||||||
montauk::print(session_home);
|
montauk::print(session_home);
|
||||||
montauk::putchar('\n');
|
montauk::putchar('\n');
|
||||||
}
|
}
|
||||||
|
sync_cwd();
|
||||||
char path[128];
|
char path[128];
|
||||||
build_dir_path(cwd, path, sizeof(path));
|
build_dir_path(cwd, path, sizeof(path));
|
||||||
montauk::print("PWD=");
|
montauk::print("PWD=");
|
||||||
@@ -331,6 +355,7 @@ static constexpr uint8_t SC_RIGHT = 0x4D;
|
|||||||
// ---- Entry point ----
|
// ---- Entry point ----
|
||||||
|
|
||||||
extern "C" void _start() {
|
extern "C" void _start() {
|
||||||
|
sync_cwd();
|
||||||
read_session();
|
read_session();
|
||||||
|
|
||||||
montauk::print("\n");
|
montauk::print("\n");
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ const char* var_user_value(int idx);
|
|||||||
// ---- Session (main.cpp) ----
|
// ---- Session (main.cpp) ----
|
||||||
|
|
||||||
void read_session();
|
void read_session();
|
||||||
|
void sync_cwd();
|
||||||
|
|
||||||
// ---- Builtins (builtins.cpp) ----
|
// ---- Builtins (builtins.cpp) ----
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ const char* var_get(const char* name) {
|
|||||||
if (streq(name, "USER")) return session_user[0] ? session_user : nullptr;
|
if (streq(name, "USER")) return session_user[0] ? session_user : nullptr;
|
||||||
if (streq(name, "HOME")) return session_home[0] ? session_home : nullptr;
|
if (streq(name, "HOME")) return session_home[0] ? session_home : nullptr;
|
||||||
if (streq(name, "PWD")) {
|
if (streq(name, "PWD")) {
|
||||||
|
sync_cwd();
|
||||||
build_dir_path(cwd, synth, sizeof(synth));
|
build_dir_path(cwd, synth, sizeof(synth));
|
||||||
return synth;
|
return synth;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,19 +72,8 @@ static inline int gettimeofday(struct timeval *tv, struct timezone *tz) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ====================================================================
|
/* getcwd is provided by libc now */
|
||||||
getcwd stub (for debug info)
|
char *getcwd(char *buf, size_t size);
|
||||||
==================================================================== */
|
|
||||||
|
|
||||||
static inline char *getcwd(char *buf, size_t size) {
|
|
||||||
if (buf && size > 4) {
|
|
||||||
buf[0] = '0';
|
|
||||||
buf[1] = ':';
|
|
||||||
buf[2] = '/';
|
|
||||||
buf[3] = '\0';
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ====================================================================
|
/* ====================================================================
|
||||||
POSIX file access stubs
|
POSIX file access stubs
|
||||||
|
|||||||
+17
-14
@@ -11,21 +11,24 @@ extern "C" void _start() {
|
|||||||
char args[256];
|
char args[256];
|
||||||
montauk::getargs((char *)&args, 256);
|
montauk::getargs((char *)&args, 256);
|
||||||
|
|
||||||
if (*args) {
|
const char* path = montauk::skip_spaces((const char *)&args);
|
||||||
const char* arg = montauk::skip_spaces((const char *)&args);
|
if (*path == '\0') {
|
||||||
int fd = montauk::open(arg);
|
|
||||||
montauk::close(fd);
|
|
||||||
|
|
||||||
if (fd >= 0) { /* file already exists */
|
|
||||||
montauk::exit(0);
|
|
||||||
} else {
|
|
||||||
int fd = montauk::fcreate(arg);
|
|
||||||
montauk::close(fd);
|
|
||||||
|
|
||||||
montauk::exit(0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
montauk::print("usage: touch [filename]\n");
|
montauk::print("usage: touch [filename]\n");
|
||||||
montauk::exit(-1);
|
montauk::exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fd = montauk::open(path);
|
||||||
|
if (fd >= 0) {
|
||||||
|
montauk::close(fd);
|
||||||
|
montauk::exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = montauk::fcreate(path);
|
||||||
|
if (fd < 0) {
|
||||||
|
montauk::print("touch: failed to create file\n");
|
||||||
|
montauk::exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
montauk::close(fd);
|
||||||
|
montauk::exit(0);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user