⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_cgi.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements.  See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License.  You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * http_script: keeps all script-related ramblings together. * * Compliant to CGI/1.1 spec * * Adapted by rst from original NCSA code by Rob McCool * * Apache adds some new env vars; REDIRECT_URL and REDIRECT_QUERY_STRING for * custom error responses, and DOCUMENT_ROOT because we found it useful. * It also adds SERVER_ADMIN - useful for scripts to know who to mail when * they fail. */#include "apr.h"#include "apr_strings.h"#include "apr_thread_proc.h"    /* for RLIMIT stuff */#include "apr_optional.h"#include "apr_buckets.h"#include "apr_lib.h"#include "apr_poll.h"#define APR_WANT_STRFUNC#define APR_WANT_MEMFUNC#include "apr_want.h"#define CORE_PRIVATE#include "util_filter.h"#include "ap_config.h"#include "httpd.h"#include "http_config.h"#include "http_request.h"#include "http_core.h"#include "http_protocol.h"#include "http_main.h"#include "http_log.h"#include "util_script.h"#include "ap_mpm.h"#include "mod_core.h"#include "mod_cgi.h"module AP_MODULE_DECLARE_DATA cgi_module;static APR_OPTIONAL_FN_TYPE(ap_register_include_handler) *cgi_pfn_reg_with_ssi;static APR_OPTIONAL_FN_TYPE(ap_ssi_get_tag_and_value) *cgi_pfn_gtv;static APR_OPTIONAL_FN_TYPE(ap_ssi_parse_string) *cgi_pfn_ps;static APR_OPTIONAL_FN_TYPE(ap_cgi_build_command) *cgi_build_command;/* Read and discard the data in the brigade produced by a CGI script */static void discard_script_output(apr_bucket_brigade *bb);/* KLUDGE --- for back-combatibility, we don't have to check ExecCGI * in ScriptAliased directories, which means we need to know if this * request came through ScriptAlias or not... so the Alias module * leaves a note for us. */static int is_scriptaliased(request_rec *r){    const char *t = apr_table_get(r->notes, "alias-forced-type");    return t && (!strcasecmp(t, "cgi-script"));}/* Configuration stuff */#define DEFAULT_LOGBYTES 10385760#define DEFAULT_BUFBYTES 1024typedef struct {    const char *logname;    long        logbytes;    apr_size_t  bufbytes;} cgi_server_conf;static void *create_cgi_config(apr_pool_t *p, server_rec *s){    cgi_server_conf *c =    (cgi_server_conf *) apr_pcalloc(p, sizeof(cgi_server_conf));    c->logname = NULL;    c->logbytes = DEFAULT_LOGBYTES;    c->bufbytes = DEFAULT_BUFBYTES;    return c;}static void *merge_cgi_config(apr_pool_t *p, void *basev, void *overridesv){    cgi_server_conf *base = (cgi_server_conf *) basev,                    *overrides = (cgi_server_conf *) overridesv;    return overrides->logname ? overrides : base;}static const char *set_scriptlog(cmd_parms *cmd, void *dummy, const char *arg){    server_rec *s = cmd->server;    cgi_server_conf *conf = ap_get_module_config(s->module_config,                                                 &cgi_module);    conf->logname = ap_server_root_relative(cmd->pool, arg);    if (!conf->logname) {        return apr_pstrcat(cmd->pool, "Invalid ScriptLog path ",                           arg, NULL);    }    return NULL;}static const char *set_scriptlog_length(cmd_parms *cmd, void *dummy,                                        const char *arg){    server_rec *s = cmd->server;    cgi_server_conf *conf = ap_get_module_config(s->module_config,                                                 &cgi_module);    conf->logbytes = atol(arg);    return NULL;}static const char *set_scriptlog_buffer(cmd_parms *cmd, void *dummy,                                        const char *arg){    server_rec *s = cmd->server;    cgi_server_conf *conf = ap_get_module_config(s->module_config,                                                 &cgi_module);    conf->bufbytes = atoi(arg);    return NULL;}static const command_rec cgi_cmds[] ={AP_INIT_TAKE1("ScriptLog", set_scriptlog, NULL, RSRC_CONF,     "the name of a log for script debugging info"),AP_INIT_TAKE1("ScriptLogLength", set_scriptlog_length, NULL, RSRC_CONF,     "the maximum length (in bytes) of the script debug log"),AP_INIT_TAKE1("ScriptLogBuffer", set_scriptlog_buffer, NULL, RSRC_CONF,     "the maximum size (in bytes) to record of a POST request"),    {NULL}};static int log_scripterror(request_rec *r, cgi_server_conf * conf, int ret,                           apr_status_t rv, char *error){    apr_file_t *f = NULL;    apr_finfo_t finfo;    char time_str[APR_CTIME_LEN];    int log_flags = rv ? APLOG_ERR : APLOG_ERR;    ap_log_rerror(APLOG_MARK, log_flags, rv, r,                  "%s: %s", error, r->filename);    /* XXX Very expensive mainline case! Open, then getfileinfo! */    if (!conf->logname ||        ((apr_stat(&finfo, conf->logname,                   APR_FINFO_SIZE, r->pool) == APR_SUCCESS) &&         (finfo.size > conf->logbytes)) ||        (apr_file_open(&f, conf->logname,                       APR_APPEND|APR_WRITE|APR_CREATE, APR_OS_DEFAULT,                       r->pool) != APR_SUCCESS)) {        return ret;    }    /* "%% [Wed Jun 19 10:53:21 1996] GET /cgi-bin/printenv HTTP/1.0" */    apr_ctime(time_str, apr_time_now());    apr_file_printf(f, "%%%% [%s] %s %s%s%s %s\n", time_str, r->method, r->uri,                    r->args ? "?" : "", r->args ? r->args : "", r->protocol);    /* "%% 500 /usr/local/apache/cgi-bin */    apr_file_printf(f, "%%%% %d %s\n", ret, r->filename);    apr_file_printf(f, "%%error\n%s\n", error);    apr_file_close(f);    return ret;}/* Soak up stderr from a script and redirect it to the error log. */static apr_status_t log_script_err(request_rec *r, apr_file_t *script_err){    char argsbuffer[HUGE_STRING_LEN];    char *newline;    apr_status_t rv;    while ((rv = apr_file_gets(argsbuffer, HUGE_STRING_LEN,                               script_err)) == APR_SUCCESS) {        newline = strchr(argsbuffer, '\n');        if (newline) {            *newline = '\0';        }        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                      "%s", argsbuffer);    }    return rv;}static int log_script(request_rec *r, cgi_server_conf * conf, int ret,                      char *dbuf, const char *sbuf, apr_bucket_brigade *bb,                      apr_file_t *script_err){    const apr_array_header_t *hdrs_arr = apr_table_elts(r->headers_in);    const apr_table_entry_t *hdrs = (const apr_table_entry_t *) hdrs_arr->elts;    char argsbuffer[HUGE_STRING_LEN];    apr_file_t *f = NULL;    apr_bucket *e;    const char *buf;    apr_size_t len;    apr_status_t rv;    int first;    int i;    apr_finfo_t finfo;    char time_str[APR_CTIME_LEN];    /* XXX Very expensive mainline case! Open, then getfileinfo! */    if (!conf->logname ||        ((apr_stat(&finfo, conf->logname,                   APR_FINFO_SIZE, r->pool) == APR_SUCCESS) &&         (finfo.size > conf->logbytes)) ||        (apr_file_open(&f, conf->logname,                       APR_APPEND|APR_WRITE|APR_CREATE, APR_OS_DEFAULT,                       r->pool) != APR_SUCCESS)) {        /* Soak up script output */        discard_script_output(bb);        log_script_err(r, script_err);        return ret;    }    /* "%% [Wed Jun 19 10:53:21 1996] GET /cgi-bin/printenv HTTP/1.0" */    apr_ctime(time_str, apr_time_now());    apr_file_printf(f, "%%%% [%s] %s %s%s%s %s\n", time_str, r->method, r->uri,                    r->args ? "?" : "", r->args ? r->args : "", r->protocol);    /* "%% 500 /usr/local/apache/cgi-bin" */    apr_file_printf(f, "%%%% %d %s\n", ret, r->filename);    apr_file_puts("%request\n", f);    for (i = 0; i < hdrs_arr->nelts; ++i) {        if (!hdrs[i].key)            continue;        apr_file_printf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);    }    if ((r->method_number == M_POST || r->method_number == M_PUT) &&        *dbuf) {        apr_file_printf(f, "\n%s\n", dbuf);    }    apr_file_puts("%response\n", f);    hdrs_arr = apr_table_elts(r->err_headers_out);    hdrs = (const apr_table_entry_t *) hdrs_arr->elts;    for (i = 0; i < hdrs_arr->nelts; ++i) {        if (!hdrs[i].key)            continue;        apr_file_printf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);    }    if (sbuf && *sbuf)        apr_file_printf(f, "%s\n", sbuf);    first = 1;    for (e = APR_BRIGADE_FIRST(bb);         e != APR_BRIGADE_SENTINEL(bb);         e = APR_BUCKET_NEXT(e))    {        if (APR_BUCKET_IS_EOS(e)) {            break;        }        rv = apr_bucket_read(e, &buf, &len, APR_BLOCK_READ);        if (rv != APR_SUCCESS || (len == 0)) {            break;        }        if (first) {            apr_file_puts("%stdout\n", f);            first = 0;        }        apr_file_write(f, buf, &len);        apr_file_puts("\n", f);    }    if (apr_file_gets(argsbuffer, HUGE_STRING_LEN, script_err) == APR_SUCCESS) {        apr_file_puts("%stderr\n", f);        apr_file_puts(argsbuffer, f);        while (apr_file_gets(argsbuffer, HUGE_STRING_LEN,                             script_err) == APR_SUCCESS) {            apr_file_puts(argsbuffer, f);        }        apr_file_puts("\n", f);    }    apr_brigade_destroy(bb);    apr_file_close(script_err);    apr_file_close(f);    return ret;}/* 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 void cgi_child_errfn(apr_pool_t *pool, apr_status_t err,                            const char *description){    apr_file_t *stderr_log;    char errbuf[200];    apr_file_open_stderr(&stderr_log, pool);    /* Escape the logged string because it may be something that     * came in over the network.     */    apr_file_printf(stderr_log,                    "(%d)%s: %s\n",                    err,                    apr_strerror(err, errbuf, sizeof(errbuf)),#ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED                    ap_escape_logitem(pool,#endif                    description#ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED                    )#endif                    );}static apr_status_t run_cgi_child(apr_file_t **script_out,                                  apr_file_t **script_in,                                  apr_file_t **script_err,                                  const char *command,                                  const char * const argv[],                                  request_rec *r,                                  apr_pool_t *p,                                  cgi_exec_info_t *e_info){    const char * const *env;    apr_procattr_t *procattr;    apr_proc_t *procnew;    apr_status_t rc = APR_SUCCESS;#if defined(RLIMIT_CPU)  || defined(RLIMIT_NPROC) || \    defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined (RLIMIT_AS)    core_dir_config *conf = ap_get_module_config(r->per_dir_config,                                                 &core_module);#endif#ifdef DEBUG_CGI#ifdef OS2    /* Under OS/2 need to use device con. */    FILE *dbg = fopen("con", "w");#else    FILE *dbg = fopen("/dev/tty", "w");#endif    int i;#endif    RAISE_SIGSTOP(CGI_CHILD);#ifdef DEBUG_CGI    fprintf(dbg, "Attempting to exec %s as CGI child (argv0 = %s)\n",            r->filename, argv[0]);#endif    env = (const char * const *)ap_create_environment(p, r->subprocess_env);#ifdef DEBUG_CGI    fprintf(dbg, "Environment: \n");    for (i = 0; env[i]; ++i)        fprintf(dbg, "'%s'\n", env[i]);#endif    /* Transmute ourselves into the script.     * NB only ISINDEX scripts get decoded arguments.     */    if (((rc = apr_procattr_create(&procattr, p)) != APR_SUCCESS) ||        ((rc = apr_procattr_io_set(procattr,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -