| author | |
| committer | |
| log | 936d0b18b116ea126893d2f165f9be72f8bef845 |
| tree | 8481d2c4265d34217e6b045cbf1c7e34c30aab51 |
| parent | 0cd89e9176ab36fc5e267120dc4d75cb79d32684 |
| signature |
closes #35115 files changed, 77 insertions(+), 21 deletions(-)
lib/std/c.zig+2| ... | ... | @@ -62,6 +62,8 @@ pub fn versionCheck(glibc_version: builtin.Version) type { |
| 62 | 62 | }; |
| 63 | 63 | } |
| 64 | 64 | |
| 65 | pub extern "c" var environ: [*:null]?[*:0]u8; | |
| 66 | ||
| 65 | 67 | pub extern "c" fn fopen(filename: [*:0]const u8, modes: [*:0]const u8) ?*FILE; |
| 66 | 68 | pub extern "c" fn fclose(stream: *FILE) c_int; |
| 67 | 69 | pub extern "c" fn fwrite(ptr: [*]const u8, size_of_type: usize, item_count: usize, stream: *FILE) usize; |
lib/std/os.zig+44-5| ... | ... | @@ -70,6 +70,8 @@ else switch (builtin.os) { |
| 70 | 70 | pub usingnamespace @import("os/bits.zig"); |
| 71 | 71 | |
| 72 | 72 | /// See also `getenv`. Populated by startup code before main(). |
| 73 | /// TODO this is a footgun because the value will be undefined when using `zig build-lib`. | |
| 74 | /// https://github.com/ziglang/zig/issues/4524 | |
| 73 | 75 | pub var environ: [][*:0]u8 = undefined; |
| 74 | 76 | |
| 75 | 77 | /// Populated by startup code before main(). |
| ... | ... | @@ -922,7 +924,11 @@ pub const execveC = execveZ; |
| 922 | 924 | /// Like `execve` except the parameters are null-terminated, |
| 923 | 925 | /// matching the syscall API on all targets. This removes the need for an allocator. |
| 924 | 926 | /// This function ignores PATH environment variable. See `execvpeZ` for that. |
| 925 | pub fn execveZ(path: [*:0]const u8, child_argv: [*:null]const ?[*:0]const u8, envp: [*:null]const ?[*:0]const u8) ExecveError { | |
| 927 | pub fn execveZ( | |
| 928 | path: [*:0]const u8, | |
| 929 | child_argv: [*:null]const ?[*:0]const u8, | |
| 930 | envp: [*:null]const ?[*:0]const u8, | |
| 931 | ) ExecveError { | |
| 926 | 932 | switch (errno(system.execve(path, child_argv, envp))) { |
| 927 | 933 | 0 => unreachable, |
| 928 | 934 | EFAULT => unreachable, |
| ... | ... | @@ -966,7 +972,7 @@ pub fn execvpeZ_expandArg0( |
| 966 | 972 | envp: [*:null]const ?[*:0]const u8, |
| 967 | 973 | ) ExecveError { |
| 968 | 974 | const file_slice = mem.toSliceConst(u8, file); |
| 969 | if (mem.indexOfScalar(u8, file_slice, '/') != null) return execveC(file, child_argv, envp); | |
| 975 | if (mem.indexOfScalar(u8, file_slice, '/') != null) return execveZ(file, child_argv, envp); | |
| 970 | 976 | |
| 971 | 977 | const PATH = getenvZ("PATH") orelse "/usr/local/bin:/bin/:/usr/bin"; |
| 972 | 978 | var path_buf: [MAX_PATH_BYTES]u8 = undefined; |
| ... | ... | @@ -993,7 +999,7 @@ pub fn execvpeZ_expandArg0( |
| 993 | 999 | .expand => child_argv[0] = full_path, |
| 994 | 1000 | .no_expand => {}, |
| 995 | 1001 | } |
| 996 | err = execveC(full_path, child_argv, envp); | |
| 1002 | err = execveZ(full_path, child_argv, envp); | |
| 997 | 1003 | switch (err) { |
| 998 | 1004 | error.AccessDenied => seen_eacces = true, |
| 999 | 1005 | error.FileNotFound, error.NotDir => {}, |
| ... | ... | @@ -1007,7 +1013,7 @@ pub fn execvpeZ_expandArg0( |
| 1007 | 1013 | /// Like `execvpe` except the parameters are null-terminated, |
| 1008 | 1014 | /// matching the syscall API on all targets. This removes the need for an allocator. |
| 1009 | 1015 | /// This function also uses the PATH environment variable to get the full path to the executable. |
| 1010 | /// If `file` is an absolute path, this is the same as `execveC`. | |
| 1016 | /// If `file` is an absolute path, this is the same as `execveZ`. | |
| 1011 | 1017 | pub fn execvpeZ( |
| 1012 | 1018 | file: [*:0]const u8, |
| 1013 | 1019 | argv: [*:null]const ?[*:0]const u8, |
| ... | ... | @@ -1097,8 +1103,37 @@ pub fn freeNullDelimitedEnvMap(allocator: *mem.Allocator, envp_buf: []?[*:0]u8) |
| 1097 | 1103 | |
| 1098 | 1104 | /// Get an environment variable. |
| 1099 | 1105 | /// See also `getenvZ`. |
| 1100 | /// TODO make this go through libc when we have it | |
| 1101 | 1106 | pub fn getenv(key: []const u8) ?[]const u8 { |
| 1107 | if (builtin.os == .windows) { | |
| 1108 | // TODO update this to use the ProcessEnvironmentBlock | |
| 1109 | @compileError("TODO implement std.os.getenv for Windows"); | |
| 1110 | } | |
| 1111 | if (builtin.link_libc) { | |
| 1112 | var small_key_buf: [64]u8 = undefined; | |
| 1113 | if (key.len < small_key_buf.len) { | |
| 1114 | mem.copy(u8, &small_key_buf, key); | |
| 1115 | small_key_buf[key.len] = 0; | |
| 1116 | const key0 = small_key_buf[0..key.len :0]; | |
| 1117 | return getenvZ(key0); | |
| 1118 | } | |
| 1119 | // Search the entire `environ` because we don't have a null terminated pointer. | |
| 1120 | var ptr = std.c.environ; | |
| 1121 | while (ptr.*) |line| : (ptr += 1) { | |
| 1122 | var line_i: usize = 0; | |
| 1123 | while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {} | |
| 1124 | const this_key = line[0..line_i]; | |
| 1125 | ||
| 1126 | if (!mem.eql(u8, this_key, key)) continue; | |
| 1127 | ||
| 1128 | var end_i: usize = line_i; | |
| 1129 | while (line[end_i] != 0) : (end_i += 1) {} | |
| 1130 | const value = line[line_i + 1 .. end_i]; | |
| 1131 | ||
| 1132 | return value; | |
| 1133 | } | |
| 1134 | return null; | |
| 1135 | } | |
| 1136 | // TODO see https://github.com/ziglang/zig/issues/4524 | |
| 1102 | 1137 | for (environ) |ptr| { |
| 1103 | 1138 | var line_i: usize = 0; |
| 1104 | 1139 | while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {} |
| ... | ... | @@ -1120,6 +1155,10 @@ pub const getenvC = getenvZ; |
| 1120 | 1155 | /// Get an environment variable with a null-terminated name. |
| 1121 | 1156 | /// See also `getenv`. |
| 1122 | 1157 | pub fn getenvZ(key: [*:0]const u8) ?[]const u8 { |
| 1158 | if (builtin.os == .windows) { | |
| 1159 | // TODO update this to use the ProcessEnvironmentBlock | |
| 1160 | @compileError("TODO implement std.os.getenv for Windows"); | |
| 1161 | } | |
| 1123 | 1162 | if (builtin.link_libc) { |
| 1124 | 1163 | const value = system.getenv(key) orelse return null; |
| 1125 | 1164 | return mem.toSliceConst(u8, value); |
lib/std/process.zig+22-9| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | 1 | const std = @import("std.zig"); |
| 2 | const builtin = std.builtin; | |
| 3 | 3 | const os = std.os; |
| 4 | 4 | const fs = std.fs; |
| 5 | 5 | const BufMap = std.BufMap; |
| ... | ... | @@ -31,13 +31,13 @@ test "getCwdAlloc" { |
| 31 | 31 | testing.allocator.free(cwd); |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | /// Caller must free result when done. | |
| 35 | /// TODO make this go through libc when we have it | |
| 34 | /// Caller owns resulting `BufMap`. | |
| 36 | 35 | pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 37 | 36 | var result = BufMap.init(allocator); |
| 38 | 37 | errdefer result.deinit(); |
| 39 | 38 | |
| 40 | 39 | if (builtin.os == .windows) { |
| 40 | // TODO update this to use the ProcessEnvironmentBlock | |
| 41 | 41 | const ptr = try os.windows.GetEnvironmentStringsW(); |
| 42 | 42 | defer os.windows.FreeEnvironmentStringsW(ptr); |
| 43 | 43 | |
| ... | ... | @@ -95,15 +95,29 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 95 | 95 | } |
| 96 | 96 | } |
| 97 | 97 | return result; |
| 98 | } else if (builtin.link_libc) { | |
| 99 | var ptr = std.c.environ; | |
| 100 | while (ptr.*) |line| : (ptr += 1) { | |
| 101 | var line_i: usize = 0; | |
| 102 | while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {} | |
| 103 | const key = line[0..line_i]; | |
| 104 | ||
| 105 | var end_i: usize = line_i; | |
| 106 | while (line[end_i] != 0) : (end_i += 1) {} | |
| 107 | const value = line[line_i + 1 .. end_i]; | |
| 108 | ||
| 109 | try result.set(key, value); | |
| 110 | } | |
| 111 | return result; | |
| 98 | 112 | } else { |
| 99 | for (os.environ) |ptr| { | |
| 113 | for (os.environ) |line| { | |
| 100 | 114 | var line_i: usize = 0; |
| 101 | while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {} | |
| 102 | const key = ptr[0..line_i]; | |
| 115 | while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {} | |
| 116 | const key = line[0..line_i]; | |
| 103 | 117 | |
| 104 | 118 | var end_i: usize = line_i; |
| 105 | while (ptr[end_i] != 0) : (end_i += 1) {} | |
| 106 | const value = ptr[line_i + 1 .. end_i]; | |
| 119 | while (line[end_i] != 0) : (end_i += 1) {} | |
| 120 | const value = line[line_i + 1 .. end_i]; | |
| 107 | 121 | |
| 108 | 122 | try result.set(key, value); |
| 109 | 123 | } |
| ... | ... | @@ -125,7 +139,6 @@ pub const GetEnvVarOwnedError = error{ |
| 125 | 139 | }; |
| 126 | 140 | |
| 127 | 141 | /// Caller must free returned memory. |
| 128 | /// TODO make this go through libc when we have it | |
| 129 | 142 | pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 { |
| 130 | 143 | if (builtin.os == .windows) { |
| 131 | 144 | const key_with_null = try std.unicode.utf8ToUtf16LeWithNull(allocator, key); |
lib/std/start.zig+8-2| ... | ... | @@ -21,7 +21,9 @@ comptime { |
| 21 | 21 | @export(main, .{ .name = "main", .linkage = .Weak }); |
| 22 | 22 | } |
| 23 | 23 | } else if (builtin.os == .windows) { |
| 24 | if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) { | |
| 24 | if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and | |
| 25 | !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) | |
| 26 | { | |
| 25 | 27 | @export(WinMainCRTStartup, .{ .name = "WinMainCRTStartup" }); |
| 26 | 28 | } |
| 27 | 29 | } else if (builtin.os == .uefi) { |
| ... | ... | @@ -34,7 +36,11 @@ comptime { |
| 34 | 36 | } |
| 35 | 37 | } |
| 36 | 38 | |
| 37 | fn _DllMainCRTStartup(hinstDLL: std.os.windows.HINSTANCE, fdwReason: std.os.windows.DWORD, lpReserved: std.os.windows.LPVOID) callconv(.Stdcall) std.os.windows.BOOL { | |
| 39 | fn _DllMainCRTStartup( | |
| 40 | hinstDLL: std.os.windows.HINSTANCE, | |
| 41 | fdwReason: std.os.windows.DWORD, | |
| 42 | lpReserved: std.os.windows.LPVOID, | |
| 43 | ) callconv(.Stdcall) std.os.windows.BOOL { | |
| 38 | 44 | if (@hasDecl(root, "DllMain")) { |
| 39 | 45 | return root.DllMain(hinstDLL, fdwReason, lpReserved); |
| 40 | 46 | } |
src/os.cpp+1-5| ... | ... | @@ -81,11 +81,7 @@ static clock_serv_t macos_monotonic_clock; |
| 81 | 81 | #include <errno.h> |
| 82 | 82 | #include <time.h> |
| 83 | 83 | |
| 84 | // Apple doesn't provide the environ global variable | |
| 85 | #if defined(__APPLE__) && !defined(environ) | |
| 86 | #include <crt_externs.h> | |
| 87 | #define environ (*_NSGetEnviron()) | |
| 88 | #elif defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) || defined(ZIG_OS_DRAGONFLY) | |
| 84 | #if !defined(environ) | |
| 89 | 85 | extern char **environ; |
| 90 | 86 | #endif |
| 91 | 87 |