From 78ec64f5061d988d6072069c7c7bbc0595afb8ce Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Tue, 6 Mar 2012 21:09:25 -0700 Subject: [PATCH] remove "#if 0" sections (they will come back later) --- eris.c | 723 +++------------------------------------------------------ 1 file changed, 33 insertions(+), 690 deletions(-) diff --git a/eris.c b/eris.c index a50d1e1..f081a4e 100644 --- a/eris.c +++ b/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

Directory Listing: /", stdout); - hdl_encode_html(nurl, nl); - fputs("

\n
\n", stdout);
-            if (nl != 0) {
-                for (i = nl - 2; i > 0; --i)
-                    if (nurl[i] == '/')
-                        break;
-                fputs(" 0)
-                    fputs("/", stdout);
-                fputs("\">Parent directory", stdout);
-                fputs("\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("", stdout);
-                if (de->d_name[0] == ':')
-                    de->d_name[0] = '.';        /* fnord special ... */
-                hdl_encode_html(de->d_name, dl);
-                fputs("\n", stdout);
-                size += 22 + (dl << 1);
-            }
-            closedir(dir);
-            fputs("
\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; }