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; + } }