diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 50dbca98..a124e6b3 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -64,7 +64,7 @@ namespace Kernel BAN::ErrorOr tell(int fd); BAN::ErrorOr fstat(int fd, struct stat*); - BAN::ErrorOr stat(BAN::StringView path, struct stat*); + BAN::ErrorOr stat(BAN::StringView path, struct stat*, int flags); BAN::ErrorOr mount(BAN::StringView source, BAN::StringView target); diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index c135a420..ebdba27d 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -522,9 +522,9 @@ namespace Kernel return {}; } - BAN::ErrorOr Process::stat(BAN::StringView path, struct stat* out) + BAN::ErrorOr Process::stat(BAN::StringView path, struct stat* out, int flags) { - int fd = TRY(open(path, O_RDONLY | O_NOFOLLOW)); + int fd = TRY(open(path, flags)); auto ret = fstat(fd, out); MUST(close(fd)); return ret; diff --git a/kernel/kernel/Shell.cpp b/kernel/kernel/Shell.cpp index 50753d32..5b89ceca 100644 --- a/kernel/kernel/Shell.cpp +++ b/kernel/kernel/Shell.cpp @@ -534,7 +534,7 @@ argument_done: BAN::String entry_path; TRY(entry_path.append(entry_prefix)); TRY(entry_path.append(entry)); - TRY(Process::current().stat(entry_path, &st)); + TRY(Process::current().stat(entry_path, &st, O_RDONLY | O_NOFOLLOW)); Inode::Mode mode { st.st_mode }; @@ -577,7 +577,7 @@ argument_done: } struct stat st; - TRY(Process::current().stat(arguments[1], &st)); + TRY(Process::current().stat(arguments[1], &st, O_RDONLY | O_NOFOLLOW)); Inode::Mode mode { st.st_mode }; diff --git a/kernel/kernel/Syscall.cpp b/kernel/kernel/Syscall.cpp index 44427e69..034c52aa 100644 --- a/kernel/kernel/Syscall.cpp +++ b/kernel/kernel/Syscall.cpp @@ -128,6 +128,14 @@ namespace Kernel return ret.value(); } + long sys_stat(const char* path, struct stat* buf, int flags) + { + auto ret = Process::current().stat(path, buf, flags); + if (ret.is_error()) + return -ret.error().get_error_code(); + return 0; + } + extern "C" long sys_fork_trampoline(); extern "C" long cpp_syscall_handler(int syscall, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5) @@ -193,6 +201,9 @@ namespace Kernel case SYS_WAIT: ret = sys_wait((pid_t)arg1, (int*)arg2, (int)arg3); break; + case SYS_STAT: + ret = sys_stat((const char*)arg1, (struct stat*)arg2, (int)arg3); + break; default: Kernel::panic("Unknown syscall {}", syscall); } diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index 74f45ca0..eb264f67 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -180,8 +180,8 @@ static void init2(void* tty1) ((TTY*)tty1)->initialize_device(); - //MUST(Process::create_userspace("/usr/bin/test"sv)); - //return; + MUST(Process::create_userspace("/usr/bin/Shell"sv)); + return; Process::create_kernel( [](void*) diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index 14eee1c2..8717a5c6 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -10,6 +10,7 @@ set(LIBC_SOURCES stdio.cpp stdlib.cpp string.cpp + sys/stat.cpp sys/wait.cpp termios.cpp unistd.cpp diff --git a/libc/include/sys/syscall.h b/libc/include/sys/syscall.h index 6a04fb2d..787ef2aa 100644 --- a/libc/include/sys/syscall.h +++ b/libc/include/sys/syscall.h @@ -22,6 +22,7 @@ __BEGIN_DECLS #define SYS_EXEC 15 #define SYS_REALLOC 16 #define SYS_WAIT 17 +#define SYS_STAT 18 __END_DECLS diff --git a/libc/sys/stat.cpp b/libc/sys/stat.cpp new file mode 100644 index 00000000..4996e8f7 --- /dev/null +++ b/libc/sys/stat.cpp @@ -0,0 +1,14 @@ +#include +#include +#include +#include + +int lstat(const char* __restrict path, struct stat* __restrict buf) +{ + return syscall(SYS_STAT, path, buf, O_RDONLY | O_NOFOLLOW); +} + +int stat(const char* __restrict path, struct stat* __restrict buf) +{ + return syscall(SYS_STAT, path, buf, O_RDONLY); +} diff --git a/libc/unistd.cpp b/libc/unistd.cpp index 81df889c..0d7dd6c4 100644 --- a/libc/unistd.cpp +++ b/libc/unistd.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -145,6 +146,14 @@ long syscall(long syscall, ...) ret = Kernel::syscall(SYS_WAIT, pid, (uintptr_t)stat_loc, options); break; } + case SYS_STAT: + { + const char* path = va_arg(args, const char*); + struct stat* buf = va_arg(args, struct stat*); + int flags = va_arg(args, int); + ret = Kernel::syscall(SYS_STAT, (uintptr_t)path, (uintptr_t)buf, flags); + break; + } default: puts("LibC: Unhandeled syscall"); ret = -ENOSYS; diff --git a/userspace/Shell/main.cpp b/userspace/Shell/main.cpp index 0de2a8fd..ff59c5ee 100644 --- a/userspace/Shell/main.cpp +++ b/userspace/Shell/main.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +43,13 @@ int execute_command(BAN::StringView command) } else { + struct stat stat_buf; + if (stat(args.front(), &stat_buf) == -1) + { + fprintf(stderr, "command not found: %s\n", args.front()); + return 1; + } + pid_t pid = fork(); if (pid == 0) { @@ -63,6 +71,28 @@ int execute_command(BAN::StringView command) return 0; } +int prompt_length(BAN::StringView prompt) +{ + int length { 0 }; + bool in_escape { false }; + for (char c : prompt) + { + if (in_escape) + { + if (isalpha(c)) + in_escape = false; + } + else + { + if (c == '\e') + in_escape = true; + else + length++; + } + } + return length; +} + int main(int argc, char** argv) { tcgetattr(0, &old_termios); @@ -102,8 +132,8 @@ int main(int argc, char** argv) fread(&c, 1, sizeof(char), stdin); switch (c) { - case 'A': if (index > 0) { index--; col = buffers[index].size(); fprintf(stdout, "\e[G%s\e[K", buffers[index].data()); fflush(stdout); } break; - case 'B': if (index < buffers.size() - 1) { index++; col = buffers[index].size(); fprintf(stdout, "\e[G%s\e[K", buffers[index].data()); fflush(stdout); } break; + case 'A': if (index > 0) { index--; col = buffers[index].size(); fprintf(stdout, "\e[%dG%s\e[K", prompt_length(prompt) + 1, buffers[index].data()); fflush(stdout); } break; + case 'B': if (index < buffers.size() - 1) { index++; col = buffers[index].size(); fprintf(stdout, "\e[%dG%s\e[K", prompt_length(prompt) + 1, buffers[index].data()); fflush(stdout); } break; case 'C': break; case 'D': break; }