- Changes in logging and debug output
[public/netxms.git] / src / server / core / log.cpp
CommitLineData
4385fa12
VK
1/*
2** Network Management System Core
3** Copyright (C) 2003 Victor Kirhenshtein
4**
5** This program is free software; you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation; either version 2 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program; if not, write to the Free Software
17** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18**
19** $module: log.cpp
20**
21**/
22
23#include "nms_core.h"
4385fa12
VK
24
25
e40c3204
VK
26//
27// Messages generated by mc.pl (for UNIX version only)
28//
29
30#ifndef _WIN32
31extern DWORD g_dwNumMessages;
32extern char *g_szMessages[];
33#endif
34
35
4385fa12
VK
36//
37// Static data
38//
39
40#ifdef _WIN32
41static HANDLE m_hEventLog = INVALID_HANDLE_VALUE;
42#endif
43static FILE *m_hLogFile = NULL;
44static MUTEX m_mutexLogAccess = INVALID_MUTEX_HANDLE;
45
46
47//
48// Initialize log
49//
50
51void InitLog(void)
52{
53#ifdef _WIN32
54 if (g_dwFlags & AF_USE_EVENT_LOG)
55 {
56 m_hEventLog = RegisterEventSource(NULL, CORE_EVENT_SOURCE);
57 }
58 else
59 {
60#endif
61 char szTimeBuf[32];
62 struct tm *loc;
63 time_t t;
64
65 m_hLogFile = fopen(g_szLogFile, "a");
66 t = time(NULL);
67 loc = localtime(&t);
68 strftime(szTimeBuf, 32, "%d-%b-%Y %H:%M:%S", loc);
b1dd534d 69 fprintf(m_hLogFile, "\n[%s] Log file opened\n", szTimeBuf);
03ef9555 70 fflush(m_hLogFile);
4385fa12
VK
71
72 m_mutexLogAccess = MutexCreate();
73#ifdef _WIN32
74 }
75#endif
76}
77
78
79//
80// Close log
81//
82
83void CloseLog(void)
84{
85#ifdef _WIN32
86 if (g_dwFlags & AF_USE_EVENT_LOG)
87 {
88 DeregisterEventSource(m_hEventLog);
89 }
90 else
91 {
92#endif
93 if (m_hLogFile != NULL)
6e165a72
VK
94 {
95 char szTimeBuf[32];
96 struct tm *loc;
97 time_t t;
98
99 t = time(NULL);
100 loc = localtime(&t);
101 strftime(szTimeBuf, 32, "%d-%b-%Y %H:%M:%S", loc);
b1dd534d 102 fprintf(m_hLogFile, "[%s] Log file closed\n", szTimeBuf);
4385fa12 103 fclose(m_hLogFile);
6e165a72 104 }
4385fa12
VK
105 if (m_mutexLogAccess != INVALID_MUTEX_HANDLE)
106 MutexDestroy(m_mutexLogAccess);
107#ifdef _WIN32
108 }
109#endif
110}
111
112
113//
114// Write record to log file
115//
116
117static void WriteLogToFile(char *szMessage)
118{
119 char szBuffer[64];
120 time_t t;
121 struct tm *loc;
122
123 // Prevent simultaneous write to log file
124 MutexLock(m_mutexLogAccess, INFINITE);
125
126 t = time(NULL);
127 loc = localtime(&t);
48b1c0ac 128 strftime(szBuffer, 32, "[%d-%b-%Y %H:%M:%S]", loc);
4385fa12 129 fprintf(m_hLogFile, "%s %s", szBuffer, szMessage);
03ef9555 130 fflush(m_hLogFile);
4385fa12
VK
131 if (IsStandalone())
132 printf("%s %s", szBuffer, szMessage);
133
134 MutexUnlock(m_mutexLogAccess);
135}
136
137
e40c3204
VK
138//
139// Format message (UNIX version)
140//
141
142#ifndef _WIN32
143
144char *FormatMessageUX(DWORD dwMsgId, char **ppStrings)
145{
146 char *p, *pMsg;
147 int i, iSize, iLen;
148
149 if (dwMsgId >= g_dwNumMessages)
150 {
151 // No message with this ID
152 pMsg = (char *)malloc(128);
153 sprintf(pMsg, "MSG 0x%08X - Unable to find message text\n", dwMsgId);
154 }
155 else
156 {
157 iSize = strlen(g_szMessages[dwMsgId]) + 2;
158 pMsg = (char *)malloc(iSize);
159
160 for(i = 0, p = g_szMessages[dwMsgId]; *p != 0; p++)
161 if (*p == '%')
162 {
163 p++;
164 if ((*p >= '1') && (*p <= '9'))
165 {
166 iLen = strlen(ppStrings[*p - '1']);
167 iSize += iLen;
168 pMsg = (char *)realloc(pMsg, iSize);
169 strcpy(&pMsg[i], ppStrings[*p - '1']);
170 i += iLen;
171 }
172 else
173 {
174 if (*p == 0) // Handle single % character at the string end
175 break;
176 pMsg[i++] = *p;
177 }
178 }
179 else
180 {
181 pMsg[i++] = *p;
182 }
183 pMsg[i++] = '\n';
184 pMsg[i] = 0;
185 }
186
187 return pMsg;
188}
189
190#endif /* ! _WIN32 */
191
192
4385fa12
VK
193//
194// Write log record
195// Parameters:
196// msg - Message ID
197// wType - Message type (see ReportEvent() for details)
198// format - Parameter format string, each parameter represented by one character.
199// The following format characters can be used:
200// s - String
201// d - Decimal integer
202// x - Hex integer
203// e - System error code (will appear in log as textual description)
c7ca9142 204// a - IP address in network byte order
4385fa12
VK
205//
206
207void WriteLog(DWORD msg, WORD wType, char *format, ...)
208{
209 va_list args;
e40c3204 210 char *strings[16], *pMsg;
4385fa12
VK
211 int numStrings = 0;
212 DWORD error;
213
214 memset(strings, 0, sizeof(char *) * 16);
215
216 if (format != NULL)
217 {
218 va_start(args, format);
219
220 for(; (format[numStrings] != 0) && (numStrings < 16); numStrings++)
221 {
222 switch(format[numStrings])
223 {
224 case 's':
225 strings[numStrings] = strdup(va_arg(args, char *));
226 break;
227 case 'd':
228 strings[numStrings] = (char *)malloc(16);
229 sprintf(strings[numStrings], "%d", va_arg(args, LONG));
230 break;
231 case 'x':
232 strings[numStrings] = (char *)malloc(16);
233 sprintf(strings[numStrings], "0x%08X", va_arg(args, DWORD));
234 break;
c7ca9142
VK
235 case 'a':
236 strings[numStrings] = (char *)malloc(20);
237 IpToStr(va_arg(args, DWORD), strings[numStrings]);
238 break;
4385fa12
VK
239 case 'e':
240 error = va_arg(args, DWORD);
241#ifdef _WIN32
242 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
243 FORMAT_MESSAGE_FROM_SYSTEM |
244 FORMAT_MESSAGE_IGNORE_INSERTS,
245 NULL, error,
246 MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), // Default language
e40c3204 247 (LPSTR)&pMsg,0,NULL)>0)
4385fa12 248 {
fa1d3757 249 pMsg[strcspn(pMsg,"\r\n")] = 0;
e40c3204
VK
250 strings[numStrings]=(char *)malloc(strlen(pMsg) + 1);
251 strcpy(strings[numStrings], pMsg);
252 LocalFree(pMsg);
4385fa12
VK
253 }
254 else
255 {
256 strings[numStrings] = (char *)malloc(64);
257 sprintf(strings[numStrings], "MSG 0x%08X - Unable to find message text", error);
258 }
259#else /* _WIN32 */
260 strings[numStrings] = strdup(strerror(error));
261#endif
262 break;
263 default:
264 strings[numStrings] = (char *)malloc(32);
265 sprintf(strings[numStrings], "BAD FORMAT (0x%08X)", va_arg(args, DWORD));
266 break;
267 }
268 }
269 va_end(args);
270 }
271
272#ifdef _WIN32
273 if (g_dwFlags & AF_USE_EVENT_LOG)
274 {
275 ReportEvent(m_hEventLog, wType, 0, msg, NULL, numStrings, 0, (const char **)strings, NULL);
276 }
277 else
278 {
279 LPVOID lpMsgBuf;
280
281 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY,
282 NULL, msg, 0, (LPTSTR)&lpMsgBuf, 0, strings)>0)
283 {
b1dd534d
VK
284 char *pCR;
285
286 // Replace trailing CR/LF pair with LF
287 pCR = strchr((char *)lpMsgBuf, '\r');
288 if (pCR != NULL)
289 {
290 *pCR = '\n';
291 pCR++;
292 *pCR = 0;
293 }
4385fa12
VK
294 WriteLogToFile((char *)lpMsgBuf);
295 LocalFree(lpMsgBuf);
296 }
297 else
298 {
299 char message[64];
300
b1dd534d 301 sprintf(message,"MSG 0x%08X - Unable to find message text\n",msg);
4385fa12
VK
302 WriteLogToFile(message);
303 }
304 }
305#else /* _WIN32 */
e40c3204
VK
306 pMsg = FormatMessageUX(msg, strings);
307 if (g_dwFlags & AF_USE_EVENT_LOG)
308 {
309 }
310 else
311 {
312 WriteLogToFile(pMsg);
313 }
314 free(pMsg);
3a2f672c 315#endif /* _WIN32 */
4385fa12
VK
316
317 while(--numStrings >= 0)
318 free(strings[numStrings]);
319}