pub fn createPosixBlock(
map: *const Map,
gpa: Allocator,
options: CreatePosixBlockOptions,
) Allocator.Error!PosixBlock {
const ZigProgressAction = enum { nothing, edit, delete, add };
const zig_progress_action: ZigProgressAction = action: {
const fd = options.zig_progress_fd orelse break :action .nothing;
const exists = map.contains("ZIG_PROGRESS");
if (fd >= 0) {
break :action if (exists) .edit else .add;
} else {
if (exists) break :action .delete;
}
break :action .nothing;
};
const envp = try gpa.allocSentinel(?[*:0]u8, len: {
var len: usize = map.count();
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;
}
for (map.keys(), map.values()) |key, value| {
if (mem.eql(u8, key, "ZIG_PROGRESS")) switch (zig_progress_action) {
.add => unreachable,
.delete => continue,
.edit => {
envp[envp_len] = try std.fmt.allocPrintSentinel(gpa, "{s}={d}", .{
key, options.zig_progress_fd.?,
}, 0);
envp_len += 1;
continue;
},
.nothing => {},
};
envp[envp_len] = try std.fmt.allocPrintSentinel(gpa, "{s}={s}", .{ key, value }, 0);
envp_len += 1;
}
assert(envp_len == envp.len);
return .{ .slice = envp };
}
Creates a null-delimited environment variable block in the format expected by POSIX, from a hash map plus options.