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

📄 mod_cgid.c

📁 最新apache的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
    return NULL; } static const char *set_scriptlog_length(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->logbytes = atol(arg);     return NULL; } static const char *set_scriptlog_buffer(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->bufbytes = atoi(arg);     return NULL; } static const char *set_script_socket(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->sockname = ap_server_root_relative(cmd->pool, arg);     if (!conf->sockname) {        return apr_pstrcat(cmd->pool, "Invalid Scriptsock path ",                           arg, NULL);    }    return NULL; } static const command_rec cgid_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"),     AP_INIT_TAKE1("Scriptsock", set_script_socket, NULL, RSRC_CONF,                  "the name of the socket to use for communication with "                  "the cgi daemon."),     {NULL} }; static int log_scripterror(request_rec *r, cgid_server_conf * conf, int ret,                            apr_status_t rv, char *error) {     apr_file_t *f = NULL;     struct stat 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 ||         ((stat(conf->logname, &finfo) == 0)          && (finfo.st_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 /cgid-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/cgid-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; } static int log_script(request_rec *r, cgid_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 = (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;     struct stat finfo;     char time_str[APR_CTIME_LEN];    /* XXX Very expensive mainline case! Open, then getfileinfo! */    if (!conf->logname ||         ((stat(conf->logname, &finfo) == 0)          && (finfo.st_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);        if (script_err) {            while (apr_file_gets(argsbuffer, HUGE_STRING_LEN,                                  script_err) == APR_SUCCESS)                 continue;         }        return ret;     }     /* "%% [Wed Jun 19 10:53:21 1996] GET /cgid-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/cgid-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;    APR_BRIGADE_FOREACH(e, bb) {        if (APR_BUCKET_IS_EOS(e)) {            break;        }        rv = apr_bucket_read(e, &buf, &len, APR_BLOCK_READ);        if (!APR_STATUS_IS_SUCCESS(rv) || (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 (script_err) {        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);         }     }    if (script_err) {        apr_file_close(script_err);     }    apr_file_close(f);     return ret; } static apr_status_t close_unix_socket(void *thefd){    int fd = (int)thefd;        return close(fd);}static int connect_to_daemon(int *sdptr, request_rec *r,                             cgid_server_conf *conf){    struct sockaddr_un unix_addr;    int sd;    int connect_tries;    apr_interval_time_t sliding_timer;    memset(&unix_addr, 0, sizeof(unix_addr));    unix_addr.sun_family = AF_UNIX;    strcpy(unix_addr.sun_path, conf->sockname);    connect_tries = 0;    sliding_timer = 100000; /* 100 milliseconds */    while (1) {        ++connect_tries;        if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {            return log_scripterror(r, conf, HTTP_INTERNAL_SERVER_ERROR, errno,                                    "unable to create socket to cgi daemon");        }        if (connect(sd, (struct sockaddr *)&unix_addr, sizeof(unix_addr)) < 0) {            if (errno == ECONNREFUSED && connect_tries < DEFAULT_CONNECT_ATTEMPTS) {                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, errno, r,                              "connect #%d to cgi daemon failed, sleeping before retry",                              connect_tries);                close(sd);                apr_sleep(sliding_timer);                if (sliding_timer < apr_time_from_sec(2)) {                    sliding_timer *= 2;                }            }            else {                close(sd);                return log_scripterror(r, conf, HTTP_SERVICE_UNAVAILABLE, errno,                                        "unable to connect to cgi daemon after multiple tries");            }        }        else {            apr_pool_cleanup_register(r->pool, (void *)sd, close_unix_socket,                                      apr_pool_cleanup_null);            break; /* we got connected! */        }        /* gotta try again, but make sure the cgid daemon is still around */        if (kill(daemon_pid, 0) != 0) {            return log_scripterror(r, conf, HTTP_SERVICE_UNAVAILABLE, errno,                                   "cgid daemon is gone; is Apache terminating?");        }    }    *sdptr = sd;    return OK;}static void discard_script_output(apr_bucket_brigade *bb){    apr_bucket *e;    const char *buf;    apr_size_t len;    apr_status_t rv;    APR_BRIGADE_FOREACH(e, bb) {        if (APR_BUCKET_IS_EOS(e)) {            break;        }        rv = apr_bucket_read(e, &buf, &len, APR_BLOCK_READ);        if (!APR_STATUS_IS_SUCCESS(rv)) {            break;        }    }}/****************************************************************  *  * Actual cgid handling...  */ struct cleanup_script_info {    request_rec *r;    unsigned long conn_id;    cgid_server_conf *conf;};static apr_status_t dead_yet(pid_t pid, apr_interval_time_t max_wait){    apr_interval_time_t interval = 10000; /* 10 ms */    apr_interval_time_t total = 0;    do {#ifdef _AIX        /* On AIX, for processes like mod_cgid's script children where         * SIGCHLD is ignored, kill(pid,0) returns success for up to         * one second after the script child exits, based on when a         * daemon runs to clean up unnecessary process table entries.         * getpgid() can report the proper info (-1/ESRCH) immediately.         */        if (getpgid(pid) < 0) {#else        if (kill(pid, 0) < 0) {#endif            return APR_SUCCESS;        }        apr_sleep(interval);        total = total + interval;        if (interval < 500000) {            interval *= 2;        }    } while (total < max_wait);    return APR_EGENERAL;}static apr_status_t cleanup_nonchild_process(request_rec *r, pid_t pid){    kill(pid, SIGTERM); /* in case it isn't dead yet */    if (dead_yet(pid, apr_time_from_sec(3)) == APR_SUCCESS) {        return APR_SUCCESS;    }    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                  "CGI process %" APR_PID_T_FMT " didn't exit, sending SIGKILL",                  pid);    kill(pid, SIGKILL);    if (dead_yet(pid, apr_time_from_sec(3)) == APR_SUCCESS) {        return APR_SUCCESS;    }    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                  "CGI process %" APR_PID_T_FMT " didn't exit, sending SIGKILL again",                  pid);    kill(pid, SIGKILL);    return APR_EGENERAL;}static apr_status_t cleanup_script(void *vptr){    struct cleanup_script_info *info = vptr;    int sd;    int rc;    cgid_req_t req = {0};    pid_t pid;    apr_status_t stat;    rc = connect_to_daemon(&sd, info->r, info->conf);    if (rc != OK) {        return APR_EGENERAL;    }    /* we got a socket, and there is already a cleanup registered for it */    req.req_type = GETPID_REQ;    req.conn_id = info->r->connection->id;    stat = sock_write(sd, &req, sizeof(req));    if (stat != APR_SUCCESS) {        return stat;    }    /* wait for pid of script */    stat = sock_read(sd, &pid, sizeof(pid));    if (stat != APR_SUCCESS) {        return stat;    }    if (pid == 0) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, info->r,                      "daemon couldn't find CGI process for connection %lu",                      info->conn_id);        return APR_EGENERAL;    }    return cleanup_nonchild_process(info->r, pid);}static int cgid_handler(request_rec *r) {     conn_rec *c = r->connection;    int retval, nph, dbpos = 0;     char *argv0, *dbuf = NULL;     apr_bucket_brigade *bb;    apr_bucket *b;    cgid_server_conf *conf;    int is_included;    int seen_eos, child_stopped_reading;    int sd;    char **env;     apr_file_t *tempsock;    struct cleanup_script_info *info;    apr_status_t rv;    if (strcmp(r->handler,CGI_MAGIC_TYPE) && strcmp(r->handler,"cgi-script"))        return DECLINED;    if (r->method_number == M_OPTIONS) {         /* 99 out of 100 cgid scripts, this is all they support */         r->allowed |= (AP_METHOD_BIT << M_GET);         r->allowed |= (AP_METHOD_BIT << M_POST);         return DECLINED;     }     conf = ap_get_module_config(r->server->module_config, &cgid_module);     is_included = !strcmp(r->protocol, "INCLUDED");     if ((argv0 = strrchr(r->filename, '/')) != NULL)        argv0++;    else        argv0 = r->filename;     nph = !(strncmp(argv0, "nph-", 4));     argv0 = r->filename;     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 defined(OS2) || defined(WIN32)#error mod_cgid does not work on this platform.  If you teach it to, look #error at mod_cgi.c for required code in this path.#else     if (r->finfo.filetype == 0)         return log_scripterror(r, conf, HTTP_NOT_FOUND, 0,                                "script not found or unable to stat"); #endif     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);     env = ap_create_environment(r->pool, r->subprocess_env);     if ((retval = connect_to_daemon(&sd, r, conf)) != OK) {        return retval;    }

⌨️ 快捷键说明

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