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

📄 mod_cgi.c

📁 apache简化版
💻 C
📖 第 1 页 / 共 2 页
字号:
    int i;#endif    char **env;    RAISE_SIGSTOP(CGI_CHILD);#ifdef DEBUG_CGI    fprintf(dbg, "Attempting to exec %s as %sCGI child (argv0 = %s)\n",	    r->filename, cld->nph ? "NPH " : "", argv0);#endif    ap_add_cgi_vars(r);    env = ap_create_environment(r->pool, r->subprocess_env);#ifdef DEBUG_CGI    fprintf(dbg, "Environment: \n");    for (i = 0; env[i]; ++i)	fprintf(dbg, "'%s'\n", env[i]);#endif#ifndef WIN32    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.     */    ap_cleanup_for_exec();    child_pid = ap_call_exec(r, pinfo, argv0, env, 0);#ifdef WIN32    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}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 (r->method_number == M_OPTIONS) {	/* 99 out of 100 CGI scripts, this is all they support */	r->allowed |= (1 << M_GET);	r->allowed |= (1 << M_POST);	return DECLINED;    }    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;	r->filename = ap_pstrcat(r->pool, r->filename, ".EXE", NULL);	if ((stat(r->filename, &statbuf) != 0) || (!S_ISREG(statbuf.st_mode))) {	    return log_scripterror(r, conf, NOT_FOUND, 0,				   "script not found or unable to stat");	}    }#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 CHARSET_EBCDIC    /* XXX:@@@ Is the generated/included output ALWAYS in text/ebcdic format? */    /* Or must we check the Content-Type first? */    ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, 1);#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 if a buggy script fails to read everything we throw     * at it, or a buggy client sends too much, we get a SIGPIPE, so     * we have to ignore SIGPIPE while doing this.  CERN does the same     * (and in fact, they pretty nearly guarantee themselves a SIGPIPE     * on every invocation by chasing the real client data with a     * spurious newline).     */    if (ap_should_client_block(r)) {	void (*handler) (int);	int dbsize, len_read;	if (conf->logname) {	    dbuf = ap_pcalloc(r->pool, conf->bufbytes + 1);	    dbpos = 0;	}	ap_hard_timeout("copy script args", r);#ifdef SIGPIPE	handler = signal(SIGPIPE, SIG_IGN);#endif	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);	signal(SIGPIPE, handler);	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);	}#ifdef CHARSET_EBCDIC        /* Now check the Content-Type to decide if conversion is needed */        ap_checkconv(r);#endif /*CHARSET_EBCDIC*/	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;	    }	    while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) {		continue;	    }	    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);	while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) {	    continue;	}	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 + -