summaryrefslogtreecommitdiff
path: root/src/tipideed
diff options
context:
space:
mode:
Diffstat (limited to 'src/tipideed')
-rw-r--r--src/tipideed/cgi.c144
-rw-r--r--src/tipideed/regular.c25
-rw-r--r--src/tipideed/responses.c80
-rw-r--r--src/tipideed/tipideed-internal.h73
-rw-r--r--src/tipideed/tipideed.c106
5 files changed, 236 insertions, 192 deletions
diff --git a/src/tipideed/cgi.c b/src/tipideed/cgi.c
index 8dde023..0d7e104 100644
--- a/src/tipideed/cgi.c
+++ b/src/tipideed/cgi.c
@@ -21,55 +21,51 @@
#include <skalibs/env.h>
#include <skalibs/exec.h>
#include <skalibs/unix-timed.h>
-#include <skalibs/lolstdio.h>
-#include <tipidee/method.h>
-#include <tipidee/headers.h>
-#include <tipidee/response.h>
-#include <tipidee/uri.h>
+#include <tipidee/tipidee.h>
#include "tipideed-internal.h"
-static void addenv_ (tipidee_rql const *rql, char const *k, char const *v, int slash)
+static void addenv_ (tipidee_rql const *rql, char const *docroot, char const *k, char const *v, int slash)
{
if (!stralloc_cats(&g.sa, k)
|| !stralloc_catb(&g.sa, "=/", 1 + !!slash)
|| !stralloc_cats(&g.sa, v)
|| !stralloc_0(&g.sa))
- die500sys(rql, 111, "stralloc_catb") ;
+ die500sys(rql, 111, docroot, "stralloc_catb") ;
}
-#define addenv(rql, k, v) addenv_(rql, k, (v), 0)
-#define addenvslash(rql, k, v) addenv_(rql, k, (v), 1)
+#define addenv(rql, d, k, v) addenv_(rql, d, k, (v), 0)
+#define addenvslash(rql, d, k, v) addenv_(rql, d, k, (v), 1)
-static void delenv (tipidee_rql const *rql, char const *k)
+static void delenv (tipidee_rql const *rql, char const *docroot, char const *k)
{
if (!stralloc_cats(&g.sa, k)
|| !stralloc_0(&g.sa))
- die500sys(rql, 111, "stralloc_catb") ;
+ die500sys(rql, 111, docroot, "stralloc_catb") ;
}
-static inline void modify_env (tipidee_rql const *rql, tipidee_headers const *hdr, size_t cl, char const *script, char const *infopath)
+static inline void modify_env (tipidee_rql const *rql, char const *docroot, tipidee_headers const *hdr, size_t cl, char const *script, char const *infopath)
{
uint32_t got = 0 ;
- addenv(rql, "REQUEST_METHOD", tipidee_method_tostr(rql->m)) ;
+ addenv(rql, docroot, "REQUEST_METHOD", tipidee_method_tostr(rql->m)) ;
if (cl)
{
char fmt[SIZE_FMT] ;
fmt[size_fmt(fmt, cl)] = 0 ;
- addenv(rql, "CONTENT_LENGTH", fmt) ;
+ addenv(rql, docroot, "CONTENT_LENGTH", fmt) ;
}
- else delenv(rql, "CONTENT_LENGTH") ;
+ else delenv(rql, docroot, "CONTENT_LENGTH") ;
- if (infopath) addenvslash(rql, "PATH_INFO", infopath) ;
- else delenv(rql, "PATH_INFO") ;
- if (rql->uri.query) addenv(rql, "QUERY_STRING", rql->uri.query) ;
- else delenv(rql, "QUERY_STRING") ;
- addenv(rql, "SCRIPT_NAME", script) ;
- addenv(rql, "SERVER_NAME", rql->uri.host) ;
+ if (infopath) addenvslash(rql, docroot, "PATH_INFO", infopath) ;
+ else delenv(rql, docroot, "PATH_INFO") ;
+ if (rql->uri.query) addenv(rql, docroot, "QUERY_STRING", rql->uri.query) ;
+ else delenv(rql, docroot, "QUERY_STRING") ;
+ addenv(rql, docroot, "SCRIPT_NAME", script) ;
+ addenv(rql, docroot, "SERVER_NAME", rql->uri.host) ;
{
char proto[9] = "HTTP/1.1" ;
if (!rql->http_minor) proto[7] = '0' ;
- addenv(rql, "SERVER_PROTOCOL", proto) ;
+ addenv(rql, docroot, "SERVER_PROTOCOL", proto) ;
}
for (size_t i = 0 ; i < hdr->n ; i++)
@@ -84,36 +80,36 @@ static inline void modify_env (tipidee_rql const *rql, tipidee_headers const *hd
char scheme[n] ;
memcpy(scheme, val, n-1) ;
scheme[n-1] = 0 ;
- addenv(rql, "AUTH_TYPE", scheme) ;
+ addenv(rql, docroot, "AUTH_TYPE", scheme) ;
got |= 1 ;
}
}
- else if (!strcasecmp(key, "Content-Type")) { addenv(rql, "CONTENT_TYPE", val) ; got |= 2 ; }
+ else if (!strcasecmp(key, "Content-Type")) { addenv(rql, docroot, "CONTENT_TYPE", val) ; got |= 2 ; }
else if (!strcasecmp(key, "Content-Length") || !strcasecmp(key, "Connection") || !strcasecmp(key, "Host")) ;
else
{
size_t len = strlen(key), pos = g.sa.len + 5 ;
if (!stralloc_catb(&g.sa, "HTTP_", 5)) die500sys(rql, 111, "stralloc_catb") ;
- addenv(rql, key, val) ;
+ addenv(rql, docroot, key, val) ;
for (char *s = g.sa.s + pos ; len-- ; s++)
if (*s == '-') *s = '_' ;
else if (*s >= 'a' && *s <= 'z') *s -= 32 ;
}
}
- if (!(got & 1)) delenv(rql, "AUTH_TYPE") ;
- if (!(got & 2)) delenv(rql, "CONTENT_TYPE") ;
+ if (!(got & 1)) delenv(rql, docroot, "AUTH_TYPE") ;
+ if (!(got & 2)) delenv(rql, docroot, "CONTENT_TYPE") ;
}
-static inline int do_nph (tipidee_rql const *rql, char const *const *argv, char const *const *envp, char const *body, size_t bodylen) gccattr_noreturn ;
-static inline int do_nph (tipidee_rql const *rql, char const *const *argv, char const *const *envp, char const *body, size_t bodylen)
+static inline int do_nph (tipidee_rql const *rql, char const *docroot, char const *const *argv, char const *const *envp, char const *body, size_t bodylen) gccattr_noreturn ;
+static inline int do_nph (tipidee_rql const *rql, char const *docroot, char const *const *argv, char const *const *envp, char const *body, size_t bodylen)
{
int p[2] ;
- if (pipe(p) == -1) die500sys(rql, 111, "pipe") ;
+ if (pipe(p) == -1) die500sys(rql, 111, docroot, "pipe") ;
if (bodylen)
{
switch (fork())
{
- case -1 : die500sys(rql, 111, "fork") ;
+ case -1 : die500sys(rql, 111, docroot, "fork") ;
case 0 :
{
#define NAME "tipideed (nph helper for pid "
@@ -138,12 +134,12 @@ static inline int do_nph (tipidee_rql const *rql, char const *const *argv, char
}
}
close(p[1]) ;
- if (fd_move(0, p[0]) == -1) die500sys(rql, 111, "fd_move") ;
+ if (fd_move(0, p[0]) == -1) die500sys(rql, 111, docroot, "fd_move") ;
exec_e(argv, envp) ;
- die500sys(rql, errno == ENOENT ? 127 : 126, "exec nph ", argv[0]) ;
+ die500sys(rql, errno == ENOENT ? 127 : 126, docroot, "exec nph ", argv[0]) ;
}
-static inline int run_cgi (tipidee_rql const *rql, char const *const *argv, char const *const *envp, char const *body, size_t bodylen, tipidee_headers *hdr, stralloc *sa)
+static inline int run_cgi (tipidee_rql const *rql, char const *docroot, char const *const *argv, char const *const *envp, char const *body, size_t bodylen, tipidee_headers *hdr, stralloc *sa)
{
iopause_fd x[2] = { { .events = IOPAUSE_READ }, { .events = IOPAUSE_WRITE } } ;
size_t bodyw = 0 ;
@@ -157,26 +153,25 @@ static inline int run_cgi (tipidee_rql const *rql, char const *const *argv, char
{
int fd[2] = { 0, 1 } ;
pid = child_spawn2(argv[0], argv, envp, fd) ;
- if (!pid) die500sys(rql, 111, "spawn ", argv[0]) ;
+ if (!pid) die500sys(rql, 111, docroot, "spawn ", argv[0]) ;
x[0].fd = fd[0] ; x[1].fd = fd[1] ;
}
if (!bodylen)
{
close(x[1].fd) ;
x[1].fd = -1 ;
- LOLDEBUG("run_cgi: no request body, closing writing pipe to cgi") ;
}
buffer_init(&b, &buffer_read, x[0].fd, buf, 4096) ;
tain_add_g(&deadline, &g.cgitto) ;
while (x[0].fd >= 0)
{
int r = iopause_g(x, 1 + (x[1].fd >= 0), &deadline) ;
- if (r == -1) die500sys(rql, 111, "iopause") ;
+ if (r == -1) die500sys(rql, 111, docroot, "iopause") ;
if (!r)
{
kill(pid, SIGTERM) ;
- respond_504(rql) ;
strerr_warnw3x("cgi ", argv[0], " timed out") ;
+ respond_504(rql, docroot) ;
break ;
}
if (x[1].fd >= 0 && x[1].revents & (IOPAUSE_WRITE | IOPAUSE_EXCEPT))
@@ -192,7 +187,6 @@ static inline int run_cgi (tipidee_rql const *rql, char const *const *argv, char
{
close(x[1].fd) ;
x[1].fd = -1 ;
- LOLDEBUG("run_cgi: finished writing body") ;
}
}
if (x[0].fd >= 0 && x[0].revents & (IOPAUSE_READ | IOPAUSE_EXCEPT))
@@ -205,20 +199,20 @@ static inline int run_cgi (tipidee_rql const *rql, char const *const *argv, char
switch (r)
{
case -2 : break ;
- case -1 : die500sys(rql, 111, "read from cgi ", argv[0]) ;
+ case -1 : die500sys(rql, 111, docroot, "read from cgi ", argv[0]) ;
case 0 :
{
size_t n = buffer_len(&b) ;
- if (!stralloc_readyplus(sa, n)) die500sys(rql, 111, "stralloc_readyplus") ;
+ if (!stralloc_readyplus(sa, n)) die500sys(rql, 111, docroot, "stralloc_readyplus") ;
buffer_getnofill(&b, sa->s + sa->len, n) ;
sa->len += n ;
rstate = 1 ;
break ;
}
- case 400 : die502x(rql, 2, "invalid headers", " from cgi ", argv[0]) ;
- case 413 : die502x(rql, 2, hdr->n >= TIPIDEE_HEADERS_MAX ? "Too many headers" : "Too much header data", " from cgi ", argv[0]) ;
- case 500 : die500x(rql, 101, "can't happen: ", "avltreen_insert failed", " in do_cgi") ;
- default : die500x(rql, 101, "can't happen: ", "unknown tipidee_headers_parse return code", " in do_cgi") ;
+ case 400 : die502x(rql, 2, docroot, "invalid headers", " from cgi ", argv[0]) ;
+ case 413 : die502x(rql, 2, docroot, hdr->n >= TIPIDEE_HEADERS_MAX ? "Too many headers" : "Too much header data", " from cgi ", argv[0]) ;
+ case 500 : die500x(rql, 101, docroot, "can't happen: ", "avltreen_insert failed", " in do_cgi") ;
+ default : die500x(rql, 101, docroot, "can't happen: ", "unknown tipidee_headers_parse return code", " in do_cgi") ;
}
if (!rstate) break ;
}
@@ -227,13 +221,12 @@ static inline int run_cgi (tipidee_rql const *rql, char const *const *argv, char
if (!slurpn(x[0].fd, sa, g.maxcgibody))
{
if (error_isagain(errno)) break ;
- else if (errno == ENOBUFS) die502x(rql, 2, "Too fat body", " from cgi ", argv[0]) ;
- else die500sys(rql, 111, "read body", " from cgi ", argv[0]) ;
+ else if (errno == ENOBUFS) die502x(rql, 2, docroot, "Too fat body", " from cgi ", argv[0]) ;
+ else die500sys(rql, 111, docroot, "read body", " from cgi ", argv[0]) ;
}
close(x[0].fd) ;
x[0].fd = -1 ;
rstate = 2 ;
- LOLDEBUG("run_cgi: rstate = 2") ;
}
}
}
@@ -243,7 +236,7 @@ static inline int run_cgi (tipidee_rql const *rql, char const *const *argv, char
return rstate == 2 ;
}
-static inline int local_redirect (tipidee_rql *rql, char const *loc, char *uribuf, char const *cginame)
+static inline int local_redirect (tipidee_rql *rql, char const *docroot, char const *loc, char *uribuf, char const *cginame)
{
size_t n ;
size_t hostlen = strlen(rql->uri.host) ;
@@ -253,7 +246,7 @@ static inline int local_redirect (tipidee_rql *rql, char const *loc, char *uribu
memcpy(hosttmp, rql->uri.host, hostlen + 1) ;
n = tipidee_uri_parse(uribuf, URI_BUFSIZE, loc, &rql->uri) ;
if (!n || n + hostlen + 1 > URI_BUFSIZE)
- die502x(rql, 2, "cgi ", cginame, " returned an invalid ", "Location", " value", " for local redirection") ;
+ die502x(rql, 2, docroot, "cgi ", cginame, " returned an invalid ", "Location", " value", " for local redirection") ;
memcpy(uribuf + n, hosttmp, hostlen + 1) ;
rql->uri.host = uribuf + n ;
rql->uri.port = port ;
@@ -292,11 +285,11 @@ static inline void print_cgi_headers (tipidee_headers const *hdr, size_t rbodyle
buffer_putnoflush(buffer_1, "\r\n", 2) ;
}
-static inline int process_cgi_output (tipidee_rql *rql, tipidee_headers const *hdr, char const *rbody, size_t rbodylen, char *uribuf, char const *cginame)
+static inline int process_cgi_output (tipidee_rql *rql, char const *docroot, tipidee_headers const *hdr, char const *rbody, size_t rbodylen, char *uribuf, char const *cginame)
{
char const *location = tipidee_headers_search(hdr, "Location") ;
char const *x = tipidee_headers_search(hdr, "Status") ;
- char const *reason_phrase = "OK" ;
+ char const *reason = "OK" ;
unsigned int status = 0 ;
tain deadline ;
tain_add_g(&deadline, &g.writetto) ;
@@ -304,23 +297,28 @@ static inline int process_cgi_output (tipidee_rql *rql, tipidee_headers const *h
{
size_t m = uint_scan(x, &status) ;
if (!m || (x[m] && x[m] != ' '))
- die502x(rql, 2, "cgi ", cginame, " returned an invalid ", "Status", " header") ;
- reason_phrase = x[m] ? x + m + 1 : "" ;
+ die502x(rql, 2, docroot, "cgi ", cginame, " returned an invalid ", "Status", " header") ;
+ if (x[m]) reason = x + m + 1 ;
+ else
+ {
+ tipidee_defaulttext dt ;
+ reason = tipidee_util_defaulttext(status, &dt) ? dt.reason : "" ;
+ }
if (!location && (status == 301 || status == 302 || status == 307 || status == 308))
- die502x(rql, 2, "cgi ", cginame, " returned a redirection status code without a ", "Location", " header") ;
+ die502x(rql, 2, docroot, "cgi ", cginame, " returned a redirection status code without a ", "Location", " header") ;
if (status < 100 || status > 999)
- die502x(rql, 2, "cgi ", cginame, " returned an invalid ", "Status", " value") ;
+ die502x(rql, 2, docroot, "cgi ", cginame, " returned an invalid ", "Status", " value") ;
}
if (location)
{
- if (!location[0]) die502x(rql, 2, "cgi ", cginame, " returned an invalid ", "Location", " header") ;
- if (location[0] == '/' && location[1] != '/') return local_redirect(rql, location, uribuf, cginame) ;
+ if (!location[0]) die502x(rql, 2, docroot, "cgi ", cginame, " returned an invalid ", "Location", " header") ;
+ if (location[0] == '/' && location[1] != '/') return local_redirect(rql, docroot, location, uribuf, cginame) ;
if (rbodylen)
{
if (!status)
- die502x(rql, 2, "cgi ", cginame, " didn't output a ", "Status", " header", " for a client redirect response with document") ;
+ die502x(rql, 2, docroot, "cgi ", cginame, " didn't output a ", "Status", " header", " for a client redirect response with document") ;
if (status < 300 || status > 399)
- die502x(rql, 2, "cgi ", cginame, " returned an invalid ", "Status", " value", " for a client redirect response with document") ;
+ die502x(rql, 2, docroot, "cgi ", cginame, " returned an invalid ", "Status", " value", " for a client redirect response with document") ;
}
else
{
@@ -329,12 +327,12 @@ static inline int process_cgi_output (tipidee_rql *rql, tipidee_headers const *h
char const *key = hdr->buf + hdr->list[i].left ;
if (!strcasecmp(key, "Location") || !strcasecmp(key, "Status")) continue ;
if (str_start(key, "X-CGI-")) continue ;
- die502x(rql, 2, "cgi ", cginame, " returned extra headers", " for a client redirect response without document") ;
+ die502x(rql, 2, docroot, "cgi ", cginame, " returned extra headers", " for a client redirect response without document") ;
}
if (!status)
{
status = 302 ;
- reason_phrase = "Found" ;
+ reason = "Found" ;
}
}
}
@@ -342,19 +340,19 @@ static inline int process_cgi_output (tipidee_rql *rql, tipidee_headers const *h
{
if (!status) status = 200 ;
if (!tipidee_headers_search(hdr, "Content-Type"))
- die502x(rql, 2, "cgi ", cginame, " didn't output a ", "Content-Type", " header") ;
+ die502x(rql, 2, docroot, "cgi ", cginame, " didn't output a ", "Content-Type", " header") ;
}
x = tipidee_headers_search(hdr, "Content-Length") ;
if (x)
{
size_t cln ;
if (!size0_scan(x, &cln))
- die502x(rql, 2, "cgi ", cginame, " returned an invalid ", "Content-Length", " header") ;
+ die502x(rql, 2, docroot, "cgi ", cginame, " returned an invalid ", "Content-Length", " header") ;
if (cln != rbodylen)
- die502x(rql, 2, "cgi ", cginame, " returned a mismatching ", "Content-Length", " header") ;
+ die502x(rql, 2, docroot, "cgi ", cginame, " returned a mismatching ", "Content-Length", " header") ;
}
- tipidee_response_status(buffer_1, rql, status, reason_phrase) ;
+ tipidee_response_status(buffer_1, rql, status, reason) ;
tipidee_response_header_common_put_g(buffer_1, !g.cont) ;
print_cgi_headers(hdr, rbodylen) ;
if (buffer_timed_put_g(buffer_1, "\r\n", 2, &deadline) < 2)
@@ -370,26 +368,26 @@ static inline int process_cgi_output (tipidee_rql *rql, tipidee_headers const *h
return 0 ;
}
-static inline int do_cgi (tipidee_rql *rql, char const *const *argv, char const *const *envp, char const *body, size_t bodylen, char *uribuf)
+static inline int do_cgi (tipidee_rql *rql, char const *docroot, char const *const *argv, char const *const *envp, char const *body, size_t bodylen, char *uribuf)
{
static stralloc sa = STRALLOC_ZERO ;
tipidee_headers hdr ;
char hdrbuf[2048] ;
sa.len = 0 ;
tipidee_headers_init(&hdr, hdrbuf, 2048) ;
- if (!run_cgi(rql, argv, envp, body, bodylen, &hdr, &sa)) return 0 ;
- return process_cgi_output(rql, &hdr, sa.s, sa.len, uribuf, argv[0]) ;
+ if (!run_cgi(rql, docroot, argv, envp, body, bodylen, &hdr, &sa)) return 0 ;
+ return process_cgi_output(rql, docroot, &hdr, sa.s, sa.len, uribuf, argv[0]) ;
}
-int respond_cgi (tipidee_rql *rql, char const *fn, size_t docrootlen, char const *infopath, char *uribuf, tipidee_headers const *hdr, tipidee_resattr const *ra, char const *body, size_t bodylen)
+int respond_cgi (tipidee_rql *rql, char const *docroot, char const *fn, size_t docrootlen, char const *infopath, char *uribuf, tipidee_headers const *hdr, tipidee_resattr const *ra, char const *body, size_t bodylen)
{
size_t sabase = g.sa.len ;
size_t envmax = g.envlen + 16 + TIPIDEE_HEADERS_MAX ;
char const *argv[2] = { fn, 0 } ;
char const *envp[envmax] ;
- modify_env(rql, hdr, bodylen, fn + docrootlen, infopath) ;
+ modify_env(rql, docroot, hdr, bodylen, fn + docrootlen, infopath) ;
env_merge(envp, envmax, (char const *const *)environ, g.envlen, g.sa.s + g.cwdlen + 1, g.sa.len - (g.cwdlen+1)) ;
g.sa.len = sabase ;
- return ra->isnph ? do_nph(rql, argv, envp, body, bodylen) :
- do_cgi(rql, argv, envp, body, bodylen, uribuf) ;
+ return ra->isnph ? do_nph(rql, docroot, argv, envp, body, bodylen) :
+ do_cgi(rql, docroot, argv, envp, body, bodylen, uribuf) ;
}
diff --git a/src/tipideed/regular.c b/src/tipideed/regular.c
index 845f12b..aa937ad 100644
--- a/src/tipideed/regular.c
+++ b/src/tipideed/regular.c
@@ -4,7 +4,6 @@
#include <errno.h>
-#include <skalibs/uint64.h>
#include <skalibs/stat.h>
#include <skalibs/types.h>
#include <skalibs/buffer.h>
@@ -18,24 +17,12 @@
#include <tipidee/log.h>
#include "tipideed-internal.h"
-int respond_regular (tipidee_rql const *rql, char const *fn, struct stat const *st, tipidee_resattr const *ra)
+int respond_regular (tipidee_rql const *rql, char const *docroot, char const *fn, struct stat const *st, tipidee_resattr const *ra)
{
- tain deadline ;
- char fmt[128] ;
- size_t n = tipidee_response_status(buffer_1, rql, 200, "OK") ;
- n += tipidee_response_header_common_put_g(buffer_1, !g.cont) ;
- {
- size_t l = tipidee_response_header_lastmodified(fmt, 128, st) ;
- if (l) n += buffer_putnoflush(buffer_1, fmt, l) ;
- }
- n += buffer_putsnoflush(buffer_1, "Content-Type: ") ;
- n += buffer_putsnoflush(buffer_1, ra->content_type) ;
- n += buffer_putsnoflush(buffer_1, "\r\nContent-Length: ") ;
- fmt[uint64_fmt(fmt, st->st_size)] = 0 ;
- n += buffer_putsnoflush(buffer_1, fmt) ;
- n += buffer_putnoflush(buffer_1, "\r\n\r\n", 4) ;
if (rql->m == TIPIDEE_METHOD_HEAD)
{
+ tain deadline ;
+ tipidee_response_file_g(buffer_1, rql, 200, "OK", st, ra->content_type, 2 | !g.cont) ;
tipidee_log_answer(g.logv, rql, 200, st->st_size) ;
tain_add_g(&deadline, &g.writetto) ;
if (!buffer_timed_flush_g(buffer_1, &deadline))
@@ -46,14 +33,14 @@ int respond_regular (tipidee_rql const *rql, char const *fn, struct stat const *
int fd = open_read(fn) ;
if (fd == -1)
{
- buffer_unput(buffer_1, n) ;
if (errno == EACCES)
{
- respond_403(rql) ;
+ respond_403(rql, docroot) ;
return 0 ;
}
- else die500sys(rql, 111, "open ", fn) ;
+ else die500sys(rql, 111, docroot, "open ", fn) ;
}
+ tipidee_response_file_g(buffer_1, rql, 200, "OK", st, ra->content_type, 2 | !g.cont) ;
tipidee_log_answer(g.logv, rql, 200, st->st_size) ;
send_file(fd, st->st_size, fn) ;
fd_close(fd) ;
diff --git a/src/tipideed/responses.c b/src/tipideed/responses.c
index e5706e2..0d0840c 100644
--- a/src/tipideed/responses.c
+++ b/src/tipideed/responses.c
@@ -1,44 +1,99 @@
/* ISC license. */
+#include <skalibs/bsdsnowflake.h>
+
#include <unistd.h>
+#include <skalibs/stat.h>
#include <skalibs/types.h>
#include <skalibs/buffer.h>
#include <skalibs/strerr.h>
#include <skalibs/tai.h>
+#include <skalibs/djbunix.h>
#include <skalibs/unix-timed.h>
-#include <tipidee/rql.h>
#include <tipidee/log.h>
+#include <tipidee/util.h>
#include <tipidee/response.h>
#include "tipideed-internal.h"
-void response_error (tipidee_rql const *rql, unsigned int status, char const *rsl, char const *text, uint32_t options)
+void response_error_early (tipidee_rql const *rql, unsigned int status, char const *reason, char const *text, uint32_t options)
{
tain deadline ;
- tipidee_response_error(buffer_1, rql, status, rsl, text, options & 1 || !g.cont) ;
+ tipidee_response_error_nofile_g(buffer_1, rql, status, reason, text, options & 1 || !g.cont) ;
+ tain_add_g(&deadline, &g.writetto) ;
+ if (!buffer_timed_flush_g(buffer_1, &deadline))
+ strerr_diefu1sys(111, "write to stdout") ;
+}
+
+void response_error_early_and_exit (tipidee_rql const *rql, unsigned int status, char const *reason, char const *text)
+{
+ response_error_early(rql, status, reason, text, 1) ;
+ log_and_exit(1) ;
+}
+
+void response_error (tipidee_rql const *rql, char const *docroot, unsigned int status, uint32_t options)
+{
+ tain deadline ;
+ tipidee_defaulttext dt ;
+ char const *file = tipidee_conf_get_errorfile(&g.conf, docroot, status) ;
+ if (!tipidee_util_defaulttext(status, &dt))
+ {
+ char fmt[UINT_FMT] ;
+ fmt[uint_fmt(fmt, status)] = 0 ;
+ strerr_dief2x(101, "can't happen: unknown response code ", fmt) ;
+ }
+
+ if (file)
+ {
+ int fd = open_read(file) ;
+ if (fd == -1) strerr_warnwu3sys("open ", "custom error file ", file) ;
+ else
+ {
+ struct stat st ;
+ if (fstat(fd, &st) == -1)
+ {
+ fd_close(fd) ;
+ strerr_warnwu3sys("stat ", "custom error file ", file) ;
+ }
+ else if (!S_ISREG(st.st_mode))
+ {
+ fd_close(fd) ;
+ strerr_warnw3x("custom error file ", file, " is not a regular file") ;
+ }
+ else
+ {
+ tipidee_response_file_g(buffer_1, rql, status, dt.reason, &st, tipidee_conf_get_content_type(&g.conf, file), options) ;
+ tipidee_log_answer(g.logv, rql, status, st.st_size) ;
+ send_file(fd, st.st_size, file) ;
+ fd_close(fd) ;
+ return ;
+ }
+ }
+ }
+
+ tipidee_response_error_nofile_g(buffer_1, rql, status, dt.reason, dt.text, options & 1 || !g.cont) ;
+ tipidee_log_answer(g.logv, rql, status, 0) ;
tain_add_g(&deadline, &g.writetto) ;
- if (!(options & 2)) tipidee_log_answer(g.logv, rql, status, 0) ;
if (!buffer_timed_flush_g(buffer_1, &deadline))
strerr_diefu1sys(111, "write to stdout") ;
}
-void response_error_and_exit (tipidee_rql const *rql, unsigned int status, char const *rsl, char const *text, uint32_t options)
+void response_error_and_exit (tipidee_rql const *rql, char const *docroot, unsigned int status)
{
- response_error(rql, status, rsl, text, options | 1) ;
- tipidee_log_exit(g.logv, 0) ;
- _exit(0) ;
+ response_error(rql, docroot, status, 1) ;
+ log_and_exit(0) ;
}
-void response_error_and_die (tipidee_rql const *rql, int e, unsigned int status, char const *rsl, char const *text, char const *const *v, unsigned int n, uint32_t options)
+void response_error_and_die (tipidee_rql const *rql, int e, char const *docroot, unsigned int status, char const *const *v, unsigned int n, uint32_t options)
{
- response_error(rql, status, rsl, text, options | 1) ;
+ response_error(rql, docroot, status, options | 1) ;
if (options & 1) strerr_dievsys(e, v, n) ;
else strerr_diev(e, v, n) ;
}
-void exit_405 (tipidee_rql const *rql, uint32_t options)
+void exit_405_ (tipidee_rql const *rql, uint32_t options)
{
tain deadline ;
tipidee_response_status(buffer_1, rql, 405, "Method Not Allowed") ;
@@ -50,8 +105,7 @@ void exit_405 (tipidee_rql const *rql, uint32_t options)
tain_add_g(&deadline, &g.writetto) ;
if (!buffer_timed_flush_g(buffer_1, &deadline))
strerr_diefu1sys(111, "write to stdout") ;
- tipidee_log_exit(g.logv, 0) ;
- _exit(0) ;
+ log_and_exit(0) ;
}
void respond_30x (tipidee_rql const *rql, tipidee_redirection const *rd)
diff --git a/src/tipideed/tipideed-internal.h b/src/tipideed/tipideed-internal.h
index fe01152..a4f6d95 100644
--- a/src/tipideed/tipideed-internal.h
+++ b/src/tipideed/tipideed-internal.h
@@ -71,42 +71,38 @@ extern void tipideed_harden (unsigned int) ;
/* Responses */
-extern void response_error (tipidee_rql const *, unsigned int, char const *, char const *, uint32_t) ; /* set bit 0 for Connection: close, bit 1 for preexit */
-extern void response_error_and_exit (tipidee_rql const *, unsigned int, char const *, char const *, uint32_t) gccattr_noreturn ;
-extern void response_error_and_die (tipidee_rql const *, int e, unsigned int, char const *, char const *, char const *const *, unsigned int, uint32_t) gccattr_noreturn ;
-
- /*
- preexit is meant to be called before tipidee_log_request(), it won't log an answer line.
- Use for early parsing, when the request isn't even validated yet.
- exit is meant to be called after tipidee_log_request(), it will log an answer line.
- respond can only happen after tipidee_log_request(), it will log an answer line.
-
- exit will log an informational exit line.
- die will not; there will be a fatal line instead.
- die will log an answer line. There is no "predie", we just use strerr_die instead.
- */
-
-#define preexit_400(r, s) response_error_and_exit(r, 400, "Bad Request", s, 2)
-#define exit_400(r, s) response_error_and_exit(r, 400, "Bad Request", s, 0)
-extern void exit_405 (tipidee_rql const *, uint32_t) gccattr_noreturn ; /* set bit 0 for Allow: POST, bit 1 for preexit */
-#define preexit_408(r) response_error_and_exit(r, 408, "Request Timeout", "", 2)
-#define exit_408(r) response_error_and_exit(r, 408, "Request Timeout", "", 0)
-#define preexit_413(r, s) response_error_and_exit(r, 413, "Request Entity Too Large", s, 2)
-#define exit_413(r, s) response_error_and_exit(r, 413, "Request Entity Too Large", s, 0)
-#define preexit_501(r, s) response_error_and_exit(r, 501, "Not Implemented", s, 2)
-#define exit_501(r, s) response_error_and_exit(r, 501, "Not Implemented", s, 0)
-
-#define respond_403(r) response_error(r, 403, "Forbidden", "Missing credentials to access the URI.", 0)
-#define respond_404(r) response_error(r, 404, "Not Found", "The request URI was not found.", 0)
-#define respond_414(r) response_error(r, 414, "URI Too Long", "The request URI had an oversized component.", 0)
+extern void response_error_early (tipidee_rql const *, unsigned int, char const *, char const *, uint32_t) ; /* set bit 0 for Connection: close */
+extern void response_error_early_and_exit (tipidee_rql const *, unsigned int, char const *, char const *) gccattr_noreturn ;
+extern void exit_405_ (tipidee_rql const *, uint32_t) gccattr_noreturn ; /* set bit 0 for Allow: POST, bit 1 for preexit */
+
+#define eexit_400(r, s) response_error_early_and_exit(r, 400, "Bad Request", s)
+#define eexit_405(r) exit_405_((r), 3)
+#define eexit_408(r) response_error_early_and_exit((r), 408, "Request Timeout", 0)
+#define eexit_413(r, s) response_error_early_and_exit(r, 413, "Request Entity Too Large", s)
+#define eexit_501(r, s) response_error_early_and_exit(r, 501, "Not Implemented", s)
+
+
+extern void response_error (tipidee_rql const *, char const *, unsigned int, uint32_t) ; /* set bit 0 for Connection: close */
+extern void response_error_and_exit (tipidee_rql const *, char const *, unsigned int) gccattr_noreturn ;
+extern void response_error_and_die (tipidee_rql const *, int, char const *, unsigned int, char const *const *, unsigned int, uint32_t) gccattr_noreturn ; /* set bit 0 for diesys */
+
+#define exit_400(r, d) response_error_and_exit(r, (d), 400)
+#define exit_405(r) exit_405_((r), 0)
+#define exit_408(r, d) response_error_and_exit(r, (d), 408)
+#define exit_413(r, d) response_error_and_exit(r, (d), 413)
+#define exit_501(r, d) response_error_and_exit(r, (d), 501)
+
extern void respond_30x (tipidee_rql const *, tipidee_redirection const *) ;
-#define respond_504(r) response_error(r, 504, "Gateway Timeout", "The CGI script took too long to answer.", 0)
+#define respond_403(r, d) response_error(r, (d), 403, 0)
+#define respond_404(r, d) response_error(r, (d), 404, 0)
+#define respond_414(r, d) response_error(r, (d), 414, 0)
+#define respond_504(r, d) response_error(r, (d), 504, 0)
-#define diefx(r, e, status, rsl, text, ...) response_error_and_die(r, e, status, rsl, text, strerr_array(PROG, ": fatal: ", __VA_ARGS__), sizeof(strerr_array(__VA_ARGS__))/sizeof(char const *)+2, 0)
-#define diefusys(r, e, status, rsl, text, ...) response_error_and_die(r, e, status, rsl, text, strerr_array(PROG, ": fatal: ", "unable to ", __VA_ARGS__), sizeof(strerr_array(__VA_ARGS__))/sizeof(char const *)+3, 1)
-#define die500x(r, e, ...) diefx(r, e, 500, "Internal Server Error", "Bad server configuration.", __VA_ARGS__)
-#define die500sys(r, e, ...) diefusys(r, e, 500, "Internal Server Error", "System error.", __VA_ARGS__)
-#define die502x(r, e, ...) diefx(r, e, 502, "Bad Gateway", "Bad CGI script.", __VA_ARGS__)
+#define diefx(r, e, d, status, ...) response_error_and_die(r, e, d, status, strerr_array(PROG, ": fatal: ", __VA_ARGS__), sizeof(strerr_array(__VA_ARGS__))/sizeof(char const *)+2, 0)
+#define diefusys(r, e, d, status, ...) response_error_and_die(r, e, d, status, strerr_array(PROG, ": fatal: ", "unable to ", __VA_ARGS__), sizeof(strerr_array(__VA_ARGS__))/sizeof(char const *)+3, 1)
+#define die500x(r, e, d, ...) diefx(r, e, d, 500, __VA_ARGS__)
+#define die500sys(r, e, d, ...) diefusys(r, e, d, 500, __VA_ARGS__)
+#define die502x(r, e, d, ...) diefx(r, e, d, 502, __VA_ARGS__)
/* Trace */
@@ -127,12 +123,17 @@ extern void send_file (int, uint64_t, char const *) ;
/* regular */
-extern int respond_regular (tipidee_rql const *, char const *, struct stat const *, tipidee_resattr const *) ;
+extern int respond_regular (tipidee_rql const *, char const *, char const *, struct stat const *, tipidee_resattr const *) ;
extern int respond_304 (tipidee_rql const *, char const *, struct stat const *) ;
/* cgi */
-extern int respond_cgi (tipidee_rql *, char const *, size_t, char const *, char *, tipidee_headers const *, tipidee_resattr const *, char const *, size_t) ;
+extern int respond_cgi (tipidee_rql *, char const *, char const *, size_t, char const *, char *, tipidee_headers const *, tipidee_resattr const *, char const *, size_t) ;
+
+
+ /* main */
+
+extern void log_and_exit (int) gccattr_noreturn ;
#endif
diff --git a/src/tipideed/tipideed.c b/src/tipideed/tipideed.c
index fb5ede4..b004782 100644
--- a/src/tipideed/tipideed.c
+++ b/src/tipideed/tipideed.c
@@ -45,7 +45,7 @@ static void sigchld_handler (int sig)
wait_reap() ;
}
-static inline void log_and_exit (int e)
+void log_and_exit (int e)
{
tipidee_log_exit(g.logv, e) ;
_exit(e) ;
@@ -164,7 +164,7 @@ static void inittto (tain *tto, char const *key)
else *tto = tain_infinite_relative ;
}
-static inline unsigned int indexify (tipidee_rql const *rql, char *s, struct stat *st)
+static inline unsigned int indexify (tipidee_rql const *rql, char const *docroot, char *s, struct stat *st)
{
unsigned int e = 0 ;
size_t len = strlen(s) ;
@@ -184,22 +184,22 @@ static inline unsigned int indexify (tipidee_rql const *rql, char *s, struct sta
case ENAMETOOLONG : return 414 ;
case ENOTDIR : return 404 ;
case ENOENT : continue ;
- default : die500sys(rql, 111, "stat ", s) ;
+ default : die500sys(rql, 111, docroot, "stat ", s) ;
}
}
if (i >= g.indexn) return 404 ;
- if (S_ISDIR(st->st_mode)) die500x(rql, 103, "bad document hierarchy: ", s, " is a directory") ;
+ if (S_ISDIR(st->st_mode)) die500x(rql, 102, docroot, "bad document hierarchy: ", s, " is a directory") ;
if (e == 308) s[len] = 0 ;
return e ;
}
-static inline void get_resattr (tipidee_rql const *rql, char const *res, tipidee_resattr *ra)
+static inline void get_resattr (tipidee_rql const *rql, char const *docroot, char const *res, tipidee_resattr *ra)
{
static stralloc sa = STRALLOC_ZERO ;
sa.len = 0 ;
- if (sarealpath(&sa, res) == -1 || !stralloc_0(&sa)) die500sys(rql, 111, "realpath ", res) ;
+ if (sarealpath(&sa, res) == -1 || !stralloc_0(&sa)) die500sys(rql, 111, docroot, "realpath ", res) ;
if (strncmp(sa.s, g.sa.s, g.cwdlen) || sa.s[g.cwdlen] != '/')
- die500x(rql, 102, "resource ", res, " points outside of the server's root") ;
+ die500x(rql, 102, docroot, "resource ", res, " points outside of the server's root") ;
{
char const *attr = 0 ;
@@ -211,7 +211,7 @@ static inline void get_resattr (tipidee_rql const *rql, char const *res, tipidee
errno = ENOENT ;
while (!attr)
{
- if (errno != ENOENT) die500x(rql, 102, "invalid configuration data for ", key) ;
+ if (errno != ENOENT) die500x(rql, 102, docroot, "invalid configuration data for ", key) ;
while (len > 2 && key[len] != '/') len-- ;
if (len <= 2) break ;
key[len--] = 0 ;
@@ -220,7 +220,7 @@ static inline void get_resattr (tipidee_rql const *rql, char const *res, tipidee
}
if (attr)
{
- if (*attr < '@' || *attr > 'G') die500x(rql, 102, "invalid configuration data for ", key) ;
+ if (*attr < '@' || *attr > 'G') die500x(rql, 102, docroot, "invalid configuration data for ", key) ;
ra->iscgi = *attr & ~'@' & 1 ;
if (attr[1]) ra->content_type = attr + 1 ;
if (ra->iscgi)
@@ -243,7 +243,7 @@ static inline void get_resattr (tipidee_rql const *rql, char const *res, tipidee
if (!ra->iscgi && !ra->content_type)
{
ra->content_type = tipidee_conf_get_content_type(&g.conf, sa.s + g.cwdlen) ;
- if (!ra->content_type) die500sys(rql, 111, "get content type for ", sa.s + g.cwdlen) ;
+ if (!ra->content_type) die500sys(rql, 111, docroot, "get content type for ", sa.s + g.cwdlen) ;
}
}
@@ -276,7 +276,7 @@ static inline int serve (tipidee_rql *rql, char const *docroot, char *uribuf, ti
{
tipidee_redirection rd = TIPIDEE_REDIRECTION_ZERO ;
int e = tipidee_conf_get_redirection(&g.conf, docroot, docrootlen, rql->uri.path, &rd) ;
- if (e == -1) die500sys(rql, 111, "get redirection data for ", fn) ;
+ if (e == -1) die500sys(rql, 111, docroot, "get redirection data for ", fn) ;
if (e)
{
respond_30x(rql, &rd) ;
@@ -292,49 +292,49 @@ static inline int serve (tipidee_rql *rql, char const *docroot, char *uribuf, ti
for (;;)
{
while (fn[pos] != '/') pos-- ;
- if (pos <= docrootlen) { respond_404(rql) ; return 0 ; }
+ if (pos <= docrootlen) { respond_404(rql, docroot) ; return 0 ; }
fn[pos] = 0 ;
if (stat(fn, &st) == 0) break ;
switch (errno)
{
case ENOTDIR :
case ENOENT : fn[pos--] = '/' ; break ;
- case EACCES : respond_403(rql) ; return 0 ;
- case ENAMETOOLONG : respond_414(rql) ; return 0 ;
- default : die500sys(rql, 111, "stat ", fn) ;
+ case EACCES : respond_403(rql, docroot) ; return 0 ;
+ case ENAMETOOLONG : respond_414(rql, docroot) ; return 0 ;
+ default : die500sys(rql, 111, docroot, "stat ", fn) ;
}
}
infopath = fn + pos + 1 ;
}
if (S_ISDIR(st.st_mode))
{
- if (infopath) { respond_404(rql) ; return 0 ; }
- switch (indexify(rql, fn, &st))
+ if (infopath) { respond_404(rql, docroot) ; return 0 ; }
+ switch (indexify(rql, docroot, fn, &st))
{
- case 403 : respond_403(rql) ; return 0 ;
- case 404 : respond_404(rql) ; return 0 ;
- case 414 : respond_414(rql) ; return 0 ;
+ case 403 : respond_403(rql, docroot) ; return 0 ;
+ case 404 : respond_404(rql, docroot) ; return 0 ;
+ case 414 : respond_414(rql, docroot) ; return 0 ;
case 308 : force_redirect(rql, fn) ; return 0 ;
case 0 : break ;
}
}
- LOLDEBUG("serve: %s with %s %s, docroot %s", fn, infopath ? "infopath" : "no", infopath ? infopath : "infopath", docroot) ;
+ tipidee_log_debug(g.logv, "serve: docroot ", docroot, " file ", fn, " infopath ", infopath ? infopath : "(none)") ;
- get_resattr(rql, fn, &ra) ;
+ get_resattr(rql, docroot, fn, &ra) ;
if (!ra.iscgi)
{
- if (infopath) { respond_404(rql) ; return 0 ; }
- if (rql->m == TIPIDEE_METHOD_POST) exit_405(rql, 0) ;
+ if (infopath) { respond_404(rql, docroot) ; return 0 ; }
+ if (rql->m == TIPIDEE_METHOD_POST) exit_405(rql) ;
}
if (rql->m == TIPIDEE_METHOD_OPTIONS)
return respond_options(rql, 2 | ra.iscgi) ;
- tipidee_log_resource(g.logv, rql, docroot, fn, &ra) ;
+ tipidee_log_resource(g.logv, rql, fn, &ra, infopath) ;
if (ra.iscgi)
- return respond_cgi(rql, fn, docrootlen, infopath, uribuf, hdr, &ra, body, bodylen) ;
+ return respond_cgi(rql, docroot, fn, docrootlen, infopath, uribuf, hdr, &ra, body, bodylen) ;
infopath = tipidee_headers_search(hdr, "If-Modified-Since") ;
if (infopath)
@@ -345,7 +345,7 @@ static inline int serve (tipidee_rql *rql, char const *docroot, char *uribuf, ti
&& tain_less(&actual, &wanted))
return respond_304(rql, fn, &st) ;
}
- return respond_regular(rql, fn, &st, &ra) ;
+ return respond_regular(rql, docroot, fn, &st, &ra) ;
}
int main (int argc, char const *const *argv, char const *const *envp)
@@ -403,6 +403,8 @@ int main (int argc, char const *const *argv, char const *const *envp)
init_splice_pipe() ;
if (!sig_catch(SIGCHLD, &sigchld_handler))
strerr_diefu1sys(111, "set SIGCHLD handler") ;
+ if (!sig_altignore(SIGPIPE))
+ strerr_diefu1sys(111, "ignore SIGPIPE") ;
if (!tain_now_set_stopwatch_g())
strerr_diefu1sys(111, "initialize clock") ;
tipidee_log_start(g.logv, g.sa.s + remoteip, g.sa.s + remotehost) ;
@@ -430,14 +432,15 @@ int main (int argc, char const *const *argv, char const *const *envp)
e = tipidee_rql_read_g(buffer_0, uribuf, URI_BUFSIZE, &content_length, &rql, &deadline) ;
switch (e)
{
- case -1 : log_and_exit(1) ; /* Malicious or shitty client */
+ case -1 : log_and_exit(1) ; /* bad client */
case 0 : break ;
- case 99 : g.cont = 0 ; continue ; /* timeout, it's ok */
- case 400 : preexit_400(&rql, "Syntax error in request line") ;
+ case 98 : /* client exited */
+ case 99 : g.cont = 0 ; continue ; /* timeout */
+ case 400 : eexit_400(&rql, "Syntax error in request line") ;
default : strerr_dief2x(101, "can't happen: ", "unknown tipidee_rql_read return code") ;
}
if (rql.http_major != 1) log_and_exit(1) ;
- if (rql.http_minor > 1) preexit_400(&rql, "Bad HTTP version") ;
+ if (rql.http_minor > 1) eexit_400(&rql, "Bad HTTP version") ;
content_length = 0 ;
tipidee_headers_init(&hdr, hdrbuf, HDR_BUFSIZE) ;
@@ -446,9 +449,9 @@ int main (int argc, char const *const *argv, char const *const *envp)
{
case -1 : log_and_exit(1) ; /* connection issue, client timeout, etc. */
case 0 : break ;
- case 400 : preexit_400(&rql, "Syntax error in headers") ;
- case 408 : preexit_408(&rql) ; /* timeout */
- case 413 : preexit_413(&rql, hdr.n >= TIPIDEE_HEADERS_MAX ? "Too many headers" : "Too much header data") ;
+ case 400 : eexit_400(&rql, "Syntax error in headers") ;
+ case 408 : eexit_408(&rql) ; /* timeout */
+ case 413 : eexit_413(&rql, hdr.n >= TIPIDEE_HEADERS_MAX ? "Too many headers" : "Too much header data") ;
case 500 : strerr_dief2x(101, "can't happen: ", "avltreen_insert failed") ;
default : strerr_dief2x(101, "can't happen: ", "unknown tipidee_headers_parse return code") ;
}
@@ -467,7 +470,7 @@ int main (int argc, char const *const *argv, char const *const *envp)
x = tipidee_headers_search(&hdr, "Transfer-Encoding") ;
if (x)
{
- if (strcasecmp(x, "chunked")) preexit_400(&rql, "unsupported Transfer-Encoding") ;
+ if (strcasecmp(x, "chunked")) eexit_400(&rql, "unsupported Transfer-Encoding") ;
else tcoding = TIPIDEE_TRANSFERCODING_CHUNKED ;
}
else
@@ -475,7 +478,7 @@ int main (int argc, char const *const *argv, char const *const *envp)
x = tipidee_headers_search(&hdr, "Content-Length") ;
if (x)
{
- if (!size_scan(x, &content_length)) preexit_400(&rql, "Invalid Content-Length") ;
+ if (!size_scan(x, &content_length)) eexit_400(&rql, "Invalid Content-Length") ;
else if (content_length) tcoding = TIPIDEE_TRANSFERCODING_FIXED ;
else tcoding = TIPIDEE_TRANSFERCODING_NONE ;
}
@@ -483,7 +486,7 @@ int main (int argc, char const *const *argv, char const *const *envp)
}
if (tcoding != TIPIDEE_TRANSFERCODING_NONE && rql.m != TIPIDEE_METHOD_POST)
- preexit_400(&rql, "only POST requests can have an entity body") ;
+ eexit_400(&rql, "only POST requests can have an entity body") ;
switch (rql.m)
{
@@ -495,9 +498,9 @@ int main (int argc, char const *const *argv, char const *const *envp)
if (!rql.uri.path) { respond_options(&rql, 1) ; continue ; }
break ;
case TIPIDEE_METHOD_PUT :
- case TIPIDEE_METHOD_DELETE : exit_405(&rql, 3) ;
- case TIPIDEE_METHOD_CONNECT : preexit_501(&rql, "CONNECT method unsupported") ;
- case TIPIDEE_METHOD_PRI : preexit_501(&rql, "PRI method attempted with HTTP version 1") ;
+ case TIPIDEE_METHOD_DELETE : eexit_405(&rql) ;
+ case TIPIDEE_METHOD_CONNECT : eexit_501(&rql, "CONNECT method unsupported") ;
+ case TIPIDEE_METHOD_PRI : eexit_501(&rql, "PRI method attempted with HTTP version 1") ;
default : strerr_dief2x(101, "can't happen: ", "unknown HTTP method") ;
}
@@ -509,13 +512,13 @@ int main (int argc, char const *const *argv, char const *const *envp)
char *p = strchr(x, ':') ;
if (p)
{
- if (!uint160_scan(p+1, &rql.uri.port)) preexit_400(&rql, "Invalid Host header") ;
+ if (!uint160_scan(p+1, &rql.uri.port)) eexit_400(&rql, "Invalid Host header") ;
*p = 0 ;
}
- if (!*x || *x == '.') preexit_400(&rql, "Invalid Host header") ;
+ if (!*x || *x == '.') eexit_400(&rql, "Invalid Host header") ;
rql.uri.host = x ;
}
- else if (!rql.uri.host) preexit_400(&rql, "Missing Host header") ;
+ else if (!rql.uri.host) eexit_400(&rql, "Missing Host header") ;
}
else if (!rql.uri.host) rql.uri.host = g.defaulthost ;
if (!rql.uri.port) rql.uri.port = g.defaultport ;
@@ -541,12 +544,12 @@ int main (int argc, char const *const *argv, char const *const *envp)
{
case TIPIDEE_TRANSFERCODING_FIXED :
{
- if (content_length > g.maxrqbody) exit_413(&rql, "Request body too large") ;
- if (!stralloc_ready(&bodysa, content_length)) die500sys(&rql, 111, "stralloc_ready") ;
+ if (content_length > g.maxrqbody) exit_413(&rql, docroot) ;
+ if (!stralloc_ready(&bodysa, content_length)) die500sys(&rql, 111, docroot, "stralloc_ready") ;
if (buffer_timed_get_g(buffer_0, bodysa.s, content_length, &deadline) < content_length)
{
- if (errno == ETIMEDOUT) exit_408(&rql) ;
- else exit_400(&rql, "Request body does not match Content-Length") ;
+ if (errno == ETIMEDOUT) exit_408(&rql, docroot) ;
+ else exit_400(&rql, docroot) ;
}
bodysa.len = content_length ;
break ;
@@ -555,9 +558,9 @@ int main (int argc, char const *const *argv, char const *const *envp)
{
if (!tipidee_util_chunked_read_g(buffer_0, &bodysa, g.maxrqbody, &deadline))
{
- if (error_temp(errno)) die500sys(&rql, 111, "decode chunked body") ;
- else if (errno == EMSGSIZE) exit_413(&rql, "Request body too large") ;
- else exit_400(&rql, "Invalid chunked body") ;
+ if (error_temp(errno)) die500sys(&rql, 111, docroot, "decode chunked body") ;
+ else if (errno == EMSGSIZE) exit_413(&rql, docroot) ;
+ else exit_400(&rql, docroot) ;
}
break ;
}
@@ -569,8 +572,9 @@ int main (int argc, char const *const *argv, char const *const *envp)
while (serve(&rql, docroot, uribuf, &hdr, bodysa.s, bodysa.len))
if (localredirs++ >= MAX_LOCALREDIRS)
- die502x(&rql, 2, "too many local redirections - possible loop involving path ", rql.uri.path) ;
+ die502x(&rql, 2, docroot, "too many local redirections - possible loop involving path ", rql.uri.path) ;
}
}
+
log_and_exit(0) ;
}