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