static void rra_glog_handler(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer DECLARE_UNUSED(user_data)) { fprintf (stderr, "%s: %s/%s\n", get_log_level_string(log_level), log_domain, message); }
/********************************************************************* * * Function : log_error * * Description : This is the error-reporting and logging function. * * Parameters : * 1 : loglevel = the type of message to be logged * 2 : fmt = the main string we want logged, printf-like * 3 : ... = arguments to be inserted in fmt (printf-like). * * Returns : N/A * *********************************************************************/ void log_error(int loglevel, const char *fmt, ...) { va_list ap; char *outbuf = NULL; static char *outbuf_save = NULL; char tempbuf[BUFFER_SIZE]; size_t length = 0; const char * src = fmt; long thread_id; char timestamp[30]; /* * XXX: Make this a config option, * why else do we allocate instead of using * an array? */ size_t log_buffer_size = BUFFER_SIZE; #if defined(_WIN32) && !defined(_WIN_CONSOLE) /* * Irrespective of debug setting, a GET/POST/CONNECT makes * the taskbar icon animate. (There is an option to disable * this but checking that is handled inside LogShowActivity()). */ if ((loglevel == LOG_LEVEL_GPC) || (loglevel == LOG_LEVEL_CRUNCH)) { LogShowActivity(); } #endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */ /* * verify that the loglevel applies to current * settings and that logging is enabled. * Bail out otherwise. */ if ((0 == (loglevel & debug)) #ifndef _WIN32 || (logfp == NULL) #endif ) { if (loglevel == LOG_LEVEL_FATAL) { fatal_error("Fatal error. You're not supposed to" "see this message. Please file a bug report."); } return; } thread_id = get_thread_id(); get_log_timestamp(timestamp, sizeof(timestamp)); /* protect the whole function because of the static buffer (outbuf) */ lock_logfile(); 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 = outbuf_save; /* * Memsetting the whole buffer to zero (in theory) * makes things easier later on. */ memset(outbuf, 0, log_buffer_size); /* Add prefix for everything but Common Log Format messages */ if (loglevel != LOG_LEVEL_CLF) { length = (size_t)snprintf(outbuf, log_buffer_size, "%s %08lx %s: ", timestamp, thread_id, get_log_level_string(loglevel)); } /* get ready to scan var. args. */ va_start(ap, fmt); /* build formatted message from fmt and var-args */ while ((*src) && (length < log_buffer_size-2)) { const char *sval = NULL; /* %N string */ int ival; /* %N string length or an error code */ unsigned uval; /* %u value */ long lval; /* %l value */ unsigned long ulval; /* %ul value */ char ch; const char *format_string = tempbuf; ch = *src++; if (ch != '%') { outbuf[length++] = ch; /* * XXX: Only necessary on platforms where multiple threads * can write to the buffer at the same time because we * don't support mutexes (OS/2 for example). */ outbuf[length] = '\0'; continue; } outbuf[length] = '\0'; ch = *src++; switch (ch) { case '%': tempbuf[0] = '%'; tempbuf[1] = '\0'; break; case 'd': ival = va_arg(ap, int); snprintf(tempbuf, sizeof(tempbuf), "%d", ival); break; case 'u': uval = va_arg(ap, unsigned); snprintf(tempbuf, sizeof(tempbuf), "%u", uval); break; case 'l': /* this is a modifier that must be followed by u, lu, or d */ ch = *src++; if (ch == 'd') { lval = va_arg(ap, long); snprintf(tempbuf, sizeof(tempbuf), "%ld", lval); } else if (ch == 'u') { ulval = va_arg(ap, unsigned long); snprintf(tempbuf, sizeof(tempbuf), "%lu", ulval); }