mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
os: rename env to be posix-like, do not allocate on posix
This commit is contained in:
@ -243,9 +243,9 @@ pub const GlobalState = struct {
|
||||
// maybe once for logging) so for now this is an easy way to do
|
||||
// this. Env vars are useful for logging too because they are
|
||||
// easy to set.
|
||||
if ((try internal_os.getEnvVarOwned(self.alloc, "GHOSTTY_LOG"))) |v| {
|
||||
defer self.alloc.free(v);
|
||||
if (v.len > 0) {
|
||||
if ((try internal_os.getenv(self.alloc, "GHOSTTY_LOG"))) |v| {
|
||||
defer v.deinit(self.alloc);
|
||||
if (v.value.len > 0) {
|
||||
self.logging = .{ .stderr = {} };
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,61 @@ pub fn appendEnv(
|
||||
});
|
||||
}
|
||||
|
||||
/// The result of getenv, with a shared deinit to properly handle allocation
|
||||
/// on Windows.
|
||||
pub const GetEnvResult = struct {
|
||||
value: []const u8,
|
||||
|
||||
pub fn deinit(self: GetEnvResult, alloc: Allocator) void {
|
||||
switch (builtin.os.tag) {
|
||||
.windows => alloc.free(self.value),
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// Gets the value of an environment variable, or null if not found.
|
||||
/// This will allocate on Windows but not on other platforms. The returned
|
||||
/// value should have deinit called to do the proper cleanup no matter what
|
||||
/// platform you are on.
|
||||
pub fn getenv(alloc: Allocator, key: []const u8) !?GetEnvResult {
|
||||
return switch (builtin.os.tag) {
|
||||
// Non-Windows doesn't need to allocate
|
||||
else => if (std.os.getenv(key)) |v| .{ .value = v } else null,
|
||||
|
||||
// Windows needs to allocate
|
||||
.windows => if (std.process.getEnvVarOwned(alloc, key)) |v| .{
|
||||
.value = v,
|
||||
} else |err| switch (err) {
|
||||
error.EnvironmentVariableNotFound => null,
|
||||
else => err,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn setenv(key: [:0]const u8, value: [:0]const u8) c_int {
|
||||
return switch (builtin.os.tag) {
|
||||
.windows => c._putenv_s(key.ptr, value.ptr),
|
||||
else => c.setenv(key.ptr, value.ptr, 1),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn unsetenv(key: [:0]const u8) c_int {
|
||||
return switch (builtin.os.tag) {
|
||||
.windows => c._putenv_s(key.ptr, ""),
|
||||
else => c.unsetenv(key.ptr),
|
||||
};
|
||||
}
|
||||
|
||||
const c = struct {
|
||||
// POSIX
|
||||
extern "c" fn setenv(name: ?[*]const u8, value: ?[*]const u8, overwrite: c_int) c_int;
|
||||
extern "c" fn unsetenv(name: ?[*]const u8) c_int;
|
||||
|
||||
// Windows
|
||||
extern "c" fn _putenv_s(varname: ?[*]const u8, value_string: ?[*]const u8) c_int;
|
||||
};
|
||||
|
||||
test "appendEnv empty" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
@ -46,36 +101,3 @@ test "appendEnv existing" {
|
||||
try testing.expectEqualStrings(result, "a:b:foo");
|
||||
}
|
||||
}
|
||||
|
||||
extern "c" fn setenv(name: ?[*]const u8, value: ?[*]const u8, overwrite: c_int) c_int;
|
||||
extern "c" fn unsetenv(name: ?[*]const u8) c_int;
|
||||
extern "c" fn _putenv_s(varname: ?[*]const u8, value_string: ?[*]const u8) c_int;
|
||||
|
||||
pub fn setEnv(key: [:0]const u8, value: [:0]const u8) c_int {
|
||||
if (builtin.os.tag == .windows) {
|
||||
return _putenv_s(key.ptr, value.ptr);
|
||||
} else {
|
||||
return setenv(key.ptr, value.ptr, 1);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unsetEnv(key: [:0]const u8) c_int {
|
||||
if (builtin.os.tag == .windows) {
|
||||
return _putenv_s(key.ptr, "");
|
||||
} else {
|
||||
return unsetenv(key.ptr);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the value of an environment variable, or null if not found.
|
||||
/// The returned value is always allocated so it must be freed.
|
||||
pub fn getEnvVarOwned(alloc: std.mem.Allocator, key: []const u8) !?[]u8 {
|
||||
if (std.process.getEnvVarOwned(alloc, key)) |v| {
|
||||
return v;
|
||||
} else |err| switch (err) {
|
||||
error.EnvironmentVariableNotFound => {},
|
||||
else => return err,
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -12,8 +12,8 @@ pub fn ensureLocale(alloc: std.mem.Allocator) !void {
|
||||
|
||||
// Get our LANG env var. We use this many times but we also need
|
||||
// the original value later.
|
||||
const lang = try internal_os.getEnvVarOwned(alloc, "LANG");
|
||||
defer if (lang) |v| alloc.free(v);
|
||||
const lang = try internal_os.getenv(alloc, "LANG");
|
||||
defer if (lang) |v| v.deinit(alloc);
|
||||
|
||||
// On macOS, pre-populate the LANG env var with system preferences.
|
||||
// When launching the .app, LANG is not set so we must query it from the
|
||||
@ -22,7 +22,7 @@ pub fn ensureLocale(alloc: std.mem.Allocator) !void {
|
||||
if (comptime builtin.target.isDarwin()) {
|
||||
// Set the lang if it is not set or if its empty.
|
||||
if (lang) |l| {
|
||||
if (l.len == 0) {
|
||||
if (l.value.len == 0) {
|
||||
setLangFromCocoa();
|
||||
}
|
||||
}
|
||||
@ -37,13 +37,13 @@ pub fn ensureLocale(alloc: std.mem.Allocator) !void {
|
||||
// setlocale failed. This is probably because the LANG env var is
|
||||
// invalid. Try to set it without the LANG var set to use the system
|
||||
// default.
|
||||
if ((try internal_os.getEnvVarOwned(alloc, "LANG"))) |old_lang| {
|
||||
defer alloc.free(old_lang);
|
||||
if (old_lang.len > 0) {
|
||||
if ((try internal_os.getenv(alloc, "LANG"))) |old_lang| {
|
||||
defer old_lang.deinit(alloc);
|
||||
if (old_lang.value.len > 0) {
|
||||
// We don't need to do both of these things but we do them
|
||||
// both to be sure that lang is either empty or unset completely.
|
||||
_ = internal_os.setEnv("LANG", "");
|
||||
_ = internal_os.unsetEnv("LANG");
|
||||
_ = internal_os.setenv("LANG", "");
|
||||
_ = internal_os.unsetenv("LANG");
|
||||
|
||||
if (setlocale(LC_ALL, "")) |v| {
|
||||
log.info("setlocale after unset lang result={s}", .{v});
|
||||
@ -59,7 +59,7 @@ pub fn ensureLocale(alloc: std.mem.Allocator) !void {
|
||||
// Failure again... fallback to en_US.UTF-8
|
||||
log.warn("setlocale failed with LANG and system default. Falling back to en_US.UTF-8", .{});
|
||||
if (setlocale(LC_ALL, "en_US.UTF-8")) |v| {
|
||||
_ = internal_os.setEnv("LANG", "en_US.UTF-8");
|
||||
_ = internal_os.setenv("LANG", "en_US.UTF-8");
|
||||
log.info("setlocale default result={s}", .{v});
|
||||
return;
|
||||
} else log.err("setlocale failed even with the fallback, uncertain results", .{});
|
||||
@ -100,7 +100,7 @@ fn setLangFromCocoa() void {
|
||||
log.info("detected system locale={s}", .{env_value});
|
||||
|
||||
// Set it onto our environment
|
||||
if (internal_os.setEnv("LANG", env_value) < 0) {
|
||||
if (internal_os.setenv("LANG", env_value) < 0) {
|
||||
log.err("error setting locale env var", .{});
|
||||
return;
|
||||
}
|
||||
|
Reference in New Issue
Block a user