mirror of https://github.com/nealey/eris.git
Gut compile-time options, add command-line options
This commit is contained in:
parent
10258ec975
commit
18e2662b50
12
Makefile
12
Makefile
|
@ -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
371
fnord.c
|
@ -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.");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue