merge Debian changes from 3.0.7 to 3.0.10
[privoxy.git] / jcc.c
diff --git a/jcc.c b/jcc.c
index 5c25ff7..2d96ac9 100644 (file)
--- a/jcc.c
+++ b/jcc.c
@@ -1,4 +1,4 @@
-const char jcc_rcs[] = "$Id: jcc.c,v 1.178 2008/05/10 13:23:38 fabiankeil Exp $";
+const char jcc_rcs[] = "$Id: jcc.c,v 1.186 2008/09/04 08:13:58 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/jcc.c,v $
@@ -33,6 +33,39 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.178 2008/05/10 13:23:38 fabiankeil Exp $"
  *
  * Revisions   :
  *    $Log: jcc.c,v $
+ *    Revision 1.186  2008/09/04 08:13:58  fabiankeil
+ *    Prepare for critical sections on Windows by adding a
+ *    layer of indirection before the pthread mutex functions.
+ *
+ *    Revision 1.185  2008/08/30 12:03:07  fabiankeil
+ *    Remove FEATURE_COOKIE_JAR.
+ *
+ *    Revision 1.184  2008/08/22 15:34:45  fabiankeil
+ *    - Silence LLVM/Clang complaint.
+ *    - Make received_hup_signal static.
+ *    - Hide definitions for basedir, pidfile and received_hup_signal
+ *      from __EMX__ as they only seem to be used in case of #ifdef unix.
+ *
+ *    Revision 1.183  2008/08/21 07:09:35  fabiankeil
+ *    Accept Shoutcast responses again. Problem reported
+ *    and fix suggested by Stefan in #2062860.
+ *
+ *    Revision 1.182  2008/06/27 11:13:56  fabiankeil
+ *    Fix possible NULL-pointer dereference reported
+ *    by din_a4 in #2003937. Pointy hat to me.
+ *
+ *    Revision 1.181  2008/05/21 15:47:15  fabiankeil
+ *    Streamline sed()'s prototype and declare
+ *    the header parse and add structures static.
+ *
+ *    Revision 1.180  2008/05/21 15:26:32  fabiankeil
+ *    - Mark csp as immutable for send_crunch_response().
+ *    - Fix comment spelling.
+ *
+ *    Revision 1.179  2008/05/20 20:13:32  fabiankeil
+ *    Factor update_server_headers() out of sed(), ditch the
+ *    first_run hack and make server_patterns_light static.
+ *
  *    Revision 1.178  2008/05/10 13:23:38  fabiankeil
  *    Don't provide get_header() with the whole client state
  *    structure when it only needs access to csp->iob.
@@ -1108,7 +1141,7 @@ static int client_protocol_is_unsupported(const struct client_state *csp, char *
 static jb_err get_request_destination_elsewhere(struct client_state *csp, struct list *headers);
 static jb_err get_server_headers(struct client_state *csp);
 static const char *crunch_reason(const struct http_response *rsp);
-static void send_crunch_response(struct client_state *csp, struct http_response *rsp);
+static void send_crunch_response(const struct client_state *csp, struct http_response *rsp);
 /*
  * static int request_contains_null_bytes(const struct client_state *csp, char *buf, int len);
  */
@@ -1141,32 +1174,35 @@ static int32 server_thread(void *data);
 #define sleep(N)  DosSleep(((N) * 100))
 #endif
 
-#ifdef FEATURE_PTHREAD
-pthread_mutex_t log_mutex;
-pthread_mutex_t log_init_mutex;
+#ifdef MUTEX_LOCKS_AVAILABLE
+/*
+ * XXX: Does the locking stuff really belong in this file?
+ */
+privoxy_mutex_t log_mutex;
+privoxy_mutex_t log_init_mutex;
 
 #if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R)
-pthread_mutex_t resolver_mutex;
+privoxy_mutex_t resolver_mutex;
 #endif /* !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R) */
 
 #ifndef HAVE_GMTIME_R
-pthread_mutex_t gmtime_mutex;
+privoxy_mutex_t gmtime_mutex;
 #endif /* ndef HAVE_GMTIME_R */
 
 #ifndef HAVE_LOCALTIME_R
-pthread_mutex_t localtime_mutex;
+privoxy_mutex_t localtime_mutex;
 #endif /* ndef HAVE_GMTIME_R */
 
 #ifndef HAVE_RANDOM
-pthread_mutex_t rand_mutex;
+privoxy_mutex_t rand_mutex;
 #endif /* ndef HAVE_RANDOM */
 
-#endif /* FEATURE_PTHREAD */
+#endif /* def MUTEX_LOCKS_AVAILABLE */
 
-#if defined(unix) || defined(__EMX__)
+#if defined(unix)
 const char *basedir = NULL;
 const char *pidfile = NULL;
-int received_hup_signal = 0;
+static int received_hup_signal = 0;
 #endif /* defined unix */
 
 /* HTTP snipplets. */
@@ -1275,6 +1311,13 @@ static const struct cruncher crunchers_light[] = {
 };
 
 
+/*
+ * XXX: Don't we really mean
+ *
+ * #if defined(unix)
+ *
+ * here?
+ */
 #if !defined(_WIN32) && !defined(__OS2__) && !defined(AMIGA)
 /*********************************************************************
  *
@@ -1308,7 +1351,9 @@ static void sig_handler(int the_signal)
          break;
 
       case SIGHUP:
+#if defined(unix)
          received_hup_signal = 1;
+#endif
          break;         
 
       default:
@@ -1501,7 +1546,7 @@ static jb_err get_server_headers(struct client_state *csp)
       {
          /*
           * It's a bodyless continue response, don't
-          * stop header parsing after reaching it's end.
+          * stop header parsing after reaching its end.
           *
           * As a result Privoxy will concatenate the
           * next response's head and parse and deliver
@@ -1627,7 +1672,7 @@ static const char *crunch_reason(const struct http_response *rsp)
  * Returns     :  Nothing.
  *
  *********************************************************************/
-static void send_crunch_response(struct client_state *csp, struct http_response *rsp)
+static void send_crunch_response(const struct client_state *csp, struct http_response *rsp)
 {
       const struct http_request *http = csp->http;
       char status_code[4];
@@ -1910,10 +1955,15 @@ static jb_err change_request_destination(struct client_state *csp)
       log_error(LOG_LEVEL_ERROR, "Couldn't parse rewritten request: %s.",
          jb_err_to_string(err));
    }
-   http->ocmd = strdup(http->cmd); /* XXX: ocmd is a misleading name */
-   if (http->ocmd == NULL)
+   else
    {
-      log_error(LOG_LEVEL_FATAL, "Out of memory copying rewritten HTTP request line");
+      /* XXX: ocmd is a misleading name */
+      http->ocmd = strdup(http->cmd);
+      if (http->ocmd == NULL)
+      {
+         log_error(LOG_LEVEL_FATAL,
+            "Out of memory copying rewritten HTTP request line");
+      }
    }
 
    return err;
@@ -2175,7 +2225,7 @@ static void chat(struct client_state *csp)
    list_append_list_unique(csp->headers, headers);
    destroy_list(headers);
 
-   err = sed(client_patterns, add_client_headers, csp);
+   err = sed(csp, FILTER_CLIENT_HEADERS);
    if (JB_ERR_OK != err)
    {
       assert(err == JB_ERR_PARSE);
@@ -2708,10 +2758,11 @@ static void chat(struct client_state *csp)
 
             assert(csp->headers->first->str);
             assert(!http->ssl);
-            if (strncmpic(csp->headers->first->str, "HTTP", 4))
+            if (strncmpic(csp->headers->first->str, "HTTP", 4) &&
+                strncmpic(csp->headers->first->str, "ICY", 3))
             {
                /*
-                * It doesn't look like a HTTP response:
+                * It doesn't look like a HTTP (or Shoutcast) response:
                 * tell the client and log the problem.
                 */
                if (strlen(csp->headers->first->str) > 30)
@@ -2729,10 +2780,11 @@ static void chat(struct client_state *csp)
                return;
             }
 
-            /* we have now received the entire header.
+            /*
+             * We have now received the entire server header,
              * filter it and send the result to the client
              */
-            if (JB_ERR_OK != sed(server_patterns, add_server_headers, csp))
+            if (JB_ERR_OK != sed(csp, FILTER_SERVER_HEADERS))
             {
                log_error(LOG_LEVEL_FATAL, "Failed to parse server headers.");
             }
@@ -2910,6 +2962,97 @@ static void usage(const char *myname)
 #endif /* #if !defined(_WIN32) || defined(_WIN_CONSOLE) */
 
 
+#ifdef MUTEX_LOCKS_AVAILABLE
+/*********************************************************************
+ *
+ * Function    :  privoxy_mutex_lock
+ *
+ * Description :  Locks a mutex.
+ *
+ * Parameters  :
+ *          1  :  mutex = The mutex to lock.
+ *
+ * Returns     :  Void. May exit in case of errors.
+ *
+ *********************************************************************/
+void privoxy_mutex_lock(privoxy_mutex_t *mutex)
+{
+#ifdef FEATURE_PTHREAD
+   int err = pthread_mutex_lock(mutex);
+   if (err)
+   {
+      if (mutex != &log_mutex)
+      {
+         log_error(LOG_LEVEL_FATAL,
+            "Mutex locking failed: %s.\n", strerror(err));
+      }
+      exit(1);
+   }
+#else
+   EnterCriticalSection(mutex);
+#endif /* def FEATURE_PTHREAD */
+}
+
+
+/*********************************************************************
+ *
+ * Function    :  privoxy_mutex_unlock
+ *
+ * Description :  Unlocks a mutex.
+ *
+ * Parameters  :
+ *          1  :  mutex = The mutex to unlock.
+ *
+ * Returns     :  Void. May exit in case of errors.
+ *
+ *********************************************************************/
+void privoxy_mutex_unlock(privoxy_mutex_t *mutex)
+{
+#ifdef FEATURE_PTHREAD
+   int err = pthread_mutex_unlock(mutex);
+   if (err)
+   {
+      if (mutex != &log_mutex)
+      {
+         log_error(LOG_LEVEL_FATAL,
+            "Mutex unlocking failed: %s.\n", strerror(err));
+      }
+      exit(1);
+   }
+#else
+   LeaveCriticalSection(mutex);
+#endif /* def FEATURE_PTHREAD */
+}
+
+
+/*********************************************************************
+ *
+ * Function    :  privoxy_mutex_init
+ *
+ * Description :  Prepares a mutex.
+ *
+ * Parameters  :
+ *          1  :  mutex = The mutex to initialize.
+ *
+ * Returns     :  Void. May exit in case of errors.
+ *
+ *********************************************************************/
+static void privoxy_mutex_init(privoxy_mutex_t *mutex)
+{
+#ifdef FEATURE_PTHREAD
+   int err = pthread_mutex_init(mutex, 0);
+   if (err)
+   {
+      printf("Fatal error. Mutex initialization failed: %s.\n",
+         strerror(err));
+      exit(1);
+   }
+#else
+   InitializeCriticalSection(mutex);
+#endif /* def FEATURE_PTHREAD */
+}
+#endif /* def MUTEX_LOCKS_AVAILABLE */
+
 /*********************************************************************
  *
  * Function    :  initialize_mutexes
@@ -2923,15 +3066,13 @@ static void usage(const char *myname)
  *********************************************************************/
 static void initialize_mutexes(void)
 {
-   int err = 0;
-
-#ifdef FEATURE_PTHREAD
+#ifdef MUTEX_LOCKS_AVAILABLE
    /*
     * Prepare global mutex semaphores
     */
-   err = pthread_mutex_init(&log_mutex, 0);
+   privoxy_mutex_init(&log_mutex);
 
-   if (!err) err = pthread_mutex_init(&log_init_mutex, 0);
+   privoxy_mutex_init(&log_init_mutex);
 
    /*
     * XXX: The assumptions below are a bit naive
@@ -2942,37 +3083,24 @@ static void initialize_mutexes(void)
     * thread safe.
     */
 #if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R)
-   if (!err) err = pthread_mutex_init(&resolver_mutex, 0);
+   privoxy_mutex_init(&resolver_mutex);
 #endif /* !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R) */
    /*
     * XXX: should we use a single mutex for
     * localtime() and gmtime() as well?
     */
 #ifndef HAVE_GMTIME_R
-   if (!err) err = pthread_mutex_init(&gmtime_mutex, 0);
+   privoxy_mutex_init(&gmtime_mutex);
 #endif /* ndef HAVE_GMTIME_R */
 
 #ifndef HAVE_LOCALTIME_R
-   if (!err) err = pthread_mutex_init(&localtime_mutex, 0);
+   privoxy_mutex_init(&localtime_mutex);
 #endif /* ndef HAVE_GMTIME_R */
 
 #ifndef HAVE_RANDOM
-   if (!err) err = pthread_mutex_init(&rand_mutex, 0);
+   privoxy_mutex_init(&rand_mutex);
 #endif /* ndef HAVE_RANDOM */
-#endif /* FEATURE_PTHREAD */
-
-   /*
-    * TODO: mutex support for mingw32 would be swell.
-    */
-
-   if (err)
-   {
-      printf("Fatal error. Mutex initialization failed: %s.\n",
-         strerror(err));
-      exit(1);
-   }
-
-   return;
+#endif /* def MUTEX_LOCKS_AVAILABLE */
 }
 
 
@@ -3188,15 +3316,6 @@ int main(int argc, const char *argv[])
    random_seed = (unsigned int)time(NULL);
 #ifdef HAVE_RANDOM
    srandom(random_seed);
-#elif defined (_WIN32)
-   /*
-    * See pick_from_range() in miscutil.c for details.
-    */
-   log_error(LOG_LEVEL_INFO,
-      "No thread-safe PRNG implemented for your platform. "
-      "Using weak \'randomization\' factor which will "
-      "limit the already questionable usefulness of "
-      "header-time-randomizing actions (disabled by default).");
 #else
    srand(random_seed);
 #endif /* ifdef HAVE_RANDOM */
@@ -3541,23 +3660,6 @@ static void listen_loop(void)
       }
 #endif
 
-#ifdef __OS2__
-#ifdef FEATURE_COOKIE_JAR
-      /*
-       * Need a workaround here: we have to fclose() the jarfile, or we die because it's
-       * already open.  I think unload_configfile() is not being run, which should do
-       * this work.  Until that can get resolved, we'll use this workaround.
-       */
-       if (csp)
-         if(csp->config)
-           if (csp->config->jar)
-           {
-             fclose(csp->config->jar);
-             csp->config->jar = NULL;
-           }
-#endif /* FEATURE_COOKIE_JAR */
-#endif /* __OS2__ */
-
       if ( NULL == (csp = (struct client_state *) zalloc(sizeof(*csp))) )
       {
          log_error(LOG_LEVEL_FATAL, "malloc(%d) for csp failed: %E", sizeof(*csp));
@@ -3855,13 +3957,6 @@ static void listen_loop(void)
 #endif
    freez(configfile);
 
-#ifdef FEATURE_COOKIE_JAR
-   if (NULL != config->jar)
-   {
-      fclose(config->jar);
-   }
-#endif
-
 #if defined(_WIN32) && !defined(_WIN_CONSOLE)
    /* Cleanup - remove taskbar icon etc. */
    TermLogWindow();