summaryrefslogtreecommitdiff
path: root/tests/suite/ecore/src/lib/ecore_exe.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/suite/ecore/src/lib/ecore_exe.c')
-rw-r--r--tests/suite/ecore/src/lib/ecore_exe.c2507
1 files changed, 1234 insertions, 1273 deletions
diff --git a/tests/suite/ecore/src/lib/ecore_exe.c b/tests/suite/ecore/src/lib/ecore_exe.c
index e83dfe9c91..883243a923 100644
--- a/tests/suite/ecore/src/lib/ecore_exe.c
+++ b/tests/suite/ecore/src/lib/ecore_exe.c
@@ -1,5 +1,5 @@
#ifdef HAVE_CONFIG_H
-# include <config.h>
+#include <config.h>
#endif
#include <sys/time.h>
@@ -14,7 +14,7 @@
#include <fcntl.h>
#ifdef HAVE_SYS_WAIT_H
-# include <sys/wait.h>
+#include <sys/wait.h>
#endif
#include "Ecore.h"
@@ -82,40 +82,39 @@
* hurt. The user code may need to be informed that a timeout is in progress.
*/
-struct _Ecore_Exe
-{
- EINA_INLIST;
- ECORE_MAGIC;
- pid_t pid;
- void *data;
- char *tag, *cmd;
- Ecore_Exe_Flags flags;
- Ecore_Fd_Handler *write_fd_handler; /* the fd_handler to handle write to child - if this was used, or NULL if not */
- Ecore_Fd_Handler *read_fd_handler; /* the fd_handler to handle read from child - if this was used, or NULL if not */
- Ecore_Fd_Handler *error_fd_handler; /* the fd_handler to handle errors from child - if this was used, or NULL if not */
- void *write_data_buf; /* a data buffer for data to write to the child -
- * realloced as needed for more data and flushed when the fd handler says writes are possible
- */
- int write_data_size; /* the size in bytes of the data buffer */
- int write_data_offset; /* the offset in bytes in the data buffer */
- void *read_data_buf; /* data read from the child awating delivery to an event */
- int read_data_size; /* data read from child in bytes */
- void *error_data_buf; /* errors read from the child awating delivery to an event */
- int error_data_size; /* errors read from child in bytes */
- int child_fd_write; /* fd to write TO to send data to the child */
- int child_fd_read; /* fd to read FROM when child has sent us (the parent) data */
- int child_fd_error; /* fd to read FROM when child has sent us (the parent) errors */
- int child_fd_write_x; /* fd to write TO to send data to the child */
- int child_fd_read_x; /* fd to read FROM when child has sent us (the parent) data */
- int child_fd_error_x; /* fd to read FROM when child has sent us (the parent) errors */
- Eina_Bool close_stdin : 1;
-
- int start_bytes, end_bytes, start_lines, end_lines; /* Number of bytes/lines to auto pipe at start/end of stdout/stderr. */
-
- Ecore_Timer *doomsday_clock; /* The Timer of Death. Muahahahaha. */
- void *doomsday_clock_dead; /* data for the doomsday clock */
-
- Ecore_Exe_Cb pre_free_cb;
+struct _Ecore_Exe {
+ EINA_INLIST;
+ ECORE_MAGIC;
+ pid_t pid;
+ void *data;
+ char *tag, *cmd;
+ Ecore_Exe_Flags flags;
+ Ecore_Fd_Handler *write_fd_handler; /* the fd_handler to handle write to child - if this was used, or NULL if not */
+ Ecore_Fd_Handler *read_fd_handler; /* the fd_handler to handle read from child - if this was used, or NULL if not */
+ Ecore_Fd_Handler *error_fd_handler; /* the fd_handler to handle errors from child - if this was used, or NULL if not */
+ void *write_data_buf; /* a data buffer for data to write to the child -
+ * realloced as needed for more data and flushed when the fd handler says writes are possible
+ */
+ int write_data_size; /* the size in bytes of the data buffer */
+ int write_data_offset; /* the offset in bytes in the data buffer */
+ void *read_data_buf; /* data read from the child awating delivery to an event */
+ int read_data_size; /* data read from child in bytes */
+ void *error_data_buf; /* errors read from the child awating delivery to an event */
+ int error_data_size; /* errors read from child in bytes */
+ int child_fd_write; /* fd to write TO to send data to the child */
+ int child_fd_read; /* fd to read FROM when child has sent us (the parent) data */
+ int child_fd_error; /* fd to read FROM when child has sent us (the parent) errors */
+ int child_fd_write_x; /* fd to write TO to send data to the child */
+ int child_fd_read_x; /* fd to read FROM when child has sent us (the parent) data */
+ int child_fd_error_x; /* fd to read FROM when child has sent us (the parent) errors */
+ Eina_Bool close_stdin:1;
+
+ int start_bytes, end_bytes, start_lines, end_lines; /* Number of bytes/lines to auto pipe at start/end of stdout/stderr. */
+
+ Ecore_Timer *doomsday_clock; /* The Timer of Death. Muahahahaha. */
+ void *doomsday_clock_dead; /* data for the doomsday clock */
+
+ Ecore_Exe_Cb pre_free_cb;
};
@@ -131,25 +130,35 @@ struct _Ecore_Exe
* appended with a preceding space. The first is the command off course.
*/
-struct _ecore_exe_dead_exe
-{
- pid_t pid;
- char *cmd;
+struct _ecore_exe_dead_exe {
+ pid_t pid;
+ char *cmd;
};
-static inline void _ecore_exe_exec_it(const char *exe_cmd, Ecore_Exe_Flags flags);
-static Eina_Bool _ecore_exe_data_generic_handler(void *data, Ecore_Fd_Handler *fd_handler, Ecore_Exe_Flags flags);
-static Eina_Bool _ecore_exe_data_error_handler(void *data, Ecore_Fd_Handler *fd_handler);
-static Eina_Bool _ecore_exe_data_read_handler(void *data, Ecore_Fd_Handler *fd_handler);
-static Eina_Bool _ecore_exe_data_write_handler(void *data, Ecore_Fd_Handler *fd_handler);
+static inline void _ecore_exe_exec_it(const char *exe_cmd,
+ Ecore_Exe_Flags flags);
+static Eina_Bool _ecore_exe_data_generic_handler(void *data,
+ Ecore_Fd_Handler *
+ fd_handler,
+ Ecore_Exe_Flags flags);
+static Eina_Bool _ecore_exe_data_error_handler(void *data,
+ Ecore_Fd_Handler *
+ fd_handler);
+static Eina_Bool _ecore_exe_data_read_handler(void *data,
+ Ecore_Fd_Handler *
+ fd_handler);
+static Eina_Bool _ecore_exe_data_write_handler(void *data,
+ Ecore_Fd_Handler *
+ fd_handler);
static void _ecore_exe_flush(Ecore_Exe * exe);
-static void _ecore_exe_event_exe_data_free(void *data __UNUSED__, void *ev);
+static void _ecore_exe_event_exe_data_free(void *data __UNUSED__,
+ void *ev);
static Ecore_Exe *_ecore_exe_is_it_alive(pid_t pid);
static Eina_Bool _ecore_exe_make_sure_its_dead(void *data);
static Eina_Bool _ecore_exe_make_sure_its_really_dead(void *data);
static Ecore_Exe_Event_Add *_ecore_exe_event_add_new(void);
static void _ecore_exe_event_add_free(void *data, void *ev);
-static void _ecore_exe_dead_attach(Ecore_Exe *exe);
+static void _ecore_exe_dead_attach(Ecore_Exe * exe);
EAPI int ECORE_EXE_EVENT_ADD = 0;
EAPI int ECORE_EXE_EVENT_DEL = 0;
@@ -174,14 +183,12 @@ static int _ecore_exe_check_errno(int result, const char *file, int line);
#define E_IF_NO_ERRNO_NOLOOP(result, foo, ok) \
if (((ok) = _ecore_exe_check_errno( (result) = (foo), __FILE__, __LINE__)))
-static int
-_ecore_exe_check_errno(int result, const char *file, int line)
+static int _ecore_exe_check_errno(int result, const char *file, int line)
{
- int saved_errno = errno;
+ int saved_errno = errno;
- if (result == -1)
- {
- perror("*** errno reports ");
+ if (result == -1) {
+ perror("*** errno reports ");
/* What is currently supported -
*
* pipe
@@ -237,64 +244,65 @@ _ecore_exe_check_errno(int result, const char *file, int line)
* // Something failed, cleanup.
* }
*/
- switch (saved_errno)
- {
- case EACCES:
- case EAGAIN:
- case EINTR:
- { /* Not now, try later. */
- ERR("*** Must try again in %s @%u.", file, line);
- result = -1;
- break;
- }
- case EMFILE:
- case ENFILE:
- case ENOLCK:
- { /* Low on resources. */
- ERR("*** Low on resources in %s @%u.", file,
- line);
- result = 0;
- break;
- }
- case EIO:
- { /* I/O error. */
- ERR("*** I/O error in %s @%u.", file, line);
- result = 0;
- break;
- }
- case EFAULT:
- case EBADF:
- case EINVAL:
- case EROFS:
- case EISDIR:
- case EDEADLK:
- case EPERM:
- case EBUSY:
- { /* Programmer fucked up. */
- ERR("*** NAUGHTY PROGRAMMER!!!\n"
- "*** SPANK SPANK SPANK!!!\n"
- "*** Now go fix your code in %s @%u. Tut tut tut!",
- file, line);
- result = 0;
- break;
- }
- default:
- { /* Unsupported errno code, please add this one. */
- ERR("*** NAUGHTY PROGRAMMER!!!\n"
- "*** SPANK SPANK SPANK!!!\n"
- "*** Unsupported errno code %d, please add this one.\n"
- "*** Now go fix your code in %s @%u, from %s @%u. Tut tut tut!",
- saved_errno, __FILE__, __LINE__, file, line);
- result = 0;
- break;
- }
- }
- }
- else /* Everything is fine. */
- result = 1;
-
- errno = saved_errno;
- return result;
+ switch (saved_errno) {
+ case EACCES:
+ case EAGAIN:
+ case EINTR:
+ { /* Not now, try later. */
+ ERR("*** Must try again in %s @%u.", file,
+ line);
+ result = -1;
+ break;
+ }
+ case EMFILE:
+ case ENFILE:
+ case ENOLCK:
+ { /* Low on resources. */
+ ERR("*** Low on resources in %s @%u.",
+ file, line);
+ result = 0;
+ break;
+ }
+ case EIO:
+ { /* I/O error. */
+ ERR("*** I/O error in %s @%u.", file,
+ line);
+ result = 0;
+ break;
+ }
+ case EFAULT:
+ case EBADF:
+ case EINVAL:
+ case EROFS:
+ case EISDIR:
+ case EDEADLK:
+ case EPERM:
+ case EBUSY:
+ { /* Programmer fucked up. */
+ ERR("*** NAUGHTY PROGRAMMER!!!\n"
+ "*** SPANK SPANK SPANK!!!\n"
+ "*** Now go fix your code in %s @%u. Tut tut tut!",
+ file, line);
+ result = 0;
+ break;
+ }
+ default:
+ { /* Unsupported errno code, please add this one. */
+ ERR("*** NAUGHTY PROGRAMMER!!!\n"
+ "*** SPANK SPANK SPANK!!!\n"
+ "*** Unsupported errno code %d, please add this one.\n"
+ "*** Now go fix your code in %s @%u, from %s @%u. Tut tut tut!",
+ saved_errno, __FILE__, __LINE__, file,
+ line);
+ result = 0;
+ break;
+ }
+ }
+ } else /* Everything is fine. */
+ result = 1;
+
+ errno = saved_errno;
+ return result;
}
/**
@@ -322,10 +330,9 @@ static int run_pri = ECORE_EXE_PRIORITY_INHERIT;
* to 19 or ECORE_EXE_PRIORITY_INHERIT on other OS.
* @ingroup Ecore_Exe_Basic_Group
*/
-EAPI void
-ecore_exe_run_priority_set(int pri)
+EAPI void ecore_exe_run_priority_set(int pri)
{
- run_pri = pri;
+ run_pri = pri;
}
/**
@@ -338,10 +345,9 @@ ecore_exe_run_priority_set(int pri)
* @return the value set by ecore_exe_run_priority_set()
* @ingroup Ecore_Exe_Basic_Group
*/
-EAPI int
-ecore_exe_run_priority_get(void)
+EAPI int ecore_exe_run_priority_get(void)
{
- return run_pri;
+ return run_pri;
}
/**
@@ -354,37 +360,34 @@ ecore_exe_run_priority_get(void)
* @return A process handle to the spawned process.
* @ingroup Ecore_Exe_Basic_Group
*/
-EAPI Ecore_Exe *
-ecore_exe_run(const char *exe_cmd, const void *data)
+EAPI Ecore_Exe *ecore_exe_run(const char *exe_cmd, const void *data)
{
/* I'm just being paranoid again, leaving in the original code in case there is a problem. */
#if 0
- Ecore_Exe *exe;
- pid_t pid;
-
- if (!exe_cmd)
- return NULL;
- pid = fork();
- if (pid)
- {
- exe = calloc(1, sizeof(Ecore_Exe));
- if (!exe)
- {
- kill(pid, SIGKILL);
- return NULL;
- }
- ECORE_MAGIC_SET(exe, ECORE_MAGIC_EXE);
- exe->pid = pid;
- exe->data = (void *)data;
- exe->cmd = strdup(exe_cmd);
- exes = _ecore_list2_append(exes, exe);
- return exe;
- }
- _ecore_exe_exec_it(exe_cmd, 0);
- exit(127);
- return NULL;
+ Ecore_Exe *exe;
+ pid_t pid;
+
+ if (!exe_cmd)
+ return NULL;
+ pid = fork();
+ if (pid) {
+ exe = calloc(1, sizeof(Ecore_Exe));
+ if (!exe) {
+ kill(pid, SIGKILL);
+ return NULL;
+ }
+ ECORE_MAGIC_SET(exe, ECORE_MAGIC_EXE);
+ exe->pid = pid;
+ exe->data = (void *) data;
+ exe->cmd = strdup(exe_cmd);
+ exes = _ecore_list2_append(exes, exe);
+ return exe;
+ }
+ _ecore_exe_exec_it(exe_cmd, 0);
+ exit(127);
+ return NULL;
#else
- return ecore_exe_pipe_run(exe_cmd, 0, data);
+ return ecore_exe_pipe_run(exe_cmd, 0, data);
#endif
}
@@ -414,282 +417,313 @@ ecore_exe_run(const char *exe_cmd, const void *data)
* @return A process handle to the spawned process.
* @ingroup Ecore_Exe_Basic_Group
*/
-EAPI Ecore_Exe *
-ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data)
+EAPI Ecore_Exe *ecore_exe_pipe_run(const char *exe_cmd,
+ Ecore_Exe_Flags flags, const void *data)
{
- Ecore_Exe *exe = NULL;
- int statusPipe[2] = { -1, -1 };
- int errorPipe[2] = { -1, -1 };
- int readPipe[2] = { -1, -1 };
- int writePipe[2] = { -1, -1 };
- int n = 0;
- int ok = 1;
- int result;
-
- if (!exe_cmd) return NULL;
- exe = calloc(1, sizeof(Ecore_Exe));
- if (!exe) return NULL;
-
- if ((flags & ECORE_EXE_PIPE_AUTO) && (!(flags & ECORE_EXE_PIPE_ERROR))
- && (!(flags & ECORE_EXE_PIPE_READ)))
- /* We need something to auto pipe. */
- flags |= ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR;
-
- exe->child_fd_error = -1;
- exe->child_fd_read = -1;
- exe->child_fd_write = -1;
- exe->child_fd_error_x = -1;
- exe->child_fd_read_x = -1;
- exe->child_fd_write_x = -1;
-
- /* Create some pipes. */
- if (ok)
- {
- E_IF_NO_ERRNO_NOLOOP(result, pipe(statusPipe), ok)
- {
- }
- }
- if (ok && (flags & ECORE_EXE_PIPE_ERROR))
- {
- E_IF_NO_ERRNO_NOLOOP(result, pipe(errorPipe), ok)
- {
- exe->child_fd_error = errorPipe[0];
- exe->child_fd_error_x = errorPipe[1];
- }
- }
- if (ok && (flags & ECORE_EXE_PIPE_READ))
- {
- E_IF_NO_ERRNO_NOLOOP(result, pipe(readPipe), ok)
- {
- exe->child_fd_read = readPipe[0];
- exe->child_fd_read_x = readPipe[1];
- }
- }
- if (ok && (flags & ECORE_EXE_PIPE_WRITE))
- {
- E_IF_NO_ERRNO_NOLOOP(result, pipe(writePipe), ok)
- {
- exe->child_fd_write = writePipe[1];
- exe->child_fd_write_x = writePipe[0];
- }
- }
- if (ok)
- {
- pid_t pid = 0;
- volatile int vfork_exec_errno = 0;
-
- /* FIXME: I should double check this. After a quick look around, this is already done, but via a more modern method. */
- /* signal(SIGPIPE, SIG_IGN); We only want EPIPE on errors */
- pid = fork();
-
- if (pid == -1)
- {
- ERR("Failed to fork process");
- pid = 0;
- }
- else if (pid == 0) /* child */
- {
- if (run_pri != ECORE_EXE_PRIORITY_INHERIT)
- {
- if ((run_pri >= -20) && (run_pri <= 19))
- setpriority(PRIO_PROCESS, 0, run_pri);
- }
- /* dup2 STDERR, STDIN, and STDOUT. dup2() allegedly closes the
- * second pipe if it's open. On the other hand, there was the
- * Great FD Leak Scare of '06, so let's be paranoid. */
- if (ok && (flags & ECORE_EXE_PIPE_ERROR))
- {
- E_NO_ERRNO(result, close(STDERR_FILENO), ok);
- E_NO_ERRNO(result, dup2(errorPipe[1], STDERR_FILENO), ok);
- }
- if (ok && (flags & ECORE_EXE_PIPE_READ))
- {
- E_NO_ERRNO(result, close(STDOUT_FILENO), ok);
- E_NO_ERRNO(result, dup2(readPipe[1], STDOUT_FILENO), ok);
- }
- if (ok && (flags & ECORE_EXE_PIPE_WRITE))
- {
- E_NO_ERRNO(result, close(STDIN_FILENO), ok);
- E_NO_ERRNO(result, dup2(writePipe[0], STDIN_FILENO), ok);
- }
-
- if (ok)
- {
- /* Setup the status pipe. */
- E_NO_ERRNO(result, close(statusPipe[0]), ok);
- E_IF_NO_ERRNO(result, fcntl(statusPipe[1], F_SETFD, FD_CLOEXEC), ok) /* close on exec shows success */
- {
- /* Run the actual command. */
- _ecore_exe_exec_it(exe_cmd, flags); /* no return */
- }
- }
-
- /* Something went 'orribly wrong. */
- vfork_exec_errno = errno;
-
- /* Close the pipes. */
- if (flags & ECORE_EXE_PIPE_ERROR)
- E_NO_ERRNO(result, close(errorPipe[1]), ok);
- if (flags & ECORE_EXE_PIPE_READ)
- E_NO_ERRNO(result, close(readPipe[1]), ok);
- if (flags & ECORE_EXE_PIPE_WRITE)
- E_NO_ERRNO(result, close(writePipe[0]), ok);
- E_NO_ERRNO(result, close(statusPipe[1]), ok);
-
- _exit(-1);
- }
- else /* parent */
- {
- /* Close the unused pipes. */
- E_NO_ERRNO(result, close(statusPipe[1]), ok);
-
- /* FIXME: after having a good look at the current e fd
- * handling, investigate fcntl(dataPipe[x], F_SETSIG, ...) */
- /* FIXME: above F_SETSIG etc. - this is async SIGIO based IO
- * which is also linux specific so we probably don't want to
- * do this as long as select() is working fine. the only time
- * we really want to think of SIGIO async IO is when it all
- * actually works basically everywhere and we can turn all
- * IO into DMA async activities (i.e. you do a read() then
- * the read is complete not on return but when you get a
- * SIGIO - the read() just starts the transfer and it is
- * completed in the background by DMA (or whatever mechanism
- * the kernel choses)) */
-
- /* Wait for it to start executing. */
- /* FIXME: this doesn't seem very nice - we sit and block
- * waiting on a child process... even though it's just
- * the segment between the fork() and the exec) it just feels
- * wrong */
- for (;;)
- {
- char buf;
-
- E_NO_ERRNO(result, read(statusPipe[0], &buf, 1), ok);
- if (result == 0)
- {
- if (vfork_exec_errno != 0)
- {
- n = vfork_exec_errno;
- ERR("Could not start \"%s\"", exe_cmd);
- pid = 0;
- }
- break;
- }
- }
-
- /* Close the status pipe. */
- E_NO_ERRNO(result, close(statusPipe[0]), ok);
- }
-
- if (pid)
- {
- /* Setup the exe structure. */
- ECORE_MAGIC_SET(exe, ECORE_MAGIC_EXE);
- exe->start_bytes = -1;
- exe->end_bytes = -1;
- exe->start_lines = -1;
- exe->end_lines = -1;
- exe->pid = pid;
- exe->flags = flags;
- exe->data = (void *)data;
- if ((exe->cmd = strdup(exe_cmd)))
- {
- if (flags & ECORE_EXE_PIPE_ERROR)
- { /* Setup the error stuff. */
- E_IF_NO_ERRNO(result,
- fcntl(exe->child_fd_error, F_SETFL,
- O_NONBLOCK), ok) {}
- E_IF_NO_ERRNO(result,
- fcntl(exe->child_fd_error, F_SETFD,
- FD_CLOEXEC), ok) {}
- E_IF_NO_ERRNO(result,
- fcntl(exe->child_fd_error_x, F_SETFD,
- FD_CLOEXEC), ok) {}
- {
- exe->error_fd_handler =
- ecore_main_fd_handler_add(exe->child_fd_error,
- ECORE_FD_READ,
- _ecore_exe_data_error_handler,
- exe, NULL, NULL);
- if (!exe->error_fd_handler)
- ok = 0;
- }
- }
- if (ok && (flags & ECORE_EXE_PIPE_READ))
- { /* Setup the read stuff. */
- E_IF_NO_ERRNO(result,
- fcntl(exe->child_fd_read, F_SETFL,
- O_NONBLOCK), ok) {}
- E_IF_NO_ERRNO(result,
- fcntl(exe->child_fd_read, F_SETFD,
- FD_CLOEXEC), ok) {}
- E_IF_NO_ERRNO(result,
- fcntl(exe->child_fd_read_x, F_SETFD,
- FD_CLOEXEC), ok) {}
- {
- exe->read_fd_handler =
- ecore_main_fd_handler_add(exe->child_fd_read,
- ECORE_FD_READ,
- _ecore_exe_data_read_handler,
- exe, NULL, NULL);
- if (!exe->read_fd_handler)
- ok = 0;
- }
- }
- if (ok && (flags & ECORE_EXE_PIPE_WRITE))
- { /* Setup the write stuff. */
- E_IF_NO_ERRNO(result,
- fcntl(exe->child_fd_write, F_SETFL,
- O_NONBLOCK), ok) {}
- E_IF_NO_ERRNO(result,
- fcntl(exe->child_fd_write, F_SETFD,
- FD_CLOEXEC), ok) {}
- E_IF_NO_ERRNO(result,
- fcntl(exe->child_fd_write_x, F_SETFD,
- FD_CLOEXEC), ok) {}
- {
- exe->write_fd_handler =
- ecore_main_fd_handler_add(exe->child_fd_write,
- ECORE_FD_WRITE,
- _ecore_exe_data_write_handler,
- exe, NULL, NULL);
- if (exe->write_fd_handler)
- ecore_main_fd_handler_active_set(exe->write_fd_handler, 0); /* Nothing to write to start with. */
- else
- ok = 0;
- }
- }
-
- exes = (Ecore_Exe *) eina_inlist_append(EINA_INLIST_GET(exes), EINA_INLIST_GET(exe));
- n = 0;
- }
- else
- ok = 0;
- }
- else
- ok = 0;
- }
-
- if (!ok)
- { /* Something went wrong, so pull down everything. */
- if (exe->pid) ecore_exe_terminate(exe);
- IF_FN_DEL(ecore_exe_free, exe);
- }
- else
- {
- Ecore_Exe_Event_Add *e;
-
- e = _ecore_exe_event_add_new();
- e->exe = exe;
- if (e) /* Send the event. */
- ecore_event_add(ECORE_EXE_EVENT_ADD, e,
- _ecore_exe_event_add_free, NULL);
- /* INF("Running as %d for %s.\n", exe->pid, exe->cmd); */
- }
-
- errno = n;
- return exe;
+ Ecore_Exe *exe = NULL;
+ int statusPipe[2] = { -1, -1 };
+ int errorPipe[2] = { -1, -1 };
+ int readPipe[2] = { -1, -1 };
+ int writePipe[2] = { -1, -1 };
+ int n = 0;
+ int ok = 1;
+ int result;
+
+ if (!exe_cmd)
+ return NULL;
+ exe = calloc(1, sizeof(Ecore_Exe));
+ if (!exe)
+ return NULL;
+
+ if ((flags & ECORE_EXE_PIPE_AUTO)
+ && (!(flags & ECORE_EXE_PIPE_ERROR))
+ && (!(flags & ECORE_EXE_PIPE_READ)))
+ /* We need something to auto pipe. */
+ flags |= ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR;
+
+ exe->child_fd_error = -1;
+ exe->child_fd_read = -1;
+ exe->child_fd_write = -1;
+ exe->child_fd_error_x = -1;
+ exe->child_fd_read_x = -1;
+ exe->child_fd_write_x = -1;
+
+ /* Create some pipes. */
+ if (ok) {
+ E_IF_NO_ERRNO_NOLOOP(result, pipe(statusPipe), ok) {
+ }
+ }
+ if (ok && (flags & ECORE_EXE_PIPE_ERROR)) {
+ E_IF_NO_ERRNO_NOLOOP(result, pipe(errorPipe), ok) {
+ exe->child_fd_error = errorPipe[0];
+ exe->child_fd_error_x = errorPipe[1];
+ }
+ }
+ if (ok && (flags & ECORE_EXE_PIPE_READ)) {
+ E_IF_NO_ERRNO_NOLOOP(result, pipe(readPipe), ok) {
+ exe->child_fd_read = readPipe[0];
+ exe->child_fd_read_x = readPipe[1];
+ }
+ }
+ if (ok && (flags & ECORE_EXE_PIPE_WRITE)) {
+ E_IF_NO_ERRNO_NOLOOP(result, pipe(writePipe), ok) {
+ exe->child_fd_write = writePipe[1];
+ exe->child_fd_write_x = writePipe[0];
+ }
+ }
+ if (ok) {
+ pid_t pid = 0;
+ volatile int vfork_exec_errno = 0;
+
+ /* FIXME: I should double check this. After a quick look around, this is already done, but via a more modern method. */
+ /* signal(SIGPIPE, SIG_IGN); We only want EPIPE on errors */
+ pid = fork();
+
+ if (pid == -1) {
+ ERR("Failed to fork process");
+ pid = 0;
+ } else if (pid == 0) { /* child */
+ if (run_pri != ECORE_EXE_PRIORITY_INHERIT) {
+ if ((run_pri >= -20) && (run_pri <= 19))
+ setpriority(PRIO_PROCESS, 0,
+ run_pri);
+ }
+ /* dup2 STDERR, STDIN, and STDOUT. dup2() allegedly closes the
+ * second pipe if it's open. On the other hand, there was the
+ * Great FD Leak Scare of '06, so let's be paranoid. */
+ if (ok && (flags & ECORE_EXE_PIPE_ERROR)) {
+ E_NO_ERRNO(result, close(STDERR_FILENO),
+ ok);
+ E_NO_ERRNO(result,
+ dup2(errorPipe[1],
+ STDERR_FILENO), ok);
+ }
+ if (ok && (flags & ECORE_EXE_PIPE_READ)) {
+ E_NO_ERRNO(result, close(STDOUT_FILENO),
+ ok);
+ E_NO_ERRNO(result,
+ dup2(readPipe[1],
+ STDOUT_FILENO), ok);
+ }
+ if (ok && (flags & ECORE_EXE_PIPE_WRITE)) {
+ E_NO_ERRNO(result, close(STDIN_FILENO),
+ ok);
+ E_NO_ERRNO(result,
+ dup2(writePipe[0],
+ STDIN_FILENO), ok);
+ }
+
+ if (ok) {
+ /* Setup the status pipe. */
+ E_NO_ERRNO(result, close(statusPipe[0]),
+ ok);
+ E_IF_NO_ERRNO(result, fcntl(statusPipe[1], F_SETFD, FD_CLOEXEC), ok) { /* close on exec shows success */
+ /* Run the actual command. */
+ _ecore_exe_exec_it(exe_cmd, flags); /* no return */
+ }
+ }
+
+ /* Something went 'orribly wrong. */
+ vfork_exec_errno = errno;
+
+ /* Close the pipes. */
+ if (flags & ECORE_EXE_PIPE_ERROR)
+ E_NO_ERRNO(result, close(errorPipe[1]),
+ ok);
+ if (flags & ECORE_EXE_PIPE_READ)
+ E_NO_ERRNO(result, close(readPipe[1]), ok);
+ if (flags & ECORE_EXE_PIPE_WRITE)
+ E_NO_ERRNO(result, close(writePipe[0]),
+ ok);
+ E_NO_ERRNO(result, close(statusPipe[1]), ok);
+
+ _exit(-1);
+ } else { /* parent */
+
+ /* Close the unused pipes. */
+ E_NO_ERRNO(result, close(statusPipe[1]), ok);
+
+ /* FIXME: after having a good look at the current e fd
+ * handling, investigate fcntl(dataPipe[x], F_SETSIG, ...) */
+ /* FIXME: above F_SETSIG etc. - this is async SIGIO based IO
+ * which is also linux specific so we probably don't want to
+ * do this as long as select() is working fine. the only time
+ * we really want to think of SIGIO async IO is when it all
+ * actually works basically everywhere and we can turn all
+ * IO into DMA async activities (i.e. you do a read() then
+ * the read is complete not on return but when you get a
+ * SIGIO - the read() just starts the transfer and it is
+ * completed in the background by DMA (or whatever mechanism
+ * the kernel choses)) */
+
+ /* Wait for it to start executing. */
+ /* FIXME: this doesn't seem very nice - we sit and block
+ * waiting on a child process... even though it's just
+ * the segment between the fork() and the exec) it just feels
+ * wrong */
+ for (;;) {
+ char buf;
+
+ E_NO_ERRNO(result,
+ read(statusPipe[0], &buf, 1),
+ ok);
+ if (result == 0) {
+ if (vfork_exec_errno != 0) {
+ n = vfork_exec_errno;
+ ERR("Could not start \"%s\"", exe_cmd);
+ pid = 0;
+ }
+ break;
+ }
+ }
+
+ /* Close the status pipe. */
+ E_NO_ERRNO(result, close(statusPipe[0]), ok);
+ }
+
+ if (pid) {
+ /* Setup the exe structure. */
+ ECORE_MAGIC_SET(exe, ECORE_MAGIC_EXE);
+ exe->start_bytes = -1;
+ exe->end_bytes = -1;
+ exe->start_lines = -1;
+ exe->end_lines = -1;
+ exe->pid = pid;
+ exe->flags = flags;
+ exe->data = (void *) data;
+ if ((exe->cmd = strdup(exe_cmd))) {
+ if (flags & ECORE_EXE_PIPE_ERROR) { /* Setup the error stuff. */
+ E_IF_NO_ERRNO(result,
+ fcntl(exe->
+ child_fd_error,
+ F_SETFL,
+ O_NONBLOCK),
+ ok) {
+ }
+ E_IF_NO_ERRNO(result,
+ fcntl(exe->
+ child_fd_error,
+ F_SETFD,
+ FD_CLOEXEC),
+ ok) {
+ }
+ E_IF_NO_ERRNO(result,
+ fcntl(exe->
+ child_fd_error_x,
+ F_SETFD,
+ FD_CLOEXEC),
+ ok) {
+ }
+ {
+ exe->error_fd_handler =
+ ecore_main_fd_handler_add
+ (exe->child_fd_error,
+ ECORE_FD_READ,
+ _ecore_exe_data_error_handler,
+ exe, NULL, NULL);
+ if (!exe->error_fd_handler)
+ ok = 0;
+ }
+ }
+ if (ok && (flags & ECORE_EXE_PIPE_READ)) { /* Setup the read stuff. */
+ E_IF_NO_ERRNO(result,
+ fcntl(exe->
+ child_fd_read,
+ F_SETFL,
+ O_NONBLOCK),
+ ok) {
+ }
+ E_IF_NO_ERRNO(result,
+ fcntl(exe->
+ child_fd_read,
+ F_SETFD,
+ FD_CLOEXEC),
+ ok) {
+ }
+ E_IF_NO_ERRNO(result,
+ fcntl(exe->
+ child_fd_read_x,
+ F_SETFD,
+ FD_CLOEXEC),
+ ok) {
+ }
+ {
+ exe->read_fd_handler =
+ ecore_main_fd_handler_add
+ (exe->child_fd_read,
+ ECORE_FD_READ,
+ _ecore_exe_data_read_handler,
+ exe, NULL, NULL);
+ if (!exe->read_fd_handler)
+ ok = 0;
+ }
+ }
+ if (ok && (flags & ECORE_EXE_PIPE_WRITE)) { /* Setup the write stuff. */
+ E_IF_NO_ERRNO(result,
+ fcntl(exe->
+ child_fd_write,
+ F_SETFL,
+ O_NONBLOCK),
+ ok) {
+ }
+ E_IF_NO_ERRNO(result,
+ fcntl(exe->
+ child_fd_write,
+ F_SETFD,
+ FD_CLOEXEC),
+ ok) {
+ }
+ E_IF_NO_ERRNO(result,
+ fcntl(exe->
+ child_fd_write_x,
+ F_SETFD,
+ FD_CLOEXEC),
+ ok) {
+ }
+ {
+ exe->write_fd_handler =
+ ecore_main_fd_handler_add
+ (exe->child_fd_write,
+ ECORE_FD_WRITE,
+ _ecore_exe_data_write_handler,
+ exe, NULL, NULL);
+ if (exe->write_fd_handler)
+ ecore_main_fd_handler_active_set(exe->write_fd_handler, 0); /* Nothing to write to start with. */
+ else
+ ok = 0;
+ }
+ }
+
+ exes =
+ (Ecore_Exe *)
+ eina_inlist_append(EINA_INLIST_GET
+ (exes),
+ EINA_INLIST_GET
+ (exe));
+ n = 0;
+ } else
+ ok = 0;
+ } else
+ ok = 0;
+ }
+
+ if (!ok) { /* Something went wrong, so pull down everything. */
+ if (exe->pid)
+ ecore_exe_terminate(exe);
+ IF_FN_DEL(ecore_exe_free, exe);
+ } else {
+ Ecore_Exe_Event_Add *e;
+
+ e = _ecore_exe_event_add_new();
+ e->exe = exe;
+ if (e) /* Send the event. */
+ ecore_event_add(ECORE_EXE_EVENT_ADD, e,
+ _ecore_exe_event_add_free, NULL);
+ /* INF("Running as %d for %s.\n", exe->pid, exe->cmd); */
+ }
+
+ errno = n;
+ return exe;
}
/**
@@ -706,15 +740,14 @@ ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data)
* @param func The function to call before @a exe is freed.
*/
EAPI void
-ecore_exe_callback_pre_free_set(Ecore_Exe *exe, Ecore_Exe_Cb func)
+ecore_exe_callback_pre_free_set(Ecore_Exe * exe, Ecore_Exe_Cb func)
{
- if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
- {
- ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE,
- "ecore_exe_callback_pre_free_set");
- return;
- }
- exe->pre_free_cb = func;
+ if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) {
+ ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE,
+ "ecore_exe_callback_pre_free_set");
+ return;
+ }
+ exe->pre_free_cb = func;
}
/**
@@ -730,42 +763,40 @@ ecore_exe_callback_pre_free_set(Ecore_Exe *exe, Ecore_Exe_Cb func)
* @return EINA_TRUE if successful, EINA_FALSE on failure.
* @ingroup Ecore_Exe_Basic_Group
*/
-EAPI Eina_Bool
-ecore_exe_send(Ecore_Exe * exe, const void *data, int size)
+EAPI Eina_Bool ecore_exe_send(Ecore_Exe * exe, const void *data, int size)
{
- void *buf;
-
- if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
- {
- ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_send");
- return EINA_FALSE;
- }
-
- if (exe->close_stdin)
- {
- ERR("Ecore_Exe %p stdin is closed! Cannot send %d bytes from %p",
- exe, size, data);
- return EINA_FALSE;
- }
-
- if (exe->child_fd_write == -1)
- {
- ERR("Ecore_Exe %p created without ECORE_EXE_PIPE_WRITE! "
- "Cannot send %d bytes from %p", exe, size, data);
- return EINA_FALSE;
- }
-
- buf = realloc(exe->write_data_buf, exe->write_data_size + size);
- if (!buf) return EINA_FALSE;
-
- exe->write_data_buf = buf;
- memcpy((char *)exe->write_data_buf + exe->write_data_size, data, size);
- exe->write_data_size += size;
-
- if (exe->write_fd_handler)
- ecore_main_fd_handler_active_set(exe->write_fd_handler, ECORE_FD_WRITE);
-
- return EINA_TRUE;
+ void *buf;
+
+ if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) {
+ ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_send");
+ return EINA_FALSE;
+ }
+
+ if (exe->close_stdin) {
+ ERR("Ecore_Exe %p stdin is closed! Cannot send %d bytes from %p", exe, size, data);
+ return EINA_FALSE;
+ }
+
+ if (exe->child_fd_write == -1) {
+ ERR("Ecore_Exe %p created without ECORE_EXE_PIPE_WRITE! "
+ "Cannot send %d bytes from %p", exe, size, data);
+ return EINA_FALSE;
+ }
+
+ buf = realloc(exe->write_data_buf, exe->write_data_size + size);
+ if (!buf)
+ return EINA_FALSE;
+
+ exe->write_data_buf = buf;
+ memcpy((char *) exe->write_data_buf + exe->write_data_size, data,
+ size);
+ exe->write_data_size += size;
+
+ if (exe->write_fd_handler)
+ ecore_main_fd_handler_active_set(exe->write_fd_handler,
+ ECORE_FD_WRITE);
+
+ return EINA_TRUE;
}
/**
@@ -774,15 +805,14 @@ ecore_exe_send(Ecore_Exe * exe, const void *data, int size)
* @param exe The child process
* @ingroup Ecore_Exe_Basic_Group
*/
-EAPI void
-ecore_exe_close_stdin(Ecore_Exe *exe)
+EAPI void ecore_exe_close_stdin(Ecore_Exe * exe)
{
- if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
- {
- ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_close_stdin");
- return;
- }
- exe->close_stdin = 1;
+ if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) {
+ ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE,
+ "ecore_exe_close_stdin");
+ return;
+ }
+ exe->close_stdin = 1;
}
/**
@@ -797,57 +827,58 @@ ecore_exe_close_stdin(Ecore_Exe *exe)
* @ingroup Ecore_Exe_Basic_Group
*/
EAPI void
-ecore_exe_auto_limits_set(Ecore_Exe *exe, int start_bytes, int end_bytes, int start_lines, int end_lines)
+ecore_exe_auto_limits_set(Ecore_Exe * exe, int start_bytes, int end_bytes,
+ int start_lines, int end_lines)
{
- if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
- {
- ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_auto_limits_set");
- return;
- }
- /* FIXME: sanitize the input. */
- exe->start_bytes = start_bytes;
- exe->end_bytes = end_bytes;
- exe->start_lines = start_lines;
- exe->end_lines = end_lines;
-
- /* FIXME: get this can of worms working.
- *
- * capture stderr & stdout internally
- *
- * raster and onefang keep moving the goal posts on this one. It started out as
- * "show users the error output if an exe fails" and is rapidly approaching
- * "alternative method of getting the data, poll vs event driven". Some serious
- * thinking needs to be applied to this. Do we really want to go that far? If
- * so, we should change the names. The basic design will probably remain the
- * same which ever way we go. The constant goal post moving is probably due to
- * generic design methods leading to feature creep as we inspired each other to
- * more generic designs. It does seem like the closer we get to poll driven,
- * the more issues and corner cases there are.
- *
- * Instead of doing the usual register an event handler thing, we are ecore_exe,
- * we can take some short cuts. Don't send the events, just leave the exe buffers
- * as is until the user asks for them, then return the event.
- *
- * start = 0, end = 0; clogged arteries get flushed, everything is ignored.
- * start = -1, end = -1; clogged arteries get transferred to internal buffers. Actually, either == -1 means buffer everything.
- * start = X, end = 0; buffer first X out of clogged arteries, flush and ignore rest.
- * start = 0, end = X; circular buffer X
- * start = X, end = Y; buffer first X out of clogged arteries, circular buffer Y from beginning.
- *
- * bytes vs lines, which ever one reaches the limit first.
- * Before we go beyond the start+end limit, leave the end buffer empty, and store both in the start buffer, coz they overlap.
- * After we pass the the start+end limit, insert "\n...\n" at the end of the start buffer, copy the rest to the end buffer, then store in the end buffer.
- *
- * Other issues -
- * Spank programmer for polling data if polling is not turned on.
- * Spank programmer for setting up event callbacks if polling is turned on.
- * Spank programmer for freeing the event data if it came from the event system, as that autofrees.
- * Spank the programmer if they try to set the limits bigger than what has been gathered & ignored already, coz they just lost data.
- * Spank onefang and raster for opening this can of worms.
- * Should we have separate out/err limits?
- * Should we remove from the internal buffer the data that was delivered already?
- * If so, what to do about limits, start, and end? They could loose their meaning.
- */
+ if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) {
+ ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE,
+ "ecore_exe_auto_limits_set");
+ return;
+ }
+ /* FIXME: sanitize the input. */
+ exe->start_bytes = start_bytes;
+ exe->end_bytes = end_bytes;
+ exe->start_lines = start_lines;
+ exe->end_lines = end_lines;
+
+ /* FIXME: get this can of worms working.
+ *
+ * capture stderr & stdout internally
+ *
+ * raster and onefang keep moving the goal posts on this one. It started out as
+ * "show users the error output if an exe fails" and is rapidly approaching
+ * "alternative method of getting the data, poll vs event driven". Some serious
+ * thinking needs to be applied to this. Do we really want to go that far? If
+ * so, we should change the names. The basic design will probably remain the
+ * same which ever way we go. The constant goal post moving is probably due to
+ * generic design methods leading to feature creep as we inspired each other to
+ * more generic designs. It does seem like the closer we get to poll driven,
+ * the more issues and corner cases there are.
+ *
+ * Instead of doing the usual register an event handler thing, we are ecore_exe,
+ * we can take some short cuts. Don't send the events, just leave the exe buffers
+ * as is until the user asks for them, then return the event.
+ *
+ * start = 0, end = 0; clogged arteries get flushed, everything is ignored.
+ * start = -1, end = -1; clogged arteries get transferred to internal buffers. Actually, either == -1 means buffer everything.
+ * start = X, end = 0; buffer first X out of clogged arteries, flush and ignore rest.
+ * start = 0, end = X; circular buffer X
+ * start = X, end = Y; buffer first X out of clogged arteries, circular buffer Y from beginning.
+ *
+ * bytes vs lines, which ever one reaches the limit first.
+ * Before we go beyond the start+end limit, leave the end buffer empty, and store both in the start buffer, coz they overlap.
+ * After we pass the the start+end limit, insert "\n...\n" at the end of the start buffer, copy the rest to the end buffer, then store in the end buffer.
+ *
+ * Other issues -
+ * Spank programmer for polling data if polling is not turned on.
+ * Spank programmer for setting up event callbacks if polling is turned on.
+ * Spank programmer for freeing the event data if it came from the event system, as that autofrees.
+ * Spank the programmer if they try to set the limits bigger than what has been gathered & ignored already, coz they just lost data.
+ * Spank onefang and raster for opening this can of worms.
+ * Should we have separate out/err limits?
+ * Should we remove from the internal buffer the data that was delivered already?
+ * If so, what to do about limits, start, and end? They could loose their meaning.
+ */
}
/**
@@ -857,128 +888,116 @@ ecore_exe_auto_limits_set(Ecore_Exe *exe, int start_bytes, int end_bytes, int st
* @param flags Is this a ECORE_EXE_PIPE_READ or ECORE_EXE_PIPE_ERROR?
* @ingroup Ecore_Exe_Basic_Group
*/
-EAPI Ecore_Exe_Event_Data *
-ecore_exe_event_data_get(Ecore_Exe *exe, Ecore_Exe_Flags flags)
+EAPI Ecore_Exe_Event_Data *ecore_exe_event_data_get(Ecore_Exe * exe,
+ Ecore_Exe_Flags flags)
{
- Ecore_Exe_Event_Data *e = NULL;
- int is_buffered = 0;
- unsigned char *inbuf;
- int inbuf_num;
-
- if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
- {
- ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_event_data_get");
- return NULL;
- }
-
- /* Sort out what sort of event we are. */
- if (flags & ECORE_EXE_PIPE_READ)
- {
- flags = ECORE_EXE_PIPE_READ;
- if (exe->flags & ECORE_EXE_PIPE_READ_LINE_BUFFERED)
- is_buffered = 1;
- }
- else
- {
- flags = ECORE_EXE_PIPE_ERROR;
- if (exe->flags & ECORE_EXE_PIPE_ERROR_LINE_BUFFERED)
- is_buffered = 1;
- }
-
- /* Get the data. */
- if (flags & ECORE_EXE_PIPE_READ)
- {
- inbuf = exe->read_data_buf;
- inbuf_num = exe->read_data_size;
- exe->read_data_buf = NULL;
- exe->read_data_size = 0;
- }
- else
- {
- inbuf = exe->error_data_buf;
- inbuf_num = exe->error_data_size;
- exe->error_data_buf = NULL;
- exe->error_data_size = 0;
- }
-
- e = calloc(1, sizeof(Ecore_Exe_Event_Data));
- if (e)
- {
- e->exe = exe;
- e->data = inbuf;
- e->size = inbuf_num;
-
- if (is_buffered)
- { /* Deal with line buffering. */
- int max = 0;
- int count = 0;
- int i;
- int last = 0;
- char *c;
-
- c = (char *)inbuf;
- for (i = 0; i < inbuf_num; i++) /* Find the lines. */
- {
- if (inbuf[i] == '\n')
- {
- if (count >= max)
- {
- /* In testing, the lines seem to arrive in batches of 500 to 1000 lines at most, roughly speaking. */
- max += 10; /* FIXME: Maybe keep track of the largest number of lines ever sent, and add half that many instead of 10. */
- e->lines = realloc(e->lines, sizeof(Ecore_Exe_Event_Data_Line) * (max + 1)); /* Allow room for the NULL termination. */
- }
- /* raster said to leave the line endings as line endings, however -
- * This is line buffered mode, we are not dealing with binary here, but lines.
- * If we are not dealing with binary, we must be dealing with ASCII, unicode, or some other text format.
- * Thus the user is most likely gonna deal with this text as strings.
- * Thus the user is most likely gonna pass this data to str functions.
- * rasters way - the endings are always gonna be '\n'; onefangs way - they will always be '\0'
- * We are handing them the string length as a convenience.
- * Thus if they really want it in raw format, they can e->lines[i].line[e->lines[i].size - 1] = '\n'; easily enough.
- * In the default case, we can do this conversion quicker than the user can, as we already have the index and pointer.
- * Let's make it easy on them to use these as standard C strings.
- *
- * onefang is proud to announce that he has just set a new personal record for the
- * most over documentation of a simple assignment statement. B-)
- */
- inbuf[i] = '\0';
- e->lines[count].line = c;
- e->lines[count].size = i - last;
- last = i + 1;
- c = (char *)&inbuf[last];
- count++;
- }
- }
- if (count == 0) /* No lines to send, cancel the event. */
- {
- _ecore_exe_event_exe_data_free(NULL, e);
- e = NULL;
- }
- else /* NULL terminate the array, so that people know where the end is. */
- {
- e->lines[count].line = NULL;
- e->lines[count].size = 0;
- }
- if (i > last) /* Partial line left over, save it for next time. */
- {
- if (e) e->size = last;
- if (flags & ECORE_EXE_PIPE_READ)
- {
- exe->read_data_size = i - last;
- exe->read_data_buf = malloc(exe->read_data_size);
- memcpy(exe->read_data_buf, c, exe->read_data_size);
- }
- else
- {
- exe->error_data_size = i - last;
- exe->error_data_buf = malloc(exe->error_data_size);
- memcpy(exe->error_data_buf, c, exe->error_data_size);
- }
- }
- }
- }
-
- return e;
+ Ecore_Exe_Event_Data *e = NULL;
+ int is_buffered = 0;
+ unsigned char *inbuf;
+ int inbuf_num;
+
+ if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) {
+ ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE,
+ "ecore_exe_event_data_get");
+ return NULL;
+ }
+
+ /* Sort out what sort of event we are. */
+ if (flags & ECORE_EXE_PIPE_READ) {
+ flags = ECORE_EXE_PIPE_READ;
+ if (exe->flags & ECORE_EXE_PIPE_READ_LINE_BUFFERED)
+ is_buffered = 1;
+ } else {
+ flags = ECORE_EXE_PIPE_ERROR;
+ if (exe->flags & ECORE_EXE_PIPE_ERROR_LINE_BUFFERED)
+ is_buffered = 1;
+ }
+
+ /* Get the data. */
+ if (flags & ECORE_EXE_PIPE_READ) {
+ inbuf = exe->read_data_buf;
+ inbuf_num = exe->read_data_size;
+ exe->read_data_buf = NULL;
+ exe->read_data_size = 0;
+ } else {
+ inbuf = exe->error_data_buf;
+ inbuf_num = exe->error_data_size;
+ exe->error_data_buf = NULL;
+ exe->error_data_size = 0;
+ }
+
+ e = calloc(1, sizeof(Ecore_Exe_Event_Data));
+ if (e) {
+ e->exe = exe;
+ e->data = inbuf;
+ e->size = inbuf_num;
+
+ if (is_buffered) { /* Deal with line buffering. */
+ int max = 0;
+ int count = 0;
+ int i;
+ int last = 0;
+ char *c;
+
+ c = (char *) inbuf;
+ for (i = 0; i < inbuf_num; i++) { /* Find the lines. */
+ if (inbuf[i] == '\n') {
+ if (count >= max) {
+ /* In testing, the lines seem to arrive in batches of 500 to 1000 lines at most, roughly speaking. */
+ max += 10; /* FIXME: Maybe keep track of the largest number of lines ever sent, and add half that many instead of 10. */
+ e->lines = realloc(e->lines, sizeof(Ecore_Exe_Event_Data_Line) * (max + 1)); /* Allow room for the NULL termination. */
+ }
+ /* raster said to leave the line endings as line endings, however -
+ * This is line buffered mode, we are not dealing with binary here, but lines.
+ * If we are not dealing with binary, we must be dealing with ASCII, unicode, or some other text format.
+ * Thus the user is most likely gonna deal with this text as strings.
+ * Thus the user is most likely gonna pass this data to str functions.
+ * rasters way - the endings are always gonna be '\n'; onefangs way - they will always be '\0'
+ * We are handing them the string length as a convenience.
+ * Thus if they really want it in raw format, they can e->lines[i].line[e->lines[i].size - 1] = '\n'; easily enough.
+ * In the default case, we can do this conversion quicker than the user can, as we already have the index and pointer.
+ * Let's make it easy on them to use these as standard C strings.
+ *
+ * onefang is proud to announce that he has just set a new personal record for the
+ * most over documentation of a simple assignment statement. B-)
+ */
+ inbuf[i] = '\0';
+ e->lines[count].line = c;
+ e->lines[count].size = i - last;
+ last = i + 1;
+ c = (char *) &inbuf[last];
+ count++;
+ }
+ }
+ if (count == 0) { /* No lines to send, cancel the event. */
+ _ecore_exe_event_exe_data_free(NULL, e);
+ e = NULL;
+ } else { /* NULL terminate the array, so that people know where the end is. */
+
+ e->lines[count].line = NULL;
+ e->lines[count].size = 0;
+ }
+ if (i > last) { /* Partial line left over, save it for next time. */
+ if (e)
+ e->size = last;
+ if (flags & ECORE_EXE_PIPE_READ) {
+ exe->read_data_size = i - last;
+ exe->read_data_buf =
+ malloc(exe->read_data_size);
+ memcpy(exe->read_data_buf, c,
+ exe->read_data_size);
+ } else {
+ exe->error_data_size = i - last;
+ exe->error_data_buf =
+ malloc(exe->error_data_size);
+ memcpy(exe->error_data_buf, c,
+ exe->error_data_size);
+ }
+ }
+ }
+ }
+
+ return e;
}
/**
@@ -988,19 +1007,18 @@ ecore_exe_event_data_get(Ecore_Exe *exe, Ecore_Exe_Flags flags)
* @param tag The string tag to set on the process handle.
* @ingroup Ecore_Exe_Basic_Group
*/
-EAPI void
-ecore_exe_tag_set(Ecore_Exe *exe, const char *tag)
+EAPI void ecore_exe_tag_set(Ecore_Exe * exe, const char *tag)
{
- if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
- {
- ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_tag_set");
- return;
- }
- IF_FREE(exe->tag);
- if (tag)
- exe->tag = strdup(tag);
- else
- exe->tag = NULL;
+ if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) {
+ ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE,
+ "ecore_exe_tag_set");
+ return;
+ }
+ IF_FREE(exe->tag);
+ if (tag)
+ exe->tag = strdup(tag);
+ else
+ exe->tag = NULL;
}
/**
@@ -1015,15 +1033,14 @@ ecore_exe_tag_set(Ecore_Exe *exe, const char *tag)
* ecore_exe_tag_set() to change it. It might be @c NULL.
* @ingroup Ecore_Exe_Basic_Group
*/
-EAPI const char *
-ecore_exe_tag_get(const Ecore_Exe *exe)
+EAPI const char *ecore_exe_tag_get(const Ecore_Exe * exe)
{
- if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
- {
- ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_tag_get");
- return NULL;
- }
- return exe->tag;
+ if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) {
+ ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE,
+ "ecore_exe_tag_get");
+ return NULL;
+ }
+ return exe->tag;
}
/**
@@ -1037,63 +1054,61 @@ ecore_exe_tag_get(const Ecore_Exe *exe)
* called.
* @ingroup Ecore_Exe_Basic_Group
*/
-EAPI void *
-ecore_exe_free(Ecore_Exe *exe)
+EAPI void *ecore_exe_free(Ecore_Exe * exe)
{
- void *data;
- int ok = 0;
- int result;
-
- if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
- {
- ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_free");
- return NULL;
- }
-
- data = exe->data;
-
- if (exe->pre_free_cb)
- exe->pre_free_cb(data, exe);
-
- if (exe->doomsday_clock)
- {
- struct _ecore_exe_dead_exe *dead;
-
- ecore_timer_del(exe->doomsday_clock);
- exe->doomsday_clock = NULL;
- dead = exe->doomsday_clock_dead;
- if (dead)
- {
- IF_FREE(dead->cmd);
- free(dead);
- exe->doomsday_clock_dead = NULL;
- }
- }
- IF_FN_DEL(ecore_main_fd_handler_del, exe->write_fd_handler);
- IF_FN_DEL(ecore_main_fd_handler_del, exe->read_fd_handler);
- IF_FN_DEL(ecore_main_fd_handler_del, exe->error_fd_handler);
- if (exe->child_fd_write_x != -1)
- E_NO_ERRNO(result, close(exe->child_fd_write_x), ok);
- if (exe->child_fd_read_x != -1)
- E_NO_ERRNO(result, close(exe->child_fd_read_x), ok);
- if (exe->child_fd_error_x != -1)
- E_NO_ERRNO(result, close(exe->child_fd_error_x), ok);
- if (exe->child_fd_write != -1)
- E_NO_ERRNO(result, close(exe->child_fd_write), ok);
- if (exe->child_fd_read != -1)
- E_NO_ERRNO(result, close(exe->child_fd_read), ok);
- if (exe->child_fd_error != -1)
- E_NO_ERRNO(result, close(exe->child_fd_error), ok);
- IF_FREE(exe->write_data_buf);
- IF_FREE(exe->read_data_buf);
- IF_FREE(exe->error_data_buf);
- IF_FREE(exe->cmd);
-
- exes = (Ecore_Exe *) eina_inlist_remove(EINA_INLIST_GET(exes), EINA_INLIST_GET(exe));
- ECORE_MAGIC_SET(exe, ECORE_MAGIC_NONE);
- IF_FREE(exe->tag);
- free(exe);
- return data;
+ void *data;
+ int ok = 0;
+ int result;
+
+ if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) {
+ ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_free");
+ return NULL;
+ }
+
+ data = exe->data;
+
+ if (exe->pre_free_cb)
+ exe->pre_free_cb(data, exe);
+
+ if (exe->doomsday_clock) {
+ struct _ecore_exe_dead_exe *dead;
+
+ ecore_timer_del(exe->doomsday_clock);
+ exe->doomsday_clock = NULL;
+ dead = exe->doomsday_clock_dead;
+ if (dead) {
+ IF_FREE(dead->cmd);
+ free(dead);
+ exe->doomsday_clock_dead = NULL;
+ }
+ }
+ IF_FN_DEL(ecore_main_fd_handler_del, exe->write_fd_handler);
+ IF_FN_DEL(ecore_main_fd_handler_del, exe->read_fd_handler);
+ IF_FN_DEL(ecore_main_fd_handler_del, exe->error_fd_handler);
+ if (exe->child_fd_write_x != -1)
+ E_NO_ERRNO(result, close(exe->child_fd_write_x), ok);
+ if (exe->child_fd_read_x != -1)
+ E_NO_ERRNO(result, close(exe->child_fd_read_x), ok);
+ if (exe->child_fd_error_x != -1)
+ E_NO_ERRNO(result, close(exe->child_fd_error_x), ok);
+ if (exe->child_fd_write != -1)
+ E_NO_ERRNO(result, close(exe->child_fd_write), ok);
+ if (exe->child_fd_read != -1)
+ E_NO_ERRNO(result, close(exe->child_fd_read), ok);
+ if (exe->child_fd_error != -1)
+ E_NO_ERRNO(result, close(exe->child_fd_error), ok);
+ IF_FREE(exe->write_data_buf);
+ IF_FREE(exe->read_data_buf);
+ IF_FREE(exe->error_data_buf);
+ IF_FREE(exe->cmd);
+
+ exes =
+ (Ecore_Exe *) eina_inlist_remove(EINA_INLIST_GET(exes),
+ EINA_INLIST_GET(exe));
+ ECORE_MAGIC_SET(exe, ECORE_MAGIC_NONE);
+ IF_FREE(exe->tag);
+ free(exe);
+ return data;
}
/**
@@ -1102,13 +1117,13 @@ ecore_exe_free(Ecore_Exe *exe)
* @param e The given event data.
* @ingroup Ecore_Exe_Basic_Group
*/
-EAPI void
-ecore_exe_event_data_free(Ecore_Exe_Event_Data *e)
+EAPI void ecore_exe_event_data_free(Ecore_Exe_Event_Data * e)
{
- if (!e) return;
- IF_FREE(e->lines);
- IF_FREE(e->data);
- free(e);
+ if (!e)
+ return;
+ IF_FREE(e->lines);
+ IF_FREE(e->data);
+ free(e);
}
/**
@@ -1117,15 +1132,14 @@ ecore_exe_event_data_free(Ecore_Exe_Event_Data *e)
* @return The process ID on success. @c -1 otherwise.
* @ingroup Ecore_Exe_Basic_Group
*/
-EAPI pid_t
-ecore_exe_pid_get(const Ecore_Exe *exe)
+EAPI pid_t ecore_exe_pid_get(const Ecore_Exe * exe)
{
- if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
- {
- ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_pid_get");
- return -1;
- }
- return exe->pid;
+ if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) {
+ ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE,
+ "ecore_exe_pid_get");
+ return -1;
+ }
+ return exe->pid;
}
/**
@@ -1136,15 +1150,14 @@ ecore_exe_pid_get(const Ecore_Exe *exe)
* any way.
* @ingroup Ecore_Exe_Basic_Group
*/
-EAPI const char *
-ecore_exe_cmd_get(const Ecore_Exe *exe)
+EAPI const char *ecore_exe_cmd_get(const Ecore_Exe * exe)
{
- if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
- {
- ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_cmd_get");
- return NULL;
- }
- return exe->cmd;
+ if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) {
+ ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE,
+ "ecore_exe_cmd_get");
+ return NULL;
+ }
+ return exe->cmd;
}
/**
@@ -1154,15 +1167,14 @@ ecore_exe_cmd_get(const Ecore_Exe *exe)
* ecore_exe_run() or ecore_exe_pipe_run()
* @ingroup Ecore_Exe_Basic_Group
*/
-EAPI void *
-ecore_exe_data_get(const Ecore_Exe *exe)
+EAPI void *ecore_exe_data_get(const Ecore_Exe * exe)
{
- if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
- {
- ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_data_get");
- return NULL;
- }
- return exe->data;
+ if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) {
+ ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE,
+ "ecore_exe_data_get");
+ return NULL;
+ }
+ return exe->data;
}
/**
@@ -1171,15 +1183,14 @@ ecore_exe_data_get(const Ecore_Exe *exe)
* @return The flags attached to @p exe.
* @ingroup Ecore_Exe_Basic_Group
*/
-EAPI Ecore_Exe_Flags
-ecore_exe_flags_get(const Ecore_Exe *exe)
+EAPI Ecore_Exe_Flags ecore_exe_flags_get(const Ecore_Exe * exe)
{
- if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
- {
- ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_data_get");
- return 0;
- }
- return exe->flags;
+ if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) {
+ ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE,
+ "ecore_exe_data_get");
+ return 0;
+ }
+ return exe->flags;
}
/**
@@ -1193,15 +1204,13 @@ ecore_exe_flags_get(const Ecore_Exe *exe)
* @param exe Process handle to the given process.
* @ingroup Ecore_Exe_Signal_Group
*/
-EAPI void
-ecore_exe_pause(Ecore_Exe *exe)
+EAPI void ecore_exe_pause(Ecore_Exe * exe)
{
- if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
- {
- ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_pause");
- return;
- }
- kill(exe->pid, SIGSTOP);
+ if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) {
+ ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_pause");
+ return;
+ }
+ kill(exe->pid, SIGSTOP);
}
/**
@@ -1209,15 +1218,14 @@ ecore_exe_pause(Ecore_Exe *exe)
* @param exe Process handle to the given process.
* @ingroup Ecore_Exe_Signal_Group
*/
-EAPI void
-ecore_exe_continue(Ecore_Exe *exe)
+EAPI void ecore_exe_continue(Ecore_Exe * exe)
{
- if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
- {
- ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_continue");
- return;
- }
- kill(exe->pid, SIGCONT);
+ if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) {
+ ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE,
+ "ecore_exe_continue");
+ return;
+ }
+ kill(exe->pid, SIGCONT);
}
/**
@@ -1225,16 +1233,15 @@ ecore_exe_continue(Ecore_Exe *exe)
* @param exe Process handle to the given process.
* @ingroup Ecore_Exe_Signal_Group
*/
-EAPI void
-ecore_exe_interrupt(Ecore_Exe *exe)
+EAPI void ecore_exe_interrupt(Ecore_Exe * exe)
{
- if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
- {
- ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_interrupt");
- return;
- }
- _ecore_exe_dead_attach(exe);
- kill(exe->pid, SIGINT);
+ if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) {
+ ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE,
+ "ecore_exe_interrupt");
+ return;
+ }
+ _ecore_exe_dead_attach(exe);
+ kill(exe->pid, SIGINT);
}
/**
@@ -1242,16 +1249,14 @@ ecore_exe_interrupt(Ecore_Exe *exe)
* @param exe Process handle to the given process.
* @ingroup Ecore_Exe_Signal_Group
*/
-EAPI void
-ecore_exe_quit(Ecore_Exe *exe)
+EAPI void ecore_exe_quit(Ecore_Exe * exe)
{
- if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
- {
- ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_quit");
- return;
- }
- _ecore_exe_dead_attach(exe);
- kill(exe->pid, SIGQUIT);
+ if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) {
+ ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_quit");
+ return;
+ }
+ _ecore_exe_dead_attach(exe);
+ kill(exe->pid, SIGQUIT);
}
/**
@@ -1259,17 +1264,16 @@ ecore_exe_quit(Ecore_Exe *exe)
* @param exe Process handle to the given process.
* @ingroup Ecore_Exe_Signal_Group
*/
-EAPI void
-ecore_exe_terminate(Ecore_Exe *exe)
+EAPI void ecore_exe_terminate(Ecore_Exe * exe)
{
- if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
- {
- ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_terminate");
- return;
- }
- _ecore_exe_dead_attach(exe);
- INF("Sending TERM signal to %s (%d).", exe->cmd, exe->pid);
- kill(exe->pid, SIGTERM);
+ if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) {
+ ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE,
+ "ecore_exe_terminate");
+ return;
+ }
+ _ecore_exe_dead_attach(exe);
+ INF("Sending TERM signal to %s (%d).", exe->cmd, exe->pid);
+ kill(exe->pid, SIGTERM);
}
/**
@@ -1277,29 +1281,28 @@ ecore_exe_terminate(Ecore_Exe *exe)
* @param exe Process handle to the given process.
* @ingroup Ecore_Exe_Signal_Group
*/
-EAPI void
-ecore_exe_kill(Ecore_Exe *exe)
+EAPI void ecore_exe_kill(Ecore_Exe * exe)
{
- struct _ecore_exe_dead_exe *dead;
-
- if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
- {
- ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_kill");
- return;
- }
-
- dead = calloc(1, sizeof(struct _ecore_exe_dead_exe));
- if (dead)
- {
- dead->pid = exe->pid;
- dead->cmd = strdup(exe->cmd);
- IF_FN_DEL(ecore_timer_del, exe->doomsday_clock);
- exe->doomsday_clock =
- ecore_timer_add(10.0, _ecore_exe_make_sure_its_really_dead, dead);
- }
-
- INF("Sending KILL signal to %s (%d).", exe->cmd, exe->pid);
- kill(exe->pid, SIGKILL);
+ struct _ecore_exe_dead_exe *dead;
+
+ if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) {
+ ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_kill");
+ return;
+ }
+
+ dead = calloc(1, sizeof(struct _ecore_exe_dead_exe));
+ if (dead) {
+ dead->pid = exe->pid;
+ dead->cmd = strdup(exe->cmd);
+ IF_FN_DEL(ecore_timer_del, exe->doomsday_clock);
+ exe->doomsday_clock =
+ ecore_timer_add(10.0,
+ _ecore_exe_make_sure_its_really_dead,
+ dead);
+ }
+
+ INF("Sending KILL signal to %s (%d).", exe->cmd, exe->pid);
+ kill(exe->pid, SIGKILL);
}
/**
@@ -1309,18 +1312,16 @@ ecore_exe_kill(Ecore_Exe *exe)
* the signal will be ignored.
* @ingroup Ecore_Exe_Signal_Group
*/
-EAPI void
-ecore_exe_signal(Ecore_Exe *exe, int num)
+EAPI void ecore_exe_signal(Ecore_Exe * exe, int num)
{
- if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
- {
- ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_signal");
- return;
- }
- if (num == 1)
- kill(exe->pid, SIGUSR1);
- else if (num == 2)
- kill(exe->pid, SIGUSR2);
+ if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) {
+ ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_signal");
+ return;
+ }
+ if (num == 1)
+ kill(exe->pid, SIGUSR1);
+ else if (num == 2)
+ kill(exe->pid, SIGUSR2);
}
/**
@@ -1328,517 +1329,477 @@ ecore_exe_signal(Ecore_Exe *exe, int num)
* @param exe Process handle to the given process.
* @ingroup Ecore_Exe_Signal_Group
*/
-EAPI void
-ecore_exe_hup(Ecore_Exe *exe)
+EAPI void ecore_exe_hup(Ecore_Exe * exe)
{
- if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
- {
- ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_hup");
- return;
- }
- kill(exe->pid, SIGHUP);
+ if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) {
+ ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_hup");
+ return;
+ }
+ kill(exe->pid, SIGHUP);
}
-static Ecore_Exe *
-_ecore_exe_is_it_alive(pid_t pid)
+static Ecore_Exe *_ecore_exe_is_it_alive(pid_t pid)
{
- Ecore_Exe *exe = NULL;
-
- /* FIXME: There is no nice, safe, OS independent way to tell if a
- * particular PID is still alive. I have written code to do so
- * for my urunlevel busybox applet (http://urunlevel.sourceforge.net/),
- * but it's for linux only, and still not guaranteed.
- *
- * So for now, we just check that a valid Ecore_Exe structure
- * exists for it. Even that is not a guarantee, as the structure
- * can be freed without killing the process.
- *
- * I think we can safely put exe's into two categories, those users
- * that care about the life of the exe, and the run and forget type.
- * The run and forget type starts up the exe, then free's the
- * Ecore_Exe structure straight away. They can never call any of
- * the functions that can call this, so we don't worry about them.
- *
- * Those user's that care about the life of exe's will keep the
- * Ecore_Exe structure around, terminate them eventually, or
- * register for exit events. For these ones the assumption
- * that valid Ecore_Exe struct == live exe is almost valid.
- *
- * I will probably copy my urunlevel code into here someday.
- */
- exe = _ecore_exe_find(pid);
- if (exe)
- {
- if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
- exe = NULL;
- }
-
- return exe;
+ Ecore_Exe *exe = NULL;
+
+ /* FIXME: There is no nice, safe, OS independent way to tell if a
+ * particular PID is still alive. I have written code to do so
+ * for my urunlevel busybox applet (http://urunlevel.sourceforge.net/),
+ * but it's for linux only, and still not guaranteed.
+ *
+ * So for now, we just check that a valid Ecore_Exe structure
+ * exists for it. Even that is not a guarantee, as the structure
+ * can be freed without killing the process.
+ *
+ * I think we can safely put exe's into two categories, those users
+ * that care about the life of the exe, and the run and forget type.
+ * The run and forget type starts up the exe, then free's the
+ * Ecore_Exe structure straight away. They can never call any of
+ * the functions that can call this, so we don't worry about them.
+ *
+ * Those user's that care about the life of exe's will keep the
+ * Ecore_Exe structure around, terminate them eventually, or
+ * register for exit events. For these ones the assumption
+ * that valid Ecore_Exe struct == live exe is almost valid.
+ *
+ * I will probably copy my urunlevel code into here someday.
+ */
+ exe = _ecore_exe_find(pid);
+ if (exe) {
+ if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+ exe = NULL;
+ }
+
+ return exe;
}
-static Eina_Bool
-_ecore_exe_make_sure_its_dead(void *data)
+static Eina_Bool _ecore_exe_make_sure_its_dead(void *data)
{
- struct _ecore_exe_dead_exe *dead;
-
- dead = data;
- if (dead)
- {
- Ecore_Exe *exe = NULL;
-
- if ((exe = _ecore_exe_is_it_alive(dead->pid)))
- {
- if (dead->cmd)
- INF("Sending KILL signal to allegedly dead %s (%d).",
- dead->cmd, dead->pid);
- else
- INF("Sending KILL signal to allegedly dead PID %d.",
- dead->pid);
- exe->doomsday_clock =
- ecore_timer_add(10.0, _ecore_exe_make_sure_its_really_dead,
- dead);
- kill(dead->pid, SIGKILL);
- }
- else
- {
- IF_FREE(dead->cmd);
- free(dead);
- }
- }
- return ECORE_CALLBACK_CANCEL;
+ struct _ecore_exe_dead_exe *dead;
+
+ dead = data;
+ if (dead) {
+ Ecore_Exe *exe = NULL;
+
+ if ((exe = _ecore_exe_is_it_alive(dead->pid))) {
+ if (dead->cmd)
+ INF("Sending KILL signal to allegedly dead %s (%d).", dead->cmd, dead->pid);
+ else
+ INF("Sending KILL signal to allegedly dead PID %d.", dead->pid);
+ exe->doomsday_clock =
+ ecore_timer_add(10.0,
+ _ecore_exe_make_sure_its_really_dead,
+ dead);
+ kill(dead->pid, SIGKILL);
+ } else {
+ IF_FREE(dead->cmd);
+ free(dead);
+ }
+ }
+ return ECORE_CALLBACK_CANCEL;
}
-static Eina_Bool
-_ecore_exe_make_sure_its_really_dead(void *data)
+static Eina_Bool _ecore_exe_make_sure_its_really_dead(void *data)
{
- struct _ecore_exe_dead_exe *dead;
-
- dead = data;
- if (dead)
- {
- Ecore_Exe *exe = NULL;
-
- if ((exe = _ecore_exe_is_it_alive(dead->pid)))
- {
- ERR("RUN! The zombie wants to eat your brains! And your CPU!");
- if (dead->cmd)
- INF("%s (%d) is not really dead.", dead->cmd, dead->pid);
- else
- INF("PID %d is not really dead.", dead->pid);
- exe->doomsday_clock = NULL;
- }
- IF_FREE(dead->cmd);
- free(dead);
- }
- return ECORE_CALLBACK_CANCEL;
+ struct _ecore_exe_dead_exe *dead;
+
+ dead = data;
+ if (dead) {
+ Ecore_Exe *exe = NULL;
+
+ if ((exe = _ecore_exe_is_it_alive(dead->pid))) {
+ ERR("RUN! The zombie wants to eat your brains! And your CPU!");
+ if (dead->cmd)
+ INF("%s (%d) is not really dead.",
+ dead->cmd, dead->pid);
+ else
+ INF("PID %d is not really dead.",
+ dead->pid);
+ exe->doomsday_clock = NULL;
+ }
+ IF_FREE(dead->cmd);
+ free(dead);
+ }
+ return ECORE_CALLBACK_CANCEL;
}
-void
-_ecore_exe_init(void)
+void _ecore_exe_init(void)
{
- ECORE_EXE_EVENT_ADD = ecore_event_type_new();
- ECORE_EXE_EVENT_DEL = ecore_event_type_new();
- ECORE_EXE_EVENT_DATA = ecore_event_type_new();
- ECORE_EXE_EVENT_ERROR = ecore_event_type_new();
+ ECORE_EXE_EVENT_ADD = ecore_event_type_new();
+ ECORE_EXE_EVENT_DEL = ecore_event_type_new();
+ ECORE_EXE_EVENT_DATA = ecore_event_type_new();
+ ECORE_EXE_EVENT_ERROR = ecore_event_type_new();
}
-void
-_ecore_exe_shutdown(void)
+void _ecore_exe_shutdown(void)
{
- while (exes)
- ecore_exe_free(exes);
+ while (exes)
+ ecore_exe_free(exes);
}
-Ecore_Exe *
-_ecore_exe_find(pid_t pid)
+Ecore_Exe *_ecore_exe_find(pid_t pid)
{
- Ecore_Exe *exe;
-
- EINA_INLIST_FOREACH(exes, exe)
- {
- if (exe->pid == pid)
- return exe;
- }
- return NULL;
+ Ecore_Exe *exe;
+
+ EINA_INLIST_FOREACH(exes, exe) {
+ if (exe->pid == pid)
+ return exe;
+ }
+ return NULL;
}
-Ecore_Timer *
-_ecore_exe_doomsday_clock_get(Ecore_Exe *exe)
+Ecore_Timer *_ecore_exe_doomsday_clock_get(Ecore_Exe * exe)
{
- return exe->doomsday_clock;
+ return exe->doomsday_clock;
}
-void
-_ecore_exe_doomsday_clock_set(Ecore_Exe *exe, Ecore_Timer *dc)
+void _ecore_exe_doomsday_clock_set(Ecore_Exe * exe, Ecore_Timer * dc)
{
- exe->doomsday_clock = dc;
+ exe->doomsday_clock = dc;
}
static inline void
_ecore_exe_exec_it(const char *exe_cmd, Ecore_Exe_Flags flags)
{
- char use_sh = 1;
- char *buf = NULL;
- char **args = NULL;
- int save_errno = 0;
-
- /* So what is this doing?
- *
- * We are trying to avoid wrapping the exe call with /bin/sh -c.
- * We conservatively search for certain shell meta characters,
- * If we don't find them, we can call the exe directly.
- */
- if (!strpbrk(exe_cmd, "|&;<>()$`\\\"'*?#"))
- {
- char *token;
- char pre_command = 1;
- int num_tokens = 0;
-
- if (!(buf = strdup(exe_cmd)))
- return;
-
- token = strtok(buf, " \t\n\v");
- while (token)
- {
- if (token[0] == '~')
- break;
- if (pre_command)
- {
- if (token[0] == '[')
- break;
- if (strchr(token, '='))
- break;
- else
- pre_command = 0;
- }
- num_tokens++;
- token = strtok(NULL, " \t\n\v");
- }
- IF_FREE(buf);
- if ((!token) && (num_tokens))
- {
- int i = 0;
-
- if (!(buf = strdup(exe_cmd)))
- return;
-
- token = strtok(buf, " \t\n\v");
- use_sh = 0;
- if (!(args = (char **)calloc(num_tokens + 1, sizeof(char *))))
- {
- IF_FREE(buf);
- return;
- }
- for (i = 0; i < num_tokens; i++)
- {
- if (token)
- args[i] = token;
- token = strtok(NULL, " \t\n\v");
- }
- args[num_tokens] = NULL;
- }
- }
-
- if (!(flags & ECORE_EXE_NOT_LEADER)) setsid();
- if ((flags & ECORE_EXE_USE_SH))
- {
- errno = 0;
- execl("/bin/sh", "/bin/sh", "-c", exe_cmd, (char *)NULL);
- }
- else if (use_sh)
- { /* We have to use a shell to run this. */
- if (!shell)
- { /* Find users preferred shell. */
- shell = getenv("SHELL");
- if (!shell)
- shell = "/bin/sh";
- }
- errno = 0;
- execl(shell, shell, "-c", exe_cmd, (char *)NULL);
- }
- else
- { /* We can run this directly. */
- errno = 0;
- execvp(args[0], args);
- }
-
- save_errno = errno;
- IF_FREE(buf);
- IF_FREE(args);
- errno = save_errno;
- return;
+ char use_sh = 1;
+ char *buf = NULL;
+ char **args = NULL;
+ int save_errno = 0;
+
+ /* So what is this doing?
+ *
+ * We are trying to avoid wrapping the exe call with /bin/sh -c.
+ * We conservatively search for certain shell meta characters,
+ * If we don't find them, we can call the exe directly.
+ */
+ if (!strpbrk(exe_cmd, "|&;<>()$`\\\"'*?#")) {
+ char *token;
+ char pre_command = 1;
+ int num_tokens = 0;
+
+ if (!(buf = strdup(exe_cmd)))
+ return;
+
+ token = strtok(buf, " \t\n\v");
+ while (token) {
+ if (token[0] == '~')
+ break;
+ if (pre_command) {
+ if (token[0] == '[')
+ break;
+ if (strchr(token, '='))
+ break;
+ else
+ pre_command = 0;
+ }
+ num_tokens++;
+ token = strtok(NULL, " \t\n\v");
+ }
+ IF_FREE(buf);
+ if ((!token) && (num_tokens)) {
+ int i = 0;
+
+ if (!(buf = strdup(exe_cmd)))
+ return;
+
+ token = strtok(buf, " \t\n\v");
+ use_sh = 0;
+ if (!
+ (args =
+ (char **) calloc(num_tokens + 1,
+ sizeof(char *)))) {
+ IF_FREE(buf);
+ return;
+ }
+ for (i = 0; i < num_tokens; i++) {
+ if (token)
+ args[i] = token;
+ token = strtok(NULL, " \t\n\v");
+ }
+ args[num_tokens] = NULL;
+ }
+ }
+
+ if (!(flags & ECORE_EXE_NOT_LEADER))
+ setsid();
+ if ((flags & ECORE_EXE_USE_SH)) {
+ errno = 0;
+ execl("/bin/sh", "/bin/sh", "-c", exe_cmd, (char *) NULL);
+ } else if (use_sh) { /* We have to use a shell to run this. */
+ if (!shell) { /* Find users preferred shell. */
+ shell = getenv("SHELL");
+ if (!shell)
+ shell = "/bin/sh";
+ }
+ errno = 0;
+ execl(shell, shell, "-c", exe_cmd, (char *) NULL);
+ } else { /* We can run this directly. */
+ errno = 0;
+ execvp(args[0], args);
+ }
+
+ save_errno = errno;
+ IF_FREE(buf);
+ IF_FREE(args);
+ errno = save_errno;
+ return;
}
static Eina_Bool
-_ecore_exe_data_generic_handler(void *data, Ecore_Fd_Handler *fd_handler, Ecore_Exe_Flags flags)
+_ecore_exe_data_generic_handler(void *data, Ecore_Fd_Handler * fd_handler,
+ Ecore_Exe_Flags flags)
{
- Ecore_Exe *exe;
- int child_fd;
- int event_type;
-
- exe = data;
-
- /* Sort out what sort of handler we are. */
- if (flags & ECORE_EXE_PIPE_READ)
- {
- flags = ECORE_EXE_PIPE_READ;
- event_type = ECORE_EXE_EVENT_DATA;
- child_fd = exe->child_fd_read;
- }
- else
- {
- flags = ECORE_EXE_PIPE_ERROR;
- event_type = ECORE_EXE_EVENT_ERROR;
- child_fd = exe->child_fd_error;
- }
-
- if ((fd_handler)
- && (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)))
- {
- unsigned char *inbuf;
- int inbuf_num;
-
- /* Get any left over data from last time. */
- if (flags & ECORE_EXE_PIPE_READ)
- {
- inbuf = exe->read_data_buf;
- inbuf_num = exe->read_data_size;
- exe->read_data_buf = NULL;
- exe->read_data_size = 0;
- }
- else
- {
- inbuf = exe->error_data_buf;
- inbuf_num = exe->error_data_size;
- exe->error_data_buf = NULL;
- exe->error_data_size = 0;
- }
-
- for (;;)
- {
- int num, lost_exe;
- char buf[READBUFSIZ];
-
- lost_exe = 0;
- errno = 0;
- if ((num = read(child_fd, buf, READBUFSIZ)) < 1)
- /* FIXME: SPEED/SIZE TRADE OFF - add a smaller READBUFSIZE
- * (currently 64k) to inbuf, use that instead of buf, and
- * save ourselves a memcpy(). */
- {
- lost_exe = ((errno == EIO) ||
- (errno == EBADF) ||
- (errno == EPIPE) ||
- (errno == EINVAL) || (errno == ENOSPC));
- if ((errno != EAGAIN) && (errno != EINTR))
- perror("_ecore_exe_generic_handler() read problem ");
- }
- if (num > 0)
- { /* data got read. */
- inbuf = realloc(inbuf, inbuf_num + num);
- memcpy(inbuf + inbuf_num, buf, num);
- inbuf_num += num;
- }
- else
- { /* No more data to read. */
- if (inbuf)
- {
- Ecore_Exe_Event_Data *e;
-
- /* Stash the data away for later. */
- if (flags & ECORE_EXE_PIPE_READ)
- {
- exe->read_data_buf = inbuf;
- exe->read_data_size = inbuf_num;
- }
- else
- {
- exe->error_data_buf = inbuf;
- exe->error_data_size = inbuf_num;
- }
-
- if (!(exe->flags & ECORE_EXE_PIPE_AUTO))
- {
- e = ecore_exe_event_data_get(exe, flags);
- if (e) /* Send the event. */
- ecore_event_add(event_type, e,
- _ecore_exe_event_exe_data_free,
- NULL);
- }
- }
- if (lost_exe)
- {
- if (flags & ECORE_EXE_PIPE_READ)
- {
- if (exe->read_data_size)
- INF("There are %d bytes left unsent from the dead exe %s.",
- exe->read_data_size, exe->cmd);
- }
- else
- {
- if (exe->error_data_size)
- INF("There are %d bytes left unsent from the dead exe %s.",
- exe->error_data_size, exe->cmd);
- }
- /* Thought about this a bit. If the exe has actually
- * died, this won't do any harm as it must have died
- * recently and the pid has not had a chance to recycle.
- * It is also a paranoid catchall, coz the usual ecore_signal
- * mechenism should kick in. But let's give it a good
- * kick in the head anyway.
- */
- ecore_exe_terminate(exe);
- }
- break;
- }
- }
- }
-
- return ECORE_CALLBACK_RENEW;
+ Ecore_Exe *exe;
+ int child_fd;
+ int event_type;
+
+ exe = data;
+
+ /* Sort out what sort of handler we are. */
+ if (flags & ECORE_EXE_PIPE_READ) {
+ flags = ECORE_EXE_PIPE_READ;
+ event_type = ECORE_EXE_EVENT_DATA;
+ child_fd = exe->child_fd_read;
+ } else {
+ flags = ECORE_EXE_PIPE_ERROR;
+ event_type = ECORE_EXE_EVENT_ERROR;
+ child_fd = exe->child_fd_error;
+ }
+
+ if ((fd_handler)
+ &&
+ (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)))
+ {
+ unsigned char *inbuf;
+ int inbuf_num;
+
+ /* Get any left over data from last time. */
+ if (flags & ECORE_EXE_PIPE_READ) {
+ inbuf = exe->read_data_buf;
+ inbuf_num = exe->read_data_size;
+ exe->read_data_buf = NULL;
+ exe->read_data_size = 0;
+ } else {
+ inbuf = exe->error_data_buf;
+ inbuf_num = exe->error_data_size;
+ exe->error_data_buf = NULL;
+ exe->error_data_size = 0;
+ }
+
+ for (;;) {
+ int num, lost_exe;
+ char buf[READBUFSIZ];
+
+ lost_exe = 0;
+ errno = 0;
+ if ((num = read(child_fd, buf, READBUFSIZ)) < 1)
+ /* FIXME: SPEED/SIZE TRADE OFF - add a smaller READBUFSIZE
+ * (currently 64k) to inbuf, use that instead of buf, and
+ * save ourselves a memcpy(). */
+ {
+ lost_exe = ((errno == EIO) ||
+ (errno == EBADF) ||
+ (errno == EPIPE) ||
+ (errno == EINVAL)
+ || (errno == ENOSPC));
+ if ((errno != EAGAIN) && (errno != EINTR))
+ perror
+ ("_ecore_exe_generic_handler() read problem ");
+ }
+ if (num > 0) { /* data got read. */
+ inbuf = realloc(inbuf, inbuf_num + num);
+ memcpy(inbuf + inbuf_num, buf, num);
+ inbuf_num += num;
+ } else { /* No more data to read. */
+ if (inbuf) {
+ Ecore_Exe_Event_Data *e;
+
+ /* Stash the data away for later. */
+ if (flags & ECORE_EXE_PIPE_READ) {
+ exe->read_data_buf = inbuf;
+ exe->read_data_size =
+ inbuf_num;
+ } else {
+ exe->error_data_buf =
+ inbuf;
+ exe->error_data_size =
+ inbuf_num;
+ }
+
+ if (!
+ (exe->
+ flags & ECORE_EXE_PIPE_AUTO))
+ {
+ e = ecore_exe_event_data_get(exe, flags);
+ if (e) /* Send the event. */
+ ecore_event_add
+ (event_type, e,
+ _ecore_exe_event_exe_data_free,
+ NULL);
+ }
+ }
+ if (lost_exe) {
+ if (flags & ECORE_EXE_PIPE_READ) {
+ if (exe->read_data_size)
+ INF("There are %d bytes left unsent from the dead exe %s.", exe->read_data_size, exe->cmd);
+ } else {
+ if (exe->error_data_size)
+ INF("There are %d bytes left unsent from the dead exe %s.", exe->error_data_size, exe->cmd);
+ }
+ /* Thought about this a bit. If the exe has actually
+ * died, this won't do any harm as it must have died
+ * recently and the pid has not had a chance to recycle.
+ * It is also a paranoid catchall, coz the usual ecore_signal
+ * mechenism should kick in. But let's give it a good
+ * kick in the head anyway.
+ */
+ ecore_exe_terminate(exe);
+ }
+ break;
+ }
+ }
+ }
+
+ return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
-_ecore_exe_data_error_handler(void *data, Ecore_Fd_Handler *fd_handler)
+_ecore_exe_data_error_handler(void *data, Ecore_Fd_Handler * fd_handler)
{
- return _ecore_exe_data_generic_handler(data, fd_handler,
- ECORE_EXE_PIPE_ERROR);
+ return _ecore_exe_data_generic_handler(data, fd_handler,
+ ECORE_EXE_PIPE_ERROR);
}
static Eina_Bool
-_ecore_exe_data_read_handler(void *data, Ecore_Fd_Handler *fd_handler)
+_ecore_exe_data_read_handler(void *data, Ecore_Fd_Handler * fd_handler)
{
- return _ecore_exe_data_generic_handler(data, fd_handler,
- ECORE_EXE_PIPE_READ);
+ return _ecore_exe_data_generic_handler(data, fd_handler,
+ ECORE_EXE_PIPE_READ);
}
static Eina_Bool
-_ecore_exe_data_write_handler(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)
+_ecore_exe_data_write_handler(void *data,
+ Ecore_Fd_Handler * fd_handler __UNUSED__)
{
- Ecore_Exe *exe;
-
- exe = data;
- if ((exe->write_fd_handler) &&
- (ecore_main_fd_handler_active_get
- (exe->write_fd_handler, ECORE_FD_WRITE)))
- _ecore_exe_flush(exe);
-
- /* If we have sent all there is to send, and we need to close the pipe, then close it. */
- if ((exe->close_stdin == 1)
- && (exe->write_data_size == exe->write_data_offset))
- {
- int ok = 0;
- int result;
-
- INF("Closing stdin for %s", exe->cmd);
- /* if (exe->child_fd_write != -1) E_NO_ERRNO(result, fsync(exe->child_fd_write), ok); This a) doesn't work, and b) isn't needed. */
- IF_FN_DEL(ecore_main_fd_handler_del, exe->write_fd_handler);
- if (exe->child_fd_write != -1)
- E_NO_ERRNO(result, close(exe->child_fd_write), ok);
- exe->child_fd_write = -1;
- IF_FREE(exe->write_data_buf);
- }
-
- return ECORE_CALLBACK_RENEW;
+ Ecore_Exe *exe;
+
+ exe = data;
+ if ((exe->write_fd_handler) &&
+ (ecore_main_fd_handler_active_get
+ (exe->write_fd_handler, ECORE_FD_WRITE)))
+ _ecore_exe_flush(exe);
+
+ /* If we have sent all there is to send, and we need to close the pipe, then close it. */
+ if ((exe->close_stdin == 1)
+ && (exe->write_data_size == exe->write_data_offset)) {
+ int ok = 0;
+ int result;
+
+ INF("Closing stdin for %s", exe->cmd);
+ /* if (exe->child_fd_write != -1) E_NO_ERRNO(result, fsync(exe->child_fd_write), ok); This a) doesn't work, and b) isn't needed. */
+ IF_FN_DEL(ecore_main_fd_handler_del,
+ exe->write_fd_handler);
+ if (exe->child_fd_write != -1)
+ E_NO_ERRNO(result, close(exe->child_fd_write), ok);
+ exe->child_fd_write = -1;
+ IF_FREE(exe->write_data_buf);
+ }
+
+ return ECORE_CALLBACK_RENEW;
}
-static void
-_ecore_exe_flush(Ecore_Exe *exe)
+static void _ecore_exe_flush(Ecore_Exe * exe)
{
- int count;
-
- /* check whether we need to write anything at all. */
- if ((exe->child_fd_write == -1) || (!exe->write_data_buf))
- return;
- if (exe->write_data_size == exe->write_data_offset)
- return;
-
- count = write(exe->child_fd_write,
- (char *)exe->write_data_buf + exe->write_data_offset,
- exe->write_data_size - exe->write_data_offset);
- if (count < 1)
- {
- if (errno == EIO || errno == EBADF || errno == EPIPE || errno == EINVAL || errno == ENOSPC) /* we lost our exe! */
- {
- ecore_exe_terminate(exe);
- if (exe->write_fd_handler)
- ecore_main_fd_handler_active_set(exe->write_fd_handler, 0);
- }
- }
- else
- {
- exe->write_data_offset += count;
- if (exe->write_data_offset >= exe->write_data_size)
- { /* Nothing left to write, clean up. */
- exe->write_data_size = 0;
- exe->write_data_offset = 0;
- IF_FREE(exe->write_data_buf);
- if (exe->write_fd_handler)
- ecore_main_fd_handler_active_set(exe->write_fd_handler, 0);
- }
- }
+ int count;
+
+ /* check whether we need to write anything at all. */
+ if ((exe->child_fd_write == -1) || (!exe->write_data_buf))
+ return;
+ if (exe->write_data_size == exe->write_data_offset)
+ return;
+
+ count = write(exe->child_fd_write,
+ (char *) exe->write_data_buf +
+ exe->write_data_offset,
+ exe->write_data_size - exe->write_data_offset);
+ if (count < 1) {
+ if (errno == EIO || errno == EBADF || errno == EPIPE || errno == EINVAL || errno == ENOSPC) { /* we lost our exe! */
+ ecore_exe_terminate(exe);
+ if (exe->write_fd_handler)
+ ecore_main_fd_handler_active_set(exe->
+ write_fd_handler,
+ 0);
+ }
+ } else {
+ exe->write_data_offset += count;
+ if (exe->write_data_offset >= exe->write_data_size) { /* Nothing left to write, clean up. */
+ exe->write_data_size = 0;
+ exe->write_data_offset = 0;
+ IF_FREE(exe->write_data_buf);
+ if (exe->write_fd_handler)
+ ecore_main_fd_handler_active_set(exe->
+ write_fd_handler,
+ 0);
+ }
+ }
}
-static void
-_ecore_exe_event_exe_data_free(void *data __UNUSED__, void *ev)
+static void _ecore_exe_event_exe_data_free(void *data __UNUSED__, void *ev)
{
- Ecore_Exe_Event_Data *e;
+ Ecore_Exe_Event_Data *e;
- e = ev;
- ecore_exe_event_data_free(e);
+ e = ev;
+ ecore_exe_event_data_free(e);
}
-static Ecore_Exe_Event_Add *
-_ecore_exe_event_add_new(void)
+static Ecore_Exe_Event_Add *_ecore_exe_event_add_new(void)
{
- Ecore_Exe_Event_Add *e;
+ Ecore_Exe_Event_Add *e;
- e = calloc(1, sizeof(Ecore_Exe_Event_Add));
- return e;
+ e = calloc(1, sizeof(Ecore_Exe_Event_Add));
+ return e;
}
-static void
-_ecore_exe_event_add_free(void *data __UNUSED__, void *ev)
+static void _ecore_exe_event_add_free(void *data __UNUSED__, void *ev)
{
- Ecore_Exe_Event_Add *e;
+ Ecore_Exe_Event_Add *e;
- e = ev;
- free(e);
+ e = ev;
+ free(e);
}
-void *
-_ecore_exe_event_del_new(void)
+void *_ecore_exe_event_del_new(void)
{
- Ecore_Exe_Event_Del *e;
+ Ecore_Exe_Event_Del *e;
- e = calloc(1, sizeof(Ecore_Exe_Event_Del));
- return e;
+ e = calloc(1, sizeof(Ecore_Exe_Event_Del));
+ return e;
}
-void
-_ecore_exe_event_del_free(void *data __UNUSED__, void *ev)
+void _ecore_exe_event_del_free(void *data __UNUSED__, void *ev)
{
- Ecore_Exe_Event_Del *e;
+ Ecore_Exe_Event_Del *e;
- e = ev;
- if (e->exe)
- ecore_exe_free(e->exe);
- free(e);
+ e = ev;
+ if (e->exe)
+ ecore_exe_free(e->exe);
+ free(e);
}
-static void
-_ecore_exe_dead_attach(Ecore_Exe *exe)
+static void _ecore_exe_dead_attach(Ecore_Exe * exe)
{
- struct _ecore_exe_dead_exe *dead;
-
- if (exe->doomsday_clock_dead) return;
- dead = calloc(1, sizeof(struct _ecore_exe_dead_exe));
- if (dead)
- {
- dead->pid = exe->pid;
- dead->cmd = strdup(exe->cmd);
- IF_FN_DEL(ecore_timer_del, exe->doomsday_clock);
- exe->doomsday_clock =
- ecore_timer_add(10.0, _ecore_exe_make_sure_its_dead, dead);
- exe->doomsday_clock_dead = dead;
- }
+ struct _ecore_exe_dead_exe *dead;
+
+ if (exe->doomsday_clock_dead)
+ return;
+ dead = calloc(1, sizeof(struct _ecore_exe_dead_exe));
+ if (dead) {
+ dead->pid = exe->pid;
+ dead->cmd = strdup(exe->cmd);
+ IF_FN_DEL(ecore_timer_del, exe->doomsday_clock);
+ exe->doomsday_clock =
+ ecore_timer_add(10.0, _ecore_exe_make_sure_its_dead,
+ dead);
+ exe->doomsday_clock_dead = dead;
+ }
}