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