1--- threadproc/unix/proc.c.orig	2007-10-14 11:00:37.000000000 -0700
2+++ threadproc/unix/proc.c	2009-04-06 12:34:57.000000000 -0700
3@@ -20,6 +20,9 @@
4 #include "apr_signal.h"
5 #include "apr_random.h"
6 
7+#include <crt_externs.h>
8+#include <spawn.h>
9+
10 /* Heavy on no'ops, here's what we want to pass if there is APR_NO_FILE
11  * requested for a specific child handle;
12  */
13@@ -599,6 +602,84 @@
14     return APR_SUCCESS;
15 }
16 
17+APR_DECLARE(apr_status_t) apr_proc_spawn(apr_proc_t *new,
18+                                          const char *progname,
19+                                          const char * const *args,
20+                                          const char * const *env,
21+                                          apr_procattr_t *attr,
22+                                          apr_pool_t *pool)
23+{
24+    posix_spawn_file_actions_t file_actions;
25+    int status = APR_EGENERAL;
26+
27+    new->in = attr->parent_in;
28+    new->err = attr->parent_err;
29+    new->out = attr->parent_out;
30+
31+    // XXX: attr->errchk
32+
33+    // XXX: Are those apr_pool_cleanup_* calls needed?
34+
35+    posix_spawn_file_actions_init(&file_actions);
36+
37+    if ((attr->child_in) && (attr->child_in->filedes == -1)) {
38+        posix_spawn_file_actions_addclose(&file_actions, STDIN_FILENO);
39+    }
40+    else if (attr->child_in) {
41+        posix_spawn_file_actions_adddup2(&file_actions, attr->child_in->filedes, STDIN_FILENO);
42+        posix_spawn_file_actions_addclose(&file_actions, attr->child_in->filedes);
43+    }
44+
45+    if ((attr->child_out) && (attr->child_out->filedes == -1)) {
46+        posix_spawn_file_actions_addclose(&file_actions, STDOUT_FILENO);
47+    }
48+    else if (attr->child_out) {
49+        posix_spawn_file_actions_adddup2(&file_actions, attr->child_out->filedes, STDOUT_FILENO);
50+        posix_spawn_file_actions_addclose(&file_actions, attr->child_out->filedes);
51+    }
52+
53+    if ((attr->child_err) && (attr->child_err->filedes == -1)) {
54+        posix_spawn_file_actions_addclose(&file_actions, STDERR_FILENO);
55+    }
56+    else if (attr->child_err) {
57+        posix_spawn_file_actions_adddup2(&file_actions, attr->child_err->filedes, STDERR_FILENO);
58+        posix_spawn_file_actions_addclose(&file_actions, attr->child_err->filedes);
59+    }
60+
61+    // XXX: signal
62+    // XXX: currdir, gid, uid, limit_proc
63+
64+    /* Only support APR_PROGRAM_PATH for now. */
65+    if (attr->cmdtype == APR_PROGRAM_PATH) {
66+        /* Pass existing environment; as documented, APR_PROGRAM_PATH ignores the env argument. */
67+        status = posix_spawnp(&new->pid, progname, &file_actions, NULL, args, (const char **)*_NSGetEnviron());
68+        if (status != 0) {
69+            if (attr->errfn) {
70+                char *desc;
71+
72+                desc = apr_psprintf(pool, "posix_spawn of '%s' failed", progname);
73+                attr->errfn(pool, status, desc);
74+            }
75+        }
76+    }
77+
78+    posix_spawn_file_actions_destroy(&file_actions);
79+
80+    if (attr->child_in && (attr->child_in->filedes != -1)) {
81+        apr_file_close(attr->child_in);
82+    }
83+
84+    if (attr->child_out && (attr->child_out->filedes != -1)) {
85+        apr_file_close(attr->child_out);
86+    }
87+
88+    if (attr->child_err && (attr->child_err->filedes != -1)) {
89+        apr_file_close(attr->child_err);
90+    }
91+
92+    return status;
93+}
94+
95 APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc,
96                                                   int *exitcode,
97                                                   apr_exit_why_e *exitwhy,
98