Gut compile-time options, add command-line options

This commit is contained in:
Neale Pickett 2012-02-15 16:19:02 -07:00
parent 10258ec975
commit 18e2662b50
2 changed files with 117 additions and 266 deletions

View File

@ -2,15 +2,7 @@ VERSION := $(shell head -n 1 CHANGES | tr -d :)
CFLAGS = -DFNORD='"fnord/$(VERSION)"' -Wall -Werror CFLAGS = -DFNORD='"fnord/$(VERSION)"' -Wall -Werror
all: fnord fnord-cgi fnord-idx all: fnord
fnord-cgi: CFLAGS += -DCGI
fnord-cgi: fnord.c
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $<
fnord-idx: CFLAGS += -DDIR_LIST
fnord-idx: fnord.c
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $<
clean: clean:
rm -f *.[oa] fnord fnord-cgi fnord-idx rm -f *.[oa] fnord

371
fnord.c
View File

@ -39,77 +39,6 @@
#define DUMP_c(v) DUMPf("%s = %c", #v, v) #define DUMP_c(v) DUMPf("%s = %c", #v, v)
#define DUMP_p(v) DUMPf("%s = %p", #v, v) #define DUMP_p(v) DUMPf("%s = %p", #v, v)
/*
* uncomment the following line to enable support for CGI
*/
// #define CGI
#ifdef CGI
/*
* uncomment the following line to enable support for "index.cgi" That is:
* if "index.html" is not present then look for "index.cgi"
*/
#define INDEX_CGI
#endif
/*
* the following switch will make fnord normalize the Host: HTTP header
* from "foo" to "foo:80"
*/
#define NORMALIZE_HOST
/*
* uncomment the following line to enable support for autogenerated
* directory-listings for directories without index
*/
/*
* #define DIR_LIST
*/
#ifdef DIR_LIST
/*
* uncomment the following line to enable support for system symlink
* dereferencingr. HOPE YOU KNOW WHAT YOU'RE LINKING ! e.g.: if a file
* foo is a symlink to /etc/passwd and you don't have a chroot enviroment
* then the system-wide /etc/passwd is provided !!! If the symlink is
* dangling OR this option is not active the symlink is provided as a new
* http-uri. e.g.: is foo a symlink to /etc/passwd than the clinet gets a
* href to http://<vhost>/etc/passwd
*/
/*
* #define SYSTEM_SYMLINK_DEREF
*/
#endif
/*
* uncomment the following line to get full-host redirection. If a file is
* not found locally, and $REDIRECT_HOST is set, fnord will issue a
* redirect to strcat($REDIRECT_HOST,uri). Otherwise, if $REDIRECT_URI is
* set, fnord will issue a redirect to $REDIRECT_URI. Only if those fail
* will a 404 error be returned.
*/
#define OLD_STYLE_REDIRECT
/*
* uncomment the following line to get full-host redirection. if the
* virtual host directory/symlink is a broken symlink, fnord will issue a
* redirect. If the contents of the symlink starts with an equal sign
* ('='), fnord will throw away the URI part.
*/
#define REDIRECT
/*
* uncomment the following line to make fnord chroot to the current
* working directory and drop privileges
*/
#define CHROOT
/*
* uncomment the following line to make fnord support connection
* keep-alive
*/
#define KEEPALIVE
/* /*
* the following is the time in seconds that fnord should wait for a valid * the following is the time in seconds that fnord should wait for a valid
* HTTP request * HTTP request
@ -165,12 +94,9 @@ char *ua = "?"; /* user-agent */
char *refer; /* Referrer: header */ char *refer; /* Referrer: header */
char *accept_enc; /* Accept-Encoding */ char *accept_enc; /* Accept-Encoding */
int httpversion; /* 0 == 1.0, 1 == 1.1 */ int httpversion; /* 0 == 1.0, 1 == 1.1 */
#ifdef KEEPALIVE
int keepalive = 0; /* should we keep the connection alive? */ int keepalive = 0; /* should we keep the connection alive? */
int rootdir; /* fd of root directory, so we can fchdir int rootdir; /* fd of root directory, so we can fchdir
* * back for keep-alive */ * * back for keep-alive */
#endif
#ifdef CGI
char *cookie; /* Referrer: header */ char *cookie; /* Referrer: header */
char *uri; /* copy of url before demangling */ char *uri; /* copy of url before demangling */
char *content_type; char *content_type;
@ -179,7 +105,6 @@ char *auth_type;
char *post_miss; char *post_miss;
unsigned long post_mlen; unsigned long post_mlen;
unsigned long post_len = 0; unsigned long post_len = 0;
#endif
#if _FILE_OFFSET_BITS == 64 #if _FILE_OFFSET_BITS == 64
static unsigned long long rangestart, static unsigned long long rangestart,
@ -197,17 +122,16 @@ static const char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
#define MAXHEADERLEN 8192 #define MAXHEADERLEN 8192
char *remote_ip; char *remote_ip;
#ifdef CGI
char *remote_port; char *remote_port;
char *remote_ident; char *remote_ident;
#endif
static void static void
sanitize(char *ua) sanitize(char *ua)
{ /* replace strings with underscores for * { /* replace strings with underscores for *
* logging */ * logging */
int j; int j;
if (! ua) return; if (!ua)
return;
for (j = 0; ua[j]; ++j) for (j = 0; ua[j]; ++j)
if (isspace(ua[j])) if (isspace(ua[j]))
ua[j] = '_'; ua[j] = '_';
@ -222,7 +146,7 @@ dolog(off_t len)
fprintf(stderr, "%s %ld %lu %s %s %s %s\n", fprintf(stderr, "%s %ld %lu %s %s %s %s\n",
remote_ip ? remote_ip : "0.0.0.0", remote_ip ? remote_ip : "0.0.0.0",
retcode, (unsigned long)len, host, ua, refer, url); retcode, (unsigned long) len, host, ua, refer, url);
} }
/* /*
@ -245,7 +169,6 @@ badrequest(long code, const char *httpcomment, const char *message)
exit(0); exit(0);
} }
#ifdef CGI
#define CGIENVLEN 21 #define CGIENVLEN 21
static const char *cgivars[CGIENVLEN] = { static const char *cgivars[CGIENVLEN] = {
@ -275,11 +198,11 @@ static const char *cgivars[CGIENVLEN] = {
static int static int
iscgivar(const char *s) iscgivar(const char *s)
{ {
int sl = strlen(s); int sl = strlen(s);
register unsigned int i = 0; register unsigned int i = 0;
for (; i < CGIENVLEN; i++) for (; i < CGIENVLEN; i++)
if (! strncmp(s, cgivars[i], sl)) if (!strncmp(s, cgivars[i], sl))
return 1; return 1;
return 0; return 0;
} }
@ -293,14 +216,14 @@ elen(register const char *const *e)
return i; return i;
} }
char * char *
env_append(const char *key, const char *val) env_append(const char *key, const char *val)
{ {
static char buf[MAXHEADERLEN * 2 + PATH_MAX + 200]; static char buf[MAXHEADERLEN * 2 + PATH_MAX + 200];
static char *p = buf; static char *p = buf;
char *ret = p; char *ret = p;
if (! key) { if (!key) {
p = buf; p = buf;
return NULL; return NULL;
} }
@ -337,24 +260,35 @@ do_cgi(const char *pathinfo, const char *const *envp)
cgi_env[i++] = env_append("REQUEST_METHOD", method_name[method]); cgi_env[i++] = env_append("REQUEST_METHOD", method_name[method]);
cgi_env[i++] = env_append("REQUEST_URI", uri); cgi_env[i++] = env_append("REQUEST_URI", uri);
cgi_env[i++] = env_append("SCRIPT_NAME", url); cgi_env[i++] = env_append("SCRIPT_NAME", url);
if (remote_ip) cgi_env[i++] = env_append("REMOTE_ADDR", remote_ip); if (remote_ip)
if (remote_port) cgi_env[i++] = env_append("REMOTE_PORT", remote_port); cgi_env[i++] = env_append("REMOTE_ADDR", remote_ip);
if (remote_ident) cgi_env[i++] = env_append("REMOTE_IDENT", remote_ident); if (remote_port)
if (ua) cgi_env[i++] = env_append("HTTP_USER_AGENT", ua); cgi_env[i++] = env_append("REMOTE_PORT", remote_port);
if (cookie) cgi_env[i++] = env_append("HTTP_COOKIE", cookie); if (remote_ident)
if (refer) cgi_env[i++] = env_append("HTTP_REFERER", refer); cgi_env[i++] = env_append("REMOTE_IDENT", remote_ident);
if (accept_enc) cgi_env[i++] = env_append("HTTP_ACCEPT_ENCODING", accept_enc); if (ua)
if (auth_type) cgi_env[i++] = env_append("AUTH_TYPE", auth_type); cgi_env[i++] = env_append("HTTP_USER_AGENT", ua);
if (content_type) cgi_env[i++] = env_append("CONTENT_TYPE", content_type); if (cookie)
if (content_type) cgi_env[i++] = env_append("CONTENT_LENGTH", content_len); cgi_env[i++] = env_append("HTTP_COOKIE", cookie);
if (args) cgi_env[i++] = env_append("QUERY_STRING", args); 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) { if (pathinfo) {
char *rp = realpath(pathinfo, NULL); char *rp = realpath(pathinfo, NULL);
cgi_env[i++] = env_append("PATH_INFO", pathinfo); cgi_env[i++] = env_append("PATH_INFO", pathinfo);
if (! rp) rp = pathinfo; cgi_env[i++] = env_append("PATH_TRANSLATED", rp ? rp : pathinfo);
cgi_env[i++] = env_append("PATH_TRANSLATED", rp); if (rp)
if (rp != pathinfo) free(rp); free(rp);
} }
{ {
@ -389,7 +323,7 @@ do_cgi(const char *pathinfo, const char *const *envp)
} }
{ {
char tmp[PATH_MAX]; char tmp[PATH_MAX];
i = strrchr(url, '/') - url; i = strrchr(url, '/') - url;
strncpy(tmp, url + 1, i); strncpy(tmp, url + 1, i);
@ -397,8 +331,8 @@ do_cgi(const char *pathinfo, const char *const *envp)
chdir(tmp); chdir(tmp);
} }
{ {
char tmp[PATH_MAX]; char tmp[PATH_MAX];
/* /*
* program name * program name
@ -411,7 +345,7 @@ do_cgi(const char *pathinfo, const char *const *envp)
* start cgi * start cgi
*/ */
execve(cgi_arg[0], cgi_arg, cgi_env); execve(cgi_arg[0], cgi_arg, cgi_env);
raise(SIGQUIT); /* gateway unavailable. */ raise(SIGQUIT); /* gateway unavailable. */
} }
} }
@ -604,7 +538,6 @@ start_cgi(int nph, const char *pathinfo, const char *const *envp)
} }
exit(0); exit(0);
} }
#endif
static int static int
fromhex(int c) fromhex(int c)
@ -629,9 +562,7 @@ header(char *buf, int buflen, const char *hname)
int i; int i;
char *c; char *c;
DUMPf("buflen %d, slen %d", buflen, slen);
for (i = 0; i < buflen - slen - 2; ++i) { for (i = 0; i < buflen - slen - 2; ++i) {
DUMPf("[%.*s] [%s]", slen, buf + i, hname);
if (!strncasecmp(buf + i, hname, slen)) { if (!strncasecmp(buf + i, hname, slen)) {
if (i && (buf[i - 1] && buf[i - 1] != '\n')) if (i && (buf[i - 1] && buf[i - 1] != '\n'))
continue; continue;
@ -1083,9 +1014,7 @@ handleredirect(const char *url, const char *origurl)
{ {
char symlink[1024]; char symlink[1024];
int len; int len;
#ifdef OLD_STYLE_REDIRECT
char *env;
#endif
while (*url == '/') while (*url == '/')
++url; ++url;
if ((len = readlink(url, symlink, 1023)) > 0) { if ((len = readlink(url, symlink, 1023)) > 0) {
@ -1094,32 +1023,14 @@ handleredirect(const char *url, const char *origurl)
*/ */
redirectboilerplate(); redirectboilerplate();
printf("%.*s", len, symlink); printf("%.*s", len, symlink);
#ifdef OLD_STYLE_REDIRECT
fini:
#endif
retcode = 301; retcode = 301;
printf("\r\n\r\n"); printf("\r\n\r\n");
dolog(0); dolog(0);
fflush(stdout); fflush(stdout);
exit(0); exit(0);
} }
#ifdef OLD_STYLE_REDIRECT
if ((env = getenv("REDIRECT_HOST"))) {
redirectboilerplate();
fputs(env, stdout);
while (*origurl == '/')
++origurl;
fputs(origurl, stdout);
goto fini;
} else if ((env = getenv("REDIRECT_URI"))) {
redirectboilerplate();
fputs(env, stdout);
goto fini;
}
#endif
} }
#ifdef DIR_LIST
static void static void
hdl_encode_html(const char *s, unsigned int sl) hdl_encode_html(const char *s, unsigned int sl)
{ {
@ -1127,8 +1038,7 @@ hdl_encode_html(const char *s, unsigned int sl)
for (i = 0; i < sl; ++i) { for (i = 0; i < sl; ++i) {
unsigned char ch = s[i]; unsigned char ch = s[i];
if (ch > 159) { if (ch > 159) {
encode_dec: printf("&#%u;", ch);
printf("&#%lu;", ch);
} else if ((ch > 128) || (ch < 32)) { } else if ((ch > 128) || (ch < 32)) {
putchar('_'); putchar('_');
} else if (ch == '"') } else if (ch == '"')
@ -1173,12 +1083,12 @@ handledirlist(const char *origurl)
&& ((st.st_mode & S_IRWXO) == 5)) { && ((st.st_mode & S_IRWXO) == 5)) {
if (nl) if (nl)
chdir(nurl); chdir(nurl);
if (dir = opendir(".")) { if ((dir = opendir("."))) {
struct dirent *de; struct dirent *de;
unsigned int i, unsigned int i,
size = 32 + nl; size = 32 + nl;
fputs("HTTP/1.0 200 OK\r\nServer: " FNORD fputs("HTTP/1.0 200 OK\r\nServer: " FNORD
"\r\nConnection: close\r\n", stdout); "\r\nConnection: close\r\n", stdout);
fputs("Content-Type: text/html\r\n", stdout); fputs("Content-Type: text/html\r\n", stdout);
fputs("\r\n<h3>Directory Listing: /", stdout); fputs("\r\n<h3>Directory Listing: /", stdout);
hdl_encode_html(nurl, nl); hdl_encode_html(nurl, nl);
@ -1196,7 +1106,7 @@ handledirlist(const char *origurl)
fputs("</a>\n", stdout); fputs("</a>\n", stdout);
size += 40 + i; size += 40 + i;
} }
while (de = readdir(dir)) { while ((de = readdir(dir))) {
char symlink[1024]; char symlink[1024];
char *p = de->d_name; char *p = de->d_name;
unsigned int pl, unsigned int pl,
@ -1209,14 +1119,9 @@ handledirlist(const char *origurl)
if (S_ISDIR(st.st_mode)) if (S_ISDIR(st.st_mode))
fputs("[DIR] ", stdout); fputs("[DIR] ", stdout);
else if (S_ISLNK(st.st_mode)) { else if (S_ISLNK(st.st_mode)) {
#ifdef SYSTEM_SYMLINK_DEREF if ((pl = readlink(de->d_name, symlink, 1023)) < 1)
if (stat(de->d_name, &st)) /* dangling symlink */ continue;
#endif p = symlink;
{
if ((pl = readlink(de->d_name, symlink, 1023)) < 1)
continue;
p = symlink;
}
fputs("[LNK] ", stdout); /* a symlink to * fputs("[LNK] ", stdout); /* a symlink to *
* something ... */ * something ... */
} else if (S_ISREG(st.st_mode)) } else if (S_ISREG(st.st_mode))
@ -1246,9 +1151,7 @@ handledirlist(const char *origurl)
} }
} }
} }
#endif
#ifdef INDEX_CGI
static int static int
handleindexcgi(const char *testurl, const char *origurl, char *space) handleindexcgi(const char *testurl, const char *origurl, char *space)
{ {
@ -1263,7 +1166,7 @@ handleindexcgi(const char *testurl, const char *origurl, char *space)
test = space; test = space;
++test; ++test;
ul -= 4; ul -= 4;
byte_copy(test, ul, testurl); memcpy(test, testurl, ul);
test[ul] = 'c'; test[ul] = 'c';
test[++ul] = 'g'; test[++ul] = 'g';
test[++ul] = 'i'; test[++ul] = 'i';
@ -1281,39 +1184,34 @@ handleindexcgi(const char *testurl, const char *origurl, char *space)
url = test; url = test;
return 1; /* Wow... now start "index.cgi" */ return 1; /* Wow... now start "index.cgi" */
} }
#endif
static void static void
get_ucspi_env(void) get_ucspi_env(void)
{ {
char *ucspi = getenv("PROTO"); char *ucspi = getenv("PROTO");
if (ucspi) { if (ucspi) {
int protolen = strlen(ucspi); int protolen = strlen(ucspi);
char *buf = alloca(protolen + 20); char *buf = alloca(protolen + 20);
strcpy(buf, ucspi); strcpy(buf, ucspi);
strcpy(buf + protolen, "REMOTEIP"); strcpy(buf + protolen, "REMOTEIP");
remote_ip = getenv(buf); remote_ip = getenv(buf);
#ifdef CGI
strcpy(buf + protolen, "REMOTEPORT"); strcpy(buf + protolen, "REMOTEPORT");
remote_port = getenv(buf); remote_port = getenv(buf);
strcpy(buf + protolen, "REMOTEINFO"); strcpy(buf + protolen, "REMOTEINFO");
remote_ident = getenv(buf); remote_ident = getenv(buf);
#endif
} }
} }
#ifdef CGI
static int static int
findcgi(const char *c) findcgi(const char *c)
{ {
return (c[0] == '.' && c[1] == 'c' && return (c[0] == '.' && c[1] == 'c' &&
c[2] == 'g' && c[3] == 'i' && (c[4] == '/' || c[4] == 0)); c[2] == 'g' && c[3] == 'i' && (c[4] == '/' || c[4] == 0));
} }
#endif
static int static int
serve_read_write(int fd) serve_read_write(int fd)
@ -1500,60 +1398,40 @@ int
main(int argc, char *argv[], const char *const *envp) main(int argc, char *argv[], const char *const *envp)
{ {
char buf[MAXHEADERLEN]; char buf[MAXHEADERLEN];
#if 0
char buf2[MAXHEADERLEN];
#endif
char *nurl, char *nurl,
*origurl; *origurl;
int docgi = 0;
int dirlist = 0;
int redirect = 0;
int len; int len;
int in; int in;
if (argc > 1) {
chdir(argv[1]); int opt;
#ifdef CHROOT while (-1 != (opt = getopt(argc, argv, "cdr"))) {
if (chroot(".")) { switch (opt) {
if (errno != EPERM) case 'c':
goto error500; docgi = 1;
/* break;
* else fnord was called with uid!=0, i.e. it already is chroot case 'd':
*/ dirlist = 1;
} else { break;
char *tmp; case 'r':
if (chdir("/")) redirect = 1;
goto error500; break;
if ((tmp = getenv("GID"))) { default:
long gid; fprintf(stderr, "%d Usage: %s [-d] [-r]\n", opt, argv[0]);
char *endptr; return 69;
}
gid = strtoul(tmp, &endptr, 0);
if (*endptr == 0) {
gid_t gi = gid;
if (setgroups(1, &gi))
goto error500;
} else
goto error500;
}
if ((tmp = getenv("UID"))) {
long uid;
char *endptr;
uid = strtoul(tmp, &endptr, 0);
if (*endptr == 0) {
if (setuid(uid))
goto error500;
} else
goto error500;
} }
} }
#endif
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
get_ucspi_env(); get_ucspi_env();
#ifdef KEEPALIVE
handlenext: handlenext:
encoding = 0; encoding = 0;
#endif
// alarm(20); // alarm(20);
{ {
@ -1572,7 +1450,8 @@ main(int argc, char *argv[], const char *const *envp)
if (time(&now) < fini) if (time(&now) < fini)
continue; /* fall through */ continue; /* fall through */
case -1: /* timeout or error */ case -1: /* timeout or error */
// badrequest(408,"Request Time-out","No request appeared // badrequest(408,"Request Time-out","No request
// appeared
// within a reasonable time period."); // within a reasonable time period.");
return 1; return 1;
} }
@ -1626,9 +1505,7 @@ main(int argc, char *argv[], const char *const *envp)
"<title>Bad Request</title>Only HTTP 1.x supported"); "<title>Bad Request</title>Only HTTP 1.x supported");
*space = 0; *space = 0;
httpversion = space[8] - '0'; httpversion = space[8] - '0';
#ifdef KEEPALIVE
keepalive = 0; keepalive = 0;
#endif
/* /*
* demangle path in-place * demangle path in-place
@ -1670,10 +1547,7 @@ main(int argc, char *argv[], const char *const *envp)
*/ */
} }
#ifdef CGI uri = strdup(url);
uri = alloca(space + 1);
byte_copy(uri, space + 1, url);
#endif
} }
{ {
@ -1681,31 +1555,27 @@ main(int argc, char *argv[], const char *const *envp)
ua = header(buf, len, "User-Agent"); ua = header(buf, len, "User-Agent");
refer = header(buf, len, "Referer"); refer = header(buf, len, "Referer");
accept_enc = header(buf, len, "Accept-Encoding"); accept_enc = header(buf, len, "Accept-Encoding");
#ifdef KEEPALIVE
if ((tmp = header(buf, len, "Connection"))) { /* see if it's if ((tmp = header(buf, len, "Connection"))) { /* see if it's
* "keep-alive" or * "keep-alive"
* * "close" */ * or * "close" */
if (!strcasecmp(tmp, "keep-alive")) if (!strcasecmp(tmp, "keep-alive"))
keepalive = 1; keepalive = 1;
else if (!strcasecmp(tmp, "close")) else if (!strcasecmp(tmp, "close"))
keepalive = -1; keepalive = -1;
} }
#endif
#ifdef CGI
cookie = header(buf, len, "Cookie"); cookie = header(buf, len, "Cookie");
auth_type = header(buf, len, "Authorization"); auth_type = header(buf, len, "Authorization");
if (method == POST) { if (method == POST) {
content_type = header(buf, len, "Content-Type"); content_type = header(buf, len, "Content-Type");
content_len = header(buf, len, "Content-Length"); content_len = header(buf, len, "Content-Length");
if (content_len) { if (content_len) {
scan_ulong(content_len, &post_len); post_len = strtoul(content_len, NULL, 10);
post_miss = buf + len + 1; post_miss = buf + len + 1;
post_mlen = in - len - 1; post_mlen = in - len - 1;
if (post_len <= post_mlen) if (post_len <= post_mlen)
post_mlen = post_len; post_mlen = post_len;
} }
} }
#endif
} }
port = getenv("TCPLOCALPORT"); port = getenv("TCPLOCALPORT");
@ -1728,14 +1598,12 @@ main(int argc, char *argv[], const char *const *envp)
exit(101); exit(101);
sprintf(Buf, "%s:%s", ip, port); sprintf(Buf, "%s:%s", ip, port);
host = Buf; host = Buf;
#ifdef NORMALIZE_HOST
} else { } else {
char *colon = strchr(host, ':'); char *colon = strchr(host, ':');
if (*colon == 0) { if (!colon) {
sprintf(Buf, "%s:%s", host, port); sprintf(Buf, "%s:%s", host, port);
host = Buf; host = Buf;
} }
#endif
} }
for (i = strlen(host); i >= 0; --i) for (i = strlen(host); i >= 0; --i)
if ((host[i] = tolower(host[i])) == '/') if ((host[i] = tolower(host[i])) == '/')
@ -1745,36 +1613,35 @@ main(int argc, char *argv[], const char *const *envp)
if (host[0] == '.') if (host[0] == '.')
goto hostb0rken; goto hostb0rken;
// fprintf(stderr,"host %s\n",host); // fprintf(stderr,"host %s\n",host);
#ifdef KEEPALIVE
if (keepalive > 0) { if (keepalive > 0) {
if ((rootdir = open(".", O_RDONLY)) < 0) if ((rootdir = open(".", O_RDONLY)) < 0)
keepalive = -1; keepalive = -1;
} }
#endif
if (chdir(host)) { if (chdir(host)) {
#ifdef REDIRECT if (redirect) {
char symlink[1024]; char symlink[1024];
int linklen; int linklen;
if ((linklen = readlink(host, symlink, sizeof symlink)) > 0) { if ((linklen =
/* readlink(host, symlink, sizeof symlink)) > 0) {
* it is a broken symlink. Do a redirection /*
*/ * it is a broken symlink. Do a redirection
redirectboilerplate(); */
if (symlink[0] == '=') { redirectboilerplate();
fwrite(symlink + 1, linklen - 1, 1, stdout); if (symlink[0] == '=') {
} else { fwrite(symlink + 1, linklen - 1, 1, stdout);
fwrite(symlink, linklen, 1, stdout); } else {
while (url[0] == '/') fwrite(symlink, linklen, 1, stdout);
++url; while (url[0] == '/')
fputs(url, stdout); ++url;
fputs(url, stdout);
}
retcode = 301;
fputs("\r\n\r\n", stdout);
dolog(0);
fflush(stdout);
exit(0);
} }
retcode = 301;
fputs("\r\n\r\n", stdout);
dolog(0);
fflush(stdout);
exit(0);
} }
#endif
if (chdir("default") && argc < 2) { if (chdir("default") && argc < 2) {
badrequest(404, "Not Found", badrequest(404, "Not Found",
"<title>Not Found</title>This host is not served here."); "<title>Not Found</title>This host is not served here.");
@ -1815,11 +1682,11 @@ main(int argc, char *argv[], const char *const *envp)
retcode = 401; retcode = 401;
dolog(0); dolog(0);
fputs("HTTP/1.0 401 Authorization Required\r\n" fputs("HTTP/1.0 401 Authorization Required\r\n"
"WWW-Authenticate: Basic realm=\"", stdout); "WWW-Authenticate: Basic realm=\"", stdout);
fputs(host, stdout); fputs(host, stdout);
fputs("\"\r\nConnection: close\r\n\r\n" fputs("\"\r\nConnection: close\r\n\r\n"
"Access to this site is restricted.\r\n" "Access to this site is restricted.\r\n"
"Please provide credentials.\r\n", stdout); "Please provide credentials.\r\n", stdout);
fflush(stdout); fflush(stdout);
exit(0); exit(0);
} }
@ -1837,9 +1704,9 @@ main(int argc, char *argv[], const char *const *envp)
url = nurl; url = nurl;
nurl = url + i; nurl = url + i;
} }
#ifdef CGI
nurl -= 3; nurl -= 3;
{
if (docgi) {
char *tmp, char *tmp,
*pathinfo; *pathinfo;
pathinfo = 0; pathinfo = 0;
@ -1876,13 +1743,10 @@ main(int argc, char *argv[], const char *const *envp)
*/ */
--nurl; --nurl;
} }
#ifdef INDEX_CGI
indexcgi: indexcgi:
#endif
start_cgi(0, pathinfo, envp); /* start a CGI */ start_cgi(0, pathinfo, envp); /* start a CGI */
} }
} }
#endif
{ {
int fd; int fd;
@ -1922,7 +1786,6 @@ main(int argc, char *argv[], const char *const *envp)
fputs("Server: " FNORD "\r\nContent-Type: ", stdout); fputs("Server: " FNORD "\r\nContent-Type: ", stdout);
fputs(mimetype, stdout); fputs(mimetype, stdout);
fputs("\r\n", stdout); fputs("\r\n", stdout);
#ifdef KEEPALIVE
switch (keepalive) { switch (keepalive) {
case -1: case -1:
fputs("Connection: close\r\n", stdout); fputs("Connection: close\r\n", stdout);
@ -1931,11 +1794,11 @@ main(int argc, char *argv[], const char *const *envp)
fputs("Connection: Keep-Alive\r\n", stdout); fputs("Connection: Keep-Alive\r\n", stdout);
break; break;
} }
#endif
if (encoding) { if (encoding) {
printf("Content-Encoding: %s\r\n", encoding); printf("Content-Encoding: %s\r\n", encoding);
} }
printf("Content-Length: %llu\r\n", (unsigned long long)(rangeend - rangestart)); printf("Content-Length: %llu\r\n",
(unsigned long long) (rangeend - rangestart));
printf("Last-Modified: "); printf("Last-Modified: ");
{ {
struct tm *x = gmtime(&st.st_mtime); struct tm *x = gmtime(&st.st_mtime);
@ -1952,9 +1815,9 @@ main(int argc, char *argv[], const char *const *envp)
if (rangestart || rangeend != st.st_size) { if (rangestart || rangeend != st.st_size) {
printf printf
("Accept-Ranges: bytes\r\nContent-Range: bytes %llu-%llu/%llu\r\n", ("Accept-Ranges: bytes\r\nContent-Range: bytes %llu-%llu/%llu\r\n",
(unsigned long long)rangestart, (unsigned long long) rangestart,
(unsigned long long)rangeend - 1, (unsigned long long) rangeend - 1,
(unsigned long long)st.st_size); (unsigned long long) st.st_size);
} }
fputs("\r\n", stdout); fputs("\r\n", stdout);
if (method == GET || method == POST) { if (method == GET || method == POST) {
@ -1966,7 +1829,6 @@ main(int argc, char *argv[], const char *const *envp)
case 1: case 1:
return 1; return 1;
} }
#ifdef KEEPALIVE
#ifdef TCP_CORK #ifdef TCP_CORK
if (corked) { if (corked) {
int zero = 0; int zero = 0;
@ -1980,7 +1842,6 @@ main(int argc, char *argv[], const char *const *envp)
close(rootdir); close(rootdir);
goto handlenext; goto handlenext;
} }
#endif
exit(0); exit(0);
error500: error500:
retcode = 500; retcode = 500;
@ -1991,16 +1852,14 @@ main(int argc, char *argv[], const char *const *envp)
switch (retcode) { switch (retcode) {
case 404: case 404:
{ {
#ifdef INDEX_CGI
char *space = alloca(strlen(url) + 2); char *space = alloca(strlen(url) + 2);
if (handleindexcgi(url, origurl, space)) if (handleindexcgi(url, origurl, space))
goto indexcgi; goto indexcgi;
#endif
handleredirect(url, origurl); handleredirect(url, origurl);
#ifdef DIR_LIST if (dirlist) {
handledirlist(origurl); handledirlist(origurl);
#endif }
badrequest(404, "Not Found", badrequest(404, "Not Found",
"<title>Not Found</title>No such file or directory."); "<title>Not Found</title>No such file or directory.");
} }