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:
Diffstat (limited to 'src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnvironmentAugments.Unix.cs')
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnvironmentAugments.Unix.cs51
1 files changed, 48 insertions, 3 deletions
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()