1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2025-04-21 12:27:27 +03:00

[backfire] merge r22630, r22692, r22805

git-svn-id: svn://svn.openwrt.org/openwrt/branches/backfire@22962 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
jow
2010-09-06 20:49:31 +00:00
parent 97974216cf
commit 752a6977d2
11 changed files with 500 additions and 360 deletions

View File

@@ -135,9 +135,11 @@ static int uh_cgi_error_500(struct client *cl, struct http_request *req, const c
}
void uh_cgi_request(struct client *cl, struct http_request *req, struct path_info *pi)
{
int i, hdroff, bufoff;
void uh_cgi_request(
struct client *cl, struct http_request *req,
struct path_info *pi, struct interpreter *ip
) {
int i, hdroff, bufoff, rv;
int hdrlen = 0;
int buflen = 0;
int fd_max = 0;
@@ -199,9 +201,9 @@ void uh_cgi_request(struct client *cl, struct http_request *req, struct path_inf
dup2(rfd[1], 1);
dup2(wfd[0], 0);
/* check for regular, world-executable file */
if( (pi->stat.st_mode & S_IFREG) &&
(pi->stat.st_mode & S_IXOTH)
/* check for regular, world-executable file _or_ interpreter */
if( ((pi->stat.st_mode & S_IFREG) &&
(pi->stat.st_mode & S_IXOTH)) || (ip != NULL)
) {
/* build environment */
clearenv();
@@ -320,14 +322,17 @@ void uh_cgi_request(struct client *cl, struct http_request *req, struct path_inf
if( chdir(pi->root) )
perror("chdir()");
execl(pi->phys, pi->phys, NULL);
if( ip != NULL )
execl(ip->path, ip->path, pi->phys, NULL);
else
execl(pi->phys, pi->phys, NULL);
/* in case it fails ... */
printf(
"Status: 500 Internal Server Error\r\n\r\n"
"Unable to launch the requested CGI program:\n"
" %s: %s\n",
pi->phys, strerror(errno)
ip ? ip->path : pi->phys, strerror(errno)
);
}
@@ -371,12 +376,6 @@ void uh_cgi_request(struct client *cl, struct http_request *req, struct path_inf
memset(hdr, 0, sizeof(hdr));
timeout.tv_sec = cl->server->conf->script_timeout;
timeout.tv_usec = 0;
#define ensure(x) \
do { if( x < 0 ) goto out; } while(0)
/* I/O loop, watch our pipe ends and dispatch child reads/writes from/to socket */
while( 1 )
{
@@ -386,11 +385,21 @@ void uh_cgi_request(struct client *cl, struct http_request *req, struct path_inf
FD_SET(rfd[0], &reader);
FD_SET(wfd[1], &writer);
timeout.tv_sec = (header_sent < 1) ? cl->server->conf->script_timeout : 3;
timeout.tv_usec = 0;
ensure_out(rv = select_intr(fd_max, &reader,
(content_length > -1) ? &writer : NULL, NULL, &timeout));
/* timeout */
if( rv == 0 )
{
ensure_out(kill(child, 0));
}
/* wait until we can read or write or both */
if( select_intr(fd_max, &reader,
(content_length > -1) ? &writer : NULL, NULL,
(header_sent < 1) ? &timeout : NULL) > 0
) {
else if( rv > 0 )
{
/* ready to write to cgi program */
if( FD_ISSET(wfd[1], &writer) )
{
@@ -398,7 +407,10 @@ void uh_cgi_request(struct client *cl, struct http_request *req, struct path_inf
if( content_length > 0 )
{
/* read it from socket ... */
if( (buflen = uh_tcp_recv(cl, buf, min(content_length, sizeof(buf)))) > 0 )
ensure_out(buflen = uh_tcp_recv(cl, buf,
min(content_length, sizeof(buf))));
if( buflen > 0 )
{
/* ... and write it to child's stdin */
if( write(wfd[1], buf, buflen) < 0 )
@@ -451,7 +463,7 @@ void uh_cgi_request(struct client *cl, struct http_request *req, struct path_inf
if( (res = uh_cgi_header_parse(hdr, hdrlen, &hdroff)) != NULL )
{
/* write status */
ensure(uh_http_sendf(cl, NULL,
ensure_out(uh_http_sendf(cl, NULL,
"HTTP/%.1f %03d %s\r\n"
"Connection: close\r\n",
req->version, res->statuscode,
@@ -461,7 +473,7 @@ void uh_cgi_request(struct client *cl, struct http_request *req, struct path_inf
if( !uh_cgi_header_lookup(res, "Location") &&
!uh_cgi_header_lookup(res, "Content-Type")
) {
ensure(uh_http_send(cl, NULL,
ensure_out(uh_http_send(cl, NULL,
"Content-Type: text/plain\r\n", -1));
}
@@ -469,32 +481,32 @@ void uh_cgi_request(struct client *cl, struct http_request *req, struct path_inf
if( (req->version > 1.0) &&
!uh_cgi_header_lookup(res, "Transfer-Encoding")
) {
ensure(uh_http_send(cl, NULL,
ensure_out(uh_http_send(cl, NULL,
"Transfer-Encoding: chunked\r\n", -1));
}
/* write headers from CGI program */
foreach_header(i, res->headers)
{
ensure(uh_http_sendf(cl, NULL, "%s: %s\r\n",
ensure_out(uh_http_sendf(cl, NULL, "%s: %s\r\n",
res->headers[i], res->headers[i+1]));
}
/* terminate header */
ensure(uh_http_send(cl, NULL, "\r\n", -1));
ensure_out(uh_http_send(cl, NULL, "\r\n", -1));
/* push out remaining head buffer */
if( hdroff < hdrlen )
ensure(uh_http_send(cl, req, &hdr[hdroff], hdrlen - hdroff));
ensure_out(uh_http_send(cl, req, &hdr[hdroff], hdrlen - hdroff));
}
/* ... failed and head buffer exceeded */
else if( hdrlen >= sizeof(hdr) )
{
ensure(uh_cgi_error_500(cl, req,
ensure_out(uh_cgi_error_500(cl, req,
"The CGI program generated an invalid response:\n\n"));
ensure(uh_http_send(cl, req, hdr, hdrlen));
ensure_out(uh_http_send(cl, req, hdr, hdrlen));
}
/* ... failed but free buffer space, try again */
@@ -505,7 +517,7 @@ void uh_cgi_request(struct client *cl, struct http_request *req, struct path_inf
/* push out remaining read buffer */
if( bufoff < buflen )
ensure(uh_http_send(cl, req, &buf[bufoff], buflen - bufoff));
ensure_out(uh_http_send(cl, req, &buf[bufoff], buflen - bufoff));
header_sent = 1;
continue;
@@ -513,7 +525,7 @@ void uh_cgi_request(struct client *cl, struct http_request *req, struct path_inf
/* headers complete, pass through buffer to socket */
ensure(uh_http_send(cl, req, buf, buflen));
ensure_out(uh_http_send(cl, req, buf, buflen));
}
/* looks like eof from child */
@@ -533,7 +545,7 @@ void uh_cgi_request(struct client *cl, struct http_request *req, struct path_inf
* build the required headers here.
*/
ensure(uh_http_sendf(cl, NULL,
ensure_out(uh_http_sendf(cl, NULL,
"HTTP/%.1f 200 OK\r\n"
"Content-Type: text/plain\r\n"
"%s\r\n",
@@ -541,11 +553,11 @@ void uh_cgi_request(struct client *cl, struct http_request *req, struct path_inf
? "Transfer-Encoding: chunked\r\n" : ""
));
ensure(uh_http_send(cl, req, hdr, hdrlen));
ensure_out(uh_http_send(cl, req, hdr, hdrlen));
}
/* send final chunk if we're in chunked transfer mode */
ensure(uh_http_send(cl, req, "", 0));
ensure_out(uh_http_send(cl, req, "", 0));
break;
}
}
@@ -556,13 +568,13 @@ void uh_cgi_request(struct client *cl, struct http_request *req, struct path_inf
{
if( (errno != EINTR) && ! header_sent )
{
ensure(uh_http_sendhf(cl, 504, "Gateway Timeout",
ensure_out(uh_http_sendhf(cl, 504, "Gateway Timeout",
"The CGI script took too long to produce "
"a response"));
}
/* send final chunk if we're in chunked transfer mode */
ensure(uh_http_send(cl, req, "", 0));
ensure_out(uh_http_send(cl, req, "", 0));
break;
}