| ... | ... | @@ -77,17 +77,31 @@ pub const Environ = struct { |
| 77 | 77 | /// memoized based on `block`. |
| 78 | 78 | initialized: bool = false, |
| 79 | 79 | /// Protected by `mutex`. Memoized based on `block`. Tracks whether the |
| 80 | | /// environment variables are present and non-empty. |
| 81 | | exist: struct { |
| 82 | | NO_COLOR: bool = false, |
| 83 | | CLICOLOR_FORCE: bool = false, |
| 84 | | } = .{}, |
| 80 | /// environment variables are present, ignoring their value. |
| 81 | exist: Exist = .{}, |
| 85 | 82 | /// Protected by `mutex`. Memoized based on `block`. |
| 86 | | string: struct { |
| 87 | | PATH: ?[:0]const u8 = null, |
| 88 | | } = .{}, |
| 83 | string: String = .{}, |
| 84 | /// Protected by `mutex`. Tracks the problem, if any, that occurred when |
| 85 | /// trying to scan environment variables. |
| 86 | /// |
| 87 | /// Errors are only possible on WASI. |
| 88 | err: ?Error = null, |
| 89 | |
| 90 | pub const Error = Allocator.Error || Io.UnexpectedError; |
| 89 | 91 | |
| 90 | 92 | pub const Block = []const [*:0]const u8; |
| 93 | |
| 94 | pub const Exist = struct { |
| 95 | NO_COLOR: bool = false, |
| 96 | CLICOLOR_FORCE: bool = false, |
| 97 | }; |
| 98 | |
| 99 | pub const String = switch (native_os) { |
| 100 | .openbsd, .haiku => struct { |
| 101 | PATH: ?[:0]const u8 = null, |
| 102 | }, |
| 103 | else => struct {}, |
| 104 | }; |
| 91 | 105 | }; |
| 92 | 106 | |
| 93 | 107 | pub const RobustCancel = if (std.Thread.use_pthreads or native_os == .linux) enum { |
| ... | ... | @@ -11917,13 +11931,111 @@ fn scanEnviron(t: *Threaded) void { |
| 11917 | 11931 | if (t.environ.initialized) return; |
| 11918 | 11932 | t.environ.initialized = true; |
| 11919 | 11933 | |
| 11920 | | if (native_os == .wasi) { |
| 11921 | | @panic("TODO"); |
| 11922 | | } |
| 11934 | if (is_windows) { |
| 11935 | const ptr = windows.peb().ProcessParameters.Environment; |
| 11923 | 11936 | |
| 11924 | | for (t.environ.block) |kv| { |
| 11925 | | _ = kv; |
| 11926 | | @panic("TODO"); |
| 11937 | var i: usize = 0; |
| 11938 | while (ptr[i] != 0) { |
| 11939 | const key_start = i; |
| 11940 | |
| 11941 | // There are some special environment variables that start with =, |
| 11942 | // so we need a special case to not treat = as a key/value separator |
| 11943 | // if it's the first character. |
| 11944 | // https://devblogs.microsoft.com/oldnewthing/20100506-00/?p=14133 |
| 11945 | if (ptr[key_start] == '=') i += 1; |
| 11946 | |
| 11947 | while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {} |
| 11948 | const key_w = ptr[key_start..i]; |
| 11949 | if (std.mem.eql(u16, key_w, &.{ 'N', 'O', '_', 'C', 'O', 'L', 'O', 'R' })) { |
| 11950 | t.environ.exist.NO_COLOR = true; |
| 11951 | } else if (std.mem.eql(u16, key_w, &.{ 'C', 'L', 'I', 'C', 'O', 'L', 'O', 'R', '_', 'F', 'O', 'R', 'C', 'E' })) { |
| 11952 | t.environ.exist.CLICOLOR_FORCE = true; |
| 11953 | } |
| 11954 | comptime assert(@sizeOf(Environ.String) == 0); |
| 11955 | |
| 11956 | while (ptr[i] != 0) : (i += 1) {} // skip over '=' and value |
| 11957 | i += 1; // skip over null byte |
| 11958 | } |
| 11959 | } else if (native_os == .wasi and !builtin.link_libc) { |
| 11960 | var environ_count: usize = undefined; |
| 11961 | var environ_buf_size: usize = undefined; |
| 11962 | |
| 11963 | switch (std.os.wasi.environ_sizes_get(&environ_count, &environ_buf_size)) { |
| 11964 | .SUCCESS => {}, |
| 11965 | else => |err| { |
| 11966 | t.environ.err = posix.unexpectedErrno(err); |
| 11967 | return; |
| 11968 | }, |
| 11969 | } |
| 11970 | if (environ_count == 0) return; |
| 11971 | |
| 11972 | const environ = t.allocator.alloc([*:0]u8, environ_count) catch |err| { |
| 11973 | t.environ.err = err; |
| 11974 | return; |
| 11975 | }; |
| 11976 | defer t.allocator.free(environ); |
| 11977 | const environ_buf = t.allocator.alloc(u8, environ_buf_size) catch |err| { |
| 11978 | t.environ.err = err; |
| 11979 | return; |
| 11980 | }; |
| 11981 | defer t.allocator.free(environ_buf); |
| 11982 | |
| 11983 | switch (std.os.wasi.environ_get(environ.ptr, environ_buf.ptr)) { |
| 11984 | .SUCCESS => {}, |
| 11985 | else => |err| { |
| 11986 | t.environ.err = posix.unexpectedErrno(err); |
| 11987 | return; |
| 11988 | }, |
| 11989 | } |
| 11990 | |
| 11991 | for (environ) |env| { |
| 11992 | const pair = std.mem.sliceTo(env, 0); |
| 11993 | var parts = std.mem.splitScalar(u8, pair, '='); |
| 11994 | const key = parts.first(); |
| 11995 | if (std.mem.eql(u8, key, "NO_COLOR")) { |
| 11996 | t.environ.exist.NO_COLOR = true; |
| 11997 | } else if (std.mem.eql(u8, key, "CLICOLOR_FORCE")) { |
| 11998 | t.environ.exist.CLICOLOR_FORCE = true; |
| 11999 | } |
| 12000 | comptime assert(@sizeOf(Environ.String) == 0); |
| 12001 | } |
| 12002 | } else if (builtin.link_libc) { |
| 12003 | var ptr = std.c.environ; |
| 12004 | while (ptr[0]) |line| : (ptr += 1) { |
| 12005 | var line_i: usize = 0; |
| 12006 | while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {} |
| 12007 | const key = line[0..line_i]; |
| 12008 | |
| 12009 | var end_i: usize = line_i; |
| 12010 | while (line[end_i] != 0) : (end_i += 1) {} |
| 12011 | const value = line[line_i + 1 .. end_i]; |
| 12012 | |
| 12013 | if (std.mem.eql(u8, key, "NO_COLOR")) { |
| 12014 | t.environ.exist.NO_COLOR = true; |
| 12015 | } else if (std.mem.eql(u8, key, "CLICOLOR_FORCE")) { |
| 12016 | t.environ.exist.CLICOLOR_FORCE = true; |
| 12017 | } else if (@hasField(Environ.String, "PATH") and std.mem.eql(u8, key, "PATH")) { |
| 12018 | t.environ.string.PATH = value; |
| 12019 | } |
| 12020 | } |
| 12021 | } else { |
| 12022 | for (t.environ.block) |line| { |
| 12023 | var line_i: usize = 0; |
| 12024 | while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {} |
| 12025 | const key = line[0..line_i]; |
| 12026 | |
| 12027 | var end_i: usize = line_i; |
| 12028 | while (line[end_i] != 0) : (end_i += 1) {} |
| 12029 | const value = line[line_i + 1 .. end_i]; |
| 12030 | |
| 12031 | if (std.mem.eql(u8, key, "NO_COLOR")) { |
| 12032 | t.environ.exist.NO_COLOR = true; |
| 12033 | } else if (std.mem.eql(u8, key, "CLICOLOR_FORCE")) { |
| 12034 | t.environ.exist.CLICOLOR_FORCE = true; |
| 12035 | } else if (@hasField(Environ.String, "PATH") and std.mem.eql(u8, key, "PATH")) { |
| 12036 | t.environ.string.PATH = value; |
| 12037 | } |
| 12038 | } |
| 11927 | 12039 | } |
| 11928 | 12040 | } |
| 11929 | 12041 | |