apr_proc_spawn.diff [plain text]
--- threadproc/unix/proc.c.orig 2007-10-14 11:00:37.000000000 -0700
+++ threadproc/unix/proc.c 2009-04-06 12:34:57.000000000 -0700
@@ -20,6 +20,9 @@
#include "apr_signal.h"
#include "apr_random.h"
+#include <crt_externs.h>
+#include <spawn.h>
+
/* Heavy on no'ops, here's what we want to pass if there is APR_NO_FILE
* requested for a specific child handle;
*/
@@ -599,6 +602,84 @@
return APR_SUCCESS;
}
+APR_DECLARE(apr_status_t) apr_proc_spawn(apr_proc_t *new,
+ const char *progname,
+ const char * const *args,
+ const char * const *env,
+ apr_procattr_t *attr,
+ apr_pool_t *pool)
+{
+ posix_spawn_file_actions_t file_actions;
+ int status = APR_EGENERAL;
+
+ new->in = attr->parent_in;
+ new->err = attr->parent_err;
+ new->out = attr->parent_out;
+
+ // XXX: attr->errchk
+
+ // XXX: Are those apr_pool_cleanup_* calls needed?
+
+ posix_spawn_file_actions_init(&file_actions);
+
+ if ((attr->child_in) && (attr->child_in->filedes == -1)) {
+ posix_spawn_file_actions_addclose(&file_actions, STDIN_FILENO);
+ }
+ else if (attr->child_in) {
+ posix_spawn_file_actions_adddup2(&file_actions, attr->child_in->filedes, STDIN_FILENO);
+ posix_spawn_file_actions_addclose(&file_actions, attr->child_in->filedes);
+ }
+
+ if ((attr->child_out) && (attr->child_out->filedes == -1)) {
+ posix_spawn_file_actions_addclose(&file_actions, STDOUT_FILENO);
+ }
+ else if (attr->child_out) {
+ posix_spawn_file_actions_adddup2(&file_actions, attr->child_out->filedes, STDOUT_FILENO);
+ posix_spawn_file_actions_addclose(&file_actions, attr->child_out->filedes);
+ }
+
+ if ((attr->child_err) && (attr->child_err->filedes == -1)) {
+ posix_spawn_file_actions_addclose(&file_actions, STDERR_FILENO);
+ }
+ else if (attr->child_err) {
+ posix_spawn_file_actions_adddup2(&file_actions, attr->child_err->filedes, STDERR_FILENO);
+ posix_spawn_file_actions_addclose(&file_actions, attr->child_err->filedes);
+ }
+
+ // XXX: signal
+ // XXX: currdir, gid, uid, limit_proc
+
+ /* Only support APR_PROGRAM_PATH for now. */
+ if (attr->cmdtype == APR_PROGRAM_PATH) {
+ /* Pass existing environment; as documented, APR_PROGRAM_PATH ignores the env argument. */
+ status = posix_spawnp(&new->pid, progname, &file_actions, NULL, args, (const char **)*_NSGetEnviron());
+ if (status != 0) {
+ if (attr->errfn) {
+ char *desc;
+
+ desc = apr_psprintf(pool, "posix_spawn of '%s' failed", progname);
+ attr->errfn(pool, status, desc);
+ }
+ }
+ }
+
+ posix_spawn_file_actions_destroy(&file_actions);
+
+ if (attr->child_in && (attr->child_in->filedes != -1)) {
+ apr_file_close(attr->child_in);
+ }
+
+ if (attr->child_out && (attr->child_out->filedes != -1)) {
+ apr_file_close(attr->child_out);
+ }
+
+ if (attr->child_err && (attr->child_err->filedes != -1)) {
+ apr_file_close(attr->child_err);
+ }
+
+ return status;
+}
+
APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc,
int *exitcode,
apr_exit_why_e *exitwhy,