From ab61b49aca271de66a049959620766c1938e2234 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Wed, 31 May 2023 20:57:33 +0300 Subject: [PATCH] Kernel: Add SYS_EXEC syscall --- kernel/kernel/Syscall.cpp | 11 +++++++++++ libc/include/sys/syscall.h | 1 + libc/unistd.cpp | 16 +++++++++++++++- userspace/test/test.cpp | 24 ++++++++---------------- 4 files changed, 35 insertions(+), 17 deletions(-) diff --git a/kernel/kernel/Syscall.cpp b/kernel/kernel/Syscall.cpp index 8030512ea..f7fd4012d 100644 --- a/kernel/kernel/Syscall.cpp +++ b/kernel/kernel/Syscall.cpp @@ -112,6 +112,14 @@ namespace Kernel return 0; } + long sys_exec(const char* pathname, const char* const* argv, const char* const* envp) + { + auto ret = Process::current().exec(pathname, argv, envp); + if (ret.is_error()) + return -ret.error().get_error_code(); + ASSERT_NOT_REACHED(); + } + 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) @@ -171,6 +179,9 @@ namespace Kernel case SYS_SLEEP: ret = sys_sleep((unsigned int)arg1); break; + case SYS_EXEC: + ret = sys_exec((const char*)arg1, (const char* const*)arg2, (const char* const*)arg3); + break; default: Kernel::panic("Unknown syscall {}", syscall); } diff --git a/libc/include/sys/syscall.h b/libc/include/sys/syscall.h index 1d9e67e68..a253b2141 100644 --- a/libc/include/sys/syscall.h +++ b/libc/include/sys/syscall.h @@ -19,6 +19,7 @@ __BEGIN_DECLS #define SYS_SET_TERMIOS 12 #define SYS_FORK 13 #define SYS_SLEEP 14 +#define SYS_EXEC 15 __END_DECLS diff --git a/libc/unistd.cpp b/libc/unistd.cpp index b1d3eec64..9c7918e54 100644 --- a/libc/unistd.cpp +++ b/libc/unistd.cpp @@ -2,8 +2,9 @@ #include #include #include -#include #include +#include +#include #include #include @@ -121,6 +122,14 @@ long syscall(long syscall, ...) ret = Kernel::syscall(SYS_SLEEP, seconds); break; } + case SYS_EXEC: + { + const char* pathname = va_arg(args, const char*); + const char* const* argv = va_arg(args, const char* const*); + const char* const* envp = va_arg(args, const char* const*); + ret = Kernel::syscall(SYS_EXEC, (uintptr_t)pathname, (uintptr_t)argv, (uintptr_t)envp); + break; + } default: puts("LibC: Unhandeled syscall"); ret = -ENOSYS; @@ -138,6 +147,11 @@ long syscall(long syscall, ...) return ret; } +int execv(const char* pathname, char* const argv[]) +{ + return syscall(SYS_EXEC, pathname, argv, nullptr); +} + pid_t fork(void) { return syscall(SYS_FORK); diff --git a/userspace/test/test.cpp b/userspace/test/test.cpp index 2361135cb..47253ca69 100644 --- a/userspace/test/test.cpp +++ b/userspace/test/test.cpp @@ -10,25 +10,17 @@ int main() { printf("userspace\n"); - FILE* fp = fopen("/usr/include/kernel/kprint.h", "r"); - if (fp == NULL) - ERROR("fopen"); - - char* buffer = (char*)malloc(128); - fread(buffer, 1, 100, fp); - - pid_t pid = fork(); - if (pid == 0) + if (fork() == 0) { - while (size_t n_read = fread(buffer, 1, 127, fp)) - fwrite(buffer, 1, n_read, stdout); - free(buffer); - fclose(fp); + char* argv[3]; + argv[0] = (char*)malloc(100); strcpy(argv[0], "/usr/bin/cat"); + argv[1] = (char*)malloc(100); strcpy(argv[1], "/usr/include/kernel/kprint.h"); + argv[2] = NULL; + execv("/usr/bin/cat", (char**)argv); + ERROR("execl"); return 0; } - free(buffer); - fclose(fp); - + printf("parent\n"); return 0; }