41 lines
1.1 KiB
Lua
41 lines
1.1 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[]);
|
||
|
]])
|
||
|
|
||
|
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
|
||
|
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
|