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

📄 mod_cgi.c

📁 linux网络服务器工具
💻 C
📖 第 1 页 / 共 3 页
字号:
                                   e_info->in_pipe,                                   e_info->out_pipe,                                   e_info->err_pipe)) != APR_SUCCESS) ||        ((rc = apr_procattr_dir_set(procattr,                        ap_make_dirstr_parent(r->pool,                                              r->filename))) != APR_SUCCESS) ||#ifdef RLIMIT_CPU        ((rc = apr_procattr_limit_set(procattr, APR_LIMIT_CPU,                                      conf->limit_cpu)) != APR_SUCCESS) ||#endif#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)        ((rc = apr_procattr_limit_set(procattr, APR_LIMIT_MEM,                                      conf->limit_mem)) != APR_SUCCESS) ||#endif#ifdef RLIMIT_NPROC        ((rc = apr_procattr_limit_set(procattr, APR_LIMIT_NPROC,                                      conf->limit_nproc)) != APR_SUCCESS) ||#endif        ((rc = apr_procattr_cmdtype_set(procattr,                                        e_info->cmd_type)) != APR_SUCCESS) ||        ((rc = apr_procattr_detach_set(procattr,                                        e_info->detached)) != APR_SUCCESS) ||        ((rc = apr_procattr_addrspace_set(procattr,                                        e_info->addrspace)) != APR_SUCCESS) ||        ((rc = apr_procattr_child_errfn_set(procattr, cgi_child_errfn)) != APR_SUCCESS)) {        /* Something bad happened, tell the world. */        ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,                      "couldn't set child process attributes: %s", r->filename);    }    else {        procnew = apr_pcalloc(p, sizeof(*procnew));        rc = ap_os_create_privileged_process(r, procnew, command, argv, env,                                             procattr, p);        if (rc != APR_SUCCESS) {            /* Bad things happened. Everyone should have cleaned up. */            ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_TOCLIENT, rc, r,                          "couldn't create child process: %d: %s", rc,                          apr_filepath_name_get(r->filename));        }        else {            apr_pool_note_subprocess(p, procnew, APR_KILL_AFTER_TIMEOUT);            *script_in = procnew->out;            if (!*script_in)                return APR_EBADF;            apr_file_pipe_timeout_set(*script_in, r->server->timeout);            if (e_info->prog_type == RUN_AS_CGI) {                *script_out = procnew->in;                if (!*script_out)                    return APR_EBADF;                apr_file_pipe_timeout_set(*script_out, r->server->timeout);                *script_err = procnew->err;                if (!*script_err)                    return APR_EBADF;                apr_file_pipe_timeout_set(*script_err, r->server->timeout);            }        }    }#ifdef DEBUG_CGI    fclose(dbg);#endif    return (rc);}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;}static void discard_script_output(apr_bucket_brigade *bb){    apr_bucket *e;    const char *buf;    apr_size_t len;    apr_status_t rv;    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) {            break;        }    }}#if APR_FILES_AS_SOCKETS/* A CGI bucket type is needed to catch any output to stderr from the * script; see PR 22030. */static const apr_bucket_type_t bucket_type_cgi;struct cgi_bucket_data {    apr_pollset_t *pollset;    request_rec *r;};/* Create a CGI bucket using pipes from script stdout 'out' * and stderr 'err', for request 'r'. */static apr_bucket *cgi_bucket_create(request_rec *r,                                     apr_file_t *out, apr_file_t *err,                                     apr_bucket_alloc_t *list){    apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);    apr_status_t rv;    apr_pollfd_t fd;    struct cgi_bucket_data *data = apr_palloc(r->pool, sizeof *data);    APR_BUCKET_INIT(b);    b->free = apr_bucket_free;    b->list = list;    b->type = &bucket_type_cgi;    b->length = (apr_size_t)(-1);    b->start = -1;    /* Create the pollset */    rv = apr_pollset_create(&data->pollset, 2, r->pool, 0);    AP_DEBUG_ASSERT(rv == APR_SUCCESS);    fd.desc_type = APR_POLL_FILE;    fd.reqevents = APR_POLLIN;    fd.p = r->pool;    fd.desc.f = out; /* script's stdout */    fd.client_data = (void *)1;    rv = apr_pollset_add(data->pollset, &fd);    AP_DEBUG_ASSERT(rv == APR_SUCCESS);    fd.desc.f = err; /* script's stderr */    fd.client_data = (void *)2;    rv = apr_pollset_add(data->pollset, &fd);    AP_DEBUG_ASSERT(rv == APR_SUCCESS);    data->r = r;    b->data = data;    return b;}/* Create a duplicate CGI bucket using given bucket data */static apr_bucket *cgi_bucket_dup(struct cgi_bucket_data *data,                                  apr_bucket_alloc_t *list){    apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);    APR_BUCKET_INIT(b);    b->free = apr_bucket_free;    b->list = list;    b->type = &bucket_type_cgi;    b->length = (apr_size_t)(-1);    b->start = -1;    b->data = data;    return b;}/* Handle stdout from CGI child.  Duplicate of logic from the _read * method of the real APR pipe bucket implementation. */static apr_status_t cgi_read_stdout(apr_bucket *a, apr_file_t *out,                                    const char **str, apr_size_t *len){    char *buf;    apr_status_t rv;    *str = NULL;    *len = APR_BUCKET_BUFF_SIZE;    buf = apr_bucket_alloc(*len, a->list); /* XXX: check for failure? */    rv = apr_file_read(out, buf, len);    if (rv != APR_SUCCESS && rv != APR_EOF) {        apr_bucket_free(buf);        return rv;    }    if (*len > 0) {        struct cgi_bucket_data *data = a->data;        apr_bucket_heap *h;        /* Change the current bucket to refer to what we read */        a = apr_bucket_heap_make(a, buf, *len, apr_bucket_free);        h = a->data;        h->alloc_len = APR_BUCKET_BUFF_SIZE; /* note the real buffer size */        *str = buf;        APR_BUCKET_INSERT_AFTER(a, cgi_bucket_dup(data, a->list));    }    else {        apr_bucket_free(buf);        a = apr_bucket_immortal_make(a, "", 0);        *str = a->data;    }    return rv;}/* Read method of CGI bucket: polls on stderr and stdout of the child, * sending any stderr output immediately away to the error log. */static apr_status_t cgi_bucket_read(apr_bucket *b, const char **str,                                    apr_size_t *len, apr_read_type_e block){    struct cgi_bucket_data *data = b->data;    apr_interval_time_t timeout;    apr_status_t rv;    int gotdata = 0;    timeout = block == APR_NONBLOCK_READ ? 0 : data->r->server->timeout;    do {        const apr_pollfd_t *results;        apr_int32_t num;        rv = apr_pollset_poll(data->pollset, timeout, &num, &results);        if (APR_STATUS_IS_TIMEUP(rv)) {            if (timeout) {                ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, data->r,                              "Timeout waiting for output from CGI script %s",                              data->r->filename);                return rv;            }            else {                return APR_EAGAIN;            }        }        else if (APR_STATUS_IS_EINTR(rv)) {            continue;        }        else if (rv != APR_SUCCESS) {            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, data->r,                          "poll failed waiting for CGI child");            return rv;        }        for (; num; num--, results++) {            if (results[0].client_data == (void *)1) {                /* stdout */                rv = cgi_read_stdout(b, results[0].desc.f, str, len);                if (APR_STATUS_IS_EOF(rv)) {                    rv = APR_SUCCESS;                }                gotdata = 1;            } else {                /* stderr */                apr_status_t rv2 = log_script_err(data->r, results[0].desc.f);                if (APR_STATUS_IS_EOF(rv2)) {                    apr_pollset_remove(data->pollset, &results[0]);                }            }        }    } while (!gotdata);    return rv;}static const apr_bucket_type_t bucket_type_cgi = {    "CGI", 5, APR_BUCKET_DATA,    apr_bucket_destroy_noop,    cgi_bucket_read,    apr_bucket_setaside_notimpl,    apr_bucket_split_notimpl,    apr_bucket_copy_notimpl};#endifstatic int cgi_handler(request_rec *r){    int nph;    apr_size_t dbpos = 0;    const char *argv0;    const char *command;    const char **argv;    char *dbuf = NULL;    apr_file_t *script_out = NULL, *script_in = NULL, *script_err = NULL;    apr_bucket_brigade *bb;    apr_bucket *b;    int is_included;    int seen_eos, child_stopped_reading;    apr_pool_t *p;    cgi_server_conf *conf;    apr_status_t rv;    cgi_exec_info_t e_info;    conn_rec *c = r->connection;    if(strcmp(r->handler, CGI_MAGIC_TYPE) && strcmp(r->handler, "cgi-script"))        return DECLINED;    is_included = !strcmp(r->protocol, "INCLUDED");    p = r->main ? r->main->pool : r->pool;    argv0 = apr_filepath_name_get(r->filename);    nph = !(strncmp(argv0, "nph-", 4));    conf = ap_get_module_config(r->server->module_config, &cgi_module);    if (!(ap_allow_options(r) & OPT_EXECCGI) && !is_scriptaliased(r))        return log_scripterror(r, conf, HTTP_FORBIDDEN, 0,                               "Options ExecCGI is off in this directory");    if (nph && is_included)        return log_scripterror(r, conf, HTTP_FORBIDDEN, 0,                               "attempt to include NPH CGI script");    if (r->finfo.filetype == 0)        return log_scripterror(r, conf, HTTP_NOT_FOUND, 0,                               "script not found or unable to stat");    if (r->finfo.filetype == APR_DIR)        return log_scripterror(r, conf, HTTP_FORBIDDEN, 0,                               "attempt to invoke directory as script");    if ((r->used_path_info == AP_REQ_REJECT_PATH_INFO) &&        r->path_info && *r->path_info)    {        /* default to accept */        return log_scripterror(r, conf, HTTP_NOT_FOUND, 0,                               "AcceptPathInfo off disallows user's path");    }/*    if (!ap_suexec_enabled) {        if (!ap_can_exec(&r->finfo))            return log_scripterror(r, conf, HTTP_FORBIDDEN, 0,                                   "file permissions deny server execution");    }*/    ap_add_common_vars(r);    ap_add_cgi_vars(r);    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;    e_info.addrspace   = 0;    /* build the command line */    if ((rv = cgi_build_command(&command, &argv, r, p, &e_info)) != APR_SUCCESS) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,                      "don't know how to spawn child process: %s",                      r->filename);        return HTTP_INTERNAL_SERVER_ERROR;    }    /* run the script in its own process */    if ((rv = run_cgi_child(&script_out, &script_in, &script_err,                            command, argv, r, p, &e_info)) != APR_SUCCESS) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, 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.     */    bb = apr_brigade_create(r->pool, c->bucket_alloc);    seen_eos = 0;    child_stopped_reading = 0;    if (conf->logname) {        dbuf = apr_palloc(r->pool, conf->bufbytes + 1);        dbpos = 0;    }    do {        apr_bucket *bucket;        rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,                            APR_BLOCK_READ, HUGE_STRING_LEN);        if (rv != APR_SUCCESS) {            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,                          "Error reading request entity data");            return HTTP_INTERNAL_SERVER_ERROR;        }

⌨️ 快捷键说明

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