Fixed a JS syntax problem in jumping-windows
[privoxy.git] / jcc.c
diff --git a/jcc.c b/jcc.c
index 797405f..35cec2d 100644 (file)
--- a/jcc.c
+++ b/jcc.c
@@ -1,4 +1,4 @@
-const char jcc_rcs[] = "$Id: jcc.c,v 1.92.2.4 2003/03/07 03:41:04 david__schmidt Exp $";
+const char jcc_rcs[] = "$Id: jcc.c,v 1.92.2.13 2003/11/27 19:20:27 oes Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/Attic/jcc.c,v $
@@ -33,6 +33,42 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.92.2.4 2003/03/07 03:41:04 david__schmidt
  *
  * Revisions   :
  *    $Log: jcc.c,v $
+ *    Revision 1.92.2.13  2003/11/27 19:20:27  oes
+ *    Diagnostics: Now preserve the returncode of pthread_create
+ *    in errno. Closes BR #775721. Thanks to Geoffrey Hausheer.
+ *
+ *    Revision 1.92.2.12  2003/07/11 11:34:19  oes
+ *    No longer ignore SIGCHLD. Fixes bug #769381
+ *
+ *    Revision 1.92.2.11  2003/05/14 12:32:02  oes
+ *    Close jarfile on graceful exit, remove stray line
+ *
+ *    Revision 1.92.2.10  2003/05/08 15:13:46  oes
+ *    Cosmetics: Killed a warning, a typo and an allocation left at exit
+ *
+ *    Revision 1.92.2.9  2003/04/03 15:08:42  oes
+ *    No longer rely on non-POSIX.1 extensions of getcwd().
+ *    Fixes bug #711001
+ *
+ *    Revision 1.92.2.8  2003/03/31 13:12:32  oes
+ *    Replaced setenv() by posix-compliant putenv()
+ *    Thanks to Neil McCalden (nmcc AT users.sf.net).
+ *
+ *    Revision 1.92.2.7  2003/03/17 16:48:59  oes
+ *    Added chroot ability, thanks to patch by Sviatoslav Sviridov
+ *
+ *    Revision 1.92.2.6  2003/03/11 11:55:00  oes
+ *    Clean-up and extension of improvements for forked mode:
+ *     - Child's return code now consists of flags RC_FLAG_*
+ *     - Reporting toggle to parent now properly #ifdef'ed
+ *     - Children now report blocking to parent. This enables
+ *       statistics in forked mode
+ *
+ *    Revision 1.92.2.5  2003/03/10 23:45:32  oes
+ *    Fixed bug #700381: Non-Threaded version now capable of being toggled.
+ *    Children now report having been toggled through _exit(17), parents
+ *    watch for that code and toggle themselves if found.
+ *
  *    Revision 1.92.2.4  2003/03/07 03:41:04  david__schmidt
  *    Wrapping all *_r functions (the non-_r versions of them) with mutex semaphores for OSX.  Hopefully this will take care of all of those pesky crash reports.
  *
@@ -684,7 +720,7 @@ pthread_mutex_t gethostbyname_mutex;
 #endif /* def OSX_DARWIN */
 
 #if defined(unix) || defined(__EMX__)
-const char *basedir;
+const char *basedir = NULL;
 const char *pidfile = NULL;
 int received_hup_signal = 0;
 #endif /* defined unix */
@@ -1456,7 +1492,7 @@ static void chat(struct client_state *csp)
 
                   if (write_socket(csp->cfd, hdr, hdrlen)
                    || ((flushed = flush_socket(csp->cfd, csp)) < 0)
-                   || (write_socket(csp->cfd, buf, len)))
+                   || (write_socket(csp->cfd, buf, (size_t) len)))
                   {
                      log_error(LOG_LEVEL_CONNECT, "Flush header and buffers to client failed: %E");
 
@@ -1715,7 +1751,11 @@ static int32 server_thread(void *data)
 void usage(const char *myname)
 {
    printf("Privoxy version " VERSION " (" HOME_PAGE_URL ")\n"
+#if !defined(unix)
+           "Usage: %s [--help] [--version] [configfile]\n"
+#else
            "Usage: %s [--help] [--version] [--no-daemon] [--pidfile pidfile] [--user user[.group]] [configfile]\n"
+#endif
            "Aborting.\n", myname);
  
    exit(2);
@@ -1757,6 +1797,7 @@ int main(int argc, const char *argv[])
    struct passwd *pw = NULL;
    struct group *grp = NULL;
    char *p;
+   int do_chroot = 0;
 #endif
 
    Argc = argc;
@@ -1775,8 +1816,6 @@ int main(int argc, const char *argv[])
     */
    while (++argc_pos < argc)
    {
-#if !defined(_WIN32) || defined(_WIN_CONSOLE)
-
       if (strcmp(argv[argc_pos], "--help") == 0)
       {
          usage(argv[0]);
@@ -1788,11 +1827,13 @@ int main(int argc, const char *argv[])
          exit(0);
       }
 
-      else if (strcmp(argv[argc_pos], "--no-daemon" ) == 0)
+#if defined(unix)
+
+     else if (strcmp(argv[argc_pos], "--no-daemon" ) == 0)
       {
          no_daemon = 1;
       }
-#if defined(unix)
+
       else if (strcmp(argv[argc_pos], "--pidfile" ) == 0)
       {
          if (++argc_pos == argc) usage(argv[0]);
@@ -1819,9 +1860,15 @@ int main(int argc, const char *argv[])
 
          if (p != NULL) *--p = '\0';
       }
+
+      else if (strcmp(argv[argc_pos], "--chroot" ) == 0)
+      {
+         do_chroot = 1;
+      }
+
 #endif /* defined(unix) */
+
       else
-#endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */
       {
          configfile = argv[argc_pos];
       }
@@ -1831,16 +1878,17 @@ int main(int argc, const char *argv[])
 #if defined(unix)
    if ( *configfile != '/' )
    {
-      char *abs_file;
+      char *abs_file, cwd[1024];
 
       /* make config-filename absolute here */
-      if ( !(basedir = getcwd( NULL, 1024 )))
+      if ( !(getcwd(cwd, sizeof(cwd))))
       {
          perror("get working dir failed");
          exit( 1 );
       }
 
-      if ( !(abs_file = malloc( strlen( basedir ) + strlen( configfile ) + 5 )))
+      if (!(basedir = strdup(cwd))
+      || (!(abs_file = malloc( strlen( basedir ) + strlen( configfile ) + 5 ))))
       {
          perror("malloc failed");
          exit( 1 );
@@ -1877,14 +1925,13 @@ int main(int argc, const char *argv[])
     *
     * Catch the abort, interrupt and terminate signals for a graceful exit
     * Catch the hangup signal so the errlog can be reopened.
-    * Ignore the broken pipe and child signals
-    *  FIXME: Isn't ignoring the default for SIGCHLD anyway and why ignore SIGPIPE? 
+    * Ignore the broken pipe signals (FIXME: Why?)
     */
 #if !defined(_WIN32) && !defined(__OS2__) && !defined(AMIGA)
 {
    int idx;
    const int catched_signals[] = { SIGABRT, SIGTERM, SIGINT, SIGHUP, 0 };
-   const int ignored_signals[] = { SIGPIPE, SIGCHLD, 0 };
+   const int ignored_signals[] = { SIGPIPE, 0 };
 
    for (idx = 0; catched_signals[idx] != 0; idx++)
    {
@@ -1996,10 +2043,45 @@ int main(int argc, const char *argv[])
       {
          log_error(LOG_LEVEL_FATAL, "Cannot setgid(): Insufficient permissions.");
       }
+      if (do_chroot)
+      {
+         if (!pw->pw_dir)
+         {
+            log_error(LOG_LEVEL_FATAL, "Home directory for %s undefined", pw->pw_name);
+         }
+         if (chroot(pw->pw_dir) < 0)
+         {
+            log_error(LOG_LEVEL_FATAL, "Cannot chroot to %s", pw->pw_dir);
+         }
+         if (chdir ("/"))
+         {
+            log_error(LOG_LEVEL_FATAL, "Cannot chdir /");
+         }
+      }
       if (setuid(pw->pw_uid))
       {
          log_error(LOG_LEVEL_FATAL, "Cannot setuid(): Insufficient permissions.");
       }
+      if (do_chroot)
+      {
+         char putenv_dummy[64];
+
+         strcpy(putenv_dummy, "HOME=/");
+         if (putenv(putenv_dummy) != 0)
+         {
+            log_error(LOG_LEVEL_FATAL, "Cannot putenv(): HOME");
+         }                
+
+         snprintf(putenv_dummy, 64, "USER=%s", pw->pw_name);
+         if (putenv(putenv_dummy) != 0)
+         {
+            log_error(LOG_LEVEL_FATAL, "Cannot putenv(): USER");
+         }
+      }
+   }
+   else if (do_chroot)
+   {
+      log_error(LOG_LEVEL_FATAL, "Cannot chroot without --user argument.");
    }
 }
 #endif /* defined unix */
@@ -2203,7 +2285,7 @@ static void listen_loop(void)
       }
 
 #ifdef FEATURE_TOGGLE
-      if (g_bToggleIJB)
+      if (global_toggle_state)
       {
          csp->flags |= CSP_FLAG_TOGGLED_ON;
       }
@@ -2245,8 +2327,9 @@ static void listen_loop(void)
 
             pthread_attr_init(&attrs);
             pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
-            child_id = (pthread_create(&the_thread, &attrs,
-               (void*)serve, csp) ? -1 : 0);
+            errno = pthread_create(&the_thread, &attrs,
+               (void*)serve, csp);
+            child_id = errno ? -1 : 0;
             pthread_attr_destroy(&attrs);
          }
 #endif
@@ -2288,6 +2371,7 @@ static void listen_loop(void)
 #if defined(AMIGA) && !defined(SELECTED_ONE_OPTION)
 #define SELECTED_ONE_OPTION
          csp->cfd = ReleaseSocket(csp->cfd, -1);
+         
          if((child_id = (int)CreateNewProcTags(
             NP_Entry, (ULONG)server_thread,
             NP_Output, Output(),
@@ -2312,20 +2396,32 @@ static void listen_loop(void)
           */
          if (child_id == 0)   /* child */
          {
-            int inherited_toggle_state = g_bToggleIJB;
+            int rc = 0;
+#ifdef FEATURE_TOGGLE
+            int inherited_toggle_state = global_toggle_state;
+#endif /* def FEATURE_TOGGLE */
 
             serve(csp);
+
             /* 
-             * If we've been toggled, tell Mom
+             * If we've been toggled or we've blocked the request, tell Mom
              */
-            if (inherited_toggle_state != g_bToggleIJB)
+
+#ifdef FEATURE_TOGGLE
+            if (inherited_toggle_state != global_toggle_state)
             {
-               _exit(17);
+               rc |= RC_FLAG_TOGGLED;
             }
-            else
+#endif /* def FEATURE_TOGGLE */
+
+#ifdef FEATURE_STATISTICS  
+            if (csp->flags & CSP_FLAG_REJECTED)
             {
-               _exit(0);
+               rc |= RC_FLAG_BLOCKED;
             }
+#endif /* ndef FEATURE_STATISTICS */
+
+            _exit(rc);
          }
          else if (child_id > 0) /* parent */
          {
@@ -2335,14 +2431,30 @@ static void listen_loop(void)
              */
             int child_status;
 #if !defined(_WIN32) && !defined(__CYGWIN__)
+
             wait( &child_status );
+
             /* 
-             * If the child has been toggled (return code 17), toggle ourselves
+             * Evaluate child's return code: If the child has
+             *  - been toggled, toggle ourselves
+             *  - blocked its request, bump up the stats counter
              */
-            if (WIFEXITED(child_status) && (WEXITSTATUS(child_status) == 17))
+
+#ifdef FEATURE_TOGGLE
+            if (WIFEXITED(child_status) && (WEXITSTATUS(child_status) & RC_FLAG_TOGGLED))
+            {
+               global_toggle_state = !global_toggle_state;
+            }
+#endif /* def FEATURE_TOGGLE */
+
+#ifdef FEATURE_STATISTICS
+            urls_read++;
+            if (WIFEXITED(child_status) && (WEXITSTATUS(child_status) & RC_FLAG_BLOCKED))
             {
-               g_bToggleIJB = !g_bToggleIJB;
+               urls_rejected++;
             }
+#endif /* def FEATURE_STATISTICS */ 
+
 #endif /* !defined(_WIN32) && defined(__CYGWIN__) */
             close_socket(csp->cfd);
             csp->flags &= ~CSP_FLAG_ACTIVE;
@@ -2405,8 +2517,17 @@ static void listen_loop(void)
    sweep();
 
 #if defined(unix)
-   free(basedir);
+   freez(basedir);
+#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();