Check the chdir() return code
[privoxy.git] / jcc.c
diff --git a/jcc.c b/jcc.c
index 875c8a7..d8e25d5 100644 (file)
--- a/jcc.c
+++ b/jcc.c
 #else
 #include <poll.h>
 #endif /* def __GLIBC__ */
+#else
+# ifndef FD_ZERO
+#  include <select.h>
+# endif
+#warning poll() appears to be unavailable. Your platform will become unsupported in the future.
 #endif /* HAVE_POLL */
 
 #endif
@@ -2580,7 +2585,13 @@ static void handle_established_connection(struct client_state *csp)
    char *hdr;
    char *p;
    int n;
+#ifdef HAVE_POLL
    struct pollfd poll_fds[2];
+#else
+   fd_set rfds;
+   jb_socket maxfd;
+   struct timeval timeout;
+#endif
    int server_body;
    int ms_iis5_hack = 0;
    unsigned long long byte_count = 0;
@@ -2619,6 +2630,11 @@ static void handle_established_connection(struct client_state *csp)
 
    http = csp->http;
 
+#ifndef HAVE_POLL
+   maxfd = (csp->cfd > csp->server_connection.sfd) ?
+      csp->cfd : csp->server_connection.sfd;
+#endif
+
    /* pass data between the client and server
     * until one or the other shuts down the connection.
     */
@@ -2632,6 +2648,22 @@ static void handle_established_connection(struct client_state *csp)
 
    for (;;)
    {
+#ifndef HAVE_POLL
+      FD_ZERO(&rfds);
+#ifdef FEATURE_CONNECTION_KEEP_ALIVE
+      if (!watch_client_socket)
+      {
+         maxfd = csp->server_connection.sfd;
+      }
+      else
+#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
+      {
+         FD_SET(csp->cfd, &rfds);
+      }
+
+      FD_SET(csp->server_connection.sfd, &rfds);
+#endif /* ndef HAVE_POLL */
+
 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
       if ((csp->flags & CSP_FLAG_CHUNKED)
          && !(csp->flags & CSP_FLAG_CONTENT_LENGTH_SET)
@@ -2675,6 +2707,7 @@ static void handle_established_connection(struct client_state *csp)
       }
 #endif  /* FEATURE_CONNECTION_KEEP_ALIVE */
 
+#ifdef HAVE_POLL
       poll_fds[0].fd = csp->cfd;
 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
       if (!watch_client_socket)
@@ -2695,6 +2728,11 @@ static void handle_established_connection(struct client_state *csp)
       poll_fds[1].fd = csp->server_connection.sfd;
       poll_fds[1].events = POLLIN;
       n = poll(poll_fds, 2, csp->config->socket_timeout * 1000);
+#else
+      timeout.tv_sec = csp->config->socket_timeout;
+      timeout.tv_usec = 0;
+      n = select((int)maxfd + 1, &rfds, NULL, NULL, &timeout);
+#endif /* def HAVE_POLL */
 
       /*server or client not responding in timeout */
       if (n == 0)
@@ -2713,7 +2751,11 @@ static void handle_established_connection(struct client_state *csp)
       }
       else if (n < 0)
       {
+#ifdef HAVE_POLL
          log_error(LOG_LEVEL_ERROR, "poll() failed!: %E");
+#else
+         log_error(LOG_LEVEL_ERROR, "select() failed!: %E");
+#endif
          mark_server_socket_tainted(csp);
 #ifdef FEATURE_HTTPS_INSPECTION
          close_client_and_server_ssl_connections(csp);
@@ -2730,6 +2772,7 @@ static void handle_established_connection(struct client_state *csp)
        * XXX: Make sure the client doesn't use pipelining
        * behind Privoxy's back.
        */
+#ifdef HAVE_POLL
       if ((poll_fds[0].revents & (POLLERR|POLLHUP|POLLNVAL)) != 0)
       {
          log_error(LOG_LEVEL_CONNECT,
@@ -2741,6 +2784,9 @@ static void handle_established_connection(struct client_state *csp)
       }
 
       if (poll_fds[0].revents != 0)
+#else
+      if (FD_ISSET(csp->cfd, &rfds))
+#endif /* def HAVE_POLL*/
       {
          int max_bytes_to_read = (int)csp->receive_buffer_size;
 
@@ -2751,7 +2797,7 @@ static void handle_established_connection(struct client_state *csp)
             {
                /*
                 * If the next request is already waiting, we have
-                * to stop poll()ing the client socket. Otherwise
+                * to stop select()ing the client socket. Otherwise
                 * we would always return right away and get nothing
                 * else done.
                 */
@@ -2869,7 +2915,11 @@ static void handle_established_connection(struct client_state *csp)
        * If `hdr' is null, then it's the header otherwise it's the body.
        * FIXME: Does `hdr' really mean `host'? No.
        */
+#ifdef HAVE_POLL
       if (poll_fds[1].revents != 0)
+#else
+      if (FD_ISSET(csp->server_connection.sfd, &rfds))
+#endif /* HAVE_POLL */
       {
 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
          /*
@@ -3670,7 +3720,7 @@ static void chat(struct client_state *csp)
       use_ssl_tunnel = 1;
    }
 
-   if (http->ssl && csp->action->flags & ACTION_IGNORE_CERTIFICATE_ERRORS)
+   if (http->ssl && (csp->action->flags & ACTION_IGNORE_CERTIFICATE_ERRORS))
    {
       csp->dont_verify_certificate = 1;
    }
@@ -5132,7 +5182,10 @@ int main(int argc, char **argv)
       }
 #endif
 
-      chdir("/");
+      if (chdir("/") != 0)
+      {
+         log_error(LOG_LEVEL_FATAL, "Failed to cd into '/': %E");
+      }
 
    } /* -END- if (daemon_mode) */
 
@@ -5299,6 +5352,17 @@ static jb_socket bind_port_helper(const char *haddr, int hport, int backlog)
       return JB_INVALID_SOCKET;
    }
 
+#ifndef HAVE_POLL
+#ifndef _WIN32
+   if (bfd >= FD_SETSIZE)
+   {
+      log_error(LOG_LEVEL_FATAL,
+         "Bind socket number too high to use select(): %d >= %d",
+         bfd, FD_SETSIZE);
+   }
+#endif
+#endif
+
    if (haddr == NULL)
    {
       log_error(LOG_LEVEL_INFO, "Listening on port %d on all IP addresses",