Make poll() non-optional and remove select()-based fallback code
[privoxy.git] / jcc.c
diff --git a/jcc.c b/jcc.c
index f258544..875c8a7 100644 (file)
--- a/jcc.c
+++ b/jcc.c
 
 #else /* ifndef _WIN32 */
 
-# if !defined (__OS2__)
 # include <unistd.h>
 # include <sys/wait.h>
-# endif /* ndef __OS2__ */
 # include <sys/time.h>
 # include <sys/stat.h>
 # include <sys/ioctl.h>
 #  include <OS.h>      /* declarations for threads and stuff. */
 # endif
 
-# if defined(__EMX__) || defined(__OS2__)
-#  include <sys/select.h>  /* OS/2/EMX needs a little help with select */
-# endif
-# ifdef __OS2__
-#define INCL_DOS
-# include <os2.h>
-# endif
-
 #ifdef HAVE_POLL
 #ifdef __GLIBC__
 #include <sys/poll.h>
 #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
@@ -143,7 +128,7 @@ int urls_rejected = 0;     /* total nr of urls rejected */
 int g_terminate = 0;
 #endif
 
-#if !defined(_WIN32) && !defined(__OS2__)
+#if !defined(_WIN32)
 static void sig_handler(int the_signal);
 #endif
 static int client_protocol_is_unsupported(struct client_state *csp, char *req);
@@ -177,10 +162,6 @@ static int32 server_thread(void *data);
 #define sleep(N)  Sleep(((N) * 1000))
 #endif
 
-#ifdef __OS2__
-#define sleep(N)  DosSleep(((N) * 100))
-#endif
-
 #ifdef FUZZ
 int process_fuzzed_input(char *fuzz_input_type, char *fuzz_input_file);
 void show_fuzz_usage(const char *name);
@@ -347,7 +328,7 @@ static const struct cruncher crunchers_light[] = {
  *
  * here?
  */
-#if !defined(_WIN32) && !defined(__OS2__)
+#if !defined(_WIN32)
 /*********************************************************************
  *
  * Function    :  sig_handler
@@ -573,8 +554,6 @@ static int client_has_unsupported_expectations(const struct client_state *csp)
  *********************************************************************/
 static jb_err get_request_destination_elsewhere(struct client_state *csp, struct list *headers)
 {
-   char *req;
-
    if (!(csp->config->feature_flags & RUNTIME_FEATURE_ACCEPT_INTERCEPTED_REQUESTS))
    {
       log_error(LOG_LEVEL_ERROR, "%s's request: \'%s\' is invalid."
@@ -601,15 +580,12 @@ static jb_err get_request_destination_elsewhere(struct client_state *csp, struct
    {
       /* We can't work without destination. Go spread the news.*/
 
-      req = list_to_text(headers);
-      chomp(req);
       /* XXX: Use correct size */
       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 400 0",
          csp->ip_addr_str, csp->http->cmd);
       log_error(LOG_LEVEL_ERROR,
-         "Privoxy was unable to get the destination for %s's request:\n%s\n%s",
-         csp->ip_addr_str, csp->http->cmd, req);
-      freez(req);
+         "Privoxy was unable to get the destination for %s's request: %s",
+         csp->ip_addr_str, csp->http->cmd);
 
       write_socket_delayed(csp->cfd, MISSING_DESTINATION_RESPONSE,
          strlen(MISSING_DESTINATION_RESPONSE), get_write_delay(csp));
@@ -857,7 +833,7 @@ static void send_crunch_response(struct client_state *csp, struct http_response
       {
          log_error(LOG_LEVEL_CRUNCH, "%s: https://%s%s", crunch_reason(rsp),
             http->hostport, http->path);
-         log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s https://%s%s %s\" %s %llu",
+         log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s https://%s%s %s\" %s %lu",
             csp->ip_addr_str, http->gpc, http->hostport, http->path,
             http->version, status_code, rsp->content_length);
       }
@@ -865,7 +841,7 @@ static void send_crunch_response(struct client_state *csp, struct http_response
 #endif
       {
          log_error(LOG_LEVEL_CRUNCH, "%s: %s", crunch_reason(rsp), http->url);
-         log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" %s %u",
+         log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" %s %lu",
             csp->ip_addr_str, http->ocmd, status_code, rsp->content_length);
       }
       /* Write the answer to the client */
@@ -881,8 +857,8 @@ static void send_crunch_response(struct client_state *csp, struct http_response
          {
             /* There is nothing we can do about it. */
             log_error(LOG_LEVEL_CONNECT, "Couldn't deliver the error message "
-               "for %s through client socket %d using TLS/SSL",
-               http->url, csp->cfd);
+               "for https://%s%s through client socket %d using TLS/SSL",
+               http->hostport, http->url, csp->cfd);
          }
       }
       else
@@ -1190,6 +1166,22 @@ void save_connection_destination(jb_socket sfd,
       server_connection->gateway_host = NULL;
    }
    server_connection->gateway_port = fwd->gateway_port;
+   if (NULL != fwd->auth_username)
+   {
+      server_connection->auth_username = strdup_or_die(fwd->auth_username);
+   }
+   else
+   {
+      server_connection->auth_username = NULL;
+   }
+   if (NULL != fwd->auth_password)
+   {
+      server_connection->auth_password = strdup_or_die(fwd->auth_password);
+   }
+   else
+   {
+      server_connection->auth_password = NULL;
+   }
 
    if (NULL != fwd->forward_host)
    {
@@ -1201,6 +1193,7 @@ void save_connection_destination(jb_socket sfd,
    }
    server_connection->forward_port = fwd->forward_port;
 }
+#endif /* FEATURE_CONNECTION_KEEP_ALIVE */
 
 
 /*********************************************************************
@@ -1301,7 +1294,6 @@ static void verify_request_length(struct client_state *csp)
       log_error(LOG_LEVEL_CONNECT, "Complete client request received.");
    }
 }
-#endif /* FEATURE_CONNECTION_KEEP_ALIVE */
 
 
 /*********************************************************************
@@ -1562,7 +1554,7 @@ static jb_err receive_chunked_client_request_body(struct client_state *csp)
       return JB_ERR_PARSE;
    }
    log_error(LOG_LEVEL_CONNECT,
-      "Chunked client body completely read. Length: %d", body_length);
+      "Chunked client body completely read. Length: %lu", body_length);
    csp->expected_client_content_length = body_length;
 
    return JB_ERR_OK;
@@ -1922,6 +1914,7 @@ static jb_err parse_client_request(struct client_state *csp)
       /* Assume persistence until further notice */
       csp->flags |= CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
    }
+#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
 
    if (csp->http->ssl == 0)
    {
@@ -1948,7 +1941,6 @@ static jb_err parse_client_request(struct client_state *csp)
       csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED;
    }
 #endif
-#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
 
    err = sed(csp, FILTER_CLIENT_HEADERS);
    if (JB_ERR_OK != err)
@@ -2166,21 +2158,21 @@ static int send_https_request(struct client_state *csp)
          csp->http->hostport);
       return 1;
    }
-   if (flushed != 0)
+   if (flushed != 0 || csp->expected_client_content_length != 0)
    {
       if (csp->expected_client_content_length != 0)
       {
          if (csp->expected_client_content_length < flushed)
          {
             log_error(LOG_LEVEL_ERROR,
-               "Flushed %d bytes of request body while only expecting %llu",
+               "Flushed %ld bytes of request body while only expecting %llu",
                flushed, csp->expected_client_content_length);
             csp->expected_client_content_length = 0;
          }
          else
          {
             log_error(LOG_LEVEL_CONNECT,
-               "Flushed %d bytes of request body while expecting %llu",
+               "Flushed %ld bytes of request body while expecting %llu",
                flushed, csp->expected_client_content_length);
             csp->expected_client_content_length -= (unsigned)flushed;
             if (receive_and_send_encrypted_post_data(csp))
@@ -2192,7 +2184,7 @@ static int send_https_request(struct client_state *csp)
       else
       {
          log_error(LOG_LEVEL_CONNECT,
-            "Flushed %d bytes of request body", flushed);
+            "Flushed %ld bytes of request body", flushed);
       }
    }
 
@@ -2290,7 +2282,8 @@ static jb_err process_encrypted_request(struct client_state *csp)
    err = receive_encrypted_request(csp);
    if (err != JB_ERR_OK)
    {
-      if (csp->client_iob->cur == NULL)
+      if (csp->client_iob->cur == NULL ||
+          csp->client_iob->cur == csp->client_iob->eod)
       {
          /*
           * We did not receive any data, most likely because the
@@ -2486,14 +2479,13 @@ static int cgi_page_requested(const char *host)
  *                failures etc.
  *
  *                If a connection to the server has already been
- *                opened it is reused unless the request is blocked.
+ *                opened it is reused unless the request is blocked
+ *                or the forwarder changed.
  *
  *                If a connection to the server has not yet been
- *                opened (because the previous request was crunched)
- *                the connection is dropped so that the client retries
- *                on a fresh one.
- *
- *                XXX: Forwarding settings are currently ignored.
+ *                opened (because the previous request was crunched),
+ *                or the forwarder changed, the connection is dropped
+ *                so that the client retries on a fresh one.
  *
  * Parameters  :
  *          1  :  csp = Current client state (buffers, headers, etc...)
@@ -2503,6 +2495,8 @@ static int cgi_page_requested(const char *host)
  *********************************************************************/
 static void continue_https_chat(struct client_state *csp)
 {
+   const struct forward_spec *fwd;
+
    if (JB_ERR_OK != process_encrypted_request(csp))
    {
       return;
@@ -2529,6 +2523,24 @@ static void continue_https_chat(struct client_state *csp)
       csp->flags &= ~CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
       return;
    }
+   assert(csp->server_connection.sfd != JB_INVALID_SOCKET);
+
+   fwd = forward_url(csp, csp->http);
+   if (!connection_destination_matches(&csp->server_connection, csp->http, fwd))
+   {
+      log_error(LOG_LEVEL_CONNECT,
+         "Dropping the client connection on socket %d with "
+         "server socket %d connected to %s. The forwarder has changed.",
+         csp->cfd, csp->server_connection.sfd, csp->server_connection.host);
+      csp->flags &= ~CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
+      return;
+   }
+
+   log_error(LOG_LEVEL_CONNECT,
+      "Reusing server socket %d connected to %s. Requests already sent: %u.",
+      csp->server_connection.sfd, csp->server_connection.host,
+      csp->server_connection.requests_sent_total);
+
    if (send_https_request(csp))
    {
       /*
@@ -2542,6 +2554,7 @@ static void continue_https_chat(struct client_state *csp)
          csp->cfd);
       return;
    }
+   csp->server_connection.requests_sent_total++;
    handle_established_connection(csp);
    freez(csp->receive_buffer);
 }
@@ -2567,13 +2580,7 @@ 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;
@@ -2612,11 +2619,6 @@ 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.
     */
@@ -2630,30 +2632,6 @@ static void handle_established_connection(struct client_state *csp)
 
    for (;;)
    {
-#ifndef HAVE_POLL
-#ifdef __OS2__
-      /*
-       * FD_ZERO here seems to point to an errant macro which crashes.
-       * So do this by hand for now...
-       */
-      memset(&rfds,0x00,sizeof(fd_set));
-#else
-      FD_ZERO(&rfds);
-#endif
-#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)
@@ -2678,14 +2656,14 @@ static void handle_established_connection(struct client_state *csp)
          {
             log_error(LOG_LEVEL_CONNECT,
                "Done reading from server. Content length: %llu as expected. "
-               "Bytes most recently read: %d.",
+               "Bytes most recently read: %ld.",
                byte_count, len);
          }
          else
          {
             log_error(LOG_LEVEL_CONNECT,
                "Done reading from server. Expected content length: %llu. "
-               "Actual content length: %llu. Bytes most recently read: %d.",
+               "Actual content length: %llu. Bytes most recently read: %ld.",
                csp->expected_content_length, byte_count, len);
          }
          len = 0;
@@ -2697,7 +2675,6 @@ 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)
@@ -2718,11 +2695,6 @@ 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)
@@ -2741,11 +2713,7 @@ 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);
@@ -2762,7 +2730,6 @@ 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,
@@ -2774,9 +2741,6 @@ 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;
 
@@ -2787,7 +2751,7 @@ static void handle_established_connection(struct client_state *csp)
             {
                /*
                 * If the next request is already waiting, we have
-                * to stop select()ing the client socket. Otherwise
+                * to stop poll()ing the client socket. Otherwise
                 * we would always return right away and get nothing
                 * else done.
                 */
@@ -2826,6 +2790,37 @@ static void handle_established_connection(struct client_state *csp)
 #ifdef FEATURE_HTTPS_INSPECTION
          if (client_use_ssl(csp))
          {
+            if (csp->http->status == 101)
+            {
+               len = ssl_recv_data(&(csp->ssl_client_attr),
+                  (unsigned char *)csp->receive_buffer,
+                  (size_t)max_bytes_to_read);
+               if (len == -1)
+               {
+                  log_error(LOG_LEVEL_ERROR, "Failed to receive data "
+                     "on client socket %d for an upgraded connection",
+                     csp->cfd);
+                  break;
+               }
+               if (len == 0)
+               {
+                  log_error(LOG_LEVEL_CONNECT, "Done receiving data "
+                     "on client socket %d for an upgraded connection",
+                     csp->cfd);
+                  break;
+               }
+               byte_count += (unsigned long long)len;
+               len = ssl_send_data(&(csp->ssl_server_attr),
+                  (unsigned char *)csp->receive_buffer, (size_t)len);
+               if (len == -1)
+               {
+                  log_error(LOG_LEVEL_ERROR, "Failed to send data "
+                     "on server socket %d for an upgraded connection",
+                     csp->server_connection.sfd);
+                  break;
+               }
+               continue;
+            }
             log_error(LOG_LEVEL_CONNECT, "Breaking with TLS/SSL.");
             break;
          }
@@ -2848,7 +2843,7 @@ static void handle_established_connection(struct client_state *csp)
                csp->expected_client_content_length -= (unsigned)len;
                log_error(LOG_LEVEL_CONNECT,
                   "Expected client content length set to %llu "
-                  "after reading %d bytes.",
+                  "after reading %ld bytes.",
                   csp->expected_client_content_length, len);
                if (csp->expected_client_content_length == 0)
                {
@@ -2874,11 +2869,7 @@ 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
          /*
@@ -3322,7 +3313,7 @@ static void handle_established_connection(struct client_state *csp)
                    */
                   log_error(LOG_LEVEL_CONNECT,
                      "Continuing buffering server headers from socket %d. "
-                     "Bytes most recently read: %d.", csp->cfd, len);
+                     "Bytes most recently read: %ld.", csp->cfd, len);
                   continue;
                }
             }
@@ -3667,12 +3658,6 @@ static void chat(struct client_state *csp)
 
    /* decide how to route the HTTP request */
    fwd = forward_url(csp, http);
-   if (NULL == fwd)
-   {
-      log_error(LOG_LEVEL_FATAL, "gateway spec is NULL!?!?  This can't happen!");
-      /* Never get here - LOG_LEVEL_FATAL causes program exit */
-      return;
-   }
 
 #ifdef FEATURE_HTTPS_INSPECTION
    /*
@@ -3874,7 +3859,6 @@ static void chat(struct client_state *csp)
          }
          if (JB_ERR_OK != process_encrypted_request(csp))
          {
-            log_error(LOG_LEVEL_ERROR, "Failed to parse encrypted request.");
             close_client_ssl_connection(csp);
             return;
          }
@@ -4111,10 +4095,12 @@ static void chat(struct client_state *csp)
       else
       {
          /*
-          * If server certificate is invalid, we must inform client and then
-          * close connection with client.
+          * If server certificate has been verified and is invalid,
+          * we must inform the client and then close the connection
+          * with client and server.
           */
-         if (csp->server_cert_verification_result != SSL_CERT_VALID)
+         if (csp->server_cert_verification_result != SSL_CERT_VALID &&
+             csp->server_cert_verification_result != SSL_CERT_NOT_VERIFIED)
          {
             ssl_send_certificate_error(csp);
             close_client_and_server_ssl_connections(csp);
@@ -4262,7 +4248,7 @@ static void prepare_csp_for_next_request(struct client_state *csp)
       assert(bytes_to_shift > 0);
       assert(data_length > 0);
 
-      log_error(LOG_LEVEL_CONNECT, "Shifting %d pipelined bytes by %d bytes",
+      log_error(LOG_LEVEL_CONNECT, "Shifting %lu pipelined bytes by %ld bytes",
          data_length, bytes_to_shift);
       memmove(csp->client_iob->buf, csp->client_iob->cur, data_length);
       csp->client_iob->cur = csp->client_iob->buf;
@@ -4496,6 +4482,20 @@ static void serve(struct client_state *csp)
    chat(csp);
 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
 
+   if (csp->cfd != JB_INVALID_SOCKET)
+   {
+      log_error(LOG_LEVEL_CONNECT, "Closing client socket %d. "
+         "Keep-alive: %u. Socket alive: %u. Data available: %u. "
+         "Configuration file change detected: %u. Requests received: %u.",
+         csp->cfd, 0 != (csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE),
+         socket_is_still_alive(csp->cfd), data_is_available(csp->cfd, 0),
+         config_file_change_detected, csp->requests_received_total);
+#ifdef FEATURE_HTTPS_INSPECTION
+      close_client_ssl_connection(csp);
+#endif
+      drain_and_close_socket(csp->cfd);
+   }
+
    if (csp->server_connection.sfd != JB_INVALID_SOCKET)
    {
 #ifdef FEATURE_CONNECTION_SHARING
@@ -4516,20 +4516,6 @@ static void serve(struct client_state *csp)
    mark_connection_closed(&csp->server_connection);
 #endif
 
-   if (csp->cfd != JB_INVALID_SOCKET)
-   {
-      log_error(LOG_LEVEL_CONNECT, "Closing client socket %d. "
-         "Keep-alive: %u. Socket alive: %u. Data available: %u. "
-         "Configuration file change detected: %u. Requests received: %u.",
-         csp->cfd, 0 != (csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE),
-         socket_is_still_alive(csp->cfd), data_is_available(csp->cfd, 0),
-         config_file_change_detected, csp->requests_received_total);
-#ifdef FEATURE_HTTPS_INSPECTION
-      close_client_ssl_connection(csp);
-#endif
-      drain_and_close_socket(csp->cfd);
-   }
-
    free_csp_resources(csp);
 
    csp->flags &= ~CSP_FLAG_ACTIVE;
@@ -5013,7 +4999,7 @@ int main(int argc, char **argv)
     * are handled when and where they occur without relying
     * on a signal.
     */
-#if !defined(_WIN32) && !defined(__OS2__)
+#if !defined(_WIN32)
 {
    int idx;
    const int catched_signals[] = { SIGTERM, SIGINT, SIGHUP };
@@ -5313,17 +5299,6 @@ 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",
@@ -5475,7 +5450,7 @@ static void listen_loop(void)
    for (;;)
 #endif
    {
-#if !defined(FEATURE_PTHREAD) && !defined(_WIN32) && !defined(__BEOS__) && !defined(__OS2__)
+#if !defined(FEATURE_PTHREAD) && !defined(_WIN32) && !defined(__BEOS__)
       while (waitpid(-1, NULL, WNOHANG) > 0)
       {
          /* zombie children */
@@ -5505,7 +5480,7 @@ static void listen_loop(void)
       csp = &csp_list->csp;
 
       log_error(LOG_LEVEL_CONNECT,
-         "Waiting for the next client connection. Currently active threads: %d",
+         "Waiting for the next client connection. Currently active threads: %u",
          active_threads);
 
       /*
@@ -5604,10 +5579,11 @@ static void listen_loop(void)
 #define SELECTED_ONE_OPTION
          {
             pthread_t the_thread;
+            int ret;
 
-            errno = pthread_create(&the_thread, &attrs,
+            ret = pthread_create(&the_thread, &attrs,
                (void * (*)(void *))serve, csp);
-            child_id = errno ? -1 : 0;
+            child_id = ret ? -1 : 0;
          }
 #endif
 
@@ -5619,15 +5595,6 @@ static void listen_loop(void)
             csp);
 #endif
 
-#if defined(__OS2__) && !defined(SELECTED_ONE_OPTION)
-#define SELECTED_ONE_OPTION
-         child_id = _beginthread(
-            (void(* _Optlink)(void*))serve,
-            NULL,
-            64 * 1024,
-            csp);
-#endif
-
 #if defined(__BEOS__) && !defined(SELECTED_ONE_OPTION)
 #define SELECTED_ONE_OPTION
          {
@@ -5730,7 +5697,7 @@ static void listen_loop(void)
              * XXX: If you assume ...
              */
             log_error(LOG_LEVEL_ERROR,
-               "Unable to take any additional connections: %E. Active threads: %d",
+               "Unable to take any additional connections: %E. Active threads: %u",
                active_threads);
             write_socket_delayed(csp->cfd, TOO_MANY_CONNECTIONS_RESPONSE,
                strlen(TOO_MANY_CONNECTIONS_RESPONSE), get_write_delay(csp));