httpd: stop adding our own "Content-type:" to CGI output

This commit is contained in:
Denis Vlasenko
2007-01-07 21:25:12 +00:00
parent db6a5c3f9e
commit 6998142998

View File

@@ -93,6 +93,11 @@
#include "busybox.h" #include "busybox.h"
/* amount of buffering in a pipe */
#ifndef PIPE_BUF
# define PIPE_BUF 4096
#endif
static const char httpdVersion[] = "busybox httpd/1.35 6-Oct-2004"; static const char httpdVersion[] = "busybox httpd/1.35 6-Oct-2004";
static const char default_path_httpd_conf[] = "/etc"; static const char default_path_httpd_conf[] = "/etc";
static const char httpd_conf[] = "httpd.conf"; static const char httpd_conf[] = "httpd.conf";
@@ -106,10 +111,7 @@ static const char home[] = "./";
// is checked rigorously // is checked rigorously
//#define DEBUG 1 //#define DEBUG 1
#ifndef DEBUG
#define DEBUG 0 #define DEBUG 0
#endif
#define MAX_MEMORY_BUFF 8192 /* IO buffer */ #define MAX_MEMORY_BUFF 8192 /* IO buffer */
@@ -986,7 +988,7 @@ static int sendCgi(const char *url,
int outFd; int outFd;
int firstLine = 1; int firstLine = 1;
int status; int status;
size_t post_readed_size, post_readed_idx; size_t post_read_size, post_read_idx;
if (pipe(fromCgi) != 0) if (pipe(fromCgi) != 0)
return 0; return 0;
@@ -1000,7 +1002,7 @@ static int sendCgi(const char *url,
if (!pid) { if (!pid) {
/* child process */ /* child process */
char *script; char *script;
char *purl = strdup(url); char *purl = xstrdup(url);
char realpath_buff[MAXPATHLEN]; char realpath_buff[MAXPATHLEN];
if (purl == NULL) if (purl == NULL)
@@ -1129,8 +1131,8 @@ static int sendCgi(const char *url,
/* parent process */ /* parent process */
post_readed_size = 0; post_read_size = 0;
post_readed_idx = 0; post_read_idx = 0; /* for gcc */
inFd = fromCgi[0]; inFd = fromCgi[0];
outFd = toCgi[1]; outFd = toCgi[1];
close(fromCgi[1]); close(fromCgi[1]);
@@ -1147,26 +1149,29 @@ static int sendCgi(const char *url,
FD_ZERO(&readSet); FD_ZERO(&readSet);
FD_ZERO(&writeSet); FD_ZERO(&writeSet);
FD_SET(inFd, &readSet); FD_SET(inFd, &readSet);
if (bodyLen > 0 || post_readed_size > 0) { if (bodyLen > 0 || post_read_size > 0) {
FD_SET(outFd, &writeSet); FD_SET(outFd, &writeSet);
nfound = outFd > inFd ? outFd : inFd; nfound = outFd > inFd ? outFd : inFd;
if (post_readed_size == 0) { if (post_read_size == 0) {
FD_SET(config->accepted_socket, &readSet); FD_SET(config->accepted_socket, &readSet);
if (nfound < config->accepted_socket) if (nfound < config->accepted_socket)
nfound = config->accepted_socket; nfound = config->accepted_socket;
} }
/* Now wait on the set of sockets! */ /* Now wait on the set of sockets! */
nfound = select(nfound + 1, &readSet, &writeSet, 0, NULL); nfound = select(nfound + 1, &readSet, &writeSet, NULL, NULL);
} else { } else {
if (!bodyLen) { if (!bodyLen) {
close(outFd); close(outFd); /* no more POST data to CGI */
bodyLen = -1; bodyLen = -1;
} }
nfound = select(inFd + 1, &readSet, 0, 0, NULL); nfound = select(inFd + 1, &readSet, NULL, NULL, NULL);
} }
if (nfound <= 0) { if (nfound <= 0) {
if (waitpid(pid, &status, WNOHANG) > 0) { if (waitpid(pid, &status, WNOHANG) <= 0)
/* Weird. CGI didn't exit and no fd's
* are ready, yet select returned?! */
continue;
close(inFd); close(inFd);
if (DEBUG && WIFEXITED(status)) if (DEBUG && WIFEXITED(status))
bb_error_msg("piped has exited with status=%d", WEXITSTATUS(status)); bb_error_msg("piped has exited with status=%d", WEXITSTATUS(status));
@@ -1174,68 +1179,78 @@ static int sendCgi(const char *url,
bb_error_msg("piped has exited with signal=%d", WTERMSIG(status)); bb_error_msg("piped has exited with signal=%d", WTERMSIG(status));
break; break;
} }
} else if (post_readed_size > 0 && FD_ISSET(outFd, &writeSet)) {
count = full_write(outFd, wbuf + post_readed_idx, post_readed_size); if (post_read_size > 0 && FD_ISSET(outFd, &writeSet)) {
/* Have data from peer and can write to CGI */
// huh? why full_write? what if we will block?
// (imagine that CGI does not read its stdin...)
count = full_write(outFd, wbuf + post_read_idx, post_read_size);
if (count > 0) { if (count > 0) {
post_readed_size -= count; post_read_idx += count;
post_readed_idx += count; post_read_size -= count;
if (post_readed_size == 0)
post_readed_idx = 0;
} else { } else {
post_readed_size = post_readed_idx = bodyLen = 0; /* broken pipe to CGI */ post_read_size = bodyLen = 0; /* broken pipe to CGI */
} }
} else if (bodyLen > 0 && post_readed_size == 0 && FD_ISSET(config->accepted_socket, &readSet)) { } else if (bodyLen > 0 && post_read_size == 0
&& FD_ISSET(config->accepted_socket, &readSet)
) {
/* We expect data, prev data portion is eaten by CGI
* and there *is* data to read from the peer
* (POST data?) */
count = bodyLen > (int)sizeof(wbuf) ? (int)sizeof(wbuf) : bodyLen; count = bodyLen > (int)sizeof(wbuf) ? (int)sizeof(wbuf) : bodyLen;
count = safe_read(config->accepted_socket, wbuf, count); count = safe_read(config->accepted_socket, wbuf, count);
if (count > 0) { if (count > 0) {
post_readed_size += count; post_read_size = count;
post_read_idx = 0;
bodyLen -= count; bodyLen -= count;
} else { } else {
bodyLen = 0; /* closed */ bodyLen = 0; /* closed */
} }
} }
if (FD_ISSET(inFd, &readSet)) { if (FD_ISSET(inFd, &readSet)) {
/* There is something to read from CGI */
int s = config->accepted_socket; int s = config->accepted_socket;
char *rbuf = config->buf; char *rbuf = config->buf;
#ifndef PIPE_BUF
# define PIPESIZE 4096 /* amount of buffering in a pipe */
#else
#define PIPESIZE PIPE_BUF #define PIPESIZE PIPE_BUF
#endif
#if PIPESIZE >= MAX_MEMORY_BUFF #if PIPESIZE >= MAX_MEMORY_BUFF
# error "PIPESIZE >= MAX_MEMORY_BUFF" # error "PIPESIZE >= MAX_MEMORY_BUFF"
#endif #endif
/* There is something to read */
/* NB: was safe_read. If it *has to be* safe_read, */ /* NB: was safe_read. If it *has to be* safe_read, */
/* please explain why in this comment... */ /* please explain why in this comment... */
count = full_read(inFd, rbuf, PIPESIZE); count = full_read(inFd, rbuf, PIPESIZE);
if (count == 0) if (count == 0)
break; /* closed */ break; /* closed */
if (count > 0) { if (count < 0)
continue; /* huh, error, why continue?? */
if (firstLine) { if (firstLine) {
/* full_read (above) avoids /* full_read (above) avoids
* "chopped up into small chunks" syndrome here */ * "chopped up into small chunks" syndrome here */
rbuf[count] = 0; rbuf[count] = '\0';
/* check to see if the user script added headers */ /* check to see if the user script added headers */
if (strncmp(rbuf, "HTTP/1.0 200 OK\r\n", 4) != 0) { #define HTTP_200 "HTTP/1.0 200 OK\r\n\r\n"
if (memcmp(rbuf, HTTP_200, 4) != 0) {
/* there is no "HTTP", do it ourself */ /* there is no "HTTP", do it ourself */
full_write(s, "HTTP/1.0 200 OK\r\n", 17); full_write(s, HTTP_200, sizeof(HTTP_200)-1);
} /* hmm, maybe 'else if'? */
if (!strstr(rbuf, "ontent-")) {
full_write(s, "Content-type: text/plain\r\n\r\n", 28);
} }
#undef HTTP_200
/* Example of valid GCI without "Content-type:"
* echo -en "HTTP/1.0 302 Found\r\n"
* echo -en "Location: http://www.busybox.net\r\n"
* echo -en "\r\n"
*/
//if (!strstr(rbuf, "ontent-")) {
// full_write(s, "Content-type: text/plain\r\n\r\n", 28);
//}
firstLine = 0; firstLine = 0;
} }
if (full_write(s, rbuf, count) != count) if (full_write(s, rbuf, count) != count)
break; break;
if (DEBUG) if (DEBUG)
fprintf(stderr, "cgi read %d bytes: '%.*s'\n", count, count, rbuf); fprintf(stderr, "cgi read %d bytes: '%.*s'\n", count, count, rbuf);
} } /* if (FD_ISSET(inFd)) */
} } /* while (1) */
}
return 0; return 0;
} }
#endif /* FEATURE_HTTPD_CGI */ #endif /* FEATURE_HTTPD_CGI */