1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "apr_arch_threadproc.h"
18 #include "apr_strings.h"
26 APR_DECLARE(apr_status_t) apr_procattr_create(apr_procattr_t **new, apr_pool_t *pool)
28 (*new) = (apr_procattr_t *)apr_palloc(pool,
29 sizeof(apr_procattr_t));
35 (*new)->parent_in = NULL;
36 (*new)->child_in = NULL;
37 (*new)->parent_out = NULL;
38 (*new)->child_out = NULL;
39 (*new)->parent_err = NULL;
40 (*new)->child_err = NULL;
41 (*new)->currdir = NULL;
42 (*new)->cmdtype = APR_PROGRAM;
47 APR_DECLARE(apr_status_t) apr_procattr_io_set(apr_procattr_t *attr, apr_int32_t in,
48 apr_int32_t out, apr_int32_t err)
52 if ((status = apr_file_pipe_create(&attr->child_in, &attr->parent_in,
53 attr->pool)) != APR_SUCCESS) {
58 apr_file_pipe_timeout_set(attr->child_in, -1);
59 apr_file_pipe_timeout_set(attr->parent_in, -1);
61 case APR_PARENT_BLOCK:
62 apr_file_pipe_timeout_set(attr->child_in, -1);
65 apr_file_pipe_timeout_set(attr->parent_in, -1);
72 if ((status = apr_file_pipe_create(&attr->parent_out, &attr->child_out,
73 attr->pool)) != APR_SUCCESS) {
78 apr_file_pipe_timeout_set(attr->child_out, -1);
79 apr_file_pipe_timeout_set(attr->parent_out, -1);
81 case APR_PARENT_BLOCK:
82 apr_file_pipe_timeout_set(attr->child_out, -1);
85 apr_file_pipe_timeout_set(attr->parent_out, -1);
92 if ((status = apr_file_pipe_create(&attr->parent_err, &attr->child_err,
93 attr->pool)) != APR_SUCCESS) {
98 apr_file_pipe_timeout_set(attr->child_err, -1);
99 apr_file_pipe_timeout_set(attr->parent_err, -1);
101 case APR_PARENT_BLOCK:
102 apr_file_pipe_timeout_set(attr->child_err, -1);
104 case APR_CHILD_BLOCK:
105 apr_file_pipe_timeout_set(attr->parent_err, -1);
114 APR_DECLARE(apr_status_t) apr_procattr_dir_set(apr_procattr_t *attr,
119 cwd = (char*)malloc(sizeof(char) * PATH_MAX);
120 getcwd(cwd, PATH_MAX);
121 attr->currdir = (char *)apr_pstrcat(attr->pool, cwd, "/", dir, NULL);
124 attr->currdir = (char *)apr_pstrdup(attr->pool, dir);
132 APR_DECLARE(apr_status_t) apr_procattr_cmdtype_set(apr_procattr_t *attr,
139 APR_DECLARE(apr_status_t) apr_procattr_detach_set(apr_procattr_t *attr, apr_int32_t detach)
141 attr->detached = detach;
145 APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *pool)
149 if ((pid = fork()) < 0) {
166 APR_DECLARE(apr_status_t) apr_procattr_child_errfn_set(apr_procattr_t *attr,
167 apr_child_errfn_t *errfn)
169 /* won't ever be called on this platform, so don't save the function pointer */
173 APR_DECLARE(apr_status_t) apr_procattr_error_check_set(apr_procattr_t *attr,
176 /* won't ever be used on this platform, so don't save the flag */
180 APR_DECLARE(apr_status_t) apr_procattr_addrspace_set(apr_procattr_t *attr,
181 apr_int32_t addrspace)
183 /* won't ever be used on this platform, so don't save the flag */
187 APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new, const char *progname,
188 const char * const *args,
189 const char * const *env,
190 apr_procattr_t *attr, apr_pool_t *pool)
193 char **newargs = NULL;
194 thread_id newproc, sender;
195 struct send_pipe *sp;
198 sp = (struct send_pipe *)apr_palloc(pool, sizeof(struct send_pipe));
200 new->in = attr->parent_in;
201 new->err = attr->parent_err;
202 new->out = attr->parent_out;
203 sp->in = attr->child_in ? attr->child_in->filedes : -1;
204 sp->out = attr->child_out ? attr->child_out->filedes : -1;
205 sp->err = attr->child_err ? attr->child_err->filedes : -1;
208 while (args && args[i]) {
212 newargs = (char**)malloc(sizeof(char *) * (i + 4));
213 newargs[0] = strdup("/boot/home/config/bin/apr_proc_stub");
214 if (attr->currdir == NULL) {
215 /* we require the directory , so use a temp. variable */
216 dir = malloc(sizeof(char) * PATH_MAX);
217 getcwd(dir, PATH_MAX);
218 newargs[1] = strdup(dir);
221 newargs[1] = strdup(attr->currdir);
223 newargs[2] = strdup(progname);
226 while (args && args[i]) {
227 newargs[nargs] = strdup(args[i]);
230 newargs[nargs] = NULL;
232 /* ### we should be looking at attr->cmdtype in here... */
234 newproc = load_image(nargs, (const char**)newargs, (const char**)env);
236 /* load_image copies the data so now we can free it... */
238 free (newargs[nargs]);
241 if ( newproc < B_NO_ERROR) {
245 resume_thread(newproc);
247 if (attr->child_in) {
248 apr_file_close(attr->child_in);
250 if (attr->child_out) {
251 apr_file_close(attr->child_out);
253 if (attr->child_err) {
254 apr_file_close(attr->child_err);
257 send_data(newproc, 0, (void*)sp, sizeof(struct send_pipe));
260 /* before we go charging on we need the new process to get to a
261 * certain point. When it gets there it'll let us know and we
263 receive_data(&sender, (void*)NULL,0);
268 APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc,
270 apr_exit_why_e *exitwhy,
271 apr_wait_how_e waithow,
275 return apr_proc_wait(proc, exitcode, exitwhy, waithow);
278 APR_DECLARE(apr_status_t) apr_proc_wait(apr_proc_t *proc,
280 apr_exit_why_e *exitwhy,
281 apr_wait_how_e waithow)
284 int waitpid_options = WUNTRACED;
287 apr_exit_why_e ignorewhy;
289 if (exitcode == NULL) {
292 if (exitwhy == NULL) {
293 exitwhy = &ignorewhy;
296 if (waithow != APR_WAIT) {
297 waitpid_options |= WNOHANG;
300 if ((pstatus = waitpid(proc->pid, &exit_int, waitpid_options)) > 0) {
302 if (WIFEXITED(exit_int)) {
303 *exitwhy = APR_PROC_EXIT;
304 *exitcode = WEXITSTATUS(exit_int);
306 else if (WIFSIGNALED(exit_int)) {
307 *exitwhy = APR_PROC_SIGNAL;
308 *exitcode = WTERMSIG(exit_int);
311 /* unexpected condition */
314 return APR_CHILD_DONE;
316 else if (pstatus == 0) {
317 return APR_CHILD_NOTDONE;
322 APR_DECLARE(apr_status_t) apr_procattr_child_in_set(apr_procattr_t *attr, apr_file_t *child_in,
323 apr_file_t *parent_in)
325 if (attr->child_in == NULL && attr->parent_in == NULL)
326 apr_file_pipe_create(&attr->child_in, &attr->parent_in, attr->pool);
328 if (child_in != NULL)
329 apr_file_dup(&attr->child_in, child_in, attr->pool);
331 if (parent_in != NULL)
332 apr_file_dup(&attr->parent_in, parent_in, attr->pool);
337 APR_DECLARE(apr_status_t) apr_procattr_child_out_set(apr_procattr_t *attr, apr_file_t *child_out,
338 apr_file_t *parent_out)
340 if (attr->child_out == NULL && attr->parent_out == NULL)
341 apr_file_pipe_create(&attr->child_out, &attr->parent_out, attr->pool);
343 if (child_out != NULL)
344 apr_file_dup(&attr->child_out, child_out, attr->pool);
346 if (parent_out != NULL)
347 apr_file_dup(&attr->parent_out, parent_out, attr->pool);
352 APR_DECLARE(apr_status_t) apr_procattr_child_err_set(apr_procattr_t *attr, apr_file_t *child_err,
353 apr_file_t *parent_err)
355 if (attr->child_err == NULL && attr->parent_err == NULL)
356 apr_file_pipe_create(&attr->child_err, &attr->parent_err, attr->pool);
358 if (child_err != NULL)
359 apr_file_dup(&attr->child_err, child_err, attr->pool);
361 if (parent_err != NULL)
362 apr_file_dup(&attr->parent_err, parent_err, attr->pool);
367 APR_DECLARE(apr_status_t) apr_procattr_limit_set(apr_procattr_t *attr, apr_int32_t what,