diff --git a/src/runtime/env.go b/src/runtime/env.go new file mode 100644 index 00000000..dceb6bd1 --- /dev/null +++ b/src/runtime/env.go @@ -0,0 +1,51 @@ +//go:build linux || darwin || windows + +package runtime + +// Update the C environment if cgo is loaded. +// Called from Go 1.20 and above. +// +//go:linkname syscallSetenv syscall.runtimeSetenv +func syscallSetenv(key, value string) { + keydata := cstring(key) + valdata := cstring(value) + setenv(&keydata[0], &valdata[0]) + if key == "GODEBUG" && godebugUpdate != nil { + // Starting with Go 1.20, we need to call a callback (set by + // internal/godebug) to notify the GODEBUG environment variable has + // changed. This is necessary to get archive/zip to pass tests. + godebugUpdate(key, value) + } +} + +// Update the C environment if cgo is loaded. +// Called from Go 1.20 and above. +// +//go:linkname syscallUnsetenv syscall.runtimeUnsetenv +func syscallUnsetenv(key string) { + keydata := cstring(key) + unsetenv(&keydata[0]) +} + +// Compatibility with Go 1.19 and below. +// +//go:linkname syscall_setenv_c syscall.setenv_c +func syscall_setenv_c(key string, val string) { + syscallSetenv(key, val) +} + +// Compatibility with Go 1.19 and below. +// +//go:linkname syscall_unsetenv_c syscall.unsetenv_c +func syscall_unsetenv_c(key string) { + syscallUnsetenv(key) +} + +// cstring converts a Go string to a C string. +// borrowed from syscall +func cstring(s string) []byte { + data := make([]byte, len(s)+1) + copy(data, s) + // final byte should be zero from the initial allocation + return data +} diff --git a/src/runtime/env_unix.go b/src/runtime/env_unix.go index 6fb13c56..e205c14d 100644 --- a/src/runtime/env_unix.go +++ b/src/runtime/env_unix.go @@ -2,56 +2,6 @@ package runtime -// Update the C environment if cgo is loaded. -// Called from Go 1.20 and above. -// -//go:linkname syscallSetenv syscall.runtimeSetenv -func syscallSetenv(key, value string) { - keydata := cstring(key) - valdata := cstring(value) - // ignore any errors - libc_setenv(&keydata[0], &valdata[0], 1) - if key == "GODEBUG" && godebugUpdate != nil { - // Starting with Go 1.20, we need to call a callback (set by - // internal/godebug) to notify the GODEBUG environment variable has - // changed. This is necessary to get archive/zip to pass tests. - godebugUpdate(key, value) - } -} - -// Update the C environment if cgo is loaded. -// Called from Go 1.20 and above. -// -//go:linkname syscallUnsetenv syscall.runtimeUnsetenv -func syscallUnsetenv(key string) { - keydata := cstring(key) - // ignore any errors - libc_unsetenv(&keydata[0]) -} - -// Compatibility with Go 1.19 and below. -// -//go:linkname syscall_setenv_c syscall.setenv_c -func syscall_setenv_c(key string, val string) { - syscallSetenv(key, val) -} - -// Compatibility with Go 1.19 and below. -// -//go:linkname syscall_unsetenv_c syscall.unsetenv_c -func syscall_unsetenv_c(key string) { - syscallUnsetenv(key) -} - -// cstring converts a Go string to a C string. -// borrowed from syscall -func cstring(s string) []byte { - data := make([]byte, len(s)+1) - copy(data, s) - // final byte should be zero from the initial allocation - return data -} - // int setenv(const char *name, const char *val, int replace); // //export setenv @@ -61,3 +11,13 @@ func libc_setenv(name *byte, val *byte, replace int32) int32 // //export unsetenv func libc_unsetenv(name *byte) int32 + +func setenv(key, val *byte) { + // ignore any errors + libc_setenv(key, val, 1) +} + +func unsetenv(key *byte) { + // ignore any errors + libc_unsetenv(key) +} diff --git a/src/runtime/env_windows.go b/src/runtime/env_windows.go new file mode 100644 index 00000000..d4ef13f9 --- /dev/null +++ b/src/runtime/env_windows.go @@ -0,0 +1,23 @@ +//go:build windows + +package runtime + +// Set environment variable in Windows: +// +// BOOL SetEnvironmentVariableA( +// [in] LPCSTR lpName, +// [in, optional] LPCSTR lpValue +// ); +// +//export SetEnvironmentVariableA +func _SetEnvironmentVariableA(key, val *byte) bool + +func setenv(key, val *byte) { + // ignore any errors + _SetEnvironmentVariableA(key, val) +} + +func unsetenv(key *byte) { + // ignore any errors + _SetEnvironmentVariableA(key, nil) +}