honeylisp/lib/spawn.lua

45 lines
1.2 KiB
Lua
Raw Normal View History

-- adapted from https://gist.github.com/iMega/f47f5a2ae1f02d7d5769a008538fd925
local ffi = require 'ffi'
local C = ffi.C
ffi.cdef([[
typedef int32_t pid_t;
pid_t fork(void);
int open(const char *pathname, int flags, int mode);
int close(int fd);
int dup2(int oldfd, int newfd);
int execvp(const char *file, char *const argv[]);
int kill(pid_t pid, int sig);
pid_t setsid(void);
]])
local bor = bit.bor
local ffi_cast = ffi.cast
local k_char_p_arr_t = ffi.typeof('const char * [?]')
local char_p_k_p_t = ffi.typeof('char * const *')
local function spawn(args)
if not args or #args == 0 then error("couldn't tokenize cmd_line") end
local pid = C.fork()
if pid < 0 then
error("fork failed " .. ffi.errno())
elseif pid == 0 then -- child process
C.setsid()
local argv = k_char_p_arr_t(#args + 1) -- automatically NULL terminated
for i = 1, #args do
argv[i-1] = args[i] -- args is 1-based Lua table, argv is 0-based C array
end
local res = C.execvp(args[1], ffi_cast(char_p_k_p_t, argv))
if res == -1 then error("execvp failed with " .. ffi.errno()) end
-- HERE SHOULD BE UNREACHABLE!!
else
return pid
end
end
return {spawn=spawn, kill=C.kill}