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

📄 mod_cgid.c

📁 Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相兼容的web服务器.这里给出的是Apache HTTP服务器的源码。
💻 C
📖 第 1 页 / 共 4 页
字号:
    req.req_type = req_type;    req.conn_id = r->connection->id;    req.core_module_index = core_module.module_index;    if (suexec_mod) {        req.have_suexec = 1;        req.suexec_module_index = suexec_mod->module_index;        suexec_cfg = ap_get_module_config(r->per_dir_config,                                          suexec_mod);        req.suexec_cfg = *suexec_cfg;    }    for (req.env_count = 0; env[req.env_count]; req.env_count++) {        continue;     }    req.filename_len = strlen(r->filename);    req.argv0_len = strlen(argv0);    req.uri_len = strlen(r->uri);    req.args_len = r->args ? strlen(r->args) : 0;    user = (const char *)apr_table_get(r->notes, "mod_userdir_user");    if (user != NULL) {        req.mod_userdir_user_len = strlen(user);    }    req.loglevel = r->server->loglevel;    /* Write the request header */    if ((stat = sock_write(fd, &req, sizeof(req))) != APR_SUCCESS) {        return stat;    }    /* Write filename, argv0, uri, and args */    if ((stat = sock_write(fd, r->filename, req.filename_len)) != APR_SUCCESS ||        (stat = sock_write(fd, argv0, req.argv0_len)) != APR_SUCCESS ||        (stat = sock_write(fd, r->uri, req.uri_len)) != APR_SUCCESS) {        return stat;    }    if (req.args_len) {        if ((stat = sock_write(fd, r->args, req.args_len)) != APR_SUCCESS) {            return stat;        }    }    /* write the environment variables */    for (i = 0; i < req.env_count; i++) {        apr_size_t curlen = strlen(env[i]);        if ((stat = sock_write(fd, &curlen, sizeof(curlen))) != APR_SUCCESS) {            return stat;        }                    if ((stat = sock_write(fd, env[i], curlen)) != APR_SUCCESS) {            return stat;        }    }    /* send a minimal notes table */    if (user) {        if ((stat = sock_write(fd, user, req.mod_userdir_user_len)) != APR_SUCCESS) {            return stat;        }    }#if 0#ifdef RLIMIT_CPU     if (conf->limit_cpu) {         len = 1;         stat = sock_write(fd, &len, sizeof(int));         stat = sock_write(fd, conf->limit_cpu, sizeof(struct rlimit));     }     else {         len = 0;         stat = sock_write(fd, &len, sizeof(int));     } #endif #if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)     if (conf->limit_mem) {         len = 1;         stat = sock_write(fd, &len, sizeof(int));         stat = sock_write(fd, conf->limit_mem, sizeof(struct rlimit));     }     else {         len = 0;         stat = sock_write(fd, &len, sizeof(int));     } #endif   #ifdef RLIMIT_NPROC     if (conf->limit_nproc) {         len = 1;         stat = sock_write(fd, &len, sizeof(int));         stat = sock_write(fd, conf->limit_nproc, sizeof(struct rlimit));     }     else {         len = 0;         stat = sock_write(fd, &len, sizeof(int));     } #endif#endif    return APR_SUCCESS;} static void daemon_signal_handler(int sig){    if (sig == SIGHUP) {        ++daemon_should_exit;    }}static void cgid_child_errfn(apr_pool_t *pool, apr_status_t err,                             const char *description){    request_rec *r;    void *vr;    apr_pool_userdata_get(&vr, ERRFN_USERDATA_KEY, pool);    r = vr;    /* sure we got r, but don't call ap_log_rerror() because we don't     * have r->headers_in and possibly other storage referenced by     * ap_log_rerror()     */    ap_log_error(APLOG_MARK, APLOG_ERR, err, r->server, "%s", #ifdef AP_UNSAFE_ERROR_LOG_UNESCAPED                 description#else                 ap_escape_logitem(pool, description)#endif                 );}static int cgid_server(void *data) {     struct sockaddr_un unix_addr;    int sd, sd2, rc;    mode_t omask;    apr_socklen_t len;    apr_pool_t *ptrans;    server_rec *main_server = data;    cgid_server_conf *sconf = ap_get_module_config(main_server->module_config,                                                   &cgid_module);     apr_hash_t *script_hash = apr_hash_make(pcgi);    apr_pool_create(&ptrans, pcgi);     apr_signal(SIGCHLD, SIG_IGN);     apr_signal(SIGHUP, daemon_signal_handler);    if (unlink(sconf->sockname) < 0 && errno != ENOENT) {        ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server,                     "Couldn't unlink unix domain socket %s",                     sconf->sockname);        /* just a warning; don't bail out */    }    if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {        ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server,                      "Couldn't create unix domain socket");        return errno;    }     memset(&unix_addr, 0, sizeof(unix_addr));    unix_addr.sun_family = AF_UNIX;    strcpy(unix_addr.sun_path, sconf->sockname);    omask = umask(0077); /* so that only Apache can use socket */    rc = bind(sd, (struct sockaddr *)&unix_addr, sizeof(unix_addr));    umask(omask); /* can't fail, so can't clobber errno */    if (rc < 0) {        ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server,                      "Couldn't bind unix domain socket %s",                     sconf->sockname);         return errno;    }     if (listen(sd, DEFAULT_CGID_LISTENBACKLOG) < 0) {        ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server,                      "Couldn't listen on unix domain socket");         return errno;    }     if (!geteuid()) {        if (chown(sconf->sockname, unixd_config.user_id, -1) < 0) {            ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server,                          "Couldn't change owner of unix domain socket %s",                         sconf->sockname);             return errno;        }    }        unixd_setup_child(); /* if running as root, switch to configured user/group */    while (!daemon_should_exit) {        int errfileno = STDERR_FILENO;        char *argv0;         char **env;         const char * const *argv;         apr_int32_t in_pipe;        apr_int32_t out_pipe;        apr_int32_t err_pipe;        apr_cmdtype_e cmd_type;        request_rec *r;        apr_procattr_t *procattr = NULL;        apr_proc_t *procnew = NULL;        apr_file_t *inout;        cgid_req_t cgid_req;        apr_status_t stat;        apr_pool_clear(ptrans);        len = sizeof(unix_addr);        sd2 = accept(sd, (struct sockaddr *)&unix_addr, &len);        if (sd2 < 0) {            if (errno != EINTR) {                ap_log_error(APLOG_MARK, APLOG_ERR, errno,                              (server_rec *)data,                             "Error accepting on cgid socket");            }            continue;        }               r = apr_pcalloc(ptrans, sizeof(request_rec));         procnew = apr_pcalloc(ptrans, sizeof(*procnew));        r->pool = ptrans;         stat = get_req(sd2, r, &argv0, &env, &cgid_req);         if (stat != APR_SUCCESS) {            ap_log_error(APLOG_MARK, APLOG_ERR, stat,                         main_server,                         "Error reading request on cgid socket");            close(sd2);            continue;        }        if (cgid_req.req_type == GETPID_REQ) {            pid_t pid;            pid = (pid_t)apr_hash_get(script_hash, &cgid_req.conn_id, sizeof(cgid_req.conn_id));            if (write(sd2, &pid, sizeof(pid)) != sizeof(pid)) {                ap_log_error(APLOG_MARK, APLOG_ERR, 0,                             main_server,                             "Error writing pid %" APR_PID_T_FMT " to handler", pid);            }            close(sd2);            continue;        }        apr_os_file_put(&r->server->error_log, &errfileno, 0, r->pool);        apr_os_file_put(&inout, &sd2, 0, r->pool);        if (cgid_req.req_type == SSI_REQ) {            in_pipe  = APR_NO_PIPE;            out_pipe = APR_FULL_BLOCK;            err_pipe = APR_NO_PIPE;            cmd_type = APR_SHELLCMD;        }        else {            in_pipe  = APR_CHILD_BLOCK;            out_pipe = APR_CHILD_BLOCK;            err_pipe = APR_CHILD_BLOCK;            cmd_type = APR_PROGRAM;        }        if (((rc = apr_procattr_create(&procattr, ptrans)) != APR_SUCCESS) ||            ((cgid_req.req_type == CGI_REQ) &&              (((rc = apr_procattr_io_set(procattr,                                        in_pipe,                                        out_pipe,                                        err_pipe)) != APR_SUCCESS) ||              /* XXX apr_procattr_child_*_set() is creating an unnecessary                * pipe between this process and the child being created...               * It is cleaned up with the temporary pool for this request.               */              ((rc = apr_procattr_child_err_set(procattr, r->server->error_log, NULL)) != APR_SUCCESS) ||              ((rc = apr_procattr_child_in_set(procattr, inout, NULL)) != APR_SUCCESS))) ||            ((rc = apr_procattr_child_out_set(procattr, inout, NULL)) != APR_SUCCESS) ||            ((rc = apr_procattr_dir_set(procattr,                                  ap_make_dirstr_parent(r->pool, r->filename))) != APR_SUCCESS) ||            ((rc = apr_procattr_cmdtype_set(procattr, cmd_type)) != APR_SUCCESS) ||            ((rc = apr_procattr_child_errfn_set(procattr, cgid_child_errfn)) != APR_SUCCESS)) {            /* Something bad happened, tell the world.             * ap_log_rerror() won't work because the header table used by             * ap_log_rerror() hasn't been replicated in the phony r             */            ap_log_error(APLOG_MARK, APLOG_ERR, rc, r->server,                         "couldn't set child process attributes: %s", r->filename);        }        else {            apr_pool_userdata_set(r, ERRFN_USERDATA_KEY, apr_pool_cleanup_null, ptrans);            argv = (const char * const *)create_argv(r->pool, NULL, NULL, NULL, argv0, r->args);           /* We want to close sd2 for the new CGI process too.            * If it is left open it'll make ap_pass_brigade() block            * waiting for EOF if CGI forked something running long.            * close(sd2) here should be okay, as CGI channel            * is already dup()ed by apr_procattr_child_{in,out}_set()            * above.            */            close(sd2);            rc = ap_os_create_privileged_process(r, procnew, argv0, argv,                                                  (const char * const *)env,                                                  procattr, ptrans);            if (rc != APR_SUCCESS) {                /* Bad things happened. Everyone should have cleaned up.                 * ap_log_rerror() won't work because the header table used by                 * ap_log_rerror() hasn't been replicated in the phony r                 */                ap_log_error(APLOG_MARK, APLOG_ERR, rc, r->server,                             "couldn't create child process: %d: %s", rc,                              apr_filename_of_pathname(r->filename));            }            else {                /* We don't want to leak storage for the key, so only allocate                 * a key if the key doesn't exist yet in the hash; there are                 * only a limited number of possible keys (one for each                 * possible thread in the server), so we can allocate a copy                 * of the key the first time a thread has a cgid request.                 * Note that apr_hash_set() only uses the storage passed in                 * for the key if it is adding the key to the hash for the                 * first time; new key storage isn't needed for replacing the                 * existing value of a key.                 */                void *key;                if (apr_hash_get(script_hash, &cgid_req.conn_id, sizeof(cgid_req.conn_id))) {                    key = &cgid_req.conn_id;                }                else {                    key = apr_pcalloc(pcgi, sizeof(cgid_req.conn_id));                    memcpy(key, &cgid_req.conn_id, sizeof(cgid_req.conn_id));                }                apr_hash_set(script_hash, key, sizeof(cgid_req.conn_id),                             (void *)procnew->pid);            }        }    }     return -1; } static int cgid_start(apr_pool_t *p, server_rec *main_server,                      apr_proc_t *procnew){    daemon_should_exit = 0; /* clear setting from previous generation */    if ((daemon_pid = fork()) < 0) {        ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server,                     "mod_cgid: Couldn't spawn cgid daemon process");        return DECLINED;    }    else if (daemon_pid == 0) {        if (pcgi == NULL) {            apr_pool_create(&pcgi, p);        }        cgid_server(main_server);        exit(-1);    }    procnew->pid = daemon_pid;    procnew->err = procnew->in = procnew->out = NULL;    apr_pool_note_subprocess(p, procnew, APR_KILL_AFTER_TIMEOUT);#if APR_HAS_OTHER_CHILD    apr_proc_other_child_register(procnew, cgid_maint, procnew, NULL, p);#endif    return OK;}static int cgid_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,                      server_rec *main_server) {     apr_proc_t *procnew = NULL;    int first_time = 0;    const char *userdata_key = "cgid_init";    module **m;    int ret = OK;    root_server = main_server;    root_pool = p;    apr_pool_userdata_get((void **)&procnew, userdata_key, main_server->process->pool);    if (!procnew) {        first_time = 1;        procnew = apr_pcalloc(main_server->process->pool, sizeof(*procnew));        procnew->pid = -1;        procnew->err = procnew->in = procnew->out = NULL;        apr_pool_userdata_set((const void *)procnew, userdata_key,                     apr_pool_cleanup_null, main_server->process->pool);    }    if (!first_time) {        total_modules = 0;        for (m = ap_preloaded_modules; *m != NULL; m++)            total_modules++;        ret = cgid_start(p, main_server, procnew);        if (ret != OK ) {            return ret;        }        cgid_pfn_reg_with_ssi = APR_RETRIEVE_OPTIONAL_FN(ap_register_include_handler);        cgid_pfn_gtv          = APR_RETRIEVE_OPTIONAL_FN(ap_ssi_get_tag_and_value);        cgid_pfn_ps           = APR_RETRIEVE_OPTIONAL_FN(ap_ssi_parse_string);        if ((cgid_pfn_reg_with_ssi) && (cgid_pfn_gtv) && (cgid_pfn_ps)) {            /* Required by mod_include filter. This is how mod_cgid registers             *   with mod_include to provide processing of the exec directive.             */            cgid_pfn_reg_with_ssi("exec", handle_exec);        }    }    return ret;} static void *create_cgid_config(apr_pool_t *p, server_rec *s) {     cgid_server_conf *c =     (cgid_server_conf *) apr_pcalloc(p, sizeof(cgid_server_conf));     c->logname = NULL;     c->logbytes = DEFAULT_LOGBYTES;     c->bufbytes = DEFAULT_BUFBYTES;     c->sockname = ap_server_root_relative(p, DEFAULT_SOCKET);     return c; } static void *merge_cgid_config(apr_pool_t *p, void *basev, void *overridesv) {     cgid_server_conf *base = (cgid_server_conf *) basev, *overrides = (cgid_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;     cgid_server_conf *conf = ap_get_module_config(s->module_config,                                                  &cgid_module);     conf->logname = ap_server_root_relative(cmd->pool, arg);    if (!conf->logname) {        return apr_pstrcat(cmd->pool, "Invalid ScriptLog path ",                           arg, NULL);    }

⌨️ 快捷键说明

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