- Changes in logging and debug output
[public/netxms.git] / src / server / core / tools.cpp
CommitLineData
9a19737f
VK
1/*
2** Project X - Network Management System
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: tools.cpp
20**
21**/
22
23#include "nms_core.h"
24
06e7be2f 25#include <fcntl.h>
c9ccd685
AK
26#include <sys/stat.h>
27#ifdef _WIN32
28# include <io.h>
31a11006
AK
29#else
30# ifdef HAVE_SYS_UTSNAME_H
31# include <sys/utsname.h>
32# endif
06e7be2f
VK
33#endif
34
9a19737f
VK
35
36//
37// Get system error string by call to FormatMessage
38//
39
40#ifdef _WIN32
41
42char *GetSystemErrorText(DWORD error)
43{
44 char *msgBuf;
45 static char staticBuffer[1024];
46
47 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
48 FORMAT_MESSAGE_FROM_SYSTEM |
49 FORMAT_MESSAGE_IGNORE_INSERTS,
50 NULL,error,
51 MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), // Default language
52 (LPSTR)&msgBuf,0,NULL)>0)
53 {
54 msgBuf[strcspn(msgBuf,"\r\n")]=0;
55 strncpy(staticBuffer,msgBuf,1023);
56 LocalFree(msgBuf);
57 }
58 else
59 {
60 sprintf(staticBuffer,"MSG 0x%08X - Unable to find message text",error);
61 }
62
63 return staticBuffer;
64}
65
66#endif /* _WIN32 */
0ee0c807
VK
67
68
48b1c0ac
VK
69//
70// Clean interface list from unneeded entries
71//
72
73void CleanInterfaceList(INTERFACE_LIST *pIfList)
74{
75 int i;
76
77 if (pIfList == NULL)
78 return;
79
80 // Delete loopback interface(s) from list
81 for(i = 0; i < pIfList->iNumEntries; i++)
82 if ((pIfList->pInterfaces[i].dwIpAddr & pIfList->pInterfaces[i].dwIpNetMask) == 0x0000007F)
83 {
84 pIfList->iNumEntries--;
85 memmove(&pIfList->pInterfaces[i], &pIfList->pInterfaces[i + 1],
86 sizeof(INTERFACE_INFO) * (pIfList->iNumEntries - i));
87 i--;
88 }
89}
90
91
e77547c2 92//
0fdc2761 93// Convert byte array to text representation
e77547c2
VK
94//
95
0fdc2761 96void BinToStr(BYTE *pData, DWORD dwSize, char *pStr)
e77547c2 97{
0fdc2761
VK
98 DWORD i;
99 char *pCurr;
100
101 for(i = 0, pCurr = pStr; i < dwSize; i++)
102 {
103 *pCurr++ = bin2hex(pData[i] >> 4);
104 *pCurr++ = bin2hex(pData[i] & 15);
105 }
106 *pCurr = 0;
107}
108
109
110//
111// Convert string of hexadecimal digits to byte array
112//
113
114DWORD StrToBin(char *pStr, BYTE *pData, DWORD dwSize)
115{
116 DWORD i;
e77547c2
VK
117 char *pCurr;
118
0fdc2761
VK
119 memset(pData, 0, dwSize);
120 for(i = 0, pCurr = pStr; (i < dwSize) && (*pCurr != 0); i++)
e77547c2 121 {
0fdc2761 122 pData[i] = hex2bin(*pCurr) << 4;
e77547c2 123 pCurr++;
0fdc2761 124 pData[i] |= hex2bin(*pCurr);
e77547c2
VK
125 pCurr++;
126 }
0fdc2761 127 return i;
e77547c2 128}
c7ca9142
VK
129
130
131//
132// Get system information string
133//
134
135void GetSysInfoStr(char *pszBuffer)
136{
137#ifdef _WIN32
138 DWORD dwSize;
139 char computerName[MAX_COMPUTERNAME_LENGTH + 1], osVersion[256];
140 SYSTEM_INFO sysInfo;
141 OSVERSIONINFO versionInfo;
142
143 dwSize = MAX_COMPUTERNAME_LENGTH + 1;
144 GetComputerName(computerName, &dwSize);
145
146 versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
147 GetVersionEx(&versionInfo);
148 GetSystemInfo(&sysInfo);
149
150 switch(versionInfo.dwPlatformId)
151 {
152 case VER_PLATFORM_WIN32_WINDOWS:
153 sprintf(osVersion,"Windows %s-%s",versionInfo.dwMinorVersion == 0 ? "95" :
154 (versionInfo.dwMinorVersion == 10 ? "98" :
155 (versionInfo.dwMinorVersion == 90 ? "Me" : "Unknown")),versionInfo.szCSDVersion);
156 break;
157 case VER_PLATFORM_WIN32_NT:
158 if (versionInfo.dwMajorVersion != 5)
159 sprintf(osVersion,"Windows NT %d.%d %s",versionInfo.dwMajorVersion,
160 versionInfo.dwMinorVersion,versionInfo.szCSDVersion);
161 else // Windows 2000, Windows XP or Windows Server 2003
162 sprintf(osVersion,"Windows %s%s%s",versionInfo.dwMinorVersion == 0 ? "2000" :
163 (versionInfo.dwMinorVersion == 1 ? "XP" : "Server 2003"),
164 versionInfo.szCSDVersion[0] == 0 ? "" : " ", versionInfo.szCSDVersion);
165 break;
166 default:
167 strcpy(osVersion,"Windows [Unknown Version]");
168 break;
169 }
170
171 sprintf(pszBuffer, "%s %s Build %d", computerName, osVersion, versionInfo.dwBuildNumber);
172#else
173 /* TODO: add UNIX code here */
31a11006
AK
174# ifdef HAVE_SYS_UTSNAME_H
175 struct utsname uName;
176 if (uname(&uName) == 0)
177 {
178 sprintf(pszBuffer, "%s %s Release %d", uName.nodename, uName.sysname, uName.release);
179 }
180 else
181 {
182 // size=512 was taken from locks.cpp
696fc54f 183#if HAVE_STRERROR_R
31a11006 184 strerror_r(errno, pszBuffer, 512);
696fc54f
VK
185#else
186 strncpy(pszBuffer, strerror(errno), 512);
187#endif
31a11006
AK
188 }
189# else
d9c2934a
VK
190 printf("GetSysInfoStr: code not implemented\n");
191 strcpy(pszBuffer, "UNIX");
31a11006
AK
192# endif // HAVE_SYS_UTSNAME_H
193
c7ca9142
VK
194#endif
195}
196
197
198//
199// Get IP address for local machine
200//
201
202DWORD GetLocalIpAddr(void)
203{
204 INTERFACE_LIST *pIfList;
205 DWORD dwAddr = 0;
0d978ff2 206 int i;
c7ca9142
VK
207
208 pIfList = GetLocalInterfaceList();
209 if (pIfList != NULL)
210 {
0d978ff2
VK
211 CleanInterfaceList(pIfList);
212
213 // Find first interface with IP address
214 for(i = 0; i < pIfList->iNumEntries; i++)
215 if (pIfList->pInterfaces[i].dwIpAddr != 0)
216 {
217 dwAddr = pIfList->pInterfaces[i].dwIpAddr;
218 break;
219 }
c7ca9142
VK
220 DestroyInterfaceList(pIfList);
221 }
222 return dwAddr;
223}
4d5a05a0
VK
224
225
226//
3c774461 227// Execute external command
4d5a05a0
VK
228//
229
230BOOL ExecCommand(char *pszCommand)
231{
4d5a05a0
VK
232 BOOL bSuccess = TRUE;
233
4d5a05a0
VK
234#ifdef _WIN32
235 STARTUPINFO si;
236 PROCESS_INFORMATION pi;
237
4d5a05a0
VK
238 // Fill in process startup info structure
239 memset(&si, 0, sizeof(STARTUPINFO));
240 si.cb = sizeof(STARTUPINFO);
241 si.dwFlags = 0;
242
243 // Create new process
d2a1dd18 244 if (!CreateProcess(NULL, pszCommand, NULL, NULL, FALSE, CREATE_NO_WINDOW | DETACHED_PROCESS, NULL, NULL, &si, &pi))
4d5a05a0 245 {
d2a1dd18 246 WriteLog(MSG_CREATE_PROCESS_FAILED, EVENTLOG_ERROR_TYPE, "se", pszCommand, GetLastError());
4d5a05a0
VK
247 bSuccess = FALSE;
248 }
249 else
250 {
251 // Close all handles
252 CloseHandle(pi.hThread);
253 CloseHandle(pi.hProcess);
254 }
4d5a05a0
VK
255#else
256 /* TODO: add UNIX code here */
257#endif
258
259 return bSuccess;
260}
64584976
VK
261
262
06e7be2f
VK
263//
264// Load file into memory
265//
266
267BYTE *LoadFile(char *pszFileName, DWORD *pdwFileSize)
268{
0c598d0e 269 int fd, iBufPos, iNumBytes, iBytesRead;
06e7be2f
VK
270 BYTE *pBuffer = NULL;
271 struct stat fs;
272
b1dd534d 273 DbgPrintf(AF_DEBUG_MISC, "Loading file \"%s\" into memory", pszFileName);
0c598d0e 274 fd = open(pszFileName, O_RDONLY | O_BINARY);
06e7be2f
VK
275 if (fd != -1)
276 {
277 if (fstat(fd, &fs) != -1)
278 {
279 pBuffer = (BYTE *)malloc(fs.st_size + 1);
0c598d0e 280 if (pBuffer != NULL)
06e7be2f 281 {
0c598d0e
VK
282 *pdwFileSize = fs.st_size;
283 for(iBufPos = 0; iBufPos < fs.st_size; iBufPos += iBytesRead)
284 {
285 iNumBytes = min(16384, fs.st_size - iBufPos);
286 if ((iBytesRead = read(fd, &pBuffer[iBufPos], iNumBytes)) < 0)
287 {
b1dd534d 288 DbgPrintf(AF_DEBUG_MISC, "File read operation failed");
0c598d0e
VK
289 free(pBuffer);
290 pBuffer = NULL;
291 break;
292 }
293 }
06e7be2f
VK
294 }
295 }
296 close(fd);
297 }
298 return pBuffer;
299}
8f7e2482
VK
300
301
8f7e2482
VK
302//
303// Characters to be escaped before writing to SQL
304//
305
306static char m_szSpecialChars[] = "\x01\x02\x03\x04\x05\x06\x07\x08"
307 "\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
308 "\x11\x12\x13\x14\x15\x16\x17\x18"
309 "\x19\x1A\x1B\x1C\x1D\x1E\x1F"
310 "#%\"\\'\x7F";
311
312
313//
314// Escape some special characters in string for writing into database
315//
316
317char *EncodeSQLString(const char *pszIn)
318{
319 char *pszOut;
320 int iPosIn, iPosOut, iStrSize;
321
322 // Allocate destination buffer
323 iStrSize = strlen(pszIn) + 1;
324 for(iPosIn = 0; pszIn[iPosIn] != 0; iPosIn++)
325 if (strchr(m_szSpecialChars, pszIn[iPosIn]) != NULL)
326 iStrSize += 2;
327 pszOut = (char *)malloc(iStrSize);
328
329 // TRanslate string
330 for(iPosIn = 0, iPosOut = 0; pszIn[iPosIn] != 0; iPosIn++)
331 if (strchr(m_szSpecialChars, pszIn[iPosIn]) != NULL)
332 {
333 pszOut[iPosOut++] = '#';
334 pszOut[iPosOut++] = bin2hex(pszIn[iPosIn] >> 4);
335 pszOut[iPosOut++] = bin2hex(pszIn[iPosIn] & 0x0F);
336 }
337 else
338 {
339 pszOut[iPosOut++] = pszIn[iPosIn];
340 }
341 pszOut[iPosOut] = 0;
342 return pszOut;
343}
344
345
346//
347// Restore characters encoded by EncodeSQLString()
348// Characters are decoded "in place"
349//
350
351void DecodeSQLString(char *pszStr)
352{
353 int iPosIn, iPosOut;
354
355 for(iPosIn = 0, iPosOut = 0; pszStr[iPosIn] != 0; iPosIn++)
356 {
357 if (pszStr[iPosIn] == '#')
358 {
359 iPosIn++;
360 pszStr[iPosOut] = hex2bin(pszStr[iPosIn]) << 4;
361 iPosIn++;
362 pszStr[iPosOut] |= hex2bin(pszStr[iPosIn]);
363 iPosOut++;
364 }
365 else
366 {
367 pszStr[iPosOut++] = pszStr[iPosIn];
368 }
369 }
370 pszStr[iPosOut] = 0;
371}