elua: utility func to exec a process (without spawning a shell like os.execute)

This commit is contained in:
Daniel Kolesa 2014-05-06 13:24:39 +01:00 committed by Daniel Kolesa
parent 58409c521a
commit cbeaf5b58a
2 changed files with 85 additions and 3 deletions

View File

@ -1,6 +1,11 @@
/* The Lua runtime component of the EFL */
#include <getopt.h>
#ifndef _WIN32
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#endif
#include "main.h"
@ -192,6 +197,81 @@ static int register_callbacks(lua_State *L) {
return 1;
}
static int elua_exec(lua_State *L) {
#ifndef _WIN32
pid_t cpid = fork();
if (cpid < 0) {
lua_pushnil(L);
lua_pushstring(L, strerror(errno));
return 2;
}
if (!cpid) {
const char **argv = alloca((lua_gettop(L) + 1) * sizeof(char*));
int i;
for (i = 0; i < lua_gettop(L); ++i) {
argv[i] = lua_tostring(L, i + 1);
}
argv[lua_gettop(L)] = NULL;
execv(argv[0], (char*const*)argv);
exit(1);
} else {
int status;
if (waitpid(cpid, &status, 0) < 0) {
lua_pushnil(L);
lua_pushstring(L, strerror(errno));
return 2;
}
lua_pushinteger(L, status);
return 1;
}
#else
char buf[4096]; /* temporary, only because Windows API is retarded */
char *cptr = buf;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&si, sizeof(pi));
int i;
for (i = 1; i < lua_gettop(L); ++i) {
size_t l;
const char *arg = lua_tolstring(L, i + 1, &l);
*(cptr++) = '"';
memcpy(cptr, l + 1, arg);
cptr += l;
*(cptr++) = '"'
if (i != (lua_gettop(L) - 1)) {
*(cptr++) = ' ';
} else {
cptr[0] = '\0';
}
}
if (!CreateProcess(lua_tostring(L, 1), buf, NULL, NULL, FALSE, 0, NULL,
NULL, &si, &pi)) {
LPVOID msgbuf;
DWORD dw = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NUL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msgbuf,
0, NULL);
lua_pushnil(L);
lua_pushstring(L, (const char*)msgbuf);
LocalFree(msgbuf);
return 2;
}
int status;
if (!GetExitCodeProcess(pi.hProcess, &status)) status = 0;
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
lua_pushinteger(L, status);
return 1;
#endif
}
struct Main_Data {
int argc;
char **argv;
@ -201,6 +281,7 @@ struct Main_Data {
const luaL_reg cutillib[] = {
{ "init_module", init_module },
{ "register_callbacks", register_callbacks },
{ "exec", elua_exec },
{ NULL, NULL }
};

View File

@ -2,6 +2,7 @@
-- provides a drop-in replacement of xgettext that supports Lua (but not any
-- other language)
local cutil = require("cutil")
local getopt = require("getopt")
local VERSION = "1.0.0"
@ -164,16 +165,16 @@ end
local hasxgettext = os.getenv("XGETTEXT")
if hasxgettext then
local gargs = { "\"" .. hasxgettext .. "\"" }
local gargs = { hasxgettext }
for i = 1, #opts do
gargs[#gargs + 1] = "\"" .. arg[i] .. "\""
gargs[#gargs + 1] = arg[i]
end
for i, v in ipairs(args) do
if not v:match("^.+%.lua$") then
gargs[#gargs + 1] = v
end
end
os.execute(table.concat(gargs, " "))
cutil.exec(unpack(gargs))
end
return true