Skip to content

Latest commit

 

History

History
1006 lines (970 loc) · 32.2 KB

portdiff.md

File metadata and controls

1006 lines (970 loc) · 32.2 KB
diff --git a/winhttpd.c b/winhttpd.c
index 836743b..86bf205 100644
--- a/winhttpd.c
+++ b/winhttpd.c
@@ -1,3 +1,30 @@
+//MIT License
+//
+//WinHTTPD - a port of darkhttpd for Windows OS
+//https://opensource.ieee.org/igorsikuljak/winhttpd
+//
+//Copyright(c) 2020 Igor Šikuljak <igorsikuljak@ieee.org>
+//
+//Permission is hereby granted, free of charge, to any person obtaining a copy
+//of this softwareand associated documentation files(the "Software"), to deal
+//in the Software without restriction, including without limitation the rights
+//to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
+//copies of the Software, and to permit persons to whom the Software is
+//furnished to do so, subject to the following conditions :
+//
+//The above copyright noticeand this permission notice shall be included in all
+//copies or substantial portions of the Software.
+//
+//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
+//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+//SOFTWARE.
+
+
+
 /* darkhttpd - a simple, single-threaded, static content webserver.
  * https://unix4lyfe.org/darkhttpd/
  * Copyright (c) 2003-2018 Emil Mikulic <emikulic@gmail.com>
@@ -17,9 +44,12 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+#define _CRT_SECURE_NO_WARNINGS
+#define _WINSOCK_DEPRECATED_NO_WARNINGS
+
 static const char
-pkgname[] = "darkhttpd/1.12.from.git",
-copyright[] = "copyright (c) 2003-2018 Emil Mikulic";
+pkgname[] = "WinHTTPD",
+copyright[] = "Copyright(c) 2020 Igor Sikuljak <igorsikuljak@ieee.org>";
 
 /* Possible build options: -DDEBUG -DNO_IPV6 */
 
@@ -29,7 +59,7 @@ copyright[] = "copyright (c) 2003-2018 Emil Mikulic";
 
 #ifndef DEBUG
 # define NDEBUG
-static const int debug = 0;
+static const int debug = 1;
 #else
 static const int debug = 1;
 #endif
@@ -44,31 +74,76 @@ static const int debug = 1;
 # include <sys/sendfile.h>
 #endif
 
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+//#include <sys/time.h>
+#include <sys\types.h>
+//include <sys/socket.h>
 #include <sys/stat.h>
-#include <sys/resource.h>
-#include <sys/wait.h>
-#include <sys/param.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
+//#include <sys/resource.h>
+//#include <sys/wait.h>
+//#include <sys/param.h>
+//#include <netinet/in.h>
+//#include <netinet/tcp.h>
+//#include <arpa/inet.h>
 #include <assert.h>
 #include <ctype.h>
-#include <dirent.h>
+//#include <dirent.h>
+#include "include\dirent.h"
 #include <errno.h>
 #include <fcntl.h>
-#include <grp.h>
+//#include <grp.h>
 #include <limits.h>
-#include <pwd.h>
+//#include <pwd.h>
 #include <signal.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
-#include <unistd.h>
+//#include <unistd.h>
+
+
+#include <winsock2.h>
+#include <wchar.h>
+#include <stdint.h>
+#include <ws2tcpip.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <io.h>
+#include <errno.h>
+#include <stdarg.h>
+
+#pragma comment(lib, "ws2_32.lib")
+
+typedef int gid_t;
+typedef int uid_t;
+typedef int pid_t;
+typedef unsigned long in_addr_t;
+typedef long int ssize_t;
+
+#define close(fd) _close(fd)
+#define open(path, mode) _open(path, mode)
+#define read(path, buff, size) _read(path, buff, size)
+#define lseek(path, offset, mode) _lseek(path, offset, mode)
+#define strcasecmp(first, second) _stricmp(first, second)
+#define vscprintf _vscprintf
+
+int vasprintf(char** strp, const char* format, va_list ap)
+{
+    int len = vscprintf(format, ap);
+    if (len == -1)
+        return -1;
+    char* str = (char*)malloc((size_t)len + 1);
+    if (!str)
+        return -1;
+    int retval = vsnprintf(str, (size_t) len + 1, format, ap);
+    if (retval == -1) {
+        free(str);
+        return -1;
+    }
+    *strp = str;
+    return retval;
+}
+
 
 #ifdef __sun__
 # ifndef INADDR_NONE
@@ -342,6 +417,13 @@ static void xclose(const int fd) {
         err(1, "close()");
 }
 
+// closesocket() dies on error
+static void xclosesock(const int fd) {
+    if (closesocket(fd) != 0) {
+        err(1, "closesocket()");
+    }
+}
+
 /* malloc that dies if it can't allocate. */
 static void* xmalloc(const size_t size) {
     void* ptr = malloc(size);
@@ -459,13 +541,17 @@ static void appendf(struct apbuf* buf, const char* format, ...) {
 
 /* Make the specified socket non-blocking. */
 static void nonblock_socket(const int sock) {
-    int flags = fcntl(sock, F_GETFL);
+    //int flags = fcntl(sock, F_GETFL);
+    //
+
+    //if (flags == -1)
+    //    err(1, "fcntl(F_GETFL)");
+    //flags |= O_NONBLOCK;
+    //if (fcntl(sock, F_SETFL, flags) == -1)
+    //    err(1, "fcntl() to set O_NONBLOCK");
+    u_long nonblocking_enabled = TRUE;
+    int flags = ioctlsocket(sock, FIONBIO, &nonblocking_enabled);
 
-    if (flags == -1)
-        err(1, "fcntl(F_GETFL)");
-    flags |= O_NONBLOCK;
-    if (fcntl(sock, F_SETFL, flags) == -1)
-        err(1, "fcntl() to set O_NONBLOCK");
 }
 
 /* Split string out of src with range [left:right-1] */
@@ -805,7 +891,7 @@ static void init_sockin(void) {
     /* reuse address */
     sockopt = 1;
     if (setsockopt(sockin, SOL_SOCKET, SO_REUSEADDR,
-        &sockopt, sizeof(sockopt)) == -1)
+        (char*) &sockopt, sizeof(sockopt)) == -1)
         err(1, "setsockopt(SO_REUSEADDR)");
 
 #if 0
@@ -888,10 +974,10 @@ static void usage(const char* argv0) {
         "\t\tSpecifies how many concurrent connections to accept.\n\n");
     printf("\t--log filename (default: stdout)\n"
         "\t\tSpecifies which file to append the request log to.\n\n");
-    printf("\t--chroot (default: don't chroot)\n"
-        "\t\tLocks server into wwwroot directory for added security.\n\n");
-    printf("\t--daemon (default: don't daemonize)\n"
-        "\t\tDetach from the controlling terminal and run in the background.\n\n");
+    //printf("\t--chroot (default: don't chroot)\n"
+    //    "\t\tLocks server into wwwroot directory for added security.\n\n");
+    //printf("\t--daemon (default: don't daemonize)\n"
+    //    "\t\tDetach from the controlling terminal and run in the background.\n\n");
     printf("\t--index filename (default: %s)\n"
         "\t\tDefault file to serve when a directory is requested.\n\n",
         index_name);
@@ -902,12 +988,12 @@ static void usage(const char* argv0) {
     printf("\t--default-mimetype string (optional, default: %s)\n"
         "\t\tFiles with unknown extensions are served as this mimetype.\n\n",
         octet_stream);
-    printf("\t--uid uid/uname, --gid gid/gname (default: don't privdrop)\n"
-        "\t\tDrops privileges to given uid:gid after initialization.\n\n");
-    printf("\t--pidfile filename (default: no pidfile)\n"
-        "\t\tWrite PID to the specified file.  Note that if you are\n"
-        "\t\tusing --chroot, then the pidfile must be relative to,\n"
-        "\t\tand inside the wwwroot.\n\n");
+    //printf("\t--uid uid/uname, --gid gid/gname (default: don't privdrop)\n"
+    //    "\t\tDrops privileges to given uid:gid after initialization.\n\n");
+    //printf("\t--pidfile filename (default: no pidfile)\n"
+    //    "\t\tWrite PID to the specified file.  Note that if you are\n"
+    //    "\t\tusing --chroot, then the pidfile must be relative to,\n"
+    //    "\t\tand inside the wwwroot.\n\n");
     printf("\t--no-keepalive\n"
         "\t\tDisables HTTP Keep-Alive functionality.\n\n");
 #ifdef __FreeBSD__
@@ -976,7 +1062,7 @@ static void parse_commandline(const int argc, char* argv[]) {
         exit(EXIT_SUCCESS);
     }
 
-    if (getuid() == 0)
+    //if (getuid() == 0)
         bindport = 80;
 
     wwwroot = xstrdup(argv[1]);
@@ -1008,12 +1094,12 @@ static void parse_commandline(const int argc, char* argv[]) {
                 errx(1, "missing filename after --log");
             logfile_name = argv[i];
         }
-        else if (strcmp(argv[i], "--chroot") == 0) {
-            want_chroot = 1;
-        }
-        else if (strcmp(argv[i], "--daemon") == 0) {
-            want_daemon = 1;
-        }
+        //else if (strcmp(argv[i], "--chroot") == 0) {
+        //    want_chroot = 1;
+        //}
+        //else if (strcmp(argv[i], "--daemon") == 0) {
+        //    want_daemon = 1;
+        //}
         else if (strcmp(argv[i], "--index") == 0) {
             if (++i >= argc)
                 errx(1, "missing filename after --index");
@@ -1032,36 +1118,36 @@ static void parse_commandline(const int argc, char* argv[]) {
                 errx(1, "missing string after --default-mimetype");
             default_mimetype = argv[i];
         }
-        else if (strcmp(argv[i], "--uid") == 0) {
-            struct passwd* p;
-            if (++i >= argc)
-                errx(1, "missing uid after --uid");
-            p = getpwnam(argv[i]);
-            if (!p) {
-                p = getpwuid((uid_t)xstr_to_num(argv[i]));
-            }
-            if (!p)
-                errx(1, "no such uid: `%s'", argv[i]);
-            drop_uid = p->pw_uid;
-        }
-        else if (strcmp(argv[i], "--gid") == 0) {
-            struct group* g;
-            if (++i >= argc)
-                errx(1, "missing gid after --gid");
-            g = getgrnam(argv[i]);
-            if (!g) {
-                g = getgrgid((gid_t)xstr_to_num(argv[i]));
-            }
-            if (!g) {
-                errx(1, "no such gid: `%s'", argv[i]);
-            }
-            drop_gid = g->gr_gid;
-        }
-        else if (strcmp(argv[i], "--pidfile") == 0) {
-            if (++i >= argc)
-                errx(1, "missing filename after --pidfile");
-            pidfile_name = argv[i];
-        }
+        //else if (strcmp(argv[i], "--uid") == 0) {
+        //    struct passwd* p;
+        //    if (++i >= argc)
+        //        errx(1, "missing uid after --uid");
+        //    p = getpwnam(argv[i]);
+        //    if (!p) {
+        //        p = getpwuid((uid_t)xstr_to_num(argv[i]));
+        //    }
+        //    if (!p)
+        //        errx(1, "no such uid: `%s'", argv[i]);
+        //    drop_uid = p->pw_uid;
+        //}
+        //else if (strcmp(argv[i], "--gid") == 0) {
+        //    struct group* g;
+        //    if (++i >= argc)
+        //        errx(1, "missing gid after --gid");
+        //    g = getgrnam(argv[i]);
+        //    if (!g) {
+        //        g = getgrgid((gid_t)xstr_to_num(argv[i]));
+        //    }
+        //    if (!g) {
+        //        errx(1, "no such gid: `%s'", argv[i]);
+        //    }
+        //    drop_gid = g->gr_gid;
+        //}
+        //else if (strcmp(argv[i], "--pidfile") == 0) {
+        //    if (++i >= argc)
+        //        errx(1, "missing filename after --pidfile");
+        //    pidfile_name = argv[i];
+        //}
         else if (strcmp(argv[i], "--no-keepalive") == 0) {
             want_keepalive = 0;
         }
@@ -1279,7 +1365,7 @@ static void log_connection(const struct connection* conn) {
 static void free_connection(struct connection* conn) {
     if (debug) printf("free_connection(%d)\n", conn->socket);
     log_connection(conn);
-    if (conn->socket != -1) xclose(conn->socket);
+    if (conn->socket != -1) xclosesock(conn->socket);
     if (conn->request != NULL) free(conn->request);
     if (conn->method != NULL) free(conn->method);
     if (conn->url != NULL) free(conn->url);
@@ -1860,6 +1946,44 @@ static void process_get(struct connection* conn) {
     /* work out path of file being requested */
     decoded_url = urldecode(conn->url);
 
+    // create a windows type equivalent for decoded_url
+    int iter, du_len = strlen(decoded_url);
+    char* decoded_url_win = xmalloc(du_len + 2);
+    for (iter = 0; iter < du_len; iter++)
+        if (decoded_url[iter] == '/')
+            decoded_url_win[iter] = '\\';
+        else decoded_url_win[iter] = decoded_url[iter];
+    decoded_url_win[du_len] = '\0';
+    if (decoded_url_win[du_len - 1] == '\\')
+        decoded_url_win[du_len - 1] = '\0';
+
+    struct stat path_stat;
+    xasprintf(&target, "%s%s", wwwroot, decoded_url_win);
+    stat(target, &path_stat);
+    if ((path_stat.st_mode & (_S_IFDIR | _S_IREAD)) == (_S_IFDIR | _S_IREAD)) {
+        if (decoded_url[du_len - 1] != '/') {
+            redirect(conn, "%s/", decoded_url);
+            free(decoded_url);
+            free(decoded_url_win);
+            free(target);
+            return;
+        }
+        decoded_url_win[du_len - 1] = '\\';
+        decoded_url_win[du_len] = '\0';
+    }
+    else if ((path_stat.st_mode & (_S_IFREG | _S_IREAD)) == (_S_IFREG | _S_IREAD)) {
+        if (decoded_url[du_len - 1] == '/') {
+            decoded_url[du_len - 1] = '\0';
+            redirect(conn, "%s", decoded_url);
+            free(decoded_url);
+            free(decoded_url_win);
+            free(target);
+            return;
+        }
+        decoded_url_win[du_len] = '\0';
+    }
+    free(target);
+
     /* make sure it's safe */
     if (make_safe_url(decoded_url) == NULL) {
         default_reply(conn, 400, "Bad Request",
@@ -1894,12 +2018,13 @@ static void process_get(struct connection* conn) {
     }
 
     /* does it end in a slash? serve up url/index_name */
-    if (decoded_url[strlen(decoded_url) - 1] == '/') {
-        xasprintf(&target, "%s%s%s", wwwroot, decoded_url, index_name);
+    if (decoded_url_win[strlen(decoded_url_win) - 1] == '\\') {
+        xasprintf(&target, "%s%s%s", wwwroot, decoded_url_win, index_name);
         if (!file_exists(target)) {
             free(target);
             if (no_listing) {
                 free(decoded_url);
+                free(decoded_url_win);
                 /* Return 404 instead of 403 to make --no-listing
                  * indistinguishable from the directory not existing.
                  * i.e.: Don't leak information.
@@ -1912,22 +2037,26 @@ static void process_get(struct connection* conn) {
             generate_dir_listing(conn, target);
             free(target);
             free(decoded_url);
+            free(decoded_url_win);
             return;
         }
         mimetype = url_content_type(index_name);
     }
     else {
         /* points to a file */
-        xasprintf(&target, "%s%s", wwwroot, decoded_url);
+        xasprintf(&target, "%s%s", wwwroot, decoded_url_win);
         mimetype = url_content_type(decoded_url);
     }
     free(decoded_url);
+    free(decoded_url_win);
     if (debug)
         printf("url=\"%s\", target=\"%s\", content-type=\"%s\"\n",
             conn->url, target, mimetype);
 
     /* open file */
-    conn->reply_fd = open(target, O_RDONLY | O_NONBLOCK);
+    /*conn->reply_fd = open(target, O_RDONLY | O_NONBLOCK);*/
+    // lets pray for this, win does not have non blockking supported in open()
+    conn->reply_fd = open(target, _O_BINARY | _O_RDONLY);
     free(target);
 
     if (conn->reply_fd == -1) {
@@ -2115,11 +2244,15 @@ static void process_request(struct connection* conn) {
 
 /* Receiving request. */
 static void poll_recv_request(struct connection* conn) {
-    char buf[1 << 15];
+    char * buf = (char*)malloc(1 << 15);
+    if (buf == NULL) {
+        printf("Out of memory!");
+        exit(-1);
+    }
     ssize_t recvd;
 
     assert(conn->state == RECV_REQUEST);
-    recvd = recv(conn->socket, buf, sizeof(buf), 0);
+    recvd = recv(conn->socket, buf, 1 << 15, 0);
     if (debug)
         printf("poll_recv_request(%d) got %d bytes\n",
             conn->socket, (int)recvd);
@@ -2127,6 +2260,7 @@ static void poll_recv_request(struct connection* conn) {
         if (recvd == -1) {
             if (errno == EAGAIN) {
                 if (debug) printf("poll_recv_request would have blocked\n");
+                free(buf);
                 return;
             }
             if (debug) printf("recv(%d) error: %s\n",
@@ -2134,6 +2268,7 @@ static void poll_recv_request(struct connection* conn) {
         }
         conn->conn_close = 1;
         conn->state = DONE;
+        free(buf);
         return;
     }
     conn->last_active = now;
@@ -2167,6 +2302,7 @@ static void poll_recv_request(struct connection* conn) {
      */
     if (conn->state == SEND_HEADER)
         poll_send_header(conn);
+    free(buf);
 }
 
 /* Sending header.  Assumes conn->header is not NULL. */
@@ -2251,8 +2387,12 @@ static ssize_t send_from_file(const int s, const int fd,
 # ifndef min
 #  define min(a,b) ( ((a)<(b)) ? (a) : (b) )
 # endif
-    char buf[1 << 15];
-    size_t amount = min(sizeof(buf), size);
+    char * buf = (char*)malloc(1 << 15);
+    if (buf == NULL) {
+        printf("Out of memory!");
+        exit(-1);
+    }
+    size_t amount = min(1 << 15, size);
     ssize_t numread;
 
     if (lseek(fd, ofs, SEEK_SET) == -1)
@@ -2260,10 +2400,12 @@ static ssize_t send_from_file(const int s, const int fd,
     numread = read(fd, buf, amount);
     if (numread == 0) {
         fprintf(stderr, "premature eof on fd %d\n", fd);
+        free(buf);
         return -1;
     }
     else if (numread == -1) {
         fprintf(stderr, "error reading on fd %d: %s", fd, strerror(errno));
+        free(buf);
         return -1;
     }
     else if ((size_t)numread != amount) {
@@ -2271,8 +2413,12 @@ static ssize_t send_from_file(const int s, const int fd,
             numread, amount, fd);
         return -1;
     }
-    else
-        return send(s, buf, amount, 0);
+    else {
+        int ret = send(s, buf, amount, 0); 
+        free(buf);
+        printf("sending %d bytes", ret);
+        return ret;
+    }
 #endif
 #endif
 }
@@ -2295,7 +2441,7 @@ static void poll_send_reply(struct connection* conn)
         assert(conn->reply_length >= conn->reply_sent);
         sent = send_from_file(conn->socket, conn->reply_fd,
             conn->reply_start + conn->reply_sent,
-            (size_t)(conn->reply_length - conn->reply_sent));
+            (size_t) conn->reply_length - conn->reply_sent);
         if (debug && (sent < 1))
             printf("send_from_file returned %lld (errno=%d %s)\n",
                 (long long)sent, errno, strerror(errno));
@@ -2343,7 +2489,7 @@ static void httpd_poll(void) {
     int max_fd, select_ret;
     struct connection* conn, * next;
     int bother_with_timeout = 0;
-    struct timeval timeout, t0, t1;
+    struct timeval timeout;// , t0, t1;
 
     timeout.tv_sec = timeout_secs;
     timeout.tv_usec = 0;
@@ -2378,11 +2524,11 @@ static void httpd_poll(void) {
 #undef MAX_FD_SET
 
     /* -select- */
-    if (debug) {
-        printf("select() with max_fd %d timeout %d\n",
-            max_fd, bother_with_timeout ? (int)timeout.tv_sec : 0);
-        gettimeofday(&t0, NULL);
-    }
+    //if (debug) {
+    //    printf("select() with max_fd %d timeout %d\n",
+    //        max_fd, bother_with_timeout ? (int)timeout.tv_sec : 0);
+    //    gettimeofday(&t0, NULL);
+    //}
     select_ret = select(max_fd + 1, &recv_set, &send_set, NULL,
         (bother_with_timeout) ? &timeout : NULL);
     if (select_ret == 0) {
@@ -2395,18 +2541,18 @@ static void httpd_poll(void) {
         else
             err(1, "select() failed");
     }
-    if (debug) {
-        long long sec, usec;
-        gettimeofday(&t1, NULL);
-        sec = t1.tv_sec - t0.tv_sec;
-        usec = t1.tv_usec - t0.tv_usec;
-        if (usec < 0) {
-            usec += 1000000;
-            sec--;
-        }
-        printf("select() returned %d after %lld.%06lld secs\n",
-            select_ret, sec, usec);
-    }
+    //if (debug) {
+    //    long long sec, usec;
+    //    gettimeofday(&t1, NULL);
+    //    sec = t1.tv_sec - t0.tv_sec;
+    //    usec = t1.tv_usec - t0.tv_usec;
+    //    if (usec < 0) {
+    //        usec += 1000000;
+    //        sec--;
+    //    }
+    //    printf("select() returned %d after %lld.%06lld secs\n",
+    //        select_ret, sec, usec);
+    //}
 
     /* update time */
     now = time(NULL);
@@ -2454,135 +2600,137 @@ static void httpd_poll(void) {
     }
 }
 
-/* Daemonize helpers. */
-#define PATH_DEVNULL "/dev/null"
-static int lifeline[2] = { -1, -1 };
-static int fd_null = -1;
-
-static void daemonize_start(void) {
-    pid_t f;
-
-    if (pipe(lifeline) == -1)
-        err(1, "pipe(lifeline)");
-
-    fd_null = open(PATH_DEVNULL, O_RDWR, 0);
-    if (fd_null == -1)
-        err(1, "open(" PATH_DEVNULL ")");
-
-    f = fork();
-    if (f == -1)
-        err(1, "fork");
-    else if (f != 0) {
-        /* parent: wait for child */
-        char tmp[1];
-        int status;
-        pid_t w;
-
-        if (close(lifeline[1]) == -1)
-            warn("close lifeline in parent");
-        if (read(lifeline[0], tmp, sizeof(tmp)) == -1)
-            warn("read lifeline in parent");
-        w = waitpid(f, &status, WNOHANG);
-        if (w == -1)
-            err(1, "waitpid");
-        else if (w == 0)
-            /* child is running happily */
-            exit(EXIT_SUCCESS);
-        else
-            /* child init failed, pass on its exit status */
-            exit(WEXITSTATUS(status));
-    }
-    /* else we are the child: continue initializing */
-}
-
-static void daemonize_finish(void) {
-    if (fd_null == -1)
-        return; /* didn't daemonize_start() so we're not daemonizing */
-
-    if (setsid() == -1)
-        err(1, "setsid");
-    if (close(lifeline[0]) == -1)
-        warn("close read end of lifeline in child");
-    if (close(lifeline[1]) == -1)
-        warn("couldn't cut the lifeline");
-
-    /* close all our std fds */
-    if (dup2(fd_null, STDIN_FILENO) == -1)
-        warn("dup2(stdin)");
-    if (dup2(fd_null, STDOUT_FILENO) == -1)
-        warn("dup2(stdout)");
-    if (dup2(fd_null, STDERR_FILENO) == -1)
-        warn("dup2(stderr)");
-    if (fd_null > 2)
-        close(fd_null);
-}
+///* Daemonize helpers. */
+//#define PATH_DEVNULL "/dev/null"
+//static int lifeline[2] = { -1, -1 };
+//static int fd_null = -1;
+
+//static void daemonize_start(void) {
+    //pid_t f;
+
+    //if (pipe(lifeline) == -1)
+    //    err(1, "pipe(lifeline)");
+
+    //fd_null = open(PATH_DEVNULL, O_RDWR, 0);
+    //if (fd_null == -1)
+    //    err(1, "open(" PATH_DEVNULL ")");
+
+    //f = fork();
+    //if (f == -1)
+    //    err(1, "fork");
+    //else if (f != 0) {
+    //    /* parent: wait for child */
+    //    char tmp[1];
+    //    int status;
+    //    pid_t w;
+
+    //    if (close(lifeline[1]) == -1)
+    //        warn("close lifeline in parent");
+    //    if (read(lifeline[0], tmp, sizeof(tmp)) == -1)
+    //        warn("read lifeline in parent");
+    //    w = waitpid(f, &status, WNOHANG);
+    //    if (w == -1)
+    //        err(1, "waitpid");
+    //    else if (w == 0)
+    //        /* child is running happily */
+    //        exit(EXIT_SUCCESS);
+    //    else
+    //        /* child init failed, pass on its exit status */
+    //        exit(WEXITSTATUS(status));
+    //}
+    ///* else we are the child: continue initializing */
+//}
+
+//static void daemonize_finish(void) {
+    //if (fd_null == -1)
+    //    return; /* didn't daemonize_start() so we're not daemonizing */
+
+    //if (setsid() == -1)
+    //    err(1, "setsid");
+    //if (close(lifeline[0]) == -1)
+    //    warn("close read end of lifeline in child");
+    //if (close(lifeline[1]) == -1)
+    //    warn("couldn't cut the lifeline");
+
+    ///* close all our std fds */
+    //if (dup2(fd_null, STDIN_FILENO) == -1)
+    //    warn("dup2(stdin)");
+    //if (dup2(fd_null, STDOUT_FILENO) == -1)
+    //    warn("dup2(stdout)");
+    //if (dup2(fd_null, STDERR_FILENO) == -1)
+    //    warn("dup2(stderr)");
+    //if (fd_null > 2)
+    //    close(fd_null);
+//}
 
 /* [->] pidfile helpers, based on FreeBSD src/lib/libutil/pidfile.c,v 1.3
  * Original was copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
  */
-static int pidfile_fd = -1;
-#define PIDFILE_MODE 0600
-
-static void pidfile_remove(void) {
-    if (unlink(pidfile_name) == -1)
-        err(1, "unlink(pidfile) failed");
-    /* if (flock(pidfile_fd, LOCK_UN) == -1)
-           err(1, "unlock(pidfile) failed"); */
-    xclose(pidfile_fd);
-    pidfile_fd = -1;
-}
-
-static int pidfile_read(void) {
-    char buf[16];
-    int fd, i;
-    long long pid;
-
-    fd = open(pidfile_name, O_RDONLY);
-    if (fd == -1)
-        err(1, " after create failed");
-
-    i = (int)read(fd, buf, sizeof(buf) - 1);
-    if (i == -1)
-        err(1, "read from pidfile failed");
-    xclose(fd);
-    buf[i] = '\0';
-
-    if (!str_to_num(buf, &pid)) {
-        err(1, "invalid pidfile contents: \"%s\"", buf);
-    }
-    return (int)pid;
-}
-
-static void pidfile_create(void) {
-    int error, fd;
-    char pidstr[16];
-
-    /* Open the PID file and obtain exclusive lock. */
-    fd = open(pidfile_name,
-        O_WRONLY | O_CREAT | O_EXLOCK | O_TRUNC | O_NONBLOCK, PIDFILE_MODE);
-    if (fd == -1) {
-        if ((errno == EWOULDBLOCK) || (errno == EEXIST))
-            errx(1, "daemon already running with PID %d", pidfile_read());
-        else
-            err(1, "can't create pidfile %s", pidfile_name);
-    }
-    pidfile_fd = fd;
-
-    if (ftruncate(fd, 0) == -1) {
-        error = errno;
-        pidfile_remove();
-        errno = error;
-        err(1, "ftruncate() failed");
-    }
-
-    snprintf(pidstr, sizeof(pidstr), "%d", (int)getpid());
-    if (pwrite(fd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) {
-        error = errno;
-        pidfile_remove();
-        errno = error;
-        err(1, "pwrite() failed");
-    }
-}
+//static int pidfile_fd = -1;
+//#define PIDFILE_MODE 0600
+
+//static void pidfile_remove(void) {
+    //if (unlink(pidfile_name) == -1)
+    //    err(1, "unlink(pidfile) failed");
+    ///* if (flock(pidfile_fd, LOCK_UN) == -1)
+    //       err(1, "unlock(pidfile) failed"); */
+    //xclose(pidfile_fd);
+    //pidfile_fd = -1;
+//}
+
+//static int pidfile_read(void) {
+    //char buf[16];
+    //int fd, i;
+    //long long pid;
+
+    //fd = open(pidfile_name, O_RDONLY);
+    //if (fd == -1)
+    //    err(1, " after create failed");
+
+    //i = (int)read(fd, buf, sizeof(buf) - 1);
+    //if (i == -1)
+    //    err(1, "read from pidfile failed");
+    //xclose(fd);
+    //buf[i] = '\0';
+
+    //if (!str_to_num(buf, &pid)) {
+    //    err(1, "invalid pidfile contents: \"%s\"", buf);
+    //}
+    //return (int)pid;
+//}
+
+//static void pidfile_create(void) {
+    //int error, fd;
+    //char pidstr[16];
+
+    ///* Open the PID file and obtain exclusive lock. */
+    ////fd = open(pidfile_name,
+    ////    O_WRONLY | O_CREAT | O_EXLOCK | O_TRUNC | O_NONBLOCK, PIDFILE_MODE);
+    //// no nonblocking with open() in win
+    //fd = open(pidfile_name, O_WRONLY | O_CREAT | O_EXLOCK | O_TRUNC, PIDFILE_MODE);
+    //if (fd == -1) {
+    //    if ((errno == EWOULDBLOCK) || (errno == EEXIST))
+    //        errx(1, "daemon already running with PID %d", pidfile_read());
+    //    else
+    //        err(1, "can't create pidfile %s", pidfile_name);
+    //}
+    //pidfile_fd = fd;
+
+    //if (ftruncate(fd, 0) == -1) {
+    //    error = errno;
+    //    pidfile_remove();
+    //    errno = error;
+    //    err(1, "ftruncate() failed");
+    //}
+
+    //snprintf(pidstr, sizeof(pidstr), "%d", (int)getpid());
+    //if (pwrite(fd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) {
+    //    error = errno;
+    //    pidfile_remove();
+    //    errno = error;
+    //    err(1, "pwrite() failed");
+    //}
+//}
 /* [<-] end of pidfile helpers. */
 
 /* Close all sockets and FILEs and exit. */
@@ -2604,6 +2752,27 @@ int main(int argc, char** argv) {
         xasprintf(&server_hdr, "Server: %s\r\n", pkgname);
     else
         server_hdr = xstrdup("");
+
+
+    // winsock startup code
+    WORD wVersionRequested;
+    WSADATA wsaData;
+    int code;
+
+    /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
+    wVersionRequested = MAKEWORD(2, 2);
+
+    code = WSAStartup(wVersionRequested, &wsaData);
+    if (code != 0) {
+        /* Tell the user that we could not find a usable */
+        /* Winsock DLL.                                  */
+        printf("WSAStartup failed with error: %d\n", code);
+        return 1;
+    }
+
+    // end winsock startup code
+
+
     init_sockin();
 
     /* open logfile */
@@ -2615,54 +2784,63 @@ int main(int argc, char** argv) {
             err(1, "opening logfile: fopen(\"%s\")", logfile_name);
     }
 
-    if (want_daemon)
-        daemonize_start();
+    //if (want_daemon)
+    //    daemonize_start();
 
     /* signals */
-    if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
-        err(1, "signal(ignore SIGPIPE)");
+    //if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
+    //    err(1, "signal(ignore SIGPIPE)");
     if (signal(SIGINT, stop_running) == SIG_ERR)
         err(1, "signal(SIGINT)");
     if (signal(SIGTERM, stop_running) == SIG_ERR)
         err(1, "signal(SIGTERM)");
 
-    /* security */
-    if (want_chroot) {
-        tzset(); /* read /etc/localtime before we chroot */
-        if (chdir(wwwroot) == -1)
-            err(1, "chdir(%s)", wwwroot);
-        if (chroot(wwwroot) == -1)
-            err(1, "chroot(%s)", wwwroot);
-        printf("chrooted to `%s'\n", wwwroot);
-        wwwroot[0] = '\0'; /* empty string */
-    }
-    if (drop_gid != INVALID_GID) {
-        gid_t list[1];
-        list[0] = drop_gid;
-        if (setgroups(1, list) == -1)
-            err(1, "setgroups([%d])", (int)drop_gid);
-        if (setgid(drop_gid) == -1)
-            err(1, "setgid(%d)", (int)drop_gid);
-        printf("set gid to %d\n", (int)drop_gid);
-    }
-    if (drop_uid != INVALID_UID) {
-        if (setuid(drop_uid) == -1)
-            err(1, "setuid(%d)", (int)drop_uid);
-        printf("set uid to %d\n", (int)drop_uid);
-    }
-
-    /* create pidfile */
-    if (pidfile_name) pidfile_create();
-
-    if (want_daemon) daemonize_finish();
+    ///* security */
+    //if (want_chroot) {
+    //    tzset(); /* read /etc/localtime before we chroot */
+    //    if (chdir(wwwroot) == -1)
+    //        err(1, "chdir(%s)", wwwroot);
+    //    if (chroot(wwwroot) == -1)
+    //        err(1, "chroot(%s)", wwwroot);
+    //    printf("chrooted to `%s'\n", wwwroot);
+    //    wwwroot[0] = '\0'; /* empty string */
+    //}
+    //if (drop_gid != INVALID_GID) {
+    //    gid_t list[1];
+    //    list[0] = drop_gid;
+    //    if (setgroups(1, list) == -1)
+    //        err(1, "setgroups([%d])", (int)drop_gid);
+    //    if (setgid(drop_gid) == -1)
+    //        err(1, "setgid(%d)", (int)drop_gid);
+    //    printf("set gid to %d\n", (int)drop_gid);
+    //}
+    //if (drop_uid != INVALID_UID) {
+    //    if (setuid(drop_uid) == -1)
+    //        err(1, "setuid(%d)", (int)drop_uid);
+    //    printf("set uid to %d\n", (int)drop_uid);
+    //}
+
+    ///* create pidfile */
+    //if (pidfile_name) pidfile_create();
+
+    //if (want_daemon) daemonize_finish();
 
     /* main loop */
     while (running) httpd_poll();
 
     /* clean exit */
-    xclose(sockin);
+    xclosesock(sockin);
+
+
+    // winsock cleanup call
+
+    WSACleanup();
+
+    // end winsock cleanup call
+
+
     if (logfile != NULL) fclose(logfile);
-    if (pidfile_name) pidfile_remove();
+    //if (pidfile_name) pidfile_remove();
 
     /* close and free connections */
     {
@@ -2690,22 +2868,21 @@ int main(int argc, char** argv) {
         free(server_hdr);
     }
 
-    /* usage stats */
-    {
-        struct rusage r;
-
-        getrusage(RUSAGE_SELF, &r);
-        printf("CPU time used: %u.%02u user, %u.%02u system\n",
-            (unsigned int)r.ru_utime.tv_sec,
-            (unsigned int)(r.ru_utime.tv_usec / 10000),
-            (unsigned int)r.ru_stime.tv_sec,
-            (unsigned int)(r.ru_stime.tv_usec / 10000)
-            );
-        printf("Requests: %llu\n", llu(num_requests));
-        printf("Bytes: %llu in, %llu out\n", llu(total_in), llu(total_out));
-    }
-
+    ///* usage stats */
+    //{
+    //    struct rusage r;
+
+    //    getrusage(RUSAGE_SELF, &r);
+    //    printf("CPU time used: %u.%02u user, %u.%02u system\n",
+    //        (unsigned int)r.ru_utime.tv_sec,
+    //        (unsigned int)(r.ru_utime.tv_usec / 10000),
+    //        (unsigned int)r.ru_stime.tv_sec,
+    //        (unsigned int)(r.ru_stime.tv_usec / 10000)
+    //        );
+    //    printf("Requests: %llu\n", llu(num_requests));
+    //    printf("Bytes: %llu in, %llu out\n", llu(total_in), llu(total_out));
+    //}
     return 0;
 }
 
-/* vim:set ts=4 sw=4 sts=4 expandtab tw=78: */
\ No newline at end of file
+/* vim:set ts=4 sw=4 sts=4 expandtab tw=78: */