1
0
mirror of https://github.com/apache/httpd.git synced 2025-08-08 15:02:10 +03:00

First cut at migrating mod_cgi over to APR. Still needs some work to make it Win32 friendly (use named pipes, etc.)

Submitted by: Paul Reder
Reviewed by: Bill Stoddard


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@83965 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Bill Stoddard
1999-10-11 20:44:28 +00:00
parent a9c5b29052
commit 15be4a2322

View File

@@ -166,7 +166,7 @@ static const command_rec cgi_cmds[] =
static int log_scripterror(request_rec *r, cgi_server_conf * conf, int ret,
int show_errno, char *error)
{
FILE *f;
ap_file_t *f;
struct stat finfo;
ap_log_rerror(APLOG_MARK, show_errno|APLOG_ERR, r,
@@ -175,20 +175,20 @@ static int log_scripterror(request_rec *r, cgi_server_conf * conf, int ret,
if (!conf->logname ||
((stat(ap_server_root_relative(r->pool, conf->logname), &finfo) == 0)
&& (finfo.st_size > conf->logbytes)) ||
((f = ap_pfopen(r->pool, ap_server_root_relative(r->pool, conf->logname),
"a")) == NULL)) {
(ap_open(&f, r->pool, ap_server_root_relative(r->pool, conf->logname),
APR_APPEND | APR_BUFFERED, APR_OS_DEFAULT) != APR_SUCCESS)) {
return ret;
}
/* "%% [Wed Jun 19 10:53:21 1996] GET /cgi-bin/printenv HTTP/1.0" */
fprintf(f, "%%%% [%s] %s %s%s%s %s\n", ap_get_time(), r->method, r->uri,
ap_fprintf(f, "%%%% [%s] %s %s%s%s %s\n", ap_get_time(), r->method, r->uri,
r->args ? "?" : "", r->args ? r->args : "", r->protocol);
/* "%% 500 /usr/local/apache/cgi-bin */
fprintf(f, "%%%% %d %s\n", ret, r->filename);
ap_fprintf(f, "%%%% %d %s\n", ret, r->filename);
fprintf(f, "%%error\n%s\n", error);
ap_fprintf(f, "%%error\n%s\n", error);
ap_pfclose(r->pool, f);
ap_close(f);
return ret;
}
@@ -196,17 +196,17 @@ static int log_script(request_rec *r, cgi_server_conf * conf, int ret,
char *dbuf, const char *sbuf, BUFF *script_in, BUFF *script_err)
{
ap_array_header_t *hdrs_arr = ap_table_elts(r->headers_in);
table_entry *hdrs = (table_entry *) hdrs_arr->elts;
ap_table_entry_t *hdrs = (ap_table_entry_t *) hdrs_arr->elts;
char argsbuffer[HUGE_STRING_LEN];
FILE *f;
ap_file_t *f;
int i;
struct stat finfo;
if (!conf->logname ||
((stat(ap_server_root_relative(r->pool, conf->logname), &finfo) == 0)
&& (finfo.st_size > conf->logbytes)) ||
((f = ap_pfopen(r->pool, ap_server_root_relative(r->pool, conf->logname),
"a")) == NULL)) {
(ap_open(&f, r->pool, ap_server_root_relative(r->pool, conf->logname),
APR_APPEND, APR_OS_DEFAULT) != APR_SUCCESS)) {
/* Soak up script output */
while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0)
continue;
@@ -227,55 +227,55 @@ static int log_script(request_rec *r, cgi_server_conf * conf, int ret,
}
/* "%% [Wed Jun 19 10:53:21 1996] GET /cgi-bin/printenv HTTP/1.0" */
fprintf(f, "%%%% [%s] %s %s%s%s %s\n", ap_get_time(), r->method, r->uri,
ap_fprintf(f, "%%%% [%s] %s %s%s%s %s\n", ap_get_time(), r->method, r->uri,
r->args ? "?" : "", r->args ? r->args : "", r->protocol);
/* "%% 500 /usr/local/apache/cgi-bin" */
fprintf(f, "%%%% %d %s\n", ret, r->filename);
ap_fprintf(f, "%%%% %d %s\n", ret, r->filename);
fputs("%request\n", f);
ap_puts("%request\n", f);
for (i = 0; i < hdrs_arr->nelts; ++i) {
if (!hdrs[i].key)
continue;
fprintf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
ap_fprintf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
}
if ((r->method_number == M_POST || r->method_number == M_PUT)
&& *dbuf) {
fprintf(f, "\n%s\n", dbuf);
ap_fprintf(f, "\n%s\n", dbuf);
}
fputs("%response\n", f);
ap_puts("%response\n", f);
hdrs_arr = ap_table_elts(r->err_headers_out);
hdrs = (table_entry *) hdrs_arr->elts;
hdrs = (ap_table_entry_t *) hdrs_arr->elts;
for (i = 0; i < hdrs_arr->nelts; ++i) {
if (!hdrs[i].key)
continue;
fprintf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
ap_fprintf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
}
if (sbuf && *sbuf)
fprintf(f, "%s\n", sbuf);
ap_fprintf(f, "%s\n", sbuf);
if (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0) {
fputs("%stdout\n", f);
fputs(argsbuffer, f);
ap_puts("%stdout\n", f);
ap_puts(argsbuffer, f);
while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0)
fputs(argsbuffer, f);
fputs("\n", f);
ap_puts(argsbuffer, f);
ap_puts("\n", f);
}
if (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) {
fputs("%stderr\n", f);
fputs(argsbuffer, f);
ap_puts("%stderr\n", f);
ap_puts(argsbuffer, f);
while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0)
fputs(argsbuffer, f);
fputs("\n", f);
ap_puts(argsbuffer, f);
ap_puts("\n", f);
}
ap_bclose(script_in);
ap_bclose(script_err);
ap_pfclose(r->pool, f);
ap_close(f);
return ret;
}
@@ -295,12 +295,20 @@ struct cgi_child_stuff {
char *argv0;
};
static int cgi_child(void *child_stuff, child_info *pinfo)
static int cgi_child(struct cgi_child_stuff *child_stuff,
BUFF **script_out, BUFF **script_in, BUFF **script_err)
{
struct cgi_child_stuff *cld = (struct cgi_child_stuff *) child_stuff;
struct cgi_child_stuff *cld = child_stuff;
request_rec *r = cld->r;
char err_string[MAX_STRING_LEN];
char *argv0 = cld->argv0;
int child_pid;
char **args = NULL;
char **env;
ap_context_t *child_context;
ap_procattr_t *procattr;
ap_proc_t *procnew;
ap_os_proc_t fred;
int rc;
#ifdef DEBUG_CGI
#ifdef OS2
@@ -312,7 +320,9 @@ static int cgi_child(void *child_stuff, child_info *pinfo)
int i;
#endif
char **env;
ap_block_alarms();
child_context = r->main ? r->main->pool : r->pool;
RAISE_SIGSTOP(CGI_CHILD);
#ifdef DEBUG_CGI
@@ -321,7 +331,7 @@ static int cgi_child(void *child_stuff, child_info *pinfo)
#endif
ap_add_cgi_vars(r);
env = ap_create_environment(r->pool, r->subprocess_env);
env = ap_create_environment(child_context, r->subprocess_env);
#ifdef DEBUG_CGI
fprintf(dbg, "Environment: \n");
@@ -329,40 +339,81 @@ static int cgi_child(void *child_stuff, child_info *pinfo)
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.
/* Transumute ourselves into the script.
* NB only ISINDEX scripts get decoded arguments.
*/
#ifdef TPF
ap_unblock_alarms();
return (0);
#else
ap_cleanup_for_exec();
child_pid = ap_call_exec(r, pinfo, argv0, env, 0);
#if defined(WIN32) || defined(OS2)
return (child_pid);
#else
if ((ap_createprocattr_init(&procattr, child_context) != APR_SUCCESS) ||
(ap_setprocattr_io(procattr,
script_in ? 1 : 0,
script_out ? 1 : 0,
script_err ? 1 : 0) != APR_SUCCESS) ||
(ap_setprocattr_dir(procattr, r->filename) != APR_SUCCESS) ||
(ap_setprocattr_cmdtype(procattr, APR_PROGRAM) != APR_SUCCESS)) {
/* Something bad happened, tell the world. */
ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
"couldn't create child process: %s", r->filename);
ap_unblock_alarms();
/* 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.
*/
return (-1);
}
else {
rc = ap_tokenize_to_argv(child_context, argv0, &args);
if (rc != APR_SUCCESS) {
ap_snprintf(err_string, sizeof(err_string),
"argv[] allocation failed, reason: %s (errno = %d)\n",
strerror(errno), errno);
write(STDERR_FILENO, err_string, strlen(err_string));
ap_unblock_alarms();
ap_log_error(APLOG_MARK, APLOG_ERR, NULL, "exec of %s failed", r->filename);
exit(0);
/* NOT REACHED */
return (0);
}
rc = ap_create_process(&procnew, child_context, r->filename, args,
env, procattr);
if (rc != APR_SUCCESS) {
/* Bad things happened. Everyone should have cleaned up. */
ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
"couldn't create child process: %d: %s", rc, r->filename);
}
else {
#ifndef WIN32
/* pjr - this is a cheap hack for now to get the basics working in
* stages. ap_note_subprocess and free_proc need to be redone
* to make use of ap_proc_t instead of pid.
*/
ap_get_os_proc(procnew, &fred);
ap_note_subprocess(child_context, fred, kill_after_timeout);
#endif
if (script_in) {
*script_in = ap_bcreate(child_context, B_WR);
}
if (script_out) {
*script_out = ap_bcreate(child_context, B_RD);
}
if (script_err) {
*script_err = ap_bcreate(child_context, B_RD);
}
}
ap_unblock_alarms();
return (rc);
}
#endif /* TPF */
}
@@ -449,9 +500,7 @@ static int cgi_handler(request_rec *r)
* 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)) {
if (cgi_child(&cld, &script_out, &script_in, &script_err) < 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
"couldn't spawn child process: %s", r->filename);
return HTTP_INTERNAL_SERVER_ERROR;
@@ -573,20 +622,11 @@ static const handler_rec cgi_handlers[] =
module MODULE_VAR_EXPORT cgi_module =
{
STANDARD20_MODULE_STUFF,
NULL, /* pre_config */
NULL, /* post_config */
NULL, /* open_logs */
NULL, /* child 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 ap_table_t */
cgi_handlers, /* handlers */
NULL, /* check auth */
NULL, /* check access */
NULL, /* type_checker */
NULL, /* fixups */
NULL, /* logger */
NULL /* register hooks */
};