/* Spawn the piped logger process pl->program. */ static apr_status_t piped_log_spawn(piped_log *pl) { apr_procattr_t *procattr; apr_proc_t *procnew = NULL; apr_status_t status; if (((status = apr_procattr_create(&procattr, pl->p)) != APR_SUCCESS) || ((status = apr_procattr_cmdtype_set(procattr, pl->cmdtype)) != APR_SUCCESS) || ((status = apr_procattr_child_in_set(procattr, ap_piped_log_read_fd(pl), ap_piped_log_write_fd(pl))) != APR_SUCCESS) || ((status = apr_procattr_child_errfn_set(procattr, log_child_errfn)) != APR_SUCCESS) || ((status = apr_procattr_error_check_set(procattr, 1)) != APR_SUCCESS)) { char buf[120]; /* Something bad happened, give up and go away. */ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "piped_log_spawn: unable to setup child process '%s': %s", pl->program, apr_strerror(status, buf, sizeof(buf))); } else { char **args; const char *pname; apr_file_t *outfile, *errfile; if ((status = apr_file_open_stdout(&outfile, pl->p)) == APR_SUCCESS) status = apr_procattr_child_out_set(procattr, outfile, NULL); if ((status = apr_file_open_stderr(&errfile, pl->p)) == APR_SUCCESS) status = apr_procattr_child_err_set(procattr, errfile, NULL); apr_tokenize_to_argv(pl->program, &args, pl->p); pname = apr_pstrdup(pl->p, args[0]); procnew = apr_pcalloc(pl->p, sizeof(apr_proc_t)); status = apr_proc_create(procnew, pname, (const char * const *) args, NULL, procattr, pl->p); if (status == APR_SUCCESS) { pl->pid = procnew; /* procnew->in was dup2'd from ap_piped_log_write_fd(pl); * since the original fd is still valid, close the copy to * avoid a leak. */ apr_file_close(procnew->in); procnew->in = NULL; apr_proc_other_child_register(procnew, piped_log_maintenance, pl, ap_piped_log_write_fd(pl), pl->p); close_handle_in_child(pl->p, ap_piped_log_read_fd(pl)); } else { char buf[120]; /* Something bad happened, give up and go away. */ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "unable to start piped log program '%s': %s", pl->program, apr_strerror(status, buf, sizeof(buf))); } } return status; }
AP_DECLARE(piped_log *) ap_open_piped_log_ex(apr_pool_t *p, const char *program, apr_cmdtype_e cmdtype) { piped_log *pl; pl = apr_palloc(p, sizeof (*pl)); pl->p = p; pl->program = apr_pstrdup(p, program); pl->pid = NULL; pl->cmdtype = cmdtype; if (apr_file_pipe_create(&ap_piped_log_read_fd(pl), &ap_piped_log_write_fd(pl), p) != APR_SUCCESS) { return NULL; } apr_pool_cleanup_register(p, pl, piped_log_cleanup, piped_log_cleanup_for_exec); if (piped_log_spawn(pl) != APR_SUCCESS) { apr_pool_cleanup_kill(p, pl, piped_log_cleanup); apr_file_close(ap_piped_log_read_fd(pl)); apr_file_close(ap_piped_log_write_fd(pl)); return NULL; } return pl; }
static apr_status_t piped_log_cleanup_for_exec(void *data) { piped_log *pl = data; apr_file_close(ap_piped_log_read_fd(pl)); apr_file_close(ap_piped_log_write_fd(pl)); return APR_SUCCESS; }
AP_DECLARE(piped_log *) ap_open_piped_log(apr_pool_t *p, const char *program) { piped_log *pl; apr_file_t *dummy = NULL; int rc; rc = log_child(p, program, &dummy, 0); if (rc != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_STARTUP, rc, NULL, "Couldn't start piped log process"); return NULL; } pl = apr_palloc(p, sizeof (*pl)); pl->p = p; ap_piped_log_read_fd(pl) = NULL; ap_piped_log_write_fd(pl) = dummy; apr_pool_cleanup_register(p, pl, piped_log_cleanup, piped_log_cleanup); return pl; }