Merge pull request #3707 from lateralusX/jlorenss/win-api-family-support-libmonoutils
[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-internals.h"
29 #include "mono-proclib.h"
30
31 static FILE *logFile = NULL;
32 static void *logUserData = NULL;
33
34 /**
35  * mapSyslogLevel:
36  *      
37  *      @level - GLogLevelFlags value
38  *      @returns The equivalent character identifier
39  */
40 static inline char 
41 mapLogFileLevel(GLogLevelFlags level) 
42 {
43         if (level & G_LOG_LEVEL_ERROR)
44                 return ('E');
45         if (level & G_LOG_LEVEL_CRITICAL)
46                 return ('C');
47         if (level & G_LOG_LEVEL_WARNING)
48                 return ('W');
49         if (level & G_LOG_LEVEL_MESSAGE)
50                 return ('N');
51         if (level & G_LOG_LEVEL_INFO)
52                 return ('I');
53         if (level & G_LOG_LEVEL_DEBUG)
54                 return ('D');
55         return ('I');
56 }
57
58 /**
59  * mono_log_open_logfile
60  *      
61  *      Open the logfile. If the path is not specified default to stdout. If the
62  *      open fails issue a warning and use stdout as the log file destination.
63  *
64  *      @path - Path for log file
65  *      @userData - Not used
66  */
67 void
68 mono_log_open_logfile(const char *path, void *userData)
69 {
70         if (path == NULL) {
71                 logFile = stdout;
72         } else {
73 #ifndef HOST_WIN32
74                 logFile = fopen(path, "w");
75 #else
76                 gunichar2 *wPath = g_utf8_to_utf16(path, -1, 0, 0, 0);
77                 if (wPath != NULL) {
78                         logFile = _wfopen((wchar_t *) wPath, L"w");
79                         g_free (wPath);
80                 }
81 #endif
82                 if (logFile == NULL) {
83                         g_warning("opening of log file %s failed with %s - defaulting to stdout", 
84                                   path, strerror(errno));
85                         logFile = stdout;
86                 }
87         }
88         logUserData = userData;
89 }
90
91 /**
92  * mono_log_write_logfile
93  *      
94  *      Write data to the log file.
95  *
96  *      @domain - Identifier string
97  *      @level - Logging level flags
98  *      @format - Printf format string
99  *      @vargs - Variable argument list
100  */
101 void
102 mono_log_write_logfile (const char *log_domain, GLogLevelFlags level, mono_bool hdr, const char *message)
103 {
104         time_t t;
105
106         if (logFile == NULL)
107                 logFile = stdout;
108
109         if (hdr) {
110                 pid_t pid;
111                 char logTime [80];
112
113 #ifndef HOST_WIN32
114                 struct tm tod;
115                 time(&t);
116                 localtime_r(&t, &tod);
117                 pid = getpid();
118                 strftime(logTime, sizeof(logTime), "%Y-%m-%d %H:%M:%S", &tod);
119 #else
120                 struct tm *tod;
121                 time(&t);
122                 tod = localtime(&t);
123                 pid = mono_process_current_pid ();
124                 strftime(logTime, sizeof(logTime), "%F %T", tod);
125 #endif
126                 fprintf (logFile, "%s level[%c] mono[%d]: %s\n", logTime, mapLogFileLevel (level), pid, message);
127         } else {
128                 fprintf (logFile, "%s%s%s\n",
129                         log_domain != NULL ? log_domain : "",
130                         log_domain != NULL ? ": " : "",
131                         message);
132         }
133
134         fflush(logFile);
135
136         if (level & G_LOG_LEVEL_ERROR)
137                 abort();
138 }
139
140 /**
141  * mono_log_close_logfile
142  *
143  *      Close the log file
144  */
145 void
146 mono_log_close_logfile()
147 {
148         if (logFile) {
149                 if (logFile != stdout)
150                         fclose(logFile);
151                 logFile = NULL;
152         }
153 }