Hello,

Currently there is no list of environment variables visible from within a Swift 
program.

You can use `getenv` and `setenv` from the C Standard library to access a 
variable of which you know the name, but sometimes that’s not enough.

One simple case is when using `posix_spawn` to execute a child-process. This 
API needs a list of environment variables to present to the child process. 
Usually (meaning in C) you could work around that by inheriting the environment 
by using `fork` but that’s not allowed in Swift.

So if you want a child process to inherit the environment you’ll have to have a 
list.

Foundation does use a CoreFoundation method to get that list as seen here:
https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/NSTask.swift#L226
 
<https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/NSTask.swift#L226>

If you want to stay in Swift there is no access.

So how can a C program get to the environment? That’s rather simple, there are 
2 ways:
1. The (often ignored) third parameter to `main()` is a `char **env` which is 
just a list of all environment variables that ends with a `NULL` entry
2. Include `unistd.h` and use the exported variable `extern char **environ`

So what I would propose is just harnessing the third `main()` parameter and 
creating a new static computed property named `environment`, that is a 
dictionary of `[String:String]`, on the `Process` enum. There would be a bit of 
parsing because the environment list has the format `Key=Value` so the string 
would have to be split at the first equals character.

There is a Bug on the bugtracker: https://bugs.swift.org/browse/SR-1636 
<https://bugs.swift.org/browse/SR-1636>
And I have built a patch already in a pull-request that was shot down recently: 
https://github.com/apple/swift/pull/2757 
<https://github.com/apple/swift/pull/2757>

I tried to keep as closely as possible to the implementation of 
`argv`/`Process.arguments` as that comes from the same source as the 
environment list. The patch touches `SILGen.cpp`, `GlobalObjects.cpp/h` and of 
course `Process.swift` and was created as small as possible.

If you compile with that patch you’ll get access to `Process.environment`, 
which is static (does not change when using `setenv` to change or add a 
variable) and just contains a dictionary with the environment, and 
`Process.unsafeEnvp` which is like `unsafeArgv` the original representation of 
the value at it’s original location.

As this patch only adds another static variable it will not affect existing 
Swift programs.

Thanks for reading,
Johannes Schriewer

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to