summaryrefslogtreecommitdiff
path: root/src/selection_pipe.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/selection_pipe.zig')
-rw-r--r--src/selection_pipe.zig19
1 files changed, 17 insertions, 2 deletions
diff --git a/src/selection_pipe.zig b/src/selection_pipe.zig
index fb6587f9..66444b04 100644
--- a/src/selection_pipe.zig
+++ b/src/selection_pipe.zig
@@ -32,6 +32,9 @@ pub const Request = struct {
shell: []const u8 = "",
/// Nonzero: `stop(token)` from another thread kills its commands.
token: u32 = 0,
+ /// The commands' environment, `NAME=value` each, when given; else this
+ /// process's.
+ env: []const []const u8 = &.{},
};
/// Worker-owned snapshot. `copy` is intentionally called synchronously while
@@ -47,6 +50,7 @@ pub const Job = struct {
cwds: [][]u8 = &.{},
shell: []u8 = &.{},
token: u32 = 0,
+ env: [][]u8 = &.{},
pub fn copy(gpa: std.mem.Allocator, request: Request) !*Job {
const job = try gpa.create(Job);
@@ -68,6 +72,8 @@ pub const Job = struct {
job.cwds = try dupeAll(gpa, request.cwds.len, request.cwds, true);
errdefer freeAll(gpa, job.cwds);
job.shell = try gpa.dupe(u8, request.shell);
+ errdefer gpa.free(job.shell);
+ job.env = try dupeAll(gpa, request.env.len, request.env, false);
return job;
}
@@ -100,6 +106,7 @@ pub const Job = struct {
freeAll(gpa, job.commands);
freeAll(gpa, job.cwds);
gpa.free(job.shell);
+ freeAll(gpa, job.env);
gpa.destroy(job);
}
};
@@ -232,7 +239,7 @@ pub fn runOne(
cwd: []const u8,
input: []const u8,
) Outcome {
- return runIn(gpa, io, "", command, cwd, input, 0);
+ return runIn(gpa, io, "", command, cwd, input, 0, &.{});
}
/// The commands running for a stoppable request (`Request.token`), so
@@ -306,6 +313,7 @@ pub fn runIn(
cwd: []const u8,
input: []const u8,
token: u32,
+ env: []const []const u8,
) Outcome {
const fail = struct {
fn k(kind: Failure.Kind) Outcome {
@@ -320,6 +328,12 @@ pub fn runIn(
// child inherits, is cleared across the fork (only the tty's SIGWINCH is
// ever blocked, and its default is to be ignored). A handler resets at
// exec by itself, and nothing here is ignored.
+ var environ: std.process.Environ.Map = .init(gpa);
+ defer environ.deinit();
+ for (env) |line| {
+ const eq = std.mem.indexOfScalar(u8, line, '=') orelse continue;
+ environ.put(line[0..eq], line[eq + 1 ..]) catch return fail.k(.spawn);
+ }
const none = std.posix.sigemptyset();
var kept: std.posix.sigset_t = undefined;
std.posix.sigprocmask(std.posix.SIG.SETMASK, &none, &kept);
@@ -327,6 +341,7 @@ pub fn runIn(
var child = std.process.spawn(io, .{
.argv = &.{ if (shell.len == 0) "/bin/sh" else shell, "-c", command },
.cwd = if (cwd.len == 0) .inherit else .{ .path = cwd },
+ .environ_map = if (env.len > 0) &environ else null,
.stdin = .pipe,
.stdout = .pipe,
.stderr = .pipe,
@@ -435,7 +450,7 @@ pub fn runJob(gpa: std.mem.Allocator, io: std.Io, job: *const Job) Response {
response.failure = .{ .kind = .signal, .index = @intCast(i) };
break;
}
- const output = switch (runIn(gpa, io, job.shell, command, cwd, input, job.token)) {
+ const output = switch (runIn(gpa, io, job.shell, command, cwd, input, job.token, job.env)) {
.ok => |bytes| bytes,
.failed => |f| {
// WHICH selection, because with several cursors "it failed" is