Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Common/src/Interop/Unix/System.Private.CoreLib.Native/Interop.GetEnviron.cs15
-rw-r--r--src/Native/System.Private.CoreLib.Native/config.h.in1
-rw-r--r--src/Native/System.Private.CoreLib.Native/configure.cmake3
-rw-r--r--src/Native/System.Private.CoreLib.Native/pal_environment.cpp17
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnvironmentAugments.Unix.cs51
-rw-r--r--src/System.Private.CoreLib/src/System.Private.CoreLib.csproj3
6 files changed, 87 insertions, 3 deletions
diff --git a/src/Common/src/Interop/Unix/System.Private.CoreLib.Native/Interop.GetEnviron.cs b/src/Common/src/Interop/Unix/System.Private.CoreLib.Native/Interop.GetEnviron.cs
new file mode 100644
index 000000000..539cdb3cf
--- /dev/null
+++ b/src/Common/src/Interop/Unix/System.Private.CoreLib.Native/Interop.GetEnviron.cs
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+ internal unsafe partial class Sys
+ {
+ [DllImport(Interop.Libraries.CoreLibNative, EntryPoint = "CoreLibNative_GetEnviron")]
+ internal static extern unsafe IntPtr GetEnviron();
+ }
+}
diff --git a/src/Native/System.Private.CoreLib.Native/config.h.in b/src/Native/System.Private.CoreLib.Native/config.h.in
index c7c3aafd9..3c3f11298 100644
--- a/src/Native/System.Private.CoreLib.Native/config.h.in
+++ b/src/Native/System.Private.CoreLib.Native/config.h.in
@@ -6,3 +6,4 @@
#cmakedefine01 HAVE_MACH_ABSOLUTE_TIME
#cmakedefine01 HAVE_SCHED_GETCPU
#cmakedefine01 HAVE_GNU_LIBNAMES_H
+#cmakedefine01 HAVE__NSGETENVIRON \ No newline at end of file
diff --git a/src/Native/System.Private.CoreLib.Native/configure.cmake b/src/Native/System.Private.CoreLib.Native/configure.cmake
index aaabb387c..1fbbf9c5e 100644
--- a/src/Native/System.Private.CoreLib.Native/configure.cmake
+++ b/src/Native/System.Private.CoreLib.Native/configure.cmake
@@ -1,6 +1,7 @@
include(CheckCXXSourceCompiles)
include(CheckCXXSourceRuns)
include(CheckLibraryExists)
+include(CheckFunctionExists)
check_library_exists(pthread pthread_condattr_setclock "" HAVE_PTHREAD_CONDATTR_SETCLOCK)
@@ -62,6 +63,8 @@ set(CMAKE_REQUIRED_LIBRARIES)
check_include_files(gnu/lib-names.h HAVE_GNU_LIBNAMES_H)
+check_function_exists(_NSGetEnviron HAVE__NSGETENVIRON)
+
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
${CMAKE_CURRENT_BINARY_DIR}/config.h)
diff --git a/src/Native/System.Private.CoreLib.Native/pal_environment.cpp b/src/Native/System.Private.CoreLib.Native/pal_environment.cpp
index 94660baba..15ef90c34 100644
--- a/src/Native/System.Private.CoreLib.Native/pal_environment.cpp
+++ b/src/Native/System.Private.CoreLib.Native/pal_environment.cpp
@@ -10,6 +10,9 @@
#if HAVE_SCHED_GETCPU
#include <sched.h>
#endif
+#if HAVE__NSGETENVIRON
+#include <crt_externs.h>
+#endif
extern "C" char* CoreLibNative_GetEnv(const char* variable)
@@ -30,3 +33,17 @@ extern "C" void CoreLibNative_Exit(int32_t exitCode)
{
exit(exitCode);
}
+
+extern "C" char** CoreLibNative_GetEnviron()
+{
+ char** sysEnviron;
+
+#if HAVE__NSGETENVIRON
+ sysEnviron = *(_NSGetEnviron());
+#else // HAVE__NSGETENVIRON
+ extern char **environ;
+ sysEnviron = environ;
+#endif // HAVE__NSGETENVIRON
+
+ return sysEnviron;
+} \ No newline at end of file
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnvironmentAugments.Unix.cs b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnvironmentAugments.Unix.cs
index 6d28d393b..76ead8cb7 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnvironmentAugments.Unix.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnvironmentAugments.Unix.cs
@@ -27,10 +27,55 @@ namespace Internal.Runtime.Augments
public static IEnumerable<KeyValuePair<string,string>> EnumerateEnvironmentVariables()
{
- if ("".Length != 0)
- throw new NotImplementedException(); // Need to return something better than an empty environment block.
+ IntPtr block = Interop.Sys.GetEnviron();
+ if (block == IntPtr.Zero)
+ yield break;
- return Array.Empty<KeyValuePair<string,string>>();
+ // Per man page, environment variables come back as an array of pointers to strings
+ // Parse each pointer of strings individually
+ while (ParseEntry(block, out string key, out string value))
+ {
+ if (key != null && value != null)
+ yield return new KeyValuePair<string, string>(key, value);
+
+ // Increment to next environment variable entry
+ block += IntPtr.Size;
+ }
+
+ // Use a local, unsafe function since we cannot use `yield return` inside of an `unsafe` block
+ unsafe bool ParseEntry(IntPtr current, out string key, out string value)
+ {
+ // Setup
+ key = null;
+ value = null;
+
+ // Point to current entry
+ byte* entry = *(byte**)current;
+
+ // Per man page, "The last pointer in this array has the value NULL"
+ // Therefore, if entry is null then we're at the end and can bail
+ if (entry == null)
+ return false;
+
+ // Parse each byte of the entry until we hit either the separator '=' or '\0'.
+ // This finds the split point for creating key/value strings below.
+ // On some old OS, the environment block can be corrupted.
+ // Some will not have '=', so we need to check for '\0'.
+ byte* splitpoint = entry;
+ while (*splitpoint != '=' && *splitpoint != '\0')
+ splitpoint++;
+
+ // Skip over entries starting with '=' and entries with no value (just a null-terminating char '\0')
+ if (splitpoint == entry || *splitpoint == '\0')
+ return true;
+
+ // The key is the bytes from start (0) until our splitpoint
+ key = new string((sbyte*)entry, 0, checked((int)(splitpoint - entry)));
+ // The value is the rest of the bytes starting after the splitpoint
+ value = new string((sbyte*)(splitpoint + 1));
+
+ return true;
+ }
}
private static void ExitRaw()
diff --git a/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj
index f830beb82..c865aa858 100644
--- a/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj
+++ b/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj
@@ -601,6 +601,9 @@
<Compile Include="..\..\Common\src\Interop\Unix\System.Private.CoreLib.Native\Interop.ErrNo.cs">
<Link>Interop\Unix\System.Private.CoreLib.Native\Interop.ErrNo.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\src\Interop\Unix\System.Private.CoreLib.Native\Interop.GetEnviron.cs">
+ <Link>Interop\Unix\System.Private.CoreLib.Native\Interop.GetEnviron.cs</Link>
+ </Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\Common\src\TypeSystem\Common\Utilities\LockFreeReaderHashtable.cs">