From 12ac7e660e5135268fb4664d503327f751064b1f Mon Sep 17 00:00:00 2001 From: Alexander van der Grinten Date: Sun, 21 Jan 2018 16:48:09 +0100 Subject: [PATCH] libc: Partially support environment variables --- libc/generic/ansi/src/stdlib-stubs.cpp | 8 ++-- .../posix/include/mlibc/posix_stdlib.h | 2 + libc/generic/posix/src/environment.cpp | 48 ++++++++++++++++++- 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/libc/generic/ansi/src/stdlib-stubs.cpp b/libc/generic/ansi/src/stdlib-stubs.cpp index 97107ca1..69ece926 100644 --- a/libc/generic/ansi/src/stdlib-stubs.cpp +++ b/libc/generic/ansi/src/stdlib-stubs.cpp @@ -3,8 +3,9 @@ #include #include #include -#include +#include +#include #include extern "C" int __cxa_atexit(void (*function)(void *), void *argument, void *dso_tag); @@ -177,10 +178,7 @@ void exit(int status) { _Exit(status); } // _Exit() is provided by the platform -char *getenv(const char *name) { - // TODO: should be provided by the POSIX sublibrary based on environ - return nullptr; -} +// getenv() is provided by POSIX void quick_exit(int status) { __ensure(!"Not implemented"); __builtin_unreachable(); diff --git a/libc/generic/posix/include/mlibc/posix_stdlib.h b/libc/generic/posix/include/mlibc/posix_stdlib.h index 638bac62..fc5c5ed5 100644 --- a/libc/generic/posix/include/mlibc/posix_stdlib.h +++ b/libc/generic/posix/include/mlibc/posix_stdlib.h @@ -8,6 +8,8 @@ extern "C" { long random(void); +int putenv(const char *); + #ifdef __cplusplus } #endif diff --git a/libc/generic/posix/src/environment.cpp b/libc/generic/posix/src/environment.cpp index 12c90f6d..b6ebd397 100644 --- a/libc/generic/posix/src/environment.cpp +++ b/libc/generic/posix/src/environment.cpp @@ -1,5 +1,49 @@ -char *__emptyEnviron[] = { nullptr }; +#include -char **environ = __emptyEnviron; +#include +#include +#include +#include + +static char *emptyEnvironment[] = { nullptr }; + +char **environ = emptyEnvironment; + +char *getenv(const char *name) { + for(auto it = environ; *it; it++) { + frigg::StringView view{*it}; + + size_t s = view.findFirst('='); + if(s == size_t(-1)) { + frigg::infoLogger() << "\e[35mmlibc: getenv() environment string '" + << view << "' does not contain the '=' sign\e[39m" << frigg::endLog; + continue; + } + if(view.subString(0, s) != name) + continue; + + return const_cast(view.data() + s + 1); + } + return nullptr; +} + +// Environment vector that is mutated by putenv() and setenv(). +static frigg::Vector mutEnvironment{getAllocator()}; + +int putenv(const char *string) { + // If the environ variable was changed, we copy the environment. + if(environ != mutEnvironment.data()) { + // TODO: Actually copy the entries. + __ensure(!*environ); + mutEnvironment.push(nullptr); + } + + // TODO: Replace the entry instead of adding it. + __ensure(!mutEnvironment.back()); + mutEnvironment.back() = const_cast(string); + mutEnvironment.push(nullptr); + environ = mutEnvironment.data(); + return 0; +}