File: logger.c

package info (click to toggle)
crossfire 1.75.0-9
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 24,168 kB
  • sloc: ansic: 83,169; sh: 4,659; perl: 1,736; lex: 1,443; makefile: 1,199; python: 43
file content (133 lines) | stat: -rw-r--r-- 4,134 bytes parent folder | download | duplicates (4)
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);
}