45 lines
1.2 KiB
Lua
45 lines
1.2 KiB
Lua
-- 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}
|