Commit 640389bb2b

Andrew Kelley <superjoe30@gmail.com>
2017-04-03 01:14:23
expose environment variables in standard library
closes #118
1 parent 8fd0fdd
Changed files (2)
std
std/os/index.zig
@@ -7,6 +7,7 @@ pub const posix = switch(@compileVar("os")) {
     Os.windows => windows,
     else => @compileError("Unsupported OS"),
 };
+
 const debug = @import("../debug.zig");
 const assert = debug.assert;
 
@@ -385,6 +386,8 @@ pub const ChildProcess = struct {
             .stdin = if (stdin == StdIo.Pipe) {
                 io.OutStream {
                     .fd = stdin_pipe[1],
+                    .buffer = undefined,
+                    .index = 0,
                 }
             } else {
                 null
@@ -392,8 +395,6 @@ pub const ChildProcess = struct {
             .stdout = if (stdout == StdIo.Pipe) {
                 io.InStream {
                     .fd = stdout_pipe[0],
-                    .buffer = undefined,
-                    .index = 0,
                 }
             } else {
                 null
@@ -401,8 +402,6 @@ pub const ChildProcess = struct {
             .stderr = if (stderr == StdIo.Pipe) {
                 io.InStream {
                     .fd = stderr_pipe[0],
-                    .buffer = undefined,
-                    .index = 0,
                 }
             } else {
                 null
@@ -419,3 +418,17 @@ pub const ChildProcess = struct {
         }
     }
 };
+
+pub const EnvPair = struct {
+    key: []const u8,
+    value: []const u8,
+};
+pub var environ: []const EnvPair = undefined;
+
+pub fn getEnv(key: []const u8) -> ?[]const u8 {
+    for (environ) |pair| {
+        if (mem.eql(u8, pair.key, key))
+            return pair.value;
+    }
+    return null;
+}
std/special/bootstrap.zig
@@ -32,21 +32,42 @@ export nakedcc fn _start() -> noreturn {
     callMainAndExit()
 }
 
-fn callMain() -> %void {
+fn callMain(envp: &?&u8) -> %void {
     const args = @alloca([]u8, argc);
     for (args) |_, i| {
         const ptr = argv[i];
         args[i] = ptr[0...std.cstr.len(ptr)];
     }
+
+    var env_count: usize = 0;
+    while (envp[env_count] != null; env_count += 1) {}
+    const environ = @alloca(std.os.EnvPair, env_count);
+    for (environ) |_, env_i| {
+        const ptr = ??envp[env_i];
+
+        var line_i: usize = 0;
+        while (ptr[line_i] != 0 and ptr[line_i] != '='; line_i += 1) {}
+
+        var end_i: usize = line_i;
+        while (ptr[end_i] != 0; end_i += 1) {}
+
+        environ[env_i] = std.os.EnvPair {
+            .key = ptr[0...line_i],
+            .value = ptr[line_i + 1...end_i],
+        };
+    }
+    std.os.environ = environ;
+
     return root.main(args);
 }
 
 fn callMainAndExit() -> noreturn {
-    callMain() %% exit(1);
+    const envp = @ptrcast(&?&u8, &argv[argc + 1]);
+    callMain(envp) %% exit(1);
     exit(0);
 }
 
-export fn main(c_argc: i32, c_argv: &&u8) -> i32 {
+export fn main(c_argc: i32, c_argv: &&u8, c_envp: &?&u8) -> i32 {
     @setGlobalLinkage(main, if (want_main_symbol) GlobalLinkage.Strong else GlobalLinkage.Internal);
     if (!want_main_symbol) {
         unreachable;
@@ -54,6 +75,6 @@ export fn main(c_argc: i32, c_argv: &&u8) -> i32 {
 
     argc = usize(c_argc);
     argv = c_argv;
-    callMain() %% return 1;
+    callMain(c_envp) %% return 1;
     return 0;
 }