server-1.12/common/logger.c

146 lines
4.6 KiB
C

/*
* static char *rcsid_loger_c =
* "$Id: logger.c 11578 2009-02-23 22:02:27Z lalo $ ";
*/
int reopen_logfile = 0; /* May be set in SIGHUP handler */
/*
CrossFire, A Multiplayer game for X-windows
Copyright (C) 2002 Mark Wedel & Crossfire Development Team
Copyright (C) 1992 Frank Tore Johansen
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 your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The authors can be reached via e-mail at crossfire-devel@real-time.com
*/
/**
* @file logger.c
* This handles logging, to file or strerr/stdout.
*/
#include <stdarg.h>
#include <global.h>
#include <sproto.h>
/**
* Human-readable name of log levels.
*/
static const char *const loglevel_names[] = {
"[Error] ",
"[Info] ",
"[Debug] ",
"[Monster] "
};
/**
* 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 */
fputs(loglevel_names[logLevel], stderr);
fputs(buf, stderr);
if (time_buf[0] != 0) {
fputs(time_buf, stderr);
fputs(" ", 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);
}