/* This is the special environment used for running the "exec cmd=" * variety of SSI directives. */ static void add_ssi_vars(request_rec *r) { apr_table_t *e = r->subprocess_env; if (r->path_info && r->path_info[0] != '\0') { request_rec *pa_req; apr_table_setn(e, "PATH_INFO", ap_escape_shell_cmd(r->pool, r->path_info)); pa_req = ap_sub_req_lookup_uri(ap_escape_uri(r->pool, r->path_info), r, NULL); if (pa_req->filename) { apr_table_setn(e, "PATH_TRANSLATED", apr_pstrcat(r->pool, pa_req->filename, pa_req->path_info, NULL)); } ap_destroy_sub_req(pa_req); } if (r->args) { char *arg_copy = apr_pstrdup(r->pool, r->args); apr_table_setn(e, "QUERY_STRING", r->args); ap_unescape_url(arg_copy); apr_table_setn(e, "QUERY_STRING_UNESCAPED", ap_escape_shell_cmd(r->pool, arg_copy)); } }
static apr_status_t default_build_command(const char **cmd, const char ***argv, request_rec *r, apr_pool_t *p, cgi_exec_info_t *e_info) { int numwords, x, idx; char *w; const char *args = NULL; if (e_info->process_cgi) { *cmd = r->filename; /* Do not process r->args if they contain an '=' assignment */ if (r->args && r->args[0] && !ap_strchr_c(r->args, '=')) { args = r->args; } } if (!args) { numwords = 1; } else { /* count the number of keywords */ for (x = 0, numwords = 2; args[x]; x++) { if (args[x] == '+') { ++numwords; } } } /* Everything is - 1 to account for the first parameter * which is the program name. */ if (numwords > APACHE_ARG_MAX - 1) { numwords = APACHE_ARG_MAX - 1; /* Truncate args to prevent overrun */ } *argv = apr_palloc(p, (numwords + 2) * sizeof(char *)); (*argv)[0] = *cmd; for (x = 1, idx = 1; x < numwords; x++) { w = ap_getword_nulls(p, &args, '+'); ap_unescape_url(w); (*argv)[idx++] = ap_escape_shell_cmd(p, w); } (*argv)[idx] = NULL; return APR_SUCCESS; }
/* init_ext_filter_process: get the external filter process going * This is per-filter-instance (i.e., per-request) initialization. */ static apr_status_t init_ext_filter_process(ap_filter_t *f) { ef_ctx_t *ctx = f->ctx; apr_status_t rc; ef_dir_t *dc = ctx->dc; const char * const *env; ctx->proc = apr_pcalloc(ctx->p, sizeof(*ctx->proc)); rc = apr_procattr_create(&ctx->procattr, ctx->p); ap_assert(rc == APR_SUCCESS); rc = apr_procattr_io_set(ctx->procattr, APR_CHILD_BLOCK, APR_CHILD_BLOCK, APR_CHILD_BLOCK); ap_assert(rc == APR_SUCCESS); rc = set_resource_limits(f->r, ctx->procattr); ap_assert(rc == APR_SUCCESS); if (dc->log_stderr > 0) { rc = apr_procattr_child_err_set(ctx->procattr, f->r->server->error_log, /* stderr in child */ NULL); ap_assert(rc == APR_SUCCESS); } rc = apr_procattr_child_errfn_set(ctx->procattr, child_errfn); ap_assert(rc == APR_SUCCESS); apr_pool_userdata_set(f->r, ERRFN_USERDATA_KEY, apr_pool_cleanup_null, ctx->p); rc = apr_procattr_error_check_set(ctx->procattr, 1); if (rc != APR_SUCCESS) { return rc; } /* add standard CGI variables as well as DOCUMENT_URI, DOCUMENT_PATH_INFO, * and QUERY_STRING_UNESCAPED */ ap_add_cgi_vars(f->r); ap_add_common_vars(f->r); apr_table_setn(f->r->subprocess_env, "DOCUMENT_URI", f->r->uri); apr_table_setn(f->r->subprocess_env, "DOCUMENT_PATH_INFO", f->r->path_info); if (f->r->args) { /* QUERY_STRING is added by ap_add_cgi_vars */ char *arg_copy = apr_pstrdup(f->r->pool, f->r->args); ap_unescape_url(arg_copy); apr_table_setn(f->r->subprocess_env, "QUERY_STRING_UNESCAPED", ap_escape_shell_cmd(f->r->pool, arg_copy)); } env = (const char * const *) ap_create_environment(ctx->p, f->r->subprocess_env); rc = apr_proc_create(ctx->proc, ctx->filter->command, (const char * const *)ctx->filter->args, env, /* environment */ ctx->procattr, ctx->p); if (rc != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, f->r, "couldn't create child process to run `%s'", ctx->filter->command); return rc; } apr_pool_note_subprocess(ctx->p, ctx->proc, APR_KILL_AFTER_TIMEOUT); /* We don't want the handle to the child's stdin inherited by any * other processes created by httpd. Otherwise, when we close our * handle, the child won't see EOF because another handle will still * be open. */ apr_pool_cleanup_register(ctx->p, ctx->proc->in, apr_pool_cleanup_null, /* other mechanism */ ef_close_file); #if APR_FILES_AS_SOCKETS { apr_pollfd_t pfd = { 0 }; rc = apr_pollset_create(&ctx->pollset, 2, ctx->p, 0); ap_assert(rc == APR_SUCCESS); pfd.p = ctx->p; pfd.desc_type = APR_POLL_FILE; pfd.reqevents = APR_POLLOUT; pfd.desc.f = ctx->proc->in; rc = apr_pollset_add(ctx->pollset, &pfd); ap_assert(rc == APR_SUCCESS); pfd.reqevents = APR_POLLIN; pfd.desc.f = ctx->proc->out; rc = apr_pollset_add(ctx->pollset, &pfd); ap_assert(rc == APR_SUCCESS); } #endif return APR_SUCCESS; }