Merge pull request #3100 from lambdageek/dev/monoerror-exns
[mono.git] / mono / utils / mono-log-common.c
1 /*
2  * mono-log-common.c: Platform-independent interface to the logger
3  *
4  * This module contains the POSIX syslog logger interface
5  *
6  * Author:
7  *    Neale Ferguson <neale@sinenomine.net>
8  *
9  */
10 #include <config.h>
11
12 #ifdef HAVE_UNISTD_H
13 #include <unistd.h>
14 #endif
15
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <ctype.h>
19 #include <string.h>
20 #include <glib.h>
21 #include <errno.h>
22 #include <time.h>
23 #ifndef HOST_WIN32
24 #include <sys/time.h>
25 #else
26 #include <process.h>
27 #endif
28 #include "mono-logger.h"
29
30 static FILE *logFile = NULL;
31 static void *logUserData = NULL;
32
33 /**
34  * mapSyslogLevel:
35  *      
36  *      @level - GLogLevelFlags value
37  *      @returns The equivalent character identifier
38  */
39 static inline char 
40 mapLogFileLevel(GLogLevelFlags level) 
41 {
42         if (level & G_LOG_LEVEL_ERROR)
43                 return ('E');
44         if (level & G_LOG_LEVEL_CRITICAL)
45                 return ('C');
46         if (level & G_LOG_LEVEL_WARNING)
47                 return ('W');
48         if (level & G_LOG_LEVEL_MESSAGE)
49                 return ('N');
50         if (level & G_LOG_LEVEL_INFO)
51                 return ('I');
52         if (level & G_LOG_LEVEL_DEBUG)
53                 return ('D');
54         return ('I');
55 }
56
57 /**
58  * mono_log_open_logfile
59  *      
60  *      Open the logfile. If the path is not specified default to stdout. If the
61  *      open fails issue a warning and use stdout as the log file destination.
62  *
63  *      @path - Path for log file
64  *      @userData - Not used
65  */
66 void
67 mono_log_open_logfile(const char *path, void *userData)
68 {
69         if (path == NULL) {
70                 logFile = stdout;
71         } else {
72 #ifndef HOST_WIN32
73                 logFile = fopen(path, "w");
74 #else
75                 gunichar2 *wPath = g_utf8_to_utf16(path, -1, 0, 0, 0);
76                 if (wPath != NULL) {
77                         logFile = _wfopen((wchar_t *) wPath, L"w");
78                         g_free (wPath);
79                 }
80 #endif
81                 if (logFile == NULL) {
82                         g_warning("opening of log file %s failed with %s - defaulting to stdout", 
83                                   path, strerror(errno));
84                         logFile = stdout;
85                 }
86         }
87         logUserData = userData;
88 }
89
90 /**
91  * mono_log_write_logfile
92  *      
93  *      Write data to the log file.
94  *
95  *      @domain - Identifier string
96  *      @level - Logging level flags
97  *      @format - Printf format string
98  *      @vargs - Variable argument list
99  */
100 void
101 mono_log_write_logfile(const char *domain, GLogLevelFlags level, mono_bool hdr, const char *format, va_list args)
102 {
103         time_t t;
104         char logTime[80],       
105              logMessage[512];
106         pid_t pid;
107         int iLog = 0;
108         size_t nLog;
109
110         if (logFile == NULL)
111                 logFile = stdout;
112
113         if (hdr) {
114 #ifndef HOST_WIN32
115                 struct tm tod;
116                 time(&t);
117                 localtime_r(&t, &tod);
118                 pid = getpid();
119                 strftime(logTime, sizeof(logTime), "%Y-%m-%d %H:%M:%S", &tod);
120 #else
121                 struct tm *tod;
122                 time(&t);
123                 tod = localtime(&t);
124                 pid = _getpid();
125                 strftime(logTime, sizeof(logTime), "%F %T", tod);
126 #endif
127                 iLog = snprintf(logMessage, sizeof(logMessage), "%s level[%c] mono[%d]: ",
128                                 logTime,mapLogFileLevel(level),pid);
129         }
130         nLog = sizeof(logMessage) - iLog - 2;
131         iLog = vsnprintf(logMessage+iLog, nLog, format, args);
132         logMessage[iLog++] = '\n';
133         logMessage[iLog++] = '\0';
134         fputs(logMessage, logFile);
135         fflush(logFile);
136
137         if (level == G_LOG_FLAG_FATAL)
138                 abort();
139 }
140
141 /**
142  * mono_log_close_logfile
143  *
144  *      Close the log file
145  */
146 void
147 mono_log_close_logfile()
148 {
149         if (logFile) {
150                 if (logFile != stdout)
151                         fclose(logFile);
152                 logFile = NULL;
153         }
154 }