Query for presence of environment variable

I would like to query if an environment variable is present or not. In 0.15.2, I could do this:

const is_release: bool = if (std.process.getEnvVarOwned(allocator, "GATORCAT_RELEASE")) |_| true else |_| false;

How do I do this in 0.16?

init.environ_map.contains("GATORCAT_RELEASE")

Since #30644 the environment is not stored in a global variable.

2 Likes

There’s also std.process.Environ.contains if you’re using std.process.Init.Minimal:

pub fn main(init: std.process.Init.Minimal) !void {
    // set up allocator

    const is_release = try init.environ.contains(allocator, "GATORCAT_RELEASE");
}

If you don’t care about WASI support there’s also std.process.Environ.containsConstant which doesn’t require an allocator (the equivalent in 0.15.2 was std.process.hasEnvVarConstant).

Just to clarify, Environ is the raw unprocessed data from the OS, EnvironMap is the that data processed into an array hash map.

It is odd that Environ has contains* functions, as it doesn’t have any other counterpart to the EnvironMap API.

The Environ.contains* functions just create an EnvironMap each time, which is to say they process all the data each time.

with exception to containsConstant, which uses the getPosix/Windows functions that go through the unprocessed data.

If you need it more than once use createMap to get an EnvironMap once and query that instead.

5 Likes

The environ / process args APIs are very frustrating because its hard to tell from reading the code how I am supposed to initialize them. I know it goes back to the OS, because the OS initializes them somewhere in memory for me, but its still frustrating. I wish it was a syscall instead, it would make more sense that way to me.

My normal workflow:

  1. search std docs for env var stuff
  2. find cool contains function that does what I want: Zig Documentation
  3. realize that it requires an Environ as first argument, ok cool lets go look at Environ…
  4. realize Environ has no init function, and its not clear at all how the hell I am supposed to create it

Same story for std.process.Args. Very annoying.

Think about it like this, because this is literally what it is, environment and args are passed to the entry point function, not as arguments but through specific registers since this behaviour predates standard ABIs.

What libc does, and zig used to do, is put them in global vars to be accessed easily, but that has foot guns and allows hidden control flow.

So now zig just passes them to main via std.process.Init[.Minimal]

2 Likes

How the environment (and command-line arguments) is passed to a process is platform-dependent, and not how you describe for some operating systems.

Yes I should have clarified.

I described how it is done on POSIX.

Windows includes environment in a bunch of information available globally to the process.