implement environment variables for windows
parent
55e8bbd167
commit
8ab5313043
|
@ -308,7 +308,7 @@ pub const Builder = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn processNixOSEnvVars(self: &Builder) {
|
fn processNixOSEnvVars(self: &Builder) {
|
||||||
if (os.getEnv("NIX_CFLAGS_COMPILE")) |nix_cflags_compile| {
|
if (os.getEnvVarOwned(self.allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| {
|
||||||
var it = mem.split(nix_cflags_compile, " ");
|
var it = mem.split(nix_cflags_compile, " ");
|
||||||
while (true) {
|
while (true) {
|
||||||
const word = it.next() ?? break;
|
const word = it.next() ?? break;
|
||||||
|
@ -323,8 +323,10 @@ pub const Builder = struct {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else |err| {
|
||||||
|
assert(err == error.EnvironmentVariableNotFound);
|
||||||
}
|
}
|
||||||
if (os.getEnv("NIX_LDFLAGS")) |nix_ldflags| {
|
if (os.getEnvVarOwned(self.allocator, "NIX_LDFLAGS")) |nix_ldflags| {
|
||||||
var it = mem.split(nix_ldflags, " ");
|
var it = mem.split(nix_ldflags, " ");
|
||||||
while (true) {
|
while (true) {
|
||||||
const word = it.next() ?? break;
|
const word = it.next() ?? break;
|
||||||
|
@ -342,6 +344,8 @@ pub const Builder = struct {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else |err| {
|
||||||
|
assert(err == error.EnvironmentVariableNotFound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1248,7 +1252,13 @@ pub const LibExeObjStep = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn makeC(self: &LibExeObjStep) -> %void {
|
fn makeC(self: &LibExeObjStep) -> %void {
|
||||||
const cc = os.getEnv("CC") ?? "cc";
|
const cc = os.getEnvVarOwned(self.builder.allocator, "CC") %% |err| {
|
||||||
|
if (err == error.EnvironmentVariableNotFound) {
|
||||||
|
([]const u8)("cc")
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
};
|
||||||
const builder = self.builder;
|
const builder = self.builder;
|
||||||
|
|
||||||
assert(!self.is_zig);
|
assert(!self.is_zig);
|
||||||
|
|
|
@ -564,7 +564,7 @@ pub const ChildProcess = struct {
|
||||||
const cwd_ptr = if (cwd_slice) |cwd| cwd.ptr else null;
|
const cwd_ptr = if (cwd_slice) |cwd| cwd.ptr else null;
|
||||||
|
|
||||||
const maybe_envp_buf = if (self.env_map) |env_map| {
|
const maybe_envp_buf = if (self.env_map) |env_map| {
|
||||||
%return os.createNullDelimitedEnvMap(self.allocator, env_map)
|
%return os.createWindowsEnvBlock(self.allocator, env_map)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
};
|
};
|
||||||
|
@ -578,6 +578,7 @@ pub const ChildProcess = struct {
|
||||||
const err = windows.GetLastError();
|
const err = windows.GetLastError();
|
||||||
return switch (err) {
|
return switch (err) {
|
||||||
windows.ERROR.FILE_NOT_FOUND => error.FileNotFound,
|
windows.ERROR.FILE_NOT_FOUND => error.FileNotFound,
|
||||||
|
windows.ERROR.INVALID_PARAMETER => unreachable,
|
||||||
else => error.Unexpected,
|
else => error.Unexpected,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ pub const windowsWrite = windows_util.windowsWrite;
|
||||||
pub const windowsIsTty = windows_util.windowsIsTty;
|
pub const windowsIsTty = windows_util.windowsIsTty;
|
||||||
pub const windowsIsCygwinPty = windows_util.windowsIsCygwinPty;
|
pub const windowsIsCygwinPty = windows_util.windowsIsCygwinPty;
|
||||||
pub const windowsOpen = windows_util.windowsOpen;
|
pub const windowsOpen = windows_util.windowsOpen;
|
||||||
|
pub const createWindowsEnvBlock = windows_util.createWindowsEnvBlock;
|
||||||
|
|
||||||
const debug = @import("../debug.zig");
|
const debug = @import("../debug.zig");
|
||||||
const assert = debug.assert;
|
const assert = debug.assert;
|
||||||
|
@ -48,6 +49,7 @@ const io = @import("../io.zig");
|
||||||
const base64 = @import("../base64.zig");
|
const base64 = @import("../base64.zig");
|
||||||
const ArrayList = @import("../array_list.zig").ArrayList;
|
const ArrayList = @import("../array_list.zig").ArrayList;
|
||||||
const Buffer = @import("../buffer.zig").Buffer;
|
const Buffer = @import("../buffer.zig").Buffer;
|
||||||
|
const math = @import("../index.zig").math;
|
||||||
|
|
||||||
error Unexpected;
|
error Unexpected;
|
||||||
error SystemResources;
|
error SystemResources;
|
||||||
|
@ -362,7 +364,7 @@ pub fn posixExecve(argv: []const []const u8, env_map: &const BufMap,
|
||||||
return posixExecveErrnoToErr(posix.getErrno(posix.execve(??argv_buf[0], argv_buf.ptr, envp_buf.ptr)));
|
return posixExecveErrnoToErr(posix.getErrno(posix.execve(??argv_buf[0], argv_buf.ptr, envp_buf.ptr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
const PATH = getEnv("PATH") ?? "/usr/local/bin:/bin/:/usr/bin";
|
const PATH = getEnvPosix("PATH") ?? "/usr/local/bin:/bin/:/usr/bin";
|
||||||
// PATH.len because it is >= the largest search_path
|
// PATH.len because it is >= the largest search_path
|
||||||
// +1 for the / to join the search path and exe_path
|
// +1 for the / to join the search path and exe_path
|
||||||
// +1 for the null terminating byte
|
// +1 for the null terminating byte
|
||||||
|
@ -406,29 +408,55 @@ fn posixExecveErrnoToErr(err: usize) -> error {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub var environ_raw: []&u8 = undefined;
|
pub var posix_environ_raw: []&u8 = undefined;
|
||||||
|
|
||||||
/// Caller must free result when done.
|
/// Caller must free result when done.
|
||||||
pub fn getEnvMap(allocator: &Allocator) -> %BufMap {
|
pub fn getEnvMap(allocator: &Allocator) -> %BufMap {
|
||||||
var result = BufMap.init(allocator);
|
var result = BufMap.init(allocator);
|
||||||
%defer result.deinit();
|
%defer result.deinit();
|
||||||
|
|
||||||
for (environ_raw) |ptr| {
|
if (is_windows) {
|
||||||
var line_i: usize = 0;
|
const ptr = windows.GetEnvironmentStringsA() ?? return error.OutOfMemory;
|
||||||
while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {}
|
defer assert(windows.FreeEnvironmentStringsA(ptr));
|
||||||
const key = ptr[0..line_i];
|
|
||||||
|
|
||||||
var end_i: usize = line_i;
|
var i: usize = 0;
|
||||||
while (ptr[end_i] != 0) : (end_i += 1) {}
|
while (true) {
|
||||||
const value = ptr[line_i + 1..end_i];
|
if (ptr[i] == 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
%return result.set(key, value);
|
const key_start = i;
|
||||||
|
|
||||||
|
while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {}
|
||||||
|
const key = ptr[key_start..i];
|
||||||
|
|
||||||
|
if (ptr[i] == '=') i += 1;
|
||||||
|
|
||||||
|
const value_start = i;
|
||||||
|
while (ptr[i] != 0) : (i += 1) {}
|
||||||
|
const value = ptr[value_start..i];
|
||||||
|
|
||||||
|
i += 1; // skip over null byte
|
||||||
|
|
||||||
|
%return result.set(key, value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (posix_environ_raw) |ptr| {
|
||||||
|
var line_i: usize = 0;
|
||||||
|
while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {}
|
||||||
|
const key = ptr[0..line_i];
|
||||||
|
|
||||||
|
var end_i: usize = line_i;
|
||||||
|
while (ptr[end_i] != 0) : (end_i += 1) {}
|
||||||
|
const value = ptr[line_i + 1..end_i];
|
||||||
|
|
||||||
|
%return result.set(key, value);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getEnv(key: []const u8) -> ?[]const u8 {
|
pub fn getEnvPosix(key: []const u8) -> ?[]const u8 {
|
||||||
for (environ_raw) |ptr| {
|
for (posix_environ_raw) |ptr| {
|
||||||
var line_i: usize = 0;
|
var line_i: usize = 0;
|
||||||
while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {}
|
while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {}
|
||||||
const this_key = ptr[0..line_i];
|
const this_key = ptr[0..line_i];
|
||||||
|
@ -444,6 +472,42 @@ pub fn getEnv(key: []const u8) -> ?[]const u8 {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error EnvironmentVariableNotFound;
|
||||||
|
|
||||||
|
/// Caller must free returned memory.
|
||||||
|
pub fn getEnvVarOwned(allocator: &mem.Allocator, key: []const u8) -> %[]u8 {
|
||||||
|
if (is_windows) {
|
||||||
|
const key_with_null = %return cstr.addNullByte(allocator, key);
|
||||||
|
defer allocator.free(key_with_null);
|
||||||
|
|
||||||
|
var buf = %return allocator.alloc(u8, 256);
|
||||||
|
%defer allocator.free(buf);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const windows_buf_len = %return math.cast(windows.DWORD, buf.len);
|
||||||
|
const result = windows.GetEnvironmentVariableA(key_with_null.ptr, buf.ptr, windows_buf_len);
|
||||||
|
|
||||||
|
if (result == 0) {
|
||||||
|
const err = windows.GetLastError();
|
||||||
|
return switch (err) {
|
||||||
|
windows.ERROR.ENVVAR_NOT_FOUND => error.EnvironmentVariableNotFound,
|
||||||
|
else => error.Unexpected,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result > buf.len) {
|
||||||
|
buf = %return allocator.realloc(u8, buf, result);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return allocator.shrink(u8, buf, result);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const result = getEnvPosix(key) ?? return error.EnvironmentVariableNotFound;
|
||||||
|
return mem.dupe(u8, allocator, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Caller must free the returned memory.
|
/// Caller must free the returned memory.
|
||||||
pub fn getCwd(allocator: &Allocator) -> %[]u8 {
|
pub fn getCwd(allocator: &Allocator) -> %[]u8 {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
|
|
|
@ -32,12 +32,18 @@ pub extern "kernel32" stdcallcc fn DeleteFileA(lpFileName: LPCSTR) -> bool;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: UINT) -> noreturn;
|
pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: UINT) -> noreturn;
|
||||||
|
|
||||||
|
pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsA(penv: LPCH) -> BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetCommandLineA() -> LPSTR;
|
pub extern "kernel32" stdcallcc fn GetCommandLineA() -> LPSTR;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetConsoleMode(in_hConsoleHandle: HANDLE, out_lpMode: &DWORD) -> bool;
|
pub extern "kernel32" stdcallcc fn GetConsoleMode(in_hConsoleHandle: HANDLE, out_lpMode: &DWORD) -> bool;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetCurrentDirectoryA(nBufferLength: WORD, lpBuffer: ?LPSTR) -> DWORD;
|
pub extern "kernel32" stdcallcc fn GetCurrentDirectoryA(nBufferLength: WORD, lpBuffer: ?LPSTR) -> DWORD;
|
||||||
|
|
||||||
|
pub extern "kernel32" stdcallcc fn GetEnvironmentStringsA() -> ?LPCH;
|
||||||
|
|
||||||
|
pub extern "kernel32" stdcallcc fn GetEnvironmentVariableA(lpName: LPCSTR, lpBuffer: LPSTR, nSize: DWORD) -> DWORD;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: &DWORD) -> BOOL;
|
pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: &DWORD) -> BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetLastError() -> DWORD;
|
pub extern "kernel32" stdcallcc fn GetLastError() -> DWORD;
|
||||||
|
@ -49,11 +55,11 @@ pub extern "kernel32" stdcallcc fn GetFileInformationByHandleEx(in_hFile: HANDLE
|
||||||
pub extern "kernel32" stdcallcc fn GetFinalPathNameByHandleA(hFile: HANDLE, lpszFilePath: LPSTR,
|
pub extern "kernel32" stdcallcc fn GetFinalPathNameByHandleA(hFile: HANDLE, lpszFilePath: LPSTR,
|
||||||
cchFilePath: DWORD, dwFlags: DWORD) -> DWORD;
|
cchFilePath: DWORD, dwFlags: DWORD) -> DWORD;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetProcessHeap() -> HANDLE;
|
pub extern "kernel32" stdcallcc fn GetProcessHeap() -> ?HANDLE;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetStdHandle(in_nStdHandle: DWORD) -> ?HANDLE;
|
pub extern "kernel32" stdcallcc fn GetStdHandle(in_nStdHandle: DWORD) -> ?HANDLE;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID;
|
pub extern "kernel32" stdcallcc fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> ?LPVOID;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
|
pub extern "kernel32" stdcallcc fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
|
||||||
|
|
||||||
|
@ -91,6 +97,7 @@ pub const HCRYPTPROV = ULONG_PTR;
|
||||||
pub const HINSTANCE = &@OpaqueType();
|
pub const HINSTANCE = &@OpaqueType();
|
||||||
pub const INT = c_int;
|
pub const INT = c_int;
|
||||||
pub const LPBYTE = &BYTE;
|
pub const LPBYTE = &BYTE;
|
||||||
|
pub const LPCH = &CHAR;
|
||||||
pub const LPCSTR = &const CHAR;
|
pub const LPCSTR = &const CHAR;
|
||||||
pub const LPCTSTR = &const TCHAR;
|
pub const LPCTSTR = &const TCHAR;
|
||||||
pub const LPCVOID = &const c_void;
|
pub const LPCVOID = &const c_void;
|
||||||
|
|
|
@ -3,6 +3,7 @@ const os = std.os;
|
||||||
const windows = std.os.windows;
|
const windows = std.os.windows;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
|
const BufMap = std.BufMap;
|
||||||
|
|
||||||
error WaitAbandoned;
|
error WaitAbandoned;
|
||||||
error WaitTimeOut;
|
error WaitTimeOut;
|
||||||
|
@ -111,3 +112,35 @@ pub fn windowsOpen(file_path: []const u8, desired_access: windows.DWORD, share_m
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Caller must free result.
|
||||||
|
pub fn createWindowsEnvBlock(allocator: &mem.Allocator, env_map: &const BufMap) -> %[]u8 {
|
||||||
|
// count bytes needed
|
||||||
|
const bytes_needed = {
|
||||||
|
var bytes_needed: usize = 1; // 1 for the final null byte
|
||||||
|
var it = env_map.iterator();
|
||||||
|
while (it.next()) |pair| {
|
||||||
|
// +1 for '='
|
||||||
|
// +1 for null byte
|
||||||
|
bytes_needed += pair.key.len + pair.value.len + 2;
|
||||||
|
}
|
||||||
|
bytes_needed
|
||||||
|
};
|
||||||
|
const result = %return allocator.alloc(u8, bytes_needed);
|
||||||
|
%defer allocator.free(result);
|
||||||
|
|
||||||
|
var it = env_map.iterator();
|
||||||
|
var i: usize = 0;
|
||||||
|
while (it.next()) |pair| {
|
||||||
|
mem.copy(u8, result[i..], pair.key);
|
||||||
|
i += pair.key.len;
|
||||||
|
result[i] = '=';
|
||||||
|
i += 1;
|
||||||
|
mem.copy(u8, result[i..], pair.value);
|
||||||
|
i += pair.value.len;
|
||||||
|
result[i] = 0;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
result[i] = 0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ fn callMain(argc: usize, argv: &&u8, envp: &?&u8) -> %void {
|
||||||
|
|
||||||
var env_count: usize = 0;
|
var env_count: usize = 0;
|
||||||
while (envp[env_count] != null) : (env_count += 1) {}
|
while (envp[env_count] != null) : (env_count += 1) {}
|
||||||
std.os.environ_raw = @ptrCast(&&u8, envp)[0..env_count];
|
std.os.posix_environ_raw = @ptrCast(&&u8, envp)[0..env_count];
|
||||||
|
|
||||||
std.debug.user_main_fn = root.main;
|
std.debug.user_main_fn = root.main;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue