Creates a null-delimited environment variable block in the format expected by POSIX, from a different one.
pub fn createPosixBlock(
existing: Environ,
gpa: Allocator,
options: CreatePosixBlockOptions,
) Allocator.Error!PosixBlock
pub fn createPosixBlock(
existing: Environ,
gpa: Allocator,
options: CreatePosixBlockOptions,
) Allocator.Error!PosixBlock {
const contains_zig_progress = for (existing.block.view().slice) |entry| {
if (mem.eql(u8, mem.sliceTo(entry, '='), "ZIG_PROGRESS")) break true;
} else false;
const ZigProgressAction = enum { nothing, edit, delete, add };
const zig_progress_action: ZigProgressAction = action: {
const fd = options.zig_progress_fd orelse break :action .nothing;
if (fd >= 0) {
break :action if (contains_zig_progress) .edit else .add;
} else {
if (contains_zig_progress) break :action .delete;
}
break :action .nothing;
};
const envp = try gpa.allocSentinel(?[*:0]u8, len: {
var len: usize = existing.block.slice.len;
switch (zig_progress_action) {
.add => len += 1,
.delete => len -= 1,
.nothing, .edit => {},
}
break :len len;
}, null);
var envp_len: usize = 0;
errdefer {
envp[envp_len] = null;
PosixBlock.deinit(.{ .slice = envp[0..envp_len :null] }, gpa);
}
if (zig_progress_action == .add) {
envp[envp_len] = try std.fmt.allocPrintSentinel(gpa, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?}, 0);
envp_len += 1;
}
var existing_index: usize = 0;
while (existing.block.slice[existing_index]) |entry| : (existing_index += 1) {
if (mem.eql(u8, mem.sliceTo(entry, '='), "ZIG_PROGRESS")) switch (zig_progress_action) {
.add => unreachable,
.delete => continue,
.edit => {
envp[envp_len] = try std.fmt.allocPrintSentinel(gpa, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?}, 0);
envp_len += 1;
continue;
},
.nothing => {},
};
envp[envp_len] = try gpa.dupeSentinel(u8, mem.span(entry), 0);
envp_len += 1;
}
assert(envp_len == envp.len);
return .{ .slice = envp };
}