const std = @import("std"); const ControlMessage = extern struct { const Level = enum(u32) { socket = std.posix.SOL.SOCKET, }; // WARNING: this kind enum might be wrong for non-linux posix systems. const Kind = enum(u32) { rights = 1, credentials = 2, }; const Header = extern struct { length: usize, level: Level, kind: Kind, }; header: Header, payload: union { fd: [255]std.posix.fd_t, }, pub fn alignment(length: usize) usize { return (length + @sizeOf(usize) - 1) & ~(@sizeOf(usize) - 1); } pub fn space(self: @This()) usize { return self.alignment(self.length) + self.alignment(@sizeOf(Header)); } pub fn from_fds(fds: []std.posix.fd_t) @This() { var self: @This() = .{ }; self.level = .socket; self.kind = .rights; self.length = self.alignment(@sizeOf(Header)) + (fds.len * @sizeOf(std.posix.fd_t)); @memcpy(self.payload, fds); } }; pub fn send_fds(socket: std.posix.socket_t, fds: []std.posix.fd_t) !void { var iobuf: [1]u8 = std.mem.zeroes([1]u8); const io = std.posix.iovec { .base = &iobuf, .len = iobuf.len, }; var cmsg: ControlMessage = .from_fds(fds); const msghdr = std.posix.msghdr_const { .name = null, .namelen = 0, .iov = &io, .iolen = 1, .control = &cmsg, .controllen = cmsg.control_length(), }; _ = try std.posix.sendmsg(socket, &msghdr, 0); }