forked from enlightenment/efl
Fleshed out the fork'n'pipe IPC a little more.
SVN revision: 17890
This commit is contained in:
parent
c55ae5fdd0
commit
2da426d72c
|
@ -1,6 +1,9 @@
|
||||||
#include "ecore_private.h"
|
#include "ecore_private.h"
|
||||||
#include "Ecore.h"
|
#include "Ecore.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
static Ecore_Exe *exes = NULL;
|
static Ecore_Exe *exes = NULL;
|
||||||
|
|
||||||
|
@ -52,6 +55,9 @@ ecore_exe_run(const char *exe_cmd, const void *data)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *shell = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spawns a child process with its stdin/out available for communication.
|
* Spawns a child process with its stdin/out available for communication.
|
||||||
*
|
*
|
||||||
|
@ -73,7 +79,12 @@ Ecore_Exe *
|
||||||
ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data)
|
ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data)
|
||||||
{
|
{
|
||||||
Ecore_Exe *exe;
|
Ecore_Exe *exe;
|
||||||
pid_t pid;
|
pid_t pid = 0;
|
||||||
|
int dataPipe[2] = { -1, -1 };
|
||||||
|
int statusPipe[2] = { -1, -1 };
|
||||||
|
int n;
|
||||||
|
volatile int vfork_exec_errno = 0;
|
||||||
|
char **args;
|
||||||
|
|
||||||
/* FIXME:
|
/* FIXME:
|
||||||
* if flags does not have read or write in them - just execute using
|
* if flags does not have read or write in them - just execute using
|
||||||
|
@ -99,15 +110,99 @@ ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data)
|
||||||
* chars are left, then take trailing data (if any) and put in read buf
|
* chars are left, then take trailing data (if any) and put in read buf
|
||||||
* waiting for more data.
|
* waiting for more data.
|
||||||
*
|
*
|
||||||
|
* Just for the sake of example, this currently closes the parent to child pipe,
|
||||||
|
* and leaves the other one open.
|
||||||
*/
|
*/
|
||||||
if (!exe_cmd) return NULL;
|
if (!exe_cmd) return NULL;
|
||||||
pid = fork();
|
|
||||||
|
if (shell == 0)
|
||||||
|
{
|
||||||
|
shell = getenv("SHELL");
|
||||||
|
if (shell == 0)
|
||||||
|
shell = "/bin/sh";
|
||||||
|
}
|
||||||
|
|
||||||
|
args = (char **) calloc(4, sizeof(char *));
|
||||||
|
n = 0;
|
||||||
|
args[n++] = shell;
|
||||||
|
args[n++] = "-c";
|
||||||
|
args[n++] = exe_cmd;
|
||||||
|
args[n++] = 0;
|
||||||
|
|
||||||
|
if (pipe(dataPipe) < 0 || pipe(statusPipe) < 0)
|
||||||
|
printf("Failed to create pipe\n");
|
||||||
|
signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */
|
||||||
|
pid = fork();
|
||||||
|
|
||||||
|
if (pid == 0)
|
||||||
|
{ /* child */
|
||||||
|
setsid();
|
||||||
|
close(STDIN_FILENO);
|
||||||
|
dup2(dataPipe[1], STDOUT_FILENO);
|
||||||
|
dup2(dataPipe[1], STDERR_FILENO);
|
||||||
|
close(dataPipe[0]);
|
||||||
|
close(statusPipe[0]);
|
||||||
|
fcntl(statusPipe[1], F_SETFD, FD_CLOEXEC); /* close on exec shows sucess */
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
execvp(shell, (char **) args);
|
||||||
|
|
||||||
|
vfork_exec_errno = errno;
|
||||||
|
close(statusPipe[1]);
|
||||||
|
_exit(-1);
|
||||||
|
}
|
||||||
|
else if (pid > 0)
|
||||||
|
{ /* parent */
|
||||||
|
close(dataPipe[1]);
|
||||||
|
close(statusPipe[1]);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
char buf;
|
||||||
|
|
||||||
|
n = read(statusPipe[0], &buf, 1);
|
||||||
|
|
||||||
|
if (n == 0 && vfork_exec_errno != 0)
|
||||||
|
{
|
||||||
|
errno = vfork_exec_errno;
|
||||||
|
printf("Could not exec process\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
close(statusPipe[0]);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Failed to fork process\n");
|
||||||
|
pid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
if (pid)
|
||||||
|
{
|
||||||
|
close(dataPipe[0]);
|
||||||
|
|
||||||
|
if (WIFEXITED(n))
|
||||||
|
{
|
||||||
|
n = WEXITSTATUS(n);
|
||||||
|
printf("Process %s returned %i\n", exe_cmd, n);
|
||||||
|
pid = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
n = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(args);
|
||||||
|
errno = n;
|
||||||
|
|
||||||
if (pid)
|
if (pid)
|
||||||
{
|
{
|
||||||
exe = calloc(1, sizeof(Ecore_Exe));
|
exe = calloc(1, sizeof(Ecore_Exe));
|
||||||
if (!exe)
|
if (!exe)
|
||||||
{
|
{
|
||||||
kill(pid, SIGKILL);
|
kill(pid, SIGKILL);
|
||||||
|
printf("No memory for Ecore_Exe %s\n", exe_cmd);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ECORE_MAGIC_SET(exe, ECORE_MAGIC_EXE);
|
ECORE_MAGIC_SET(exe, ECORE_MAGIC_EXE);
|
||||||
|
@ -116,9 +211,7 @@ ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data)
|
||||||
exes = _ecore_list2_append(exes, exe);
|
exes = _ecore_list2_append(exes, exe);
|
||||||
return exe;
|
return exe;
|
||||||
}
|
}
|
||||||
setsid();
|
|
||||||
execl("/bin/sh", "/bin/sh", "-c", exe_cmd, (char *)NULL);
|
|
||||||
exit(127);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue