This commit is contained in:
Axel Kittenberger 2010-11-12 14:05:10 +00:00
parent 3df30b2125
commit a2554168e6

View File

@ -566,19 +566,33 @@ l_addtoclock(lua_State *L)
* *
* @param (Lua stack) Path to binary to call * @param (Lua stack) Path to binary to call
* @params (Lua stack) list of string as arguments * @params (Lua stack) list of string as arguments
* or "<" in which case the next argument is a string that will be piped
* on stdin. the arguments will follow that one.
* *
* @return (Lua stack) the pid on success, 0 on failure. * @return (Lua stack) the pid on success, 0 on failure.
*/ */
static int static int
l_exec(lua_State *L) l_exec(lua_State *L)
{ {
/* the binary to call */
const char *binary = luaL_checkstring(L, 1); const char *binary = luaL_checkstring(L, 1);
/* number of arguments */
int argc = lua_gettop(L) - 1; int argc = lua_gettop(L) - 1;
/* the pid spawned */
pid_t pid; pid_t pid;
int i; /* the arguments position in the lua arguments */
char const **argv = s_calloc(argc + 2, sizeof(char *)); int li = 1;
/* the pipe to text */
char const *pipe_text = NULL;
/* the arguments */
char const **argv;
/* pipe file descriptors */
int pipefd[2];
/* writes a log message, prepares the message only if actually needed. */
if (check_logcat("Exec") >= settings.log_level) { if (check_logcat("Exec") >= settings.log_level) {
int i;
lua_pushvalue(L, 1); lua_pushvalue(L, 1);
for(i = 1; i <= argc; i++) { for(i = 1; i <= argc; i++) {
lua_pushstring(L, " ["); lua_pushstring(L, " [");
@ -590,16 +604,46 @@ l_exec(lua_State *L)
lua_pop(L, 1); lua_pop(L, 1);
} }
if (argc >= 2 && !strcmp(luaL_checkstring(L, 2), "<")) {
/* pipes something into stdin */
int flags;
pipe_text = luaL_checkstring(L, 3);
printf("pipe_text = %s\n", pipe_text);
/* creates the pipe */
if (pipe(pipefd) == -1) {
logstring("Error", "cannot create a pipe!");
terminate(-1); // ERRNO
}
/* sets the write end of the pipe to close on exec */
if (flags = fcntl(fd, F_GETFD) == -1) {
logstring("Error", "cannot get pipe flage!");
terminate(-1); // ERRNO
}
flags |= FD_CLOEXEC;
if (fcntl(fd, F_SETFD, flags) == -1) {
logstring("Error", "cannot set pipe flage!");
terminate(-1); // ERRNO
}
argc -= 2;
li += 2;
}
argv = s_calloc(argc + 2, sizeof(char *));
argv[0] = binary; argv[0] = binary;
for(i = 1; i <= argc; i++) { for(i = 1; i <= argc; i++) {
argv[i] = luaL_checkstring(L, i + 1); argv[i] = luaL_checkstring(L, i + li);
} }
argv[i] = NULL; argv[i] = NULL;
pid = fork(); pid = fork();
if (pid == 0) { if (pid == 0) {
/* replaces stdin for pipes */
if (pipe_text) {
dup2(pipefd[0], STDIN_FILENO);
}
/* if lsyncd runs as a daemon and has a logfile it will redirect /* if lsyncd runs as a daemon and has a logfile it will redirect
stdout/stderr of child processes to the logfile. */ stdout/stderr of child processes to the logfile. */
if (is_daemon && settings.log_file) { if (is_daemon && settings.log_file) {
@ -620,6 +664,11 @@ l_exec(lua_State *L)
exit(-1); // ERRNO exit(-1); // ERRNO
} }
if (pipe_text) {
/* first closes read-end of pipe, this is for child process only */
close(pipefd[0]);
}
free(argv); free(argv);
lua_pushnumber(L, pid); lua_pushnumber(L, pid);
return 1; return 1;