Change in porting tactics: OS/2's EMX porting layer doesn't allow multiple
[privoxy.git] / jcc.c
diff --git a/jcc.c b/jcc.c
index 44f9398..4700d2f 100644 (file)
--- a/jcc.c
+++ b/jcc.c
@@ -1,19 +1,19 @@
-const char jcc_rcs[] = "$Id: jcc.c,v 1.48 2001/10/10 19:56:46 jongfoster Exp $";
+const char jcc_rcs[] = "$Id: jcc.c,v 1.49 2001/10/23 21:41:35 jongfoster Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/jcc.c,v $
  *
- * Purpose     :  Main file.  Contains main() method, main loop, and 
+ * Purpose     :  Main file.  Contains main() method, main loop, and
  *                the main connection-handling function.
  *
  * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
  *                IJBSWA team.  http://ijbswa.sourceforge.net
  *
  *                Based on the Internet Junkbuster originally written
- *                by and Copyright (C) 1997 Anonymous Coders and 
+ *                by and Copyright (C) 1997 Anonymous Coders and
  *                Junkbusters Corporation.  http://www.junkbusters.com
  *
- *                This program is free software; you can redistribute it 
+ *                This program is free software; you can redistribute it
  *                and/or modify it under the terms of the GNU General
  *                Public License as published by the Free Software
  *                Foundation; either version 2 of the License, or (at
@@ -33,6 +33,10 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.48 2001/10/10 19:56:46 jongfoster Exp $";
  *
  * Revisions   :
  *    $Log: jcc.c,v $
+ *    Revision 1.49  2001/10/23 21:41:35  jongfoster
+ *    Added call to initialize the (statically-allocated of course)
+ *    "out of memory" CGI response.
+ *
  *    Revision 1.48  2001/10/10 19:56:46  jongfoster
  *    Moving some code that wasn't cookie-related out of an #ifdef
  *    FEATURE_COOKIE_JAR
@@ -360,9 +364,11 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.48 2001/10/10 19:56:46 jongfoster Exp $";
 
 #else /* ifndef _WIN32 */
 
+# if !defined (__OS2__)
 # include <unistd.h>
-# include <sys/time.h>
 # include <sys/wait.h>
+# endif /* ndef __OS2__ */
+# include <sys/time.h>
 # include <sys/stat.h>
 # include <signal.h>
 
@@ -371,9 +377,14 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.48 2001/10/10 19:56:46 jongfoster Exp $";
 #  include <OS.h>      /* declarations for threads and stuff. */
 # endif
 
-# ifdef __EMX__
+# 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>
+#define bzero(B,N) memset(B,0x00,n)
+# endif
 
 # ifndef FD_ZERO
 #  include <select.h>
@@ -424,6 +435,10 @@ static int32 server_thread(void *data);
 #define sleep(N)  Sleep(((N) * 1000))
 #endif
 
+#ifdef __OS2__
+#define sleep(N)  DosSleep(((N) * 100))
+#endif
+
 
 /* The vanilla wafer. */
 static const char VANILLA_WAFER[] =
@@ -442,7 +457,7 @@ static const char VANILLA_WAFER[] =
  *
  * Description :  Once a connection to the client has been accepted,
  *                this function is called (via serve()) to handle the
- *                main business of the communication.  When this 
+ *                main business of the communication.  When this
  *                function returns, the caller must close the client
  *                socket handle.
  *
@@ -461,7 +476,7 @@ static void chat(struct client_state *csp)
 {
 /*
  * This next lines are a little ugly, but they simplifies the if statements
- * below.  Basically if TOGGLE, then we want the if to test if the 
+ * below.  Basically if TOGGLE, then we want the if to test if the
  * CSP_FLAG_TOGGLED_ON flag ist set, else we don't.  And if FEATURE_FORCE_LOAD,
  * then we want the if to test for CSP_FLAG_FORCED , else we don't
  */
@@ -471,7 +486,7 @@ static void chat(struct client_state *csp)
 #   define IS_TOGGLED_ON_AND
 #endif /* ndef FEATURE_TOGGLE */
 #ifdef FEATURE_FORCE_LOAD
-#   define IS_NOT_FORCED_AND !(csp->flags & CSP_FLAG_FORCED) && 
+#   define IS_NOT_FORCED_AND !(csp->flags & CSP_FLAG_FORCED) &&
 #else /* ifndef FEATURE_FORCE_LOAD */
 #   define IS_NOT_FORCED_AND
 #endif /* def FEATURE_FORCE_LOAD */
@@ -495,7 +510,7 @@ static void chat(struct client_state *csp)
    int gif_deanimate;      /* bool, 1==will deanimate gifs */
 
    /* Function that does the content filtering for the current request */
-   char *(*content_filter)() = NULL; 
+   char *(*content_filter)() = NULL;
 
    /* Skeleton for HTTP response, if we should intercept the request */
    struct http_response *rsp;
@@ -526,7 +541,7 @@ static void chat(struct client_state *csp)
       {
          continue;   /* more to come! */
       }
+
 #ifdef FEATURE_FORCE_LOAD
       /* If this request contains the FORCE_PREFIX,
        * better get rid of it now and set the force flag --oes
@@ -537,7 +552,7 @@ static void chat(struct client_state *csp)
          strclean(req, FORCE_PREFIX);
          log_error(LOG_LEVEL_FORCE, "Enforcing request \"%s\".\n", req);
          csp->flags |= CSP_FLAG_FORCED;
-      } 
+      }
 
 #endif /* def FEATURE_FORCE_LOAD */
 
@@ -573,7 +588,7 @@ static void chat(struct client_state *csp)
     *          full orininal URL (w/url)
     *          Note that the path and/or the HTTP version may
     *          have been altered by now.
-    * 
+    *
     * connect = Open a socket to the host:port of the server
     *           and short-circuit server and client socket.
     *
@@ -585,7 +600,7 @@ static void chat(struct client_state *csp)
     *         parent's). After sending the request to the parent, we simply
     *         tunnel.
     *
-    * here's the matrix: 
+    * here's the matrix:
     *                        SSL
     *                    0        1
     *                +--------+--------+
@@ -600,7 +615,7 @@ static void chat(struct client_state *csp)
     *
     */
 
-   /* 
+   /*
     * Determine the actions for this URL
     */
 #ifdef FEATURE_TOGGLE
@@ -623,20 +638,20 @@ static void chat(struct client_state *csp)
     */
    if(http->ssl)
    {
-      if(  ( !(csp->action->flags & ACTION_LIMIT_CONNECT) && csp->http->port != 443) 
+      if(  ( !(csp->action->flags & ACTION_LIMIT_CONNECT) && csp->http->port != 443)
            || (csp->action->flags & ACTION_LIMIT_CONNECT
               && !match_portlist(csp->action->string[ACTION_STRING_LIMIT_CONNECT], csp->http->port)) )
       {
          strcpy(buf, CFORBIDDEN);
          write_socket(csp->cfd, buf, strlen(buf));
-         
+
          log_error(LOG_LEVEL_CONNECT, "Denying suspicious CONNECT request from %s", csp->ip_addr_str);
          log_error(LOG_LEVEL_CLF, "%s - - [%T] \" \" 403 0", csp->ip_addr_str);
 
          return;
       }
    }
-            
+
 
    /*
     * Downgrade http version from 1.1 to 1.0 if +downgrade
@@ -652,8 +667,8 @@ static void chat(struct client_state *csp)
     * (Re)build the HTTP request for non-SSL requests.
     * If forwarding, use the whole URL, else, use only the path.
     */
-   if (http->ssl == 0)  
-   {  
+   if (http->ssl == 0)
+   {
       freez(http->cmd);
 
       http->cmd = strsav(http->cmd, http->gpc);
@@ -723,14 +738,14 @@ static void chat(struct client_state *csp)
 
    /* We have a request. */
 
-   /* 
+   /*
     * Now, check to see if we need to intercept it, i.e.
     * If
     */
+
    if (
        /* a CGI call was detected and answered */
-        (NULL != (rsp = dispatch_cgi(csp))) 
+        (NULL != (rsp = dispatch_cgi(csp)))
 
        /* or we are enabled and... */
        || (IS_ENABLED_AND (
@@ -745,7 +760,7 @@ static void chat(struct client_state *csp)
 
           /* ..or a fast redirect kicked in */
 #ifdef FEATURE_FAST_REDIRECTS
-          || (((csp->action->flags & ACTION_FAST_REDIRECTS) != 0) && 
+          || (((csp->action->flags & ACTION_FAST_REDIRECTS) != 0) &&
                     (NULL != (rsp = redirect_url(csp))))
 #endif /* def FEATURE_FAST_REDIRECTS */
                 ))
@@ -754,7 +769,7 @@ static void chat(struct client_state *csp)
       /* Write the answer to the client */
       if ((write_socket(csp->cfd, rsp->head, rsp->head_length) != rsp->head_length)
             || (write_socket(csp->cfd, rsp->body, rsp->content_length) != rsp->content_length))
-      { 
+      {
          log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
       }
 
@@ -765,7 +780,7 @@ static void chat(struct client_state *csp)
 
       /* Log (FIXME: All intercept reasons apprear as "crunch" with Status 200) */
       log_error(LOG_LEVEL_GPC, "%s%s crunch!", http->hostport, http->path);
-      log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 3", csp->ip_addr_str, http->cmd); 
+      log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 3", csp->ip_addr_str, http->cmd);
 
       /* Clean up and return */
       free_http_response(rsp);
@@ -797,14 +812,14 @@ static void chat(struct client_state *csp)
       {
           rsp = error_response(csp, "no-such-domain", errno);
 
-         log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 404 0", 
+         log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 404 0",
                    csp->ip_addr_str, http->cmd);
       }
       else
       {
           rsp = error_response(csp, "connect-failed", errno);
 
-         log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 503 0", 
+         log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 503 0",
                    csp->ip_addr_str, http->cmd);
       }
 
@@ -813,7 +828,7 @@ static void chat(struct client_state *csp)
        {
          if ((write_socket(csp->cfd, rsp->head, rsp->head_length) != rsp->head_length)
                || (write_socket(csp->cfd, rsp->body, rsp->content_length) != rsp->content_length))
-         { 
+         {
             log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
          }
       }
@@ -841,8 +856,8 @@ static void chat(struct client_state *csp)
          log_error(LOG_LEVEL_CONNECT, "write header to: %s failed: %E",
                     http->hostport);
 
-         log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 503 0", 
-                   csp->ip_addr_str, http->cmd); 
+         log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 503 0",
+                   csp->ip_addr_str, http->cmd);
 
          rsp = error_response(csp, "connect-failed", errno);
 
@@ -850,7 +865,7 @@ static void chat(struct client_state *csp)
          {
             if ((write_socket(csp->cfd, rsp->head, n) != n)
                || (write_socket(csp->cfd, rsp->body, rsp->content_length) != rsp->content_length))
-            { 
+            {
                log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
             }
          }
@@ -867,8 +882,8 @@ static void chat(struct client_state *csp)
        * so just send the "connect succeeded" message to the
        * client, flush the rest, and get out of the way.
        */
-      log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 2\n", 
-                csp->ip_addr_str, http->cmd); 
+      log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 2\n",
+                csp->ip_addr_str, http->cmd);
 
       if (write_socket(csp->cfd, CSUCCEED, sizeof(CSUCCEED)-1) < 0)
       {
@@ -941,8 +956,8 @@ static void chat(struct client_state *csp)
          {
             log_error(LOG_LEVEL_ERROR, "read from: %s failed: %E", http->host);
 
-            log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 503 0", 
-                      csp->ip_addr_str, http->cmd); 
+            log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 503 0",
+                      csp->ip_addr_str, http->cmd);
 
             rsp = error_response(csp, "connect-failed", errno);
 
@@ -950,7 +965,7 @@ static void chat(struct client_state *csp)
             {
                if ((write_socket(csp->cfd, rsp->head, rsp->head_length) != rsp->head_length)
                    || (write_socket(csp->cfd, rsp->body, rsp->content_length) != rsp->content_length))
-               { 
+               {
                   log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
                           }
                        }
@@ -992,7 +1007,7 @@ static void chat(struct client_state *csp)
           */
          if (n == 0)
          {
-            
+
             if (server_body || http->ssl)
             {
                /*
@@ -1032,7 +1047,7 @@ static void chat(struct client_state *csp)
             }
 
             /*
-             * This is NOT the body, so 
+             * This is NOT the body, so
              * Let's pretend the server just sent us a blank line.
              */
             n = sprintf(buf, "\r\n");
@@ -1055,7 +1070,7 @@ static void chat(struct client_state *csp)
          {
             if (content_filter)
             {
-               add_to_iob(csp, buf, n); 
+               add_to_iob(csp, buf, n);
 
                /*
                 * If the buffer limit will be reached on the next read,
@@ -1065,7 +1080,7 @@ static void chat(struct client_state *csp)
                if (csp->iob->eod - csp->iob->buf + BUFFER_SIZE > csp->config->buffer_limit)
                {
                   log_error(LOG_LEVEL_ERROR, "Buffer size limit reached! Flushing and stepping back.");
-                  
+
                   hdr = sed(server_patterns, add_server_headers, csp);
                   n   = strlen(hdr);
                   byte_count += n;
@@ -1237,8 +1252,8 @@ static void chat(struct client_state *csp)
       return; /* huh? we should never get here */
    }
 
-   log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 %d", 
-             csp->ip_addr_str, http->cmd, byte_count); 
+   log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 %d",
+             csp->ip_addr_str, http->cmd, byte_count);
 }
 
 
@@ -1315,7 +1330,7 @@ static int32 server_thread(void *data)
  *                any load fails, and can't bind port.
  *
  *                Else main never returns, the process must be signaled
- *                to terminate execution.  Or, on Windows, use the 
+ *                to terminate execution.  Or, on Windows, use the
  *                "File", "Exit" menu option.
  *
  *********************************************************************/
@@ -1369,7 +1384,7 @@ int main(int argc, const char *argv[])
 #endif
 
 
-#ifndef _WIN32
+#if !defined(_WIN32) && !defined(__OS2__)
    signal(SIGPIPE, SIG_IGN);
    signal(SIGCHLD, SIG_IGN);
 
@@ -1423,8 +1438,8 @@ static void listen_loop(void)
    {
       log_error(LOG_LEVEL_FATAL, "can't bind %s:%d: %E "
          "- There may be another junkbuster or some other "
-         "proxy running on port %d", 
-         (NULL != config->haddr) ? config->haddr : "INADDR_ANY", 
+         "proxy running on port %d",
+         (NULL != config->haddr) ? config->haddr : "INADDR_ANY",
          config->hport, config->hport
       );
       /* shouldn't get here */
@@ -1436,7 +1451,7 @@ static void listen_loop(void)
 
    while (FOREVER)
    {
-#if !defined(FEATURE_PTHREAD) && !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA)
+#if !defined(FEATURE_PTHREAD) && !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__)
       while (waitpid(-1, NULL, WNOHANG) > 0)
       {
          /* zombie children */
@@ -1480,8 +1495,8 @@ static void listen_loop(void)
          {
             log_error(LOG_LEVEL_FATAL, "can't bind %s:%d: %E "
                "- There may be another junkbuster or some other "
-               "proxy running on port %d", 
-               (NULL != config->haddr) ? config->haddr : "INADDR_ANY", 
+               "proxy running on port %d",
+               (NULL != config->haddr) ? config->haddr : "INADDR_ANY",
                config->hport, config->hport
             );
             /* shouldn't get here */
@@ -1500,7 +1515,7 @@ static void listen_loop(void)
 #ifdef AMIGA
          if(!childs)
          {
-            exit(1); 
+            exit(1);
          }
 #endif
          freez(csp);
@@ -1568,6 +1583,15 @@ static void listen_loop(void)
             csp);
 #endif
 
+#if defined(__OS2__) && !defined(SELECTED_ONE_OPTION)
+#define SELECTED_ONE_OPTION
+         child_id = _beginthread(
+            serve,
+            NULL,
+            64 * 1024,
+            csp);
+#endif
+
 #if defined(__BEOS__) && !defined(SELECTED_ONE_OPTION)
 #define SELECTED_ONE_OPTION
          {