From 0c2face7b0756ac5d8523551f20a95716d77b9c5 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 27 Mar 2019 01:39:13 +0100 Subject: [PATCH] LibC: Add creat(), execvp() resolution, and exec*() environment inheritance. --- LibC/unistd.cpp | 32 ++++++++++++++++++++++++++++---- LibC/unistd.h | 1 + 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/LibC/unistd.cpp b/LibC/unistd.cpp index 6d820d6646..1c140ab88d 100644 --- a/LibC/unistd.cpp +++ b/LibC/unistd.cpp @@ -9,8 +9,10 @@ #include #include #include +#include #include #include +#include extern "C" { @@ -28,7 +30,7 @@ pid_t fork() int execv(const char* path, char* const argv[]) { - return execve(path, argv, nullptr); + return execve(path, argv, environ); } int execve(const char* filename, char* const argv[], char* const envp[]) @@ -39,8 +41,25 @@ int execve(const char* filename, char* const argv[], char* const envp[]) int execvp(const char* filename, char* const argv[]) { - // FIXME: This should do some sort of shell-like path resolution! - return execve(filename, argv, nullptr); + int rc = execve(filename, argv, nullptr); + if (rc < 0 && errno != ENOENT) { + printf("execvp failed on first with %s\n", strerror(errno)); + return rc; + } + String path = getenv("PATH"); + if (path.is_empty()) + path = "/bin:/usr/bin"; + auto parts = path.split(':'); + for (auto& part : parts) { + auto candidate = String::format("%s/%s", part.characters(), filename); + rc = execve(candidate.characters(), argv, environ); + if (rc < 0 && errno != ENOENT) { + printf("execvp failed on attempt (%s) with %s\n", candidate.characters(), strerror(errno)); + return rc; + } + } + errno = ENOENT; + return -1; } int execl(const char* filename, const char* arg0, ...) @@ -58,7 +77,7 @@ int execl(const char* filename, const char* arg0, ...) } va_end(ap); args.append(nullptr); - return execve(filename, (char* const *)args.data(), nullptr); + return execve(filename, (char* const *)args.data(), environ); } uid_t getuid() @@ -125,6 +144,11 @@ pid_t getpgrp() __RETURN_WITH_ERRNO(rc, rc, -1); } +int creat(const char* path, mode_t mode) +{ + return open(path, O_CREAT, mode); +} + int open(const char* path, int options, ...) { va_list ap; diff --git a/LibC/unistd.h b/LibC/unistd.h index 9114572fdc..b1483bcba0 100644 --- a/LibC/unistd.h +++ b/LibC/unistd.h @@ -48,6 +48,7 @@ int setuid(uid_t); int setgid(gid_t); pid_t tcgetpgrp(int fd); int tcsetpgrp(int fd, pid_t pgid); +int creat(const char* path, mode_t); int open(const char* path, int options, ...); ssize_t read(int fd, void* buf, size_t count); ssize_t write(int fd, const void* buf, size_t count);