X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=errlog.c;h=927289ff45ad1de44af54deefb4ad6bb0059cae1;hp=a6b477459d3c04492b2a72128d545068a195ebaf;hb=cae3149411d1f24e533eb6028e7fe5c3057c4626;hpb=484c53d05cfe647a9a10981ba45e9579e33dcfe8 diff --git a/errlog.c b/errlog.c index a6b47745..927289ff 100644 --- a/errlog.c +++ b/errlog.c @@ -1,4 +1,4 @@ -const char errlog_rcs[] = "$Id: errlog.c,v 1.95 2009/05/28 17:07:42 fabiankeil Exp $"; +const char errlog_rcs[] = "$Id: errlog.c,v 1.125 2016/01/26 17:12:14 diem Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/errlog.c,v $ @@ -6,14 +6,14 @@ const char errlog_rcs[] = "$Id: errlog.c,v 1.95 2009/05/28 17:07:42 fabiankeil E * 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-2014 the * Privoxy team. http://www.privoxy.org/ * * 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 @@ -38,6 +38,7 @@ const char errlog_rcs[] = "$Id: errlog.c,v 1.95 2009/05/28 17:07:42 fabiankeil E #include #include #include +#include #include "config.h" #include "miscutil.h" @@ -74,6 +75,9 @@ const char errlog_rcs[] = "$Id: errlog.c,v 1.95 2009/05/28 17:07:42 fabiankeil E #include "errlog.h" #include "project.h" #include "jcc.h" +#ifdef FEATURE_EXTERNAL_FILTERS +#include "jbsockets.h" +#endif const char errlog_h_rcs[] = ERRLOG_H_VERSION; @@ -120,9 +124,9 @@ static inline void unlock_loginit(void) #else /* ! MUTEX_LOCKS_AVAILABLE */ /* * FIXME we need a cross-platform locking mechanism. - * The locking/unlocking functions below should be + * The locking/unlocking functions below should be * fleshed out for non-pthread implementations. - */ + */ static inline void lock_logfile() {} static inline void unlock_logfile() {} static inline void lock_loginit() {} @@ -133,7 +137,7 @@ static inline void unlock_loginit() {} * * Function : fatal_error * - * Description : Displays a fatal error to standard error (or, on + * Description : Displays a fatal error to standard error (or, on * a WIN32 GUI, to a dialog box), and exits Privoxy * with status code 1. * @@ -145,25 +149,27 @@ static inline void unlock_loginit() {} *********************************************************************/ static void fatal_error(const char *error_message) { -#if defined(_WIN32) && !defined(_WIN_CONSOLE) - /* Skip timestamp and thread id for the message box. */ - const char *box_message = strstr(error_message, "Fatal error"); - if (NULL == box_message) + if (logfp != NULL) { - /* Shouldn't happen but ... */ - box_message = error_message; + fputs(error_message, logfp); } - MessageBox(g_hwndLogFrame, box_message, "Privoxy Error", - MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND | MB_TOPMOST); - - /* Cleanup - remove taskbar icon etc. */ - TermLogWindow(); -#endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */ - if (logfp != NULL) +#if defined(_WIN32) && !defined(_WIN_CONSOLE) { - fputs(error_message, logfp); + /* Skip timestamp and thread id for the message box. */ + const char *box_message = strstr(error_message, "Fatal error"); + if (NULL == box_message) + { + /* Shouldn't happen but ... */ + box_message = error_message; + } + MessageBox(g_hwndLogFrame, box_message, "Privoxy Error", + MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND | MB_TOPMOST); + + /* Cleanup - remove taskbar icon etc. */ + TermLogWindow(); } +#endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */ #if defined(unix) if (pidfile) @@ -231,7 +237,7 @@ void init_log_module(void) * XXX: we should only use the LOG_LEVEL_MINIMUM * until the first time the configuration file has * been parsed. - * + * * Parameters : 1: debug_level = The debug level to set. * * Returns : Nothing. @@ -243,12 +249,29 @@ void set_debug_level(int debug_level) } +/********************************************************************* + * + * Function : debug_level_is_enabled + * + * Description : Checks if a certain debug level is enabled. + * + * Parameters : 1: debug_level = The debug level to check. + * + * Returns : Nothing. + * + *********************************************************************/ +int debug_level_is_enabled(int debug_level) +{ + return (0 != (debug & debug_level)); +} + + /********************************************************************* * * Function : disable_logging * * Description : Disables logging. - * + * * Parameters : None. * * Returns : Nothing. @@ -316,7 +339,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 " @@ -334,6 +357,10 @@ void init_error_log(const char *prog_name, const char *logfname) log_error(LOG_LEVEL_FATAL, "init_error_log(): can't open logfile: \'%s\'", logfname); } +#ifdef FEATURE_EXTERNAL_FILTERS + mark_socket_for_close_on_execute(3); +#endif + /* set logging to be completely unbuffered */ setbuf(fp, NULL); @@ -342,6 +369,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(); @@ -359,7 +401,7 @@ void init_error_log(const char *prog_name, const char *logfname) * Description : Returns a number that is different for each thread. * * XXX: Should be moved elsewhere (miscutil.c?) - * + * * Parameters : None * * Returns : thread_id @@ -367,7 +409,7 @@ void init_error_log(const char *prog_name, const char *logfname) *********************************************************************/ static long get_thread_id(void) { - long this_thread = 1; /* was: pthread_t this_thread;*/ + long this_thread; #ifdef __OS2__ PTIB ptib; @@ -379,12 +421,11 @@ static long get_thread_id(void) this_thread = (long)pthread_self(); #ifdef __MACH__ /* - * Mac OSX (and perhaps other Mach instances) doesn't have a debuggable - * value at the first 4 bytes of pthread_self()'s return value, a pthread_t. - * pthread_t is supposed to be opaque... but it's fairly random, though, so - * we make it mostly presentable. + * Mac OSX (and perhaps other Mach instances) doesn't have a unique + * value at the lowest order 4 bytes of pthread_self()'s return value, a pthread_t, + * so trim the three lowest-order bytes from the value (16^3). */ - this_thread = abs(this_thread % 1000); + this_thread = this_thread / 4096; #endif /* def __MACH__ */ #elif defined(_WIN32) this_thread = GetCurrentThreadId(); @@ -392,6 +433,9 @@ static long get_thread_id(void) ulrc = DosGetInfoBlocks(&ptib, NULL); if (ulrc == 0) this_thread = ptib -> tib_ptib2 -> tib2_ultid; +#else + /* Forking instead of threading. */ + this_thread = 1; #endif /* def FEATURE_PTHREAD */ return this_thread; @@ -414,7 +458,7 @@ static long get_thread_id(void) static inline size_t get_log_timestamp(char *buffer, size_t buffer_size) { size_t length; - time_t now; + time_t now; struct tm tm_now; struct timeval tv_now; /* XXX: stupid name */ long msecs; @@ -422,23 +466,22 @@ 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 defined(MUTEX_LOCKS_AVAILABLE) privoxy_mutex_lock(&localtime_mutex); - tm_now = *localtime(&now); + tm_now = *localtime(&now); privoxy_mutex_unlock(&localtime_mutex); #else - tm_now = *localtime(&now); + tm_now = *localtime(&now); #endif - length = strftime(buffer, buffer_size, "%b %d %H:%M:%S", &tm_now); + length = strftime(buffer, buffer_size, "%Y-%m-%d %H:%M:%S", &tm_now); if (length > (size_t)0) { - msecs_length = snprintf(buffer+length, buffer_size - length, ".%.3ld", msecs); + msecs_length = snprintf(buffer+length, buffer_size - length, ".%.3ld", msecs); } if (msecs_length > 0) { @@ -473,7 +516,7 @@ static inline size_t get_clf_timestamp(char *buffer, size_t buffer_size) * the %z field in strftime() */ time_t now; - struct tm *tm_now; + struct tm *tm_now; struct tm gmt; #ifdef HAVE_LOCALTIME_R struct tm dummy; @@ -482,7 +525,7 @@ static inline size_t get_clf_timestamp(char *buffer, size_t buffer_size) size_t length; int tz_length = 0; - time (&now); + time (&now); #ifdef HAVE_GMTIME_R gmt = *gmtime_r(&now, &gmt); #elif defined(MUTEX_LOCKS_AVAILABLE) @@ -496,14 +539,14 @@ static inline size_t get_clf_timestamp(char *buffer, size_t buffer_size) tm_now = localtime_r(&now, &dummy); #elif defined(MUTEX_LOCKS_AVAILABLE) privoxy_mutex_lock(&localtime_mutex); - tm_now = localtime(&now); + tm_now = localtime(&now); privoxy_mutex_unlock(&localtime_mutex); #else - tm_now = localtime(&now); + tm_now = localtime(&now); #endif - days = tm_now->tm_yday - gmt.tm_yday; - hrs = ((days < -1 ? 24 : 1 < days ? -24 : days * 24) + tm_now->tm_hour - gmt.tm_hour); - mins = hrs * 60 + tm_now->tm_min - gmt.tm_min; + days = tm_now->tm_yday - gmt.tm_yday; + hrs = ((days < -1 ? 24 : 1 < days ? -24 : days * 24) + tm_now->tm_hour - gmt.tm_hour); + mins = hrs * 60 + tm_now->tm_min - gmt.tm_min; length = strftime(buffer, buffer_size, "%d/%b/%Y:%H:%M:%S ", tm_now); @@ -531,7 +574,7 @@ static inline size_t get_clf_timestamp(char *buffer, size_t buffer_size) * * Description : Translates a numerical loglevel into a string. * - * Parameters : + * Parameters : * 1 : loglevel = LOG_LEVEL_FOO * * Returns : Log level string. @@ -557,9 +600,12 @@ static inline const char *get_log_level_string(int loglevel) case LOG_LEVEL_CONNECT: log_level_string = "Connect"; break; - case LOG_LEVEL_LOG: + case LOG_LEVEL_WRITING: log_level_string = "Writing"; break; + case LOG_LEVEL_RECEIVED: + log_level_string = "Received"; + break; case LOG_LEVEL_HEADER: log_level_string = "Header"; break; @@ -574,11 +620,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; @@ -588,6 +632,9 @@ static inline const char *get_log_level_string(int loglevel) case LOG_LEVEL_CGI: log_level_string = "CGI"; break; + case LOG_LEVEL_ACTIONS: + log_level_string = "Actions"; + break; default: log_level_string = "Unknown log level"; break; @@ -598,6 +645,7 @@ static inline const char *get_log_level_string(int loglevel) } +#define LOG_BUFFER_SIZE BUFFER_SIZE /********************************************************************* * * Function : log_error @@ -617,7 +665,7 @@ void log_error(int loglevel, const char *fmt, ...) va_list ap; char *outbuf = NULL; static char *outbuf_save = NULL; - char tempbuf[BUFFER_SIZE]; + char tempbuf[LOG_BUFFER_SIZE]; size_t length = 0; const char * src = fmt; long thread_id; @@ -627,7 +675,7 @@ void log_error(int loglevel, const char *fmt, ...) * why else do we allocate instead of using * an array? */ - size_t log_buffer_size = BUFFER_SIZE; + size_t log_buffer_size = LOG_BUFFER_SIZE; #if defined(_WIN32) && !defined(_WIN_CONSOLE) /* @@ -666,17 +714,9 @@ void log_error(int loglevel, const char *fmt, ...) /* protect the whole function because of the static buffer (outbuf) */ lock_logfile(); - if (NULL == outbuf_save) + if (NULL == outbuf_save) { - outbuf_save = (char*)zalloc(log_buffer_size + 1); /* +1 for paranoia */ - if (NULL == outbuf_save) - { - snprintf(tempbuf, sizeof(tempbuf), - "%s %08lx Fatal error: Out of memory in log_error().", - timestamp, thread_id); - fatal_error(tempbuf); /* Exit */ - return; - } + outbuf_save = zalloc_or_die(log_buffer_size + 1); /* +1 for paranoia */ } outbuf = outbuf_save; @@ -727,11 +767,11 @@ void log_error(int loglevel, const char *fmt, ...) tempbuf[1] = '\0'; break; case 'd': - ival = va_arg( ap, int ); + ival = va_arg(ap, int); snprintf(tempbuf, sizeof(tempbuf), "%d", ival); break; case 'u': - uval = va_arg( ap, unsigned ); + uval = va_arg(ap, unsigned); snprintf(tempbuf, sizeof(tempbuf), "%u", uval); break; case 'l': @@ -739,12 +779,12 @@ void log_error(int loglevel, const char *fmt, ...) ch = *src++; if (ch == 'd') { - lval = va_arg( ap, long ); + lval = va_arg(ap, long); snprintf(tempbuf, sizeof(tempbuf), "%ld", lval); } else if (ch == 'u') { - ulval = va_arg( ap, unsigned long ); + ulval = va_arg(ap, unsigned long); snprintf(tempbuf, sizeof(tempbuf), "%lu", ulval); } else if ((ch == 'l') && (*src == 'u')) @@ -776,45 +816,36 @@ 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); + assert(ival >= 0); sval = va_arg(ap, char *); - if (sval == NULL) - { - format_string = "[null]"; - } - else if (ival <= 0) + assert(sval != NULL); + + while ((ival-- > 0) && (length < log_buffer_size - 6)) { - if (0 == ival) + if (isprint((int)*sval) && (*sval != '\\')) { - /* That's ok (but stupid) */ - tempbuf[0] = '\0'; + outbuf[length++] = *sval; + outbuf[length] = '\0'; } else { - /* - * That's not ok (and even more stupid) - */ - assert(ival >= 0); - format_string = "[counted string lenght < 0]"; + int ret = snprintf(outbuf + length, + log_buffer_size - length - 2, "\\x%.2x", (unsigned char)*sval); + assert(ret == 4); + length += 4; } + sval++; } - 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 - { - memcpy(tempbuf, sval, (size_t) ival); - tempbuf[ival] = '\0'; - } + /* + * 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 */ @@ -833,7 +864,7 @@ void log_error(int loglevel, const char *fmt, ...) format_string = strerror(ival); } #else /* ifndef _WIN32 */ - ival = errno; + ival = errno; #ifdef HAVE_STRERROR format_string = strerror(ival); #else /* ifndef HAVE_STRERROR */ @@ -853,14 +884,14 @@ void log_error(int loglevel, const char *fmt, ...) snprintf(tempbuf, sizeof(tempbuf), "Bad format string: \"%s\"", fmt); loglevel = LOG_LEVEL_FATAL; break; - } /* switch( p ) */ + } assert(length < log_buffer_size); length += strlcpy(outbuf + length, format_string, log_buffer_size - length); if (length >= log_buffer_size-2) { - static char warning[] = "... [too long, truncated]"; + static const char warning[] = "... [too long, truncated]"; length = log_buffer_size - sizeof(warning) - 1; length += strlcpy(outbuf + length, warning, log_buffer_size - length); @@ -868,7 +899,7 @@ void log_error(int loglevel, const char *fmt, ...) break; } - } /* for( p ... ) */ + } /* done with var. args */ va_end(ap); @@ -938,14 +969,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"; @@ -961,9 +992,6 @@ const char *jb_err_to_string(int error) return "File has been modified outside of the CGI actions editor."; case JB_ERR_COMPRESS: return "(De)compression failure"; - default: - assert(0); - return "Unknown error"; } assert(0); return "Internal error";