2010-08-08 10:06:34 +02:00
|
|
|
/* vi: set ts=2:
|
|
|
|
+-------------------+ Christian Schlittchen <corwin@amber.kn-bremen.de>
|
|
|
|
| | Enno Rehling <enno@eressea.de>
|
|
|
|
| Eressea PBEM host | Katja Zedel <katze@felidae.kn-bremen.de>
|
|
|
|
| (c) 1998 - 2003 | Henning Peters <faroul@beyond.kn-bremen.de>
|
|
|
|
| | Ingo Wilken <Ingo.Wilken@informatik.uni-oldenburg.de>
|
|
|
|
+-------------------+ Stefan Reich <reich@halbling.de>
|
|
|
|
|
|
|
|
This program may not be used, modified or distributed
|
|
|
|
without prior permission by the authors of Eressea.
|
|
|
|
*/
|
|
|
|
#include <platform.h>
|
|
|
|
#include "log.h"
|
|
|
|
#include "unicode.h"
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <time.h>
|
|
|
|
|
|
|
|
/* TODO: set from external function */
|
2012-05-16 01:56:25 +02:00
|
|
|
int log_flags = LOG_FLUSH | LOG_CPERROR | LOG_CPWARNING | LOG_CPDEBUG;
|
2010-08-08 10:06:34 +02:00
|
|
|
#ifdef STDIO_CP
|
|
|
|
static int stdio_codepage = STDIO_CP;
|
|
|
|
#else
|
|
|
|
static int stdio_codepage = 0;
|
|
|
|
#endif
|
2011-03-07 08:02:35 +01:00
|
|
|
static FILE *logfile;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
#define MAXLENGTH 4096 /* because I am lazy, CP437 output is limited to this many chars */
|
|
|
|
void log_flush(void)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
|
|
|
fflush(logfile);
|
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
void log_puts(const char *str)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
|
|
|
fflush(stdout);
|
2011-03-07 08:02:35 +01:00
|
|
|
if (!logfile)
|
|
|
|
logfile = stderr;
|
2010-08-08 10:06:34 +02:00
|
|
|
fputs(str, logfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2011-03-07 08:02:35 +01:00
|
|
|
cp_convert(const char *format, char *buffer, size_t length, int codepage)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
|
|
|
/* when console output on MSDOS, convert to codepage */
|
2011-03-07 08:02:35 +01:00
|
|
|
const char *input = format;
|
|
|
|
char *pos = buffer;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
while (pos + 1 < buffer + length && *input) {
|
2010-08-08 10:06:34 +02:00
|
|
|
size_t length = 0;
|
|
|
|
int result = 0;
|
2011-03-07 08:02:35 +01:00
|
|
|
if (codepage == 437) {
|
2010-08-08 10:06:34 +02:00
|
|
|
result = unicode_utf8_to_cp437(pos, input, &length);
|
2011-03-07 08:02:35 +01:00
|
|
|
} else if (codepage == 1252) {
|
2010-08-08 10:06:34 +02:00
|
|
|
result = unicode_utf8_to_cp1252(pos, input, &length);
|
|
|
|
}
|
2011-03-07 08:02:35 +01:00
|
|
|
if (result != 0) {
|
|
|
|
*pos = 0; /* just in case caller ignores our return value */
|
2010-08-08 10:06:34 +02:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
++pos;
|
2011-03-07 08:02:35 +01:00
|
|
|
input += length;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
*pos = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
void log_printf(const char *format, ...)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
|
|
|
va_list marker;
|
2011-03-07 08:02:35 +01:00
|
|
|
if (!logfile)
|
|
|
|
logfile = stderr;
|
2010-08-08 10:06:34 +02:00
|
|
|
va_start(marker, format);
|
|
|
|
vfprintf(logfile, format, marker);
|
|
|
|
va_end(marker);
|
|
|
|
if (log_flags & LOG_FLUSH) {
|
|
|
|
log_flush();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
void log_stdio(FILE * io, const char *format, ...)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
|
|
|
va_list marker;
|
2011-03-07 08:02:35 +01:00
|
|
|
if (!logfile)
|
|
|
|
logfile = stderr;
|
2010-08-08 10:06:34 +02:00
|
|
|
va_start(marker, format);
|
|
|
|
if (stdio_codepage) {
|
|
|
|
char buffer[MAXLENGTH];
|
|
|
|
char converted[MAXLENGTH];
|
|
|
|
|
|
|
|
vsnprintf(buffer, sizeof(buffer), format, marker);
|
2011-03-07 08:02:35 +01:00
|
|
|
if (cp_convert(buffer, converted, MAXLENGTH, stdio_codepage) == 0) {
|
2010-08-08 10:06:34 +02:00
|
|
|
fputs(converted, stderr);
|
|
|
|
} else {
|
|
|
|
/* fall back to non-converted output */
|
|
|
|
va_end(marker);
|
|
|
|
va_start(marker, format);
|
|
|
|
vfprintf(io, format, marker);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
vfprintf(io, format, marker);
|
|
|
|
}
|
|
|
|
va_end(marker);
|
|
|
|
if (log_flags & LOG_FLUSH) {
|
|
|
|
log_flush();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
void log_open(const char *filename)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2011-03-07 08:02:35 +01:00
|
|
|
if (logfile)
|
|
|
|
log_close();
|
2010-08-08 10:06:34 +02:00
|
|
|
logfile = fopen(filename, "a");
|
|
|
|
if (logfile) {
|
|
|
|
/* Get UNIX-style time and display as number and string. */
|
|
|
|
time_t ltime;
|
2011-03-07 08:02:35 +01:00
|
|
|
time(<ime);
|
|
|
|
log_printf("===\n=== Logfile started at %s===\n", ctime(<ime));
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
void log_close(void)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2011-03-07 08:02:35 +01:00
|
|
|
if (!logfile || logfile == stderr || logfile == stdout)
|
|
|
|
return;
|
2010-08-08 10:06:34 +02:00
|
|
|
if (logfile) {
|
|
|
|
/* Get UNIX-style time and display as number and string. */
|
|
|
|
time_t ltime;
|
2011-03-07 08:02:35 +01:00
|
|
|
time(<ime);
|
|
|
|
log_printf("===\n=== Logfile closed at %s===\n\n", ctime(<ime));
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
fclose(logfile);
|
|
|
|
logfile = 0;
|
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
static int check_dupe(const char *format, const char *type)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2011-03-07 08:02:35 +01:00
|
|
|
static const char *last_type; /* STATIC_XCALL: used across calls */
|
2010-08-08 10:06:34 +02:00
|
|
|
static char last_message[32]; /* STATIC_XCALL: used across calls */
|
2011-03-07 08:02:35 +01:00
|
|
|
static int dupes = 0; /* STATIC_XCALL: used across calls */
|
|
|
|
if (strncmp(last_message, format, sizeof(last_message)) == 0) {
|
2010-08-08 10:06:34 +02:00
|
|
|
++dupes;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (dupes) {
|
|
|
|
if (log_flags & LOG_CPERROR) {
|
2011-03-07 08:02:35 +01:00
|
|
|
fprintf(stderr, "%s: last message repeated %d times\n", last_type,
|
|
|
|
dupes + 1);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
dupes = 0;
|
|
|
|
}
|
|
|
|
strncpy(last_message, format, sizeof(last_message));
|
|
|
|
last_type = type;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-05-16 01:56:25 +02:00
|
|
|
void _log_debug(const char *format, ...)
|
|
|
|
{
|
|
|
|
if (log_flags & LOG_CPDEBUG) {
|
|
|
|
int dupe = check_dupe(format, "DEBUG");
|
|
|
|
|
|
|
|
fflush(stdout);
|
|
|
|
if (!logfile)
|
|
|
|
logfile = stderr;
|
|
|
|
if (logfile != stderr) {
|
|
|
|
va_list marker;
|
|
|
|
fputs("DEBUG: ", logfile);
|
|
|
|
va_start(marker, format);
|
|
|
|
vfprintf(logfile, format, marker);
|
|
|
|
va_end(marker);
|
|
|
|
}
|
|
|
|
if (!dupe) {
|
|
|
|
va_list marker;
|
|
|
|
fputs("DEBUG: ", stderr);
|
|
|
|
va_start(marker, format);
|
|
|
|
if (stdio_codepage) {
|
|
|
|
char buffer[MAXLENGTH];
|
|
|
|
char converted[MAXLENGTH];
|
|
|
|
|
|
|
|
vsnprintf(buffer, sizeof(buffer), format, marker);
|
|
|
|
if (cp_convert(buffer, converted, MAXLENGTH, stdio_codepage) == 0) {
|
|
|
|
fputs(converted, stderr);
|
|
|
|
} else {
|
|
|
|
/* fall back to non-converted output */
|
|
|
|
va_end(marker);
|
|
|
|
va_start(marker, format);
|
|
|
|
vfprintf(stderr, format, marker);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
vfprintf(stderr, format, marker);
|
|
|
|
}
|
|
|
|
va_end(marker);
|
|
|
|
}
|
|
|
|
if (log_flags & LOG_FLUSH) {
|
|
|
|
log_flush();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
void _log_warn(const char *format, ...)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2011-02-27 09:11:34 +01:00
|
|
|
if (log_flags & LOG_CPWARNING) {
|
|
|
|
int dupe = check_dupe(format, "WARNING");
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2011-02-27 09:11:34 +01:00
|
|
|
fflush(stdout);
|
2011-03-07 08:02:35 +01:00
|
|
|
if (!logfile)
|
|
|
|
logfile = stderr;
|
|
|
|
if (logfile != stderr) {
|
2011-02-27 09:11:34 +01:00
|
|
|
va_list marker;
|
|
|
|
fputs("WARNING: ", logfile);
|
|
|
|
va_start(marker, format);
|
|
|
|
vfprintf(logfile, format, marker);
|
|
|
|
va_end(marker);
|
|
|
|
}
|
|
|
|
if (!dupe) {
|
2010-08-08 10:06:34 +02:00
|
|
|
va_list marker;
|
|
|
|
fputs("WARNING: ", stderr);
|
|
|
|
va_start(marker, format);
|
|
|
|
if (stdio_codepage) {
|
|
|
|
char buffer[MAXLENGTH];
|
|
|
|
char converted[MAXLENGTH];
|
|
|
|
|
|
|
|
vsnprintf(buffer, sizeof(buffer), format, marker);
|
2011-03-07 08:02:35 +01:00
|
|
|
if (cp_convert(buffer, converted, MAXLENGTH, stdio_codepage) == 0) {
|
2010-08-08 10:06:34 +02:00
|
|
|
fputs(converted, stderr);
|
|
|
|
} else {
|
|
|
|
/* fall back to non-converted output */
|
|
|
|
va_end(marker);
|
|
|
|
va_start(marker, format);
|
|
|
|
vfprintf(stderr, format, marker);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
vfprintf(stderr, format, marker);
|
|
|
|
}
|
|
|
|
va_end(marker);
|
|
|
|
}
|
|
|
|
if (log_flags & LOG_FLUSH) {
|
|
|
|
log_flush();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
void _log_error(const char *format, ...)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
|
|
|
int dupe = check_dupe(format, "ERROR");
|
|
|
|
fflush(stdout);
|
2011-03-07 08:02:35 +01:00
|
|
|
if (!logfile)
|
|
|
|
logfile = stderr;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
if (logfile != stderr) {
|
2010-08-08 10:06:34 +02:00
|
|
|
va_list marker;
|
|
|
|
fputs("ERROR: ", logfile);
|
|
|
|
va_start(marker, format);
|
|
|
|
vfprintf(logfile, format, marker);
|
|
|
|
va_end(marker);
|
|
|
|
}
|
|
|
|
if (!dupe) {
|
2011-03-07 08:02:35 +01:00
|
|
|
if (logfile != stderr) {
|
2010-08-08 10:06:34 +02:00
|
|
|
if (log_flags & LOG_CPERROR) {
|
|
|
|
va_list marker;
|
|
|
|
|
|
|
|
fputs("ERROR: ", stderr);
|
|
|
|
va_start(marker, format);
|
|
|
|
if (stdio_codepage) {
|
|
|
|
char buffer[MAXLENGTH];
|
|
|
|
char converted[MAXLENGTH];
|
|
|
|
|
|
|
|
vsnprintf(buffer, sizeof(buffer), format, marker);
|
2011-03-07 08:02:35 +01:00
|
|
|
if (cp_convert(buffer, converted, MAXLENGTH, stdio_codepage) == 0) {
|
2010-08-08 10:06:34 +02:00
|
|
|
fputs(converted, stderr);
|
|
|
|
} else {
|
|
|
|
/* fall back to non-converted output */
|
|
|
|
va_end(marker);
|
|
|
|
va_start(marker, format);
|
|
|
|
vfprintf(stderr, format, marker);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
vfprintf(stderr, format, marker);
|
|
|
|
}
|
|
|
|
va_end(marker);
|
|
|
|
}
|
|
|
|
log_flush();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-03-07 08:02:35 +01:00
|
|
|
|
2010-08-08 10:06:34 +02:00
|
|
|
static unsigned int logfile_level = 0;
|
|
|
|
static unsigned int stderr_level = 1;
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
void _log_info(unsigned int level, const char *format, ...)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
|
|
|
va_list marker;
|
|
|
|
fflush(stdout);
|
2011-03-07 08:02:35 +01:00
|
|
|
if (!logfile)
|
|
|
|
logfile = stderr;
|
|
|
|
if (logfile_level >= level) {
|
2010-08-08 10:06:34 +02:00
|
|
|
fprintf(logfile, "INFO[%u]: ", level);
|
|
|
|
va_start(marker, format);
|
|
|
|
vfprintf(logfile, format, marker);
|
|
|
|
va_end(marker);
|
2011-03-07 08:02:35 +01:00
|
|
|
if (logfile != stderr) {
|
|
|
|
if (stderr_level >= level) {
|
|
|
|
fprintf(stderr, "INFO[%u]: ", level);
|
|
|
|
va_start(marker, format);
|
|
|
|
if (stdio_codepage) {
|
|
|
|
char buffer[MAXLENGTH];
|
|
|
|
char converted[MAXLENGTH];
|
|
|
|
|
|
|
|
vsnprintf(buffer, sizeof(buffer), format, marker);
|
|
|
|
if (cp_convert(buffer, converted, MAXLENGTH, stdio_codepage) == 0) {
|
|
|
|
fputs(converted, stderr);
|
|
|
|
} else {
|
|
|
|
/* fall back to non-converted output */
|
|
|
|
va_end(marker);
|
|
|
|
va_start(marker, format);
|
|
|
|
vfprintf(stderr, format, marker);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
vfprintf(stderr, format, marker);
|
|
|
|
}
|
|
|
|
va_end(marker);
|
|
|
|
}
|
|
|
|
if (log_flags & LOG_FLUSH) {
|
|
|
|
log_flush();
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|