1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
/*
* Crossfire -- cooperative multi-player graphical RPG and adventure game
*
* Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
* Copyright (c) 1992 Frank Tore Johansen
*
* Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
* welcome to redistribute it under certain conditions. For details, please
* see COPYING and LICENSE.
*
* The authors can be reached via e-mail at <crossfire@metalforge.org>.
*/
/**
* @file logger.c
* This handles logging, to file or strerr/stdout.
*/
#include "global.h"
#include <stdarg.h>
#include <stdlib.h>
#include "sproto.h"
int reopen_logfile = 0; /* May be set in SIGHUP handler */
/**
* Human-readable name of log levels.
*/
static const char *const loglevel_names[] = {
"[EE] ",
"[II] ",
"[DD] ",
"[MM] ",
};
/**
* Logs a message to stderr, or to file.
* Or discards the message if it is of no importance, and none have
* asked to hear messages of that logLevel.
*
* See include/logger.h for possible logLevels. Messages with llevInfo
* and llevError are always printed, regardless of debug mode.
*
* @param logLevel
* level of the message
* @param format
* message to log. Works like printf() and such
*/
void LOG(LogLevel logLevel, const char *format, ...) {
char buf[20480]; /* This needs to be really really big - larger
* than any other buffer, since that buffer may
* need to be put in this one.
*/
char time_buf[2048];
va_list ap;
va_start(ap, format);
buf[0] = '\0';
if (logLevel <= settings.debug) {
time_buf[0] = '\0';
if (settings.log_timestamp == TRUE) {
struct tm *time_tmp;
time_t now = time((time_t *)NULL);
time_tmp = localtime(&now);
if (time_tmp != NULL) {
if (strftime(time_buf, sizeof(time_buf), settings.log_timestamp_format, time_tmp) == 0) {
time_buf[0] = '\0';
}
}
}
vsnprintf(buf, sizeof(buf), format, ap);
#ifdef WIN32 /* ---win32 change log handling for win32 */
if (time_buf[0] != 0) {
fputs(time_buf, logfile);
fputs(" ", logfile);
}
fputs(loglevel_names[logLevel], logfile); /* wrote to file or stdout */
fputs(buf, logfile); /* wrote to file or stdout */
#ifdef DEBUG /* if we have a debug version, we want see ALL output */
fflush(logfile); /* so flush this! */
#endif
if (logfile != stderr) { /* if was it a logfile wrote it to screen too */
if (time_buf[0] != 0) {
fputs(time_buf, stderr);
fputs(" ", stderr);
}
fputs(loglevel_names[logLevel], stderr);
fputs(buf, stderr);
}
#else /* not WIN32 */
if (reopen_logfile) {
reopen_logfile = 0;
if (fclose(logfile) != 0) {
/* stderr has been closed if -detach was used, but it's better
* to try to report about this anyway. */
perror("tried to close log file after SIGHUP in logger.c:LOG()");
}
if ((logfile = fopen(settings.logfilename, "a")) == NULL) {
/* There's likely to be something very wrong with the OS anyway
* if reopening fails. */
perror("tried to open log file after SIGHUP in logger.c:LOG()");
emergency_save(0);
clean_tmp_files();
exit(1);
}
setvbuf(logfile, NULL, _IOLBF, 0);
LOG(llevInfo, "logfile reopened\n");
}
if (time_buf[0] != 0) {
fputs(time_buf, logfile);
fputs(" ", logfile);
}
fputs(loglevel_names[logLevel], logfile);
fputs(buf, logfile);
#endif
}
if (!exiting
&& !trying_emergency_save
&& logLevel == llevError
&& ++nroferrors > MAX_ERRORS) {
exiting = 1;
if (!trying_emergency_save)
emergency_save(0);
}
va_end(ap);
}
|