mirror of https://github.com/nealey/eris.git
remove "#if 0" sections (they will come back later)
This commit is contained in:
parent
36ec9d4466
commit
78ec64f506
723
eris.c
723
eris.c
|
@ -169,9 +169,9 @@ badrequest(long code, const char *httpcomment, const char *message)
|
|||
size_t
|
||||
extract_header_field(char *buf, char **val, int cgi)
|
||||
{
|
||||
size_t len;
|
||||
size_t pos = 0; /* Input */
|
||||
size_t len = 0; /* Output */
|
||||
|
||||
*val = NULL;
|
||||
for (len = 0; buf[len]; len += 1) {
|
||||
if (! *val) {
|
||||
if (buf[len] == ':') {
|
||||
|
@ -202,361 +202,7 @@ extract_header_field(char *buf, char **val, int cgi)
|
|||
}
|
||||
|
||||
|
||||
#define CGIENVLEN 21
|
||||
|
||||
static const char *cgivars[CGIENVLEN] = {
|
||||
"GATEWAY_INTERFACE=",
|
||||
"SERVER_PROTOCOL=",
|
||||
"SERVER_SOFTWARE=",
|
||||
"SERVER_NAME=",
|
||||
"SERVER_PORT=",
|
||||
"REQUEST_METHOD=",
|
||||
"REQUEST_URI=",
|
||||
"SCRIPT_NAME=",
|
||||
"REMOTE_ADDR=",
|
||||
"REMOTE_PORT=",
|
||||
"REMOTE_IDENT=",
|
||||
"HTTP_USER_AGENT=",
|
||||
"HTTP_COOKIE=",
|
||||
"HTTP_REFERER=",
|
||||
"HTTP_ACCEPT_ENCODING=",
|
||||
"AUTH_TYPE=",
|
||||
"CONTENT_TYPE=",
|
||||
"CONTENT_LENGTH=",
|
||||
"QUERY_STRING=",
|
||||
"PATH_INFO=",
|
||||
"PATH_TRANSLATED="
|
||||
};
|
||||
|
||||
static int
|
||||
iscgivar(const char *s)
|
||||
{
|
||||
int sl = strlen(s);
|
||||
register unsigned int i = 0;
|
||||
|
||||
for (; i < CGIENVLEN; i++)
|
||||
if (!strncmp(s, cgivars[i], sl))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
elen(register const char *const *e)
|
||||
{
|
||||
register unsigned int i = 0;
|
||||
while (e[i])
|
||||
i++;
|
||||
return i;
|
||||
}
|
||||
|
||||
char *
|
||||
env_append(const char *key, const char *val)
|
||||
{
|
||||
static char buf[MAXHEADERLEN * 2 + PATH_MAX + 200];
|
||||
static char *p = buf;
|
||||
char *ret = p;
|
||||
|
||||
if (!key) {
|
||||
p = buf;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = stpcpy(p, key);
|
||||
*(p++) = '=';
|
||||
if (val) {
|
||||
p = stpcpy(p, val) + 1;
|
||||
} else {
|
||||
*(p++) = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
static void
|
||||
do_cgi(const char *pathinfo, const char *const *envp)
|
||||
{
|
||||
const char *method_name[] = { "?", "GET", "HEAD", "POST" };
|
||||
register unsigned int en = elen(envp);
|
||||
char **cgi_arg;
|
||||
register int i;
|
||||
char **cgi_env =
|
||||
(char **) alloca((CGIENVLEN + en + 1) * sizeof(char *));
|
||||
|
||||
cgi_env[0] = "GATEWAY_INTERFACE=CGI/1.1";
|
||||
cgi_env[1] = "SERVER_PROTOCOL=HTTP/1.0";
|
||||
cgi_env[2] = "SERVER_SOFTWARE=" FNORD;
|
||||
|
||||
i = 3;
|
||||
env_append(NULL, NULL);
|
||||
cgi_env[i++] = env_append("SERVER_NAME", host);
|
||||
cgi_env[i++] = env_append("SERVER_PORT", port);
|
||||
cgi_env[i++] = env_append("REQUEST_METHOD", method_name[method]);
|
||||
cgi_env[i++] = env_append("REQUEST_URI", uri);
|
||||
cgi_env[i++] = env_append("SCRIPT_NAME", path);
|
||||
if (remote_ip)
|
||||
cgi_env[i++] = env_append("REMOTE_ADDR", remote_ip);
|
||||
if (remote_port)
|
||||
cgi_env[i++] = env_append("REMOTE_PORT", remote_port);
|
||||
if (remote_ident)
|
||||
cgi_env[i++] = env_append("REMOTE_IDENT", remote_ident);
|
||||
if (ua)
|
||||
cgi_env[i++] = env_append("HTTP_USER_AGENT", ua);
|
||||
if (cookie)
|
||||
cgi_env[i++] = env_append("HTTP_COOKIE", cookie);
|
||||
if (refer)
|
||||
cgi_env[i++] = env_append("HTTP_REFERER", refer);
|
||||
if (accept_enc)
|
||||
cgi_env[i++] = env_append("HTTP_ACCEPT_ENCODING", accept_enc);
|
||||
if (auth_type)
|
||||
cgi_env[i++] = env_append("AUTH_TYPE", auth_type);
|
||||
if (content_type)
|
||||
cgi_env[i++] = env_append("CONTENT_TYPE", content_type);
|
||||
if (content_type)
|
||||
cgi_env[i++] = env_append("CONTENT_LENGTH", content_len);
|
||||
if (args)
|
||||
cgi_env[i++] = env_append("QUERY_STRING", args);
|
||||
if (pathinfo) {
|
||||
char *rp = realpath(pathinfo, NULL);
|
||||
|
||||
cgi_env[i++] = env_append("PATH_INFO", pathinfo);
|
||||
cgi_env[i++] = env_append("PATH_TRANSLATED", rp ? rp : pathinfo);
|
||||
if (rp)
|
||||
free(rp);
|
||||
}
|
||||
|
||||
{
|
||||
unsigned int j = 0;
|
||||
for (; j < en; j++)
|
||||
if (!iscgivar(envp[j]))
|
||||
cgi_env[++i] = (char *) envp[j];
|
||||
}
|
||||
cgi_env[++i] = 0;
|
||||
|
||||
/*
|
||||
* argv
|
||||
*/
|
||||
if (args && (strchr(args, '=') == 0)) {
|
||||
int n = 3;
|
||||
for (i = 0; args[i]; ++i)
|
||||
if (args[i] == '+')
|
||||
++n;
|
||||
cgi_arg = alloca(n * sizeof(char *));
|
||||
cgi_arg[n = 1] = args;
|
||||
for (i = 0; args[i]; ++i) {
|
||||
if (args[i] == '+') {
|
||||
args[i] = 0;
|
||||
++i;
|
||||
cgi_arg[++n] = args + i;
|
||||
}
|
||||
}
|
||||
cgi_arg[++n] = 0;
|
||||
} else {
|
||||
cgi_arg = alloca(2 * sizeof(char *));
|
||||
cgi_arg[1] = 0;
|
||||
}
|
||||
|
||||
{
|
||||
char tmp[PATH_MAX];
|
||||
|
||||
DUMP_s(rpath);
|
||||
i = strrchr(rpath, '/') - rpath;
|
||||
if (i) {
|
||||
strncpy(tmp, rpath + 1, i);
|
||||
tmp[i] = 0;
|
||||
chdir(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
char tmp[PATH_MAX];
|
||||
|
||||
/*
|
||||
* program name
|
||||
*/
|
||||
cgi_arg[0] = tmp;
|
||||
tmp[0] = '.';
|
||||
strcpy(tmp + 1, rpath + i);
|
||||
|
||||
/*
|
||||
* start cgi
|
||||
*/
|
||||
execve(cgi_arg[0], cgi_arg, cgi_env);
|
||||
raise(SIGQUIT); /* gateway unavailable. */
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cgi_child(int sig)
|
||||
{
|
||||
int n,
|
||||
pid = waitpid(0, &n, WNOHANG);
|
||||
if (pid > 0) {
|
||||
if (WIFSIGNALED(n)) {
|
||||
if (WTERMSIG(n) == SIGALRM) {
|
||||
/* XXX: should kill children here */
|
||||
badrequest(504, "Gateway Timeout",
|
||||
"Gateway has run too long.");
|
||||
} else {
|
||||
badrequest(502, "Bad Gateway",
|
||||
"Gateway broken or unavailable.");
|
||||
}
|
||||
}
|
||||
}
|
||||
signal(SIGCHLD, cgi_child);
|
||||
}
|
||||
|
||||
static void
|
||||
start_cgi(int nph, const char *pathinfo, const char *const *envp)
|
||||
{
|
||||
// XXX: would it be safe to reuse headerbuf from main?
|
||||
size_t size = 0;
|
||||
int pid;
|
||||
char cgiheader[BUFFER_SIZE];
|
||||
size_t cgiheaderlen = BUFFER_SIZE;
|
||||
int cin[2];
|
||||
int cout[2];
|
||||
FILE *cinf;
|
||||
|
||||
if (pipe(cin) || pipe(cout) || !(cinf = fdopen(cin[0], "rb"))) {
|
||||
badrequest(500, "Internal Server Error",
|
||||
"Server Resource problem.");
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
if (-1 == pid) {
|
||||
badrequest(500, "Internal Server Error",
|
||||
"Unable to fork.");
|
||||
}
|
||||
if (pid) {
|
||||
/* Parent */
|
||||
int passthru = nph;
|
||||
|
||||
fcntl(cin[0], F_SETFL, O_NONBLOCK);
|
||||
signal(SIGCHLD, cgi_child);
|
||||
signal(SIGPIPE, SIG_IGN); /* NO! no signal! */
|
||||
|
||||
close(cin[1]);
|
||||
close(cout[0]);
|
||||
|
||||
alarm(CGI_TIMEOUT);
|
||||
|
||||
while (1) {
|
||||
int nfds;
|
||||
fd_set rfds, wfds;
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
FD_ZERO(&wfds);
|
||||
FD_SET(cin[0], &rfds);
|
||||
nfds = cin[0];
|
||||
|
||||
if (post_len) {
|
||||
/* have post data */
|
||||
FD_SET(cout[1], &wfds);
|
||||
if (cout[1] > nfds) {
|
||||
nfds = cout[1];
|
||||
}
|
||||
} else if (cout[1] >= 0) {
|
||||
close(cout[1]); /* no post data */
|
||||
cout[1] = -1;
|
||||
}
|
||||
|
||||
if (-1 == select(nfds+1, &rfds, &wfds, NULL, NULL)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (FD_ISSET(cin[0], &rfds)) {
|
||||
if (passthru) {
|
||||
size_t len;
|
||||
|
||||
/* Re-use this big buffer */
|
||||
len = fread(cgiheader, 1, sizeof cgiheader, cinf);
|
||||
if (0 == len) {
|
||||
/* CGI is done */
|
||||
break;
|
||||
}
|
||||
fwrite(cgiheader, 1, len, stdout);
|
||||
size += len;
|
||||
} else {
|
||||
int ret;
|
||||
|
||||
ret = read_header(cinf, cgiheader, &cgiheaderlen);
|
||||
if (0 == ret) {
|
||||
/* Call read_header again */
|
||||
} else if (-1 == ret) {
|
||||
/* EOF or error */
|
||||
badrequest(500, "CGI Error",
|
||||
"CGI output too weird");
|
||||
} else {
|
||||
/* Entire header is in memory now */
|
||||
passthru = 1;
|
||||
|
||||
/* XXX: I think we need to look for Location:
|
||||
* anywhere, but fnord got away with checking
|
||||
* only the first header field, so I will too.
|
||||
*/
|
||||
if (memcmp(cgiheader, "Location: ", 10) == 0) {
|
||||
retcode = 302;
|
||||
printf
|
||||
("HTTP/1.0 302 CGI-Redirect\r\nConnection: close\r\n");
|
||||
fwrite(cgiheader, 1, cgiheaderlen, stdout);
|
||||
dolog(0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
retcode = 200;
|
||||
printf("HTTP/1.0 200 OK\r\nServer: "
|
||||
FNORD
|
||||
"\r\nPragma: no-cache\r\nConnection: close\r\n");
|
||||
signal(SIGCHLD, SIG_IGN);
|
||||
fwrite(cgiheader, 1, cgiheaderlen, stdout);
|
||||
}
|
||||
}
|
||||
} else if (FD_ISSET(cout[1], &wfds)) {
|
||||
/*
|
||||
* write to cgi the post data
|
||||
*/
|
||||
if (post_len) {
|
||||
size_t len;
|
||||
char buf[BUFFER_SIZE];
|
||||
size_t nmemb = min(BUFFER_SIZE, post_len);
|
||||
|
||||
len = fread(buf, 1, nmemb, stdin);
|
||||
if (len < 1) {
|
||||
break;
|
||||
}
|
||||
post_len -= len;
|
||||
write(cout[1], buf, len);
|
||||
} else {
|
||||
close(cout[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
alarm(0);
|
||||
|
||||
fflush(stdout);
|
||||
dolog(size);
|
||||
cork(0);
|
||||
} else {
|
||||
/* Child */
|
||||
|
||||
close(cout[1]);
|
||||
close(cin[0]);
|
||||
|
||||
dup2(cout[0], 0);
|
||||
dup2(cin[1], 1);
|
||||
|
||||
close(cout[0]);
|
||||
close(cin[1]);
|
||||
|
||||
do_cgi(pathinfo, envp);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
int
|
||||
fromhex(int c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
|
@ -849,334 +495,6 @@ timerfc(const char *s)
|
|||
1969L) >> 2))));
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* try to return a file
|
||||
*/
|
||||
static int
|
||||
doit(char *headerbuf, size_t headerlen, char *url)
|
||||
{
|
||||
int fd = -1;
|
||||
char *accept;
|
||||
|
||||
while (url[0] == '/')
|
||||
++url;
|
||||
if ((fd = open(url, O_RDONLY)) >= 0) {
|
||||
if (fstat(fd, &st))
|
||||
goto bad;
|
||||
/*
|
||||
* no directories
|
||||
*/
|
||||
if (S_ISDIR(st.st_mode))
|
||||
goto bad;
|
||||
/*
|
||||
* see if the document has been changed
|
||||
*/
|
||||
{
|
||||
char *field =
|
||||
header(headerbuf, headerlen, "If-Modified-Since");
|
||||
|
||||
if (field) {
|
||||
time_t ims;
|
||||
|
||||
ims = timerfc(field);
|
||||
if ((ims != (time_t) - 1) && (st.st_mtime <= ims)) {
|
||||
retcode = 304;
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
}
|
||||
rangestart = 0;
|
||||
rangeend = st.st_size;
|
||||
if ((accept = header(headerbuf, headerlen, "Range"))) {
|
||||
/*
|
||||
* format: "bytes=17-23", "bytes=23-"
|
||||
*/
|
||||
if (!strncmp(accept, "bytes=", 6)) {
|
||||
accept += 6;
|
||||
rangestart = strtorange(accept, &accept, 10);
|
||||
if (*accept == '-') {
|
||||
++accept;
|
||||
if (*accept) {
|
||||
rangeend = strtorange(accept, &accept, 10);
|
||||
if (!*accept) {
|
||||
rangeend = st.st_size;
|
||||
} else {
|
||||
++rangeend;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rangestart > rangeend || rangeend > st.st_size) {
|
||||
retcode = 416;
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
return fd;
|
||||
bad:
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
redirectboilerplate()
|
||||
{
|
||||
printf
|
||||
("HTTP/1.0 301 Go Away\r\nConnection: close\r\nContent-Length: 0\r\nLocation: ");
|
||||
}
|
||||
|
||||
static void
|
||||
handleredirect(const char *url, const char *origurl)
|
||||
{
|
||||
char symlink[1024];
|
||||
int len;
|
||||
|
||||
while (*url == '/')
|
||||
++url;
|
||||
if ((len = readlink(url, symlink, 1023)) > 0) {
|
||||
/*
|
||||
* el-cheapo redirection
|
||||
*/
|
||||
redirectboilerplate();
|
||||
printf("%.*s", len, symlink);
|
||||
retcode = 301;
|
||||
printf("\r\n\r\n");
|
||||
dolog(0);
|
||||
fflush(stdout);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hdl_encode_html(const char *s, unsigned int sl)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < sl; ++i) {
|
||||
unsigned char ch = s[i];
|
||||
if (ch > 159) {
|
||||
printf("&#%u;", ch);
|
||||
} else if ((ch > 128) || (ch < 32)) {
|
||||
putchar('_');
|
||||
} else if (ch == '"')
|
||||
fputs(""", stdout);
|
||||
else if (ch == '&')
|
||||
fputs("&", stdout);
|
||||
else if (ch == '<')
|
||||
fputs("<", stdout);
|
||||
else if (ch == '>')
|
||||
fputs(">", stdout);
|
||||
else
|
||||
putchar(ch);
|
||||
}
|
||||
}
|
||||
static void
|
||||
hdl_encode_uri(const char *s, unsigned int sl)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < sl; ++i) {
|
||||
unsigned char ch = s[i];
|
||||
if ((ch != '%') && (ch > 32) && (ch < 127))
|
||||
putchar(ch);
|
||||
else
|
||||
printf("%%%02x", ch);
|
||||
}
|
||||
}
|
||||
static void
|
||||
handledirlist(const char *origurl)
|
||||
{
|
||||
DIR *dir;
|
||||
unsigned int nl;
|
||||
const char *nurl = origurl;
|
||||
|
||||
while (nurl[0] == '/')
|
||||
++nurl;
|
||||
if (nurl <= origurl)
|
||||
return;
|
||||
nl = strlen(nurl);
|
||||
if (nl && (nurl[nl - 1] != '/'))
|
||||
return;
|
||||
if (!stat(nl ? nurl : ".", &st) && (S_ISDIR(st.st_mode))
|
||||
&& ((st.st_mode & S_IRWXO) == 5)) {
|
||||
if (nl)
|
||||
chdir(nurl);
|
||||
if ((dir = opendir("."))) {
|
||||
struct dirent *de;
|
||||
unsigned int i,
|
||||
size = 32 + nl;
|
||||
fputs("HTTP/1.0 200 OK\r\nServer: " FNORD
|
||||
"\r\nConnection: close\r\n", stdout);
|
||||
fputs("Content-Type: text/html; charset=utf-8\r\n", stdout);
|
||||
fputs("\r\n<h3>Directory Listing: /", stdout);
|
||||
hdl_encode_html(nurl, nl);
|
||||
fputs("</h3>\n<pre>\n", stdout);
|
||||
if (nl != 0) {
|
||||
for (i = nl - 2; i > 0; --i)
|
||||
if (nurl[i] == '/')
|
||||
break;
|
||||
fputs("<a href=\"", stdout);
|
||||
fputs("/", stdout);
|
||||
hdl_encode_uri(nurl, i);
|
||||
if (i > 0)
|
||||
fputs("/", stdout);
|
||||
fputs("\">Parent directory", stdout);
|
||||
fputs("</a>\n", stdout);
|
||||
size += 40 + i;
|
||||
}
|
||||
while ((de = readdir(dir))) {
|
||||
char symlink[1024];
|
||||
char *p = de->d_name;
|
||||
unsigned int pl,
|
||||
dl = strlen(de->d_name);
|
||||
pl = dl;
|
||||
if (de->d_name[0] == '.')
|
||||
continue; /* hidden files -> skip */
|
||||
if (lstat(de->d_name, &st))
|
||||
continue; /* can't stat -> skip */
|
||||
if (S_ISDIR(st.st_mode))
|
||||
fputs("[DIR] ", stdout);
|
||||
else if (S_ISLNK(st.st_mode)) {
|
||||
if ((pl = readlink(de->d_name, symlink, 1023)) < 1)
|
||||
continue;
|
||||
p = symlink;
|
||||
fputs("[LNK] ", stdout); /* a symlink to *
|
||||
* something ... */
|
||||
} else if (S_ISREG(st.st_mode))
|
||||
fputs("[TXT] ", stdout);
|
||||
else
|
||||
continue; /* not a file we can provide -> skip */
|
||||
/*
|
||||
* write a href
|
||||
*/
|
||||
fputs("<a href=\"", stdout);
|
||||
hdl_encode_uri(p, pl);
|
||||
if (S_ISDIR(st.st_mode))
|
||||
fputs("/", stdout), ++size;
|
||||
fputs("\">", stdout);
|
||||
if (de->d_name[0] == ':')
|
||||
de->d_name[0] = '.'; /* fnord special ... */
|
||||
hdl_encode_html(de->d_name, dl);
|
||||
fputs("</a>\n", stdout);
|
||||
size += 22 + (dl << 1);
|
||||
}
|
||||
closedir(dir);
|
||||
fputs("</pre>\n", stdout);
|
||||
fflush(stdout);
|
||||
retcode = 200;
|
||||
dolog(size);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
handleindexcgi(const char *testurl, const char *origurl, char *space)
|
||||
{
|
||||
unsigned int ul,
|
||||
ol = strlen(origurl);
|
||||
char *test;
|
||||
while (testurl[0] == '/')
|
||||
++testurl, --ol;
|
||||
ul = strlen(testurl);
|
||||
if (strcmp(testurl + ol, "index.html"))
|
||||
return 0; /* no request for index.html */
|
||||
test = space;
|
||||
++test;
|
||||
ul -= 4;
|
||||
memcpy(test, testurl, ul);
|
||||
test[ul] = 'c';
|
||||
test[++ul] = 'g';
|
||||
test[++ul] = 'i';
|
||||
test[++ul] = 0;
|
||||
if (stat(test, &st))
|
||||
return 0; /* no index.cgi present */
|
||||
ul = 1;
|
||||
if (st.st_gid == getegid())
|
||||
ul = 010;
|
||||
if (st.st_uid == geteuid())
|
||||
ul = 0100;
|
||||
if (!(st.st_mode & ul))
|
||||
return 0; /* should be executable */
|
||||
*(--test) = '/';
|
||||
|
||||
strncpy(rpath, test, sizeof rpath);
|
||||
return 1; /* Wow... now start "index.cgi" */
|
||||
}
|
||||
|
||||
static int
|
||||
findcgi(const char *c)
|
||||
{
|
||||
return (c[0] == '.' && c[1] == 'c' &&
|
||||
c[2] == 'g' && c[3] == 'i' && (c[4] == '/' || c[4] == 0));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fake_sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
|
||||
{
|
||||
char buf[BUFFER_SIZE];
|
||||
ssize_t l, m;
|
||||
|
||||
/* is mmap quicker? does it matter? */
|
||||
if (rangestart && (*offset == rangestart)) {
|
||||
if (-1 == lseek(in_fd, *offset, SEEK_SET)) {
|
||||
/* We're screwed. The most helpful thing we can do now is die. */
|
||||
fprintf(stderr, "Unable to seek. Dying.\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
l = read(in_fd, buf, min(count, sizeof buf));
|
||||
if (-1 == l) {
|
||||
/* Also screwed. */
|
||||
fprintf(stderr, "Unable to read an open file. Dying.\n");
|
||||
exit(0);
|
||||
}
|
||||
*offset += l;
|
||||
|
||||
while (l) {
|
||||
m = write(out_fd, buf, l);
|
||||
if (-1 == m) {
|
||||
/* ALSO screwed. */
|
||||
fprintf(stderr, "Unable to write to client. Dying.\n");
|
||||
exit(0);
|
||||
}
|
||||
l -= m;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* write from offset "rangestart" to offset "rangeend" to stdout
|
||||
*/
|
||||
static int
|
||||
serve_static_data(int fd)
|
||||
{
|
||||
off_t len = rangeend - rangestart;
|
||||
off_t offset = rangestart;
|
||||
|
||||
/* XXX: A comment here asserted that files with length < 4096 were
|
||||
* faster to send with a read and write. Test this. */
|
||||
|
||||
cork(1);
|
||||
fflush(stdout);
|
||||
|
||||
while (len) {
|
||||
size_t count = min(len, SIZE_MAX);
|
||||
ssize_t sent;
|
||||
|
||||
sent = sendfile(1, fd, &offset, count);
|
||||
if (sent == -1) {
|
||||
fake_sendfile(1, fd, &offset, count);
|
||||
}
|
||||
len -= count;
|
||||
}
|
||||
cork(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
get_ucspi_env()
|
||||
{
|
||||
|
@ -1390,10 +708,9 @@ handle_request()
|
|||
}
|
||||
} else if (! strcmp(name, "IF_MODIFIED_SINCE")) {
|
||||
ims = timerfc(val);
|
||||
DUMP_d(ims);
|
||||
}
|
||||
|
||||
/* Set up env for CGI */
|
||||
/* Set up CGI environment variables */
|
||||
{
|
||||
char *d = name + strlen(name);
|
||||
char *s = val;
|
||||
|
@ -1412,6 +729,30 @@ handle_request()
|
|||
env[nheaders] = NULL;
|
||||
}
|
||||
|
||||
/* Try to change into the appropriate directory */
|
||||
{
|
||||
char fn[PATH_MAX];
|
||||
|
||||
strncpy(fn, host, sizeof fn);
|
||||
if (fn[0] == '.') {
|
||||
fn[0] = ':';
|
||||
}
|
||||
for (p = fn; *p; p += 1) {
|
||||
switch (*p) {
|
||||
case '/':
|
||||
*p = ':';
|
||||
break;
|
||||
case ':':
|
||||
*p = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((-1 == chdir(fn)) && (-1 == chdir("default"))) {
|
||||
badrequest(404, "Not Found", "This host is not served here");
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1419,7 +760,6 @@ int
|
|||
main(int argc, char *argv[], const char *const *envp)
|
||||
{
|
||||
int cwd = open(".", O_RDONLY);
|
||||
|
||||
parse_options(argc, argv);
|
||||
|
||||
setbuffer(stdout, stdout_buf, sizeof stdout_buf);
|
||||
|
@ -1427,10 +767,13 @@ main(int argc, char *argv[], const char *const *envp)
|
|||
signal(SIGPIPE, SIG_IGN);
|
||||
get_ucspi_env();
|
||||
|
||||
do {
|
||||
while (1) {
|
||||
handle_request();
|
||||
if (! keepalive) {
|
||||
break;
|
||||
}
|
||||
fchdir(cwd);
|
||||
} while (keepalive);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue