📄 mod_cgi.c
字号:
ap_chdir_file(r->filename);#endif if (!cld->debug) ap_error_log2stderr(r->server); /* Transumute outselves into the script. * NB only ISINDEX scripts get decoded arguments. */#ifdef TPF return (0);#else ap_cleanup_for_exec(); child_pid = ap_call_exec(r, pinfo, argv0, env, 0);#if defined(WIN32) || defined(OS2) return (child_pid);#else /* Uh oh. Still here. Where's the kaboom? There was supposed to be an * EARTH-shattering kaboom! * * Oh, well. Muddle through as best we can... * * Note that only stderr is available at this point, so don't pass in * a server to aplog_error. */ ap_log_error(APLOG_MARK, APLOG_ERR, NULL, "exec of %s failed", r->filename); exit(0); /* NOT REACHED */ return (0);#endif#endif /* TPF */}static int cgi_handler(request_rec *r){ int retval, nph, dbpos = 0; char *argv0, *dbuf = NULL; BUFF *script_out, *script_in, *script_err; char argsbuffer[HUGE_STRING_LEN]; int is_included = !strcmp(r->protocol, "INCLUDED"); void *sconf = r->server->module_config; cgi_server_conf *conf = (cgi_server_conf *) ap_get_module_config(sconf, &cgi_module); struct cgi_child_stuff cld; if ((argv0 = strrchr(r->filename, '/')) != NULL) argv0++; else argv0 = r->filename; nph = !(strncmp(argv0, "nph-", 4)); if (!(ap_allow_options(r) & OPT_EXECCGI) && !is_scriptaliased(r)) return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO, "Options ExecCGI is off in this directory"); if (nph && is_included) return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO, "attempt to include NPH CGI script");#if defined(OS2) || defined(WIN32) /* Allow for cgi files without the .EXE extension on them under OS/2 */ if (r->finfo.st_mode == 0) { struct stat statbuf; char *newfile; newfile = ap_pstrcat(r->pool, r->filename, ".EXE", NULL); if ((stat(newfile, &statbuf) != 0) || (!S_ISREG(statbuf.st_mode))) { return log_scripterror(r, conf, NOT_FOUND, 0, "script not found or unable to stat"); } else { r->filename = newfile; } }#else if (r->finfo.st_mode == 0) return log_scripterror(r, conf, NOT_FOUND, APLOG_NOERRNO, "script not found or unable to stat");#endif if (S_ISDIR(r->finfo.st_mode)) return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO, "attempt to invoke directory as script"); if (!ap_suexec_enabled) { if (!ap_can_exec(&r->finfo)) return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO, "file permissions deny server execution"); } if ((retval = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) return retval; ap_add_common_vars(r); cld.argv0 = argv0; cld.r = r; cld.nph = nph; cld.debug = conf->logname ? 1 : 0;#ifdef TPF cld.t.filename = r->filename; cld.t.subprocess_env = r->subprocess_env; cld.t.prog_type = FORK_FILE;#endif /* TPF */#ifdef CHARSET_EBCDIC /* The included MIME headers must ALWAYS be in text/ebcdic format. * Only after reading the MIME headers, we check the Content-Type * and switch to the necessary conversion mode. * Until then (and in case an nph- script was called), use the * configured default conversion: */ ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, r->ebcdic.conv_out);#endif /*CHARSET_EBCDIC*/ /* * we spawn out of r->main if it's there so that we can avoid * waiting for free_proc_chain to cleanup in the middle of an * SSI request -djg */ if (!ap_bspawn_child(r->main ? r->main->pool : r->pool, cgi_child, (void *) &cld, kill_after_timeout, &script_out, &script_in, &script_err)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "couldn't spawn child process: %s", r->filename); return HTTP_INTERNAL_SERVER_ERROR; } /* Transfer any put/post args, CERN style... * Note that we already ignore SIGPIPE in the core server. */ if (ap_should_client_block(r)) { int dbsize, len_read; if (conf->logname) { dbuf = ap_pcalloc(r->pool, conf->bufbytes + 1); dbpos = 0; } ap_hard_timeout("copy script args", r); while ((len_read = ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN)) > 0) { if (conf->logname) { if ((dbpos + len_read) > conf->bufbytes) { dbsize = conf->bufbytes - dbpos; } else { dbsize = len_read; } memcpy(dbuf + dbpos, argsbuffer, dbsize); dbpos += dbsize; } ap_reset_timeout(r); if (ap_bwrite(script_out, argsbuffer, len_read) < len_read) { /* silly script stopped reading, soak up remaining message */ while (ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN) > 0) { /* dump it */ } break; } } ap_bflush(script_out); ap_kill_timeout(r); } ap_bclose(script_out); /* Handle script return... */ if (script_in && !nph) { const char *location; char sbuf[MAX_STRING_LEN]; int ret; if ((ret = ap_scan_script_header_err_buff(r, script_in, sbuf))) { return log_script(r, conf, ret, dbuf, sbuf, script_in, script_err); } location = ap_table_get(r->headers_out, "Location"); if (location && location[0] == '/' && r->status == 200) { /* Soak up all the script output */ ap_hard_timeout("read from script", r); while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0) { continue; }#if defined(WIN32) || defined(NETWARE) /* Soak up stderr and redirect it to the error log. * Script output to stderr is already directed to the error log * on Unix, thanks to the magic of fork(). */ while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) { ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, r, "%s", argsbuffer); }#else while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) { continue; }#endif ap_kill_timeout(r); /* This redirect needs to be a GET no matter what the original * method was. */ r->method = ap_pstrdup(r->pool, "GET"); r->method_number = M_GET; /* We already read the message body (if any), so don't allow * the redirected request to think it has one. We can ignore * Transfer-Encoding, since we used REQUEST_CHUNKED_ERROR. */ ap_table_unset(r->headers_in, "Content-Length"); ap_internal_redirect_handler(location, r); return OK; } else if (location && r->status == 200) { /* XX Note that if a script wants to produce its own Redirect * body, it now has to explicitly *say* "Status: 302" */ return REDIRECT; } ap_send_http_header(r); if (!r->header_only) { ap_send_fb(script_in, r); } ap_bclose(script_in); ap_soft_timeout("soaking script stderr", r);#if defined(WIN32) || defined(NETWARE) /* Script output to stderr is already directed to the error log * on Unix, thanks to the magic of fork(). */ while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) { ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, r, "%s", argsbuffer); }#else while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) { continue; }#endif ap_kill_timeout(r); ap_bclose(script_err); } if (script_in && nph) { ap_send_fb(script_in, r); } return OK; /* NOT r->status, even if it has changed. */}static const handler_rec cgi_handlers[] ={ {CGI_MAGIC_TYPE, cgi_handler}, {"cgi-script", cgi_handler}, {NULL}};module MODULE_VAR_EXPORT cgi_module ={ STANDARD_MODULE_STUFF, NULL, /* initializer */ NULL, /* dir config creater */ NULL, /* dir merger --- default is to override */ create_cgi_config, /* server config */ merge_cgi_config, /* merge server config */ cgi_cmds, /* command table */ cgi_handlers, /* handlers */ NULL, /* filename translation */ NULL, /* check_user_id */ NULL, /* check auth */ NULL, /* check access */ NULL, /* type_checker */ NULL, /* fixups */ NULL, /* logger */ NULL, /* header parser */ NULL, /* child_init */ NULL, /* child_exit */ NULL /* post read-request */};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -