aboutsummaryrefslogtreecommitdiff
path: root/server.c
diff options
context:
space:
mode:
authorOmar Polo <op@omarpolo.com>2021-01-23 15:32:38 +0000
committerOmar Polo <op@omarpolo.com>2021-01-23 15:32:38 +0000
commit3309ef975cf570aeb5c1dbf568af323c19bbb3c0 (patch)
tree1759df81e1fa4c4fe8fa483285366e7ce71cb7ce /server.c
parent45b4aa6e57740fca189b4a2fd2ed9ed7ba3bf879 (diff)
accumulate the whole response line for CGI scripts
Diffstat (limited to 'server.c')
-rw-r--r--server.c61
1 files changed, 48 insertions, 13 deletions
diff --git a/server.c b/server.c
index 8337dcf..69d79c1 100644
--- a/server.c
+++ b/server.c
@@ -448,6 +448,43 @@ cgi_poll_on_client(struct pollfd *fds, struct client *c)
c->fd = fd;
}
+/* handle the read from the child process. Return like read(2) */
+static ssize_t
+read_from_cgi(struct client *c)
+{
+ void *buf;
+ size_t len;
+ ssize_t r;
+
+ /* if we haven't read a whole response line, we want to
+ * continue reading. */
+
+ if (c->code == -1) {
+ buf = c->sbuf + c->len;
+ len = sizeof(c->sbuf) - c->len;
+ } else {
+ buf = c->sbuf;
+ len = sizeof(c->sbuf);
+ }
+
+ r = read(c->fd, buf, len);
+ if (r == 0 || r == -1)
+ return r;
+
+ c->len += r;
+ c->off = 0;
+
+ if (c->code != -1)
+ return r;
+
+ if (strchr(c->sbuf, '\n') || c->len == sizeof(c->sbuf)) {
+ c->code = 0;
+ log_request(c, c->sbuf, c->len);
+ }
+
+ return r;
+}
+
void
handle_cgi(struct pollfd *fds, struct client *c)
{
@@ -457,27 +494,25 @@ handle_cgi(struct pollfd *fds, struct client *c)
cgi_poll_on_client(fds, c);
while (1) {
- if (c->len == 0) {
- if ((r = read(c->fd, c->sbuf, sizeof(c->sbuf))) == 0)
+ if (c->code == -1 || c->len == 0) {
+ switch (r = read_from_cgi(c)) {
+ case 0:
goto end;
- if (r == -1) {
+
+ case -1:
if (errno == EAGAIN || errno == EWOULDBLOCK) {
cgi_poll_on_child(fds, c);
return;
}
- goto end;
- }
- c->len = r;
- c->off = 0;
-
- /* XXX: if we haven't still read a whole
- * reply line, we should go back to poll! */
- if (c->code == -1) {
- c->code = 0;
- log_request(c, c->sbuf, sizeof(c->sbuf));
+ goto end;
}
}
+ if (c->code == -1) {
+ cgi_poll_on_child(fds, c);
+ return;
+ }
+
while (c->len > 0) {
switch (r = tls_write(c->ctx, c->sbuf + c->off, c->len)) {
case -1: