in modules/fcgid/mod_fcgid.c [182:292]
static int fcgid_handler(request_rec * r)
{
cgi_exec_info_t e_info;
const char *command;
const char **argv;
apr_status_t rv;
int http_retcode;
fcgid_cmd_conf *wrapper_conf;
if (strcmp(r->handler, "fcgid-script"))
return DECLINED;
if (!(ap_allow_options(r) & OPT_EXECCGI) && !is_scriptaliased(r))
return HTTP_FORBIDDEN;
if ((r->used_path_info == AP_REQ_REJECT_PATH_INFO) &&
r->path_info && *r->path_info)
return HTTP_NOT_FOUND;
e_info.process_cgi = 1;
e_info.cmd_type = APR_PROGRAM;
e_info.detached = 0;
e_info.in_pipe = APR_CHILD_BLOCK;
e_info.out_pipe = APR_CHILD_BLOCK;
e_info.err_pipe = APR_CHILD_BLOCK;
e_info.prog_type = RUN_AS_CGI;
e_info.bb = NULL;
e_info.ctx = NULL;
e_info.next = NULL;
wrapper_conf = get_wrapper_info(r->filename, r);
/* Check for existence of requested file, unless we use a virtual wrapper. */
if (wrapper_conf == NULL || !wrapper_conf->virtual) {
if (r->finfo.filetype == 0)
return HTTP_NOT_FOUND;
if (r->finfo.filetype == APR_DIR)
return HTTP_FORBIDDEN;
}
/* Build the command line */
if (wrapper_conf) {
if ((rv =
default_build_command(&command, &argv, r, r->pool,
&e_info)) != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
"mod_fcgid: don't know how to spawn wrapper child process: %s",
r->filename);
return HTTP_INTERNAL_SERVER_ERROR;
}
} else {
if ((rv = cgi_build_command(&command, &argv, r, r->pool,
&e_info)) != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
"mod_fcgid: don't know how to spawn child process: %s",
r->filename);
return HTTP_INTERNAL_SERVER_ERROR;
}
/* Check request like "http://localhost/cgi-bin/a.exe/defghi" */
if (r->finfo.inode == 0 && r->finfo.device == 0) {
if ((rv =
apr_stat(&r->finfo, command, APR_FINFO_IDENT,
r->pool)) != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_WARNING, rv, r,
"mod_fcgid: can't get %s file info", command);
return HTTP_NOT_FOUND;
}
}
/* Dummy up a wrapper configuration, using the requested file as
* both the executable path and command-line.
*/
wrapper_conf = apr_pcalloc(r->pool, sizeof(*wrapper_conf));
if (strlen(command) >= fcgid_min(FCGID_PATH_MAX, FCGID_CMDLINE_MAX)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"mod_fcgid: Executable path length exceeds compiled-in limit: %s",
command);
return HTTP_INTERNAL_SERVER_ERROR;
}
wrapper_conf->cgipath = apr_pstrdup(r->pool, command);
wrapper_conf->cmdline = wrapper_conf->cgipath;
wrapper_conf->inode = r->finfo.inode;
wrapper_conf->deviceid = r->finfo.device;
}
ap_add_common_vars(r);
ap_add_cgi_vars(r);
fcgid_add_cgi_vars(r);
/* Remove hop-by-hop headers handled by http
*/
apr_table_unset(r->subprocess_env, "HTTP_KEEP_ALIVE");
apr_table_unset(r->subprocess_env, "HTTP_TE");
apr_table_unset(r->subprocess_env, "HTTP_TRAILER");
apr_table_unset(r->subprocess_env, "HTTP_TRANSFER_ENCODING");
apr_table_unset(r->subprocess_env, "HTTP_UPGRADE");
/* Connection hop-by-hop header to prevent the CGI from hanging */
apr_table_set(r->subprocess_env, "HTTP_CONNECTION", "close");
/* Insert output filter */
ap_add_output_filter_handle(fcgid_filter_handle, NULL, r,
r->connection);
http_retcode = bridge_request(r, FCGI_RESPONDER, wrapper_conf);
return (http_retcode == HTTP_OK ? OK : http_retcode);
}