/* * 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 #include #include /** * 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); }