aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--river/c.zig5
-rw-r--r--river/command/spawn.zig34
2 files changed, 29 insertions, 10 deletions
diff --git a/river/c.zig b/river/c.zig
index 829bdb7..dacb06e 100644
--- a/river/c.zig
+++ b/river/c.zig
@@ -19,9 +19,12 @@ pub usingnamespace @cImport({
@cDefine("_POSIX_C_SOURCE", "200809L");
@cDefine("WLR_USE_UNSTABLE", {});
- @cInclude("time.h");
@cInclude("stdlib.h");
+ @cInclude("time.h");
+ @cInclude("unistd.h");
+
@cInclude("linux/input-event-codes.h");
+
@cInclude("wayland-server-core.h");
//@cInclude("wlr/backend.h");
//@cInclude("wlr/render/wlr_renderer.h");
diff --git a/river/command/spawn.zig b/river/command/spawn.zig
index 96e25cd..fdc3ccb 100644
--- a/river/command/spawn.zig
+++ b/river/command/spawn.zig
@@ -17,6 +17,8 @@
const std = @import("std");
+const c = @import("../c.zig");
+
const Error = @import("../command.zig").Error;
const Seat = @import("../Seat.zig");
@@ -31,17 +33,31 @@ pub fn spawn(
const cmd = try std.mem.join(allocator, " ", args[1..]);
defer allocator.free(cmd);
+ const cmdZ = try std.cstr.addNullByte(allocator, cmd);
+ defer allocator.free(cmdZ);
- const child_args = [_][]const u8{ "/bin/sh", "-c", cmd };
- const child = try std.ChildProcess.init(&child_args, allocator);
- defer child.deinit();
+ const child_args = [_:null]?[*:0]const u8{ "/bin/sh", "-c", cmdZ, null };
- std.ChildProcess.spawn(child) catch |err| {
- out.* = try std.fmt.allocPrint(
- allocator,
- "failed to spawn {}: {}.",
- .{ cmd, err },
- );
+ const pid = std.os.fork() catch {
+ out.* = try std.fmt.allocPrint(allocator, "fork/execve failed", .{});
return Error.Other;
};
+
+ if (pid == 0) {
+ // Clean things up for the child in an intermediate fork
+ if (c.setsid() < 0) unreachable;
+ if (std.os.system.sigprocmask(std.os.SIG_SETMASK, &std.os.empty_sigset, null) < 0) unreachable;
+
+ const pid2 = std.os.fork() catch std.os.exit(1);
+ if (pid2 == 0) std.os.execveZ("/bin/sh", &child_args, std.c.environ) catch std.os.exit(1);
+
+ std.os.exit(0);
+ }
+
+ // Wait the intermediate child.
+ const status = std.os.waitpid(pid, 0);
+ if (std.os.WIFEXITED(status) and std.os.WEXITSTATUS(status) != 0) {
+ out.* = try std.fmt.allocPrint(allocator, "fork/execve failed", .{});
+ return Error.Other;
+ }
}