Skip to content

Instantly share code, notes, and snippets.

@mischief
Last active August 1, 2017 14:21
Show Gist options
  • Select an option

  • Save mischief/ce429b04b7b7609b571da1df224244b5 to your computer and use it in GitHub Desktop.

Select an option

Save mischief/ce429b04b7b7609b571da1df224244b5 to your computer and use it in GitHub Desktop.
local os = require("os")
local ffi = require("ffi")
-- luajit ffi declarations
ffi.cdef[[
typedef int32_t pid_t;
pid_t fork(void);
int close(int d);
char *strerror(int n);
]]
local unistd = {
close = ffi.C.close,
fork = ffi.C.fork,
}
ffi.cdef[[
static const int AF_UNIX = 1;
static const int SOCK_STREAM = 1;
static const int PF_UNSPEC = 0;
int socketpair(int d, int type, int protocol, int sv[2]);
]]
local socket = {
AF_UNIX = ffi.C.AF_UNIX,
SOCK_STREAM = ffi.C.SOCK_STREAM,
PF_UNSPEC = ffi.C.PF_UNSPEC,
socketpair = ffi.C.socketpair,
}
ffi.cdef[[
typedef unsigned char u_char;
typedef long ssize_t;
typedef int32_t pid_t;
struct ibuf {
struct { struct ibuf *tqe_next; struct ibuf **tqe_prev; } entry;
u_char *buf;
size_t size;
size_t max;
size_t wpos;
size_t rpos;
int fd;
};
struct msgbuf {
struct { struct ibuf *tqh_first; struct ibuf **tqh_last; } bufs;
uint32_t queued;
int fd;
};
struct ibuf_read {
u_char buf[65535];
u_char *rptr;
size_t wpos;
};
struct imsg_fd {
struct { struct imsg_fd *tqe_next; struct imsg_fd **tqe_prev; } entry;
int fd;
};
struct imsgbuf {
struct { struct imsg_fd *tqh_first; struct imsg_fd **tqh_last; } fds;
struct ibuf_read r;
struct msgbuf w;
int fd;
pid_t pid;
};
struct imsg_hdr {
uint32_t type;
uint16_t len;
uint16_t flags;
uint32_t peerid;
uint32_t pid;
};
struct imsg {
struct imsg_hdr hdr;
int fd;
void *data;
};
struct ibuf *ibuf_open(size_t);
struct ibuf *ibuf_dynamic(size_t, size_t);
int ibuf_add(struct ibuf *, const void *, size_t);
void *ibuf_reserve(struct ibuf *, size_t);
void *ibuf_seek(struct ibuf *, size_t, size_t);
size_t ibuf_size(struct ibuf *);
size_t ibuf_left(struct ibuf *);
void ibuf_close(struct msgbuf *, struct ibuf *);
int ibuf_write(struct msgbuf *);
void ibuf_free(struct ibuf *);
void msgbuf_init(struct msgbuf *);
void msgbuf_clear(struct msgbuf *);
int msgbuf_write(struct msgbuf *);
void msgbuf_drain(struct msgbuf *, size_t);
void imsg_init(struct imsgbuf *, int);
ssize_t imsg_read(struct imsgbuf *);
ssize_t imsg_get(struct imsgbuf *, struct imsg *);
int imsg_compose(struct imsgbuf *, uint32_t, uint32_t, pid_t, int,
const void *, uint16_t);
int imsg_composev(struct imsgbuf *, uint32_t, uint32_t, pid_t, int,
const struct iovec *, int);
struct ibuf *imsg_create(struct imsgbuf *, uint32_t, uint32_t, pid_t, uint16_t);
int imsg_add(struct ibuf *, const void *, uint16_t);
void imsg_close(struct imsgbuf *, struct ibuf *);
void imsg_free(struct imsg *);
int imsg_flush(struct imsgbuf *);
void imsg_clear(struct imsgbuf *);
]]
local imsg = ffi.load("util")
err = function(what)
error(what .. ": " .. ffi.C.strerror(ffi.errno()))
end
-- example imsg program
local fds = ffi.new("int[2]")
local parent_ibuf = ffi.new("struct imsgbuf")
local child_ibuf = ffi.new("struct imsgbuf")
if socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM, socket.PF_UNSPEC, fds) == -1 then
err("socketpair")
end
child_main = function(b)
local data = ffi.new("int32_t[1]", {42})
local n = imsg.imsg_compose(b, 1, 0, 0, -1, data, 4)
print("child: imsg_compose="..tostring(n))
if n == -1 then
err("imsg_compose")
end
n = imsg.imsg_flush(b)
print("child: imsg_flush="..tostring(n))
if n == -1 then
err("imsg_flush")
end
return 0
end
parent_main = function(b)
local msg = ffi.new("struct imsg")
local n = imsg.imsg_read(b)
print("parent: imsg_read="..tonumber(n))
if n <= 0 then
err("imsg_read")
end
while true do
n = imsg.imsg_get(b, msg)
print("parent: imsg_get="..tonumber(n))
if n == 0 then
break
end
if n == -1 then
err("imsg_get")
end
if msg.hdr.type == 1 then
local d = ffi.cast("int32_t*", msg.data)
print(string.format("%d", d[0]))
end
end
end
local pid = unistd.fork()
if pid == -1 then
err("fork")
end
if pid == 0 then
-- child
unistd.close(fds[0])
imsg.imsg_init(child_ibuf, fds[1])
os.exit(child_main(child_ibuf))
end
-- parent
unistd.close(fds[1])
imsg.imsg_init(parent_ibuf, fds[0])
os.exit(parent_main(parent_ibuf))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment