In log_error(), log as much of %N "strings" as the buffer allows.
[privoxy.git] / errlog.c
index 0e41262..9990419 100644 (file)
--- a/errlog.c
+++ b/errlog.c
@@ -1,4 +1,4 @@
-const char errlog_rcs[] = "$Id: errlog.c,v 1.92 2009/03/20 03:39:31 ler762 Exp $";
+const char errlog_rcs[] = "$Id: errlog.c,v 1.102 2010/07/21 14:43:03 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/errlog.c,v $
@@ -6,7 +6,7 @@ const char errlog_rcs[] = "$Id: errlog.c,v 1.92 2009/03/20 03:39:31 ler762 Exp $
  * Purpose     :  Log errors to a designated destination in an elegant,
  *                printf-like fashion.
  *
- * Copyright   :  Written by and Copyright (C) 2001-2009 the SourceForge
+ * Copyright   :  Written by and Copyright (C) 2001-2010 the
  *                Privoxy team. http://www.privoxy.org/
  *
  *                Based on the Internet Junkbuster originally written
@@ -38,6 +38,7 @@ const char errlog_rcs[] = "$Id: errlog.c,v 1.92 2009/03/20 03:39:31 ler762 Exp $
 #include <stdio.h>
 #include <stdarg.h>
 #include <string.h>
+#include <ctype.h>
 
 #include "config.h"
 #include "miscutil.h"
@@ -316,7 +317,7 @@ void init_error_log(const char *prog_name, const char *logfname)
        * Currently we reopen it every time the config file
        * has been reloaded, but actually we only have to
        * reopen it if the file name changed or if the
-       * configuration reloas was caused by a SIGHUP.
+       * configuration reload was caused by a SIGHUP.
        */
       log_error(LOG_LEVEL_INFO, "Failed to reopen logfile: \'%s\'. "
          "Retrying after closing the old file descriptor first. If that "
@@ -342,6 +343,21 @@ void init_error_log(const char *prog_name, const char *logfname)
    {
       fclose(logfp);
    }
+#ifdef unix
+   if (daemon_mode && (logfp == stderr))
+   {
+      if (dup2(1, 2) == -1)
+      {
+         /*
+          * We only use fatal_error() to clear the pid
+          * file and to exit. Given that stderr has just
+          * been closed, the user will not see the error
+          * message.
+          */
+         fatal_error("Failed to reserve fd 2.");
+      }
+   }
+#endif
    logfp = fp;
    unlock_logfile();
 
@@ -422,12 +438,11 @@ static inline size_t get_log_timestamp(char *buffer, size_t buffer_size)
 
    gettimeofday(&tv_now, NULL);
    msecs = tv_now.tv_usec / 1000;
-
-   time(&now);
+   now = tv_now.tv_sec;
 
 #ifdef HAVE_LOCALTIME_R
    tm_now = *localtime_r(&now, &tm_now);
-#elif FEATURE_PTHREAD
+#elif defined(MUTEX_LOCKS_AVAILABLE)
    privoxy_mutex_lock(&localtime_mutex);
    tm_now = *localtime(&now); 
    privoxy_mutex_unlock(&localtime_mutex);
@@ -485,7 +500,7 @@ static inline size_t get_clf_timestamp(char *buffer, size_t buffer_size)
    time (&now); 
 #ifdef HAVE_GMTIME_R
    gmt = *gmtime_r(&now, &gmt);
-#elif FEATURE_PTHREAD
+#elif defined(MUTEX_LOCKS_AVAILABLE)
    privoxy_mutex_lock(&gmtime_mutex);
    gmt = *gmtime(&now);
    privoxy_mutex_unlock(&gmtime_mutex);
@@ -494,7 +509,7 @@ static inline size_t get_clf_timestamp(char *buffer, size_t buffer_size)
 #endif
 #ifdef HAVE_LOCALTIME_R
    tm_now = localtime_r(&now, &dummy);
-#elif FEATURE_PTHREAD
+#elif defined(MUTEX_LOCKS_AVAILABLE)
    privoxy_mutex_lock(&localtime_mutex);
    tm_now = localtime(&now); 
    privoxy_mutex_unlock(&localtime_mutex);
@@ -574,11 +589,9 @@ static inline const char *get_log_level_string(int loglevel)
          log_level_string = "Force";
          break;
 #endif /* def FEATURE_FORCE_LOAD */
-#ifdef FEATURE_FAST_REDIRECTS
       case LOG_LEVEL_REDIRECTS:
          log_level_string = "Redirect";
          break;
-#endif /* def FEATURE_FAST_REDIRECTS */
       case LOG_LEVEL_DEANIMATE:
          log_level_string = "Gif-Deanimate";
          break;
@@ -751,7 +764,7 @@ void log_error(int loglevel, const char *fmt, ...)
             {
                unsigned long long lluval = va_arg(ap, unsigned long long);
                snprintf(tempbuf, sizeof(tempbuf), "%llu", lluval);
-               ch = *src++;
+               src++;
             }
             else
             {
@@ -776,7 +789,8 @@ void log_error(int loglevel, const char *fmt, ...)
             break;
          case 'N':
             /*
-             * Non-standard: Print a counted unterminated string.
+             * Non-standard: Print a counted unterminated string,
+             * replacing unprintable bytes with their hex value.
              * Takes 2 parameters: int length, const char * string.
              */
             ival = va_arg(ap, int);
@@ -801,20 +815,26 @@ void log_error(int loglevel, const char *fmt, ...)
                   format_string = "[counted string lenght < 0]";
                }
             }
-            else if ((size_t)ival >= sizeof(tempbuf))
-            {
-               /*
-                * String is too long, copy as much as possible.
-                * It will be further truncated later.
-                */
-               memcpy(tempbuf, sval, sizeof(tempbuf)-1);
-               tempbuf[sizeof(tempbuf)-1] = '\0';
-            }
-            else
+            while ((ival-- > 0) && (length < log_buffer_size - 6))
             {
-               memcpy(tempbuf, sval, (size_t) ival);
-               tempbuf[ival] = '\0';
+               if (isprint((int)*sval) && (*sval != '\\'))
+               {
+                  outbuf[length++] = *sval;
+                  outbuf[length] = '\0';
+               }
+               else
+               {
+                  snprintf(outbuf + length, log_buffer_size - length - 2,
+                     "\\x%.2x", (int)*sval);
+                  length += 4;
+               }
+               sval++;
             }
+            /*
+             * XXX: In case of printable characters at the end of
+             *      the %N string, we're not using the whole buffer.
+             */
+            format_string = (length < log_buffer_size - 6) ? "" : "[too long]";
             break;
          case 'E':
             /* Non-standard: Print error code from errno */
@@ -938,14 +958,14 @@ void log_error(int loglevel, const char *fmt, ...)
  *                visible to all files that include errlog.h.
  *
  * Parameters  :
- *          1  :  error = a valid jb_err code
+ *          1  :  jb_error = a valid jb_err code
  *
  * Returns     :  A string with the jb_err translation
  *
  *********************************************************************/
-const char *jb_err_to_string(int error)
+const char *jb_err_to_string(int jb_error)
 {
-   switch (error)
+   switch (jb_error)
    {
       case JB_ERR_OK:
          return "Success, no error";