Core agent is now working on NetWare
[public/netxms.git] / src / libnetxms / tools.cpp
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 "libnetxms.h"
24
25 #ifndef _WIN32
26 #include <sys/time.h>
27 #endif
28
29 #ifdef _WIN32
30 #ifndef __GNUC__
31 #define EPOCHFILETIME (116444736000000000i64)
32 #else
33 #define EPOCHFILETIME (116444736000000000LL)
34 #endif
35 #endif
36
37
38 //
39 // Calculate number of bits in netmask
40 //
41
42 int LIBNETXMS_EXPORTABLE BitsInMask(DWORD dwMask)
43 {
44 int bits;
45 DWORD dwTemp;
46
47 for(bits = 0, dwTemp = ntohl(dwMask); dwTemp != 0; bits++, dwTemp <<= 1);
48 return bits;
49 }
50
51
52 //
53 // Convert IP address from binary form (network bytes order) to string
54 //
55
56 char LIBNETXMS_EXPORTABLE *IpToStr(DWORD dwAddr, char *szBuffer)
57 {
58 static char szInternalBuffer[32];
59 char *szBufPtr;
60
61 szBufPtr = szBuffer == NULL ? szInternalBuffer : szBuffer;
62 #if WORDS_BIGENDIAN
63 sprintf(szBufPtr, "%ld.%ld.%ld.%ld", dwAddr >> 24, (dwAddr >> 16) & 255,
64 (dwAddr >> 8) & 255, dwAddr & 255);
65 #else
66 sprintf(szBufPtr, "%ld.%ld.%ld.%ld", dwAddr & 255, (dwAddr >> 8) & 255,
67 (dwAddr >> 16) & 255, dwAddr >> 24);
68 #endif
69 return szBufPtr;
70 }
71
72
73 //
74 // Our memory allocation wrappers
75 // We need them primary because of Windows CLIB behavior:
76 // every module has it's own memory block list, so if memory block
77 // was allocated in DLL by malloc(), call to free() for this block in
78 // main program will cause crash.
79 //
80
81 void LIBNETXMS_EXPORTABLE *MemAlloc(DWORD dwSize)
82 {
83 return malloc(dwSize);
84 }
85
86 void LIBNETXMS_EXPORTABLE *MemReAlloc(void *pBlock, DWORD dwNewSize)
87 {
88 return realloc(pBlock, dwNewSize);
89 }
90
91 void LIBNETXMS_EXPORTABLE MemFree(void *pBlock)
92 {
93 if (pBlock != NULL)
94 free(pBlock);
95 }
96
97
98 //
99 // Duplicate memory block
100 //
101
102 void LIBNETXMS_EXPORTABLE *nx_memdup(const void *pData, DWORD dwSize)
103 {
104 void *pNewData;
105
106 pNewData = MemAlloc(dwSize);
107 memcpy(pNewData, pData, dwSize);
108 return pNewData;
109 }
110
111
112 //
113 // Duplicate string using MemAlloc()
114 //
115
116 char LIBNETXMS_EXPORTABLE *nx_strdup(const char *pSrc)
117 {
118 char *pDest;
119
120 pDest = (char *)MemAlloc(strlen(pSrc) + 1);
121 strcpy(pDest, pSrc);
122 return pDest;
123 }
124
125
126 //
127 // Match string against pattern with * and ? metasymbols
128 //
129
130 static BOOL MatchStringEngine(const char *pattern, const char *string)
131 {
132 const char *SPtr,*MPtr,*BPtr;
133
134 SPtr = string;
135 MPtr = pattern;
136
137 while(*MPtr!=0)
138 {
139 switch(*MPtr)
140 {
141 case '?':
142 if (*SPtr!=0)
143 {
144 SPtr++;
145 MPtr++;
146 }
147 else
148 return FALSE;
149 break;
150 case '*':
151 while(*MPtr=='*')
152 MPtr++;
153 if (*MPtr==0)
154 return TRUE;
155 if (*MPtr=='?') // Handle "*?" case
156 {
157 if (*SPtr!=0)
158 SPtr++;
159 else
160 return FALSE;
161 break;
162 }
163 BPtr=MPtr; // Text block begins here
164 while((*MPtr!=0)&&(*MPtr!='?')&&(*MPtr!='*'))
165 MPtr++; // Find the end of text block
166 while(1)
167 {
168 while((*SPtr!=0)&&(*SPtr!=*BPtr))
169 SPtr++;
170 if (strlen(SPtr)<(size_t)(MPtr-BPtr))
171 return FALSE; // Length of remained text less than remaining pattern
172 if (!memcmp(BPtr,SPtr,MPtr-BPtr))
173 break;
174 SPtr++;
175 }
176 SPtr+=(MPtr-BPtr); // Increment SPtr because we alredy match current fragment
177 break;
178 default:
179 if (*MPtr==*SPtr)
180 {
181 SPtr++;
182 MPtr++;
183 }
184 else
185 return FALSE;
186 break;
187 }
188 }
189
190 return *SPtr==0 ? TRUE : FALSE;
191 }
192
193 BOOL LIBNETXMS_EXPORTABLE MatchString(const char *pattern, const char *string, BOOL matchCase)
194 {
195 if (matchCase)
196 return MatchStringEngine(pattern, string);
197 else
198 {
199 char *tp, *ts;
200 BOOL bResult;
201
202 tp = strdup(pattern);
203 ts = strdup(string);
204 strupr(tp);
205 strupr(ts);
206 bResult = MatchStringEngine(tp, ts);
207 free(tp);
208 free(ts);
209 return bResult;
210 }
211 }
212
213
214 //
215 // Strip whitespaces and tabs off the string
216 //
217
218 void LIBNETXMS_EXPORTABLE StrStrip(char *str)
219 {
220 int i;
221
222 for(i=0;(str[i]!=0)&&((str[i]==' ')||(str[i]=='\t'));i++);
223 if (i>0)
224 memmove(str,&str[i],strlen(&str[i])+1);
225 for(i=strlen(str)-1;(i>=0)&&((str[i]==' ')||(str[i]=='\t'));i--);
226 str[i+1]=0;
227 }
228
229
230 //
231 // Add string to enumeration result set
232 //
233
234 void LIBNETXMS_EXPORTABLE NxAddResultString(NETXMS_VALUES_LIST *pList, char *pszString)
235 {
236 pList->ppStringList = (char **)MemReAlloc(pList->ppStringList, sizeof(char *) * (pList->dwNumStrings + 1));
237 pList->ppStringList[pList->dwNumStrings] = nx_strdup(pszString);
238 pList->dwNumStrings++;
239 }
240
241
242 //
243 // Get arguments for parameters like name(arg1,...)
244 // Returns FALSE on processing error
245 //
246
247 BOOL LIBNETXMS_EXPORTABLE NxGetParameterArg(char *param, int index, char *arg, int maxSize)
248 {
249 char *ptr1, *ptr2;
250 int state, currIndex, pos;
251 BOOL bResult = TRUE;
252
253 arg[0] = 0; // Default is empty string
254 ptr1 = strchr(param,'(');
255 if (ptr1 == NULL)
256 return TRUE; // No arguments at all
257 for(ptr2 = ptr1 + 1, currIndex = 1, state = 0, pos = 0; state != -1; ptr2++)
258 {
259 switch(state)
260 {
261 case 0: // Normal
262 switch(*ptr2)
263 {
264 case ')':
265 if (currIndex == index)
266 arg[pos] = 0;
267 state = -1; // Finish processing
268 break;
269 case '"':
270 state = 1; // String
271 break;
272 case '\'': // String, type 2
273 state = 2;
274 break;
275 case ',':
276 if (currIndex == index)
277 {
278 arg[pos] = 0;
279 state = -1;
280 }
281 else
282 {
283 currIndex++;
284 }
285 break;
286 case 0:
287 state = -1; // Finish processing
288 bResult = FALSE; // Set error flag
289 break;
290 default:
291 if ((currIndex == index) && (pos < maxSize - 1))
292 arg[pos++] = *ptr2;
293 }
294 break;
295 case 1: // String in ""
296 switch(*ptr2)
297 {
298 case '"':
299 state = 0; // Normal
300 break;
301 case '\\': // Escape
302 ptr2++;
303 if ((currIndex == index) && (pos < maxSize - 1))
304 arg[pos++] = *ptr2;
305 if (ptr2 == 0) // Unexpected EOL
306 {
307 bResult = FALSE;
308 state = -1;
309 }
310 break;
311 case 0:
312 state = -1; // Finish processing
313 bResult = FALSE; // Set error flag
314 break;
315 default:
316 if ((currIndex == index) && (pos < maxSize - 1))
317 arg[pos++] = *ptr2;
318 }
319 break;
320 case 2: // String in ''
321 switch(*ptr2)
322 {
323 case '\'':
324 state = 0; // Normal
325 break;
326 case '\\': // Escape
327 ptr2++;
328 if ((currIndex == index) && (pos < maxSize - 1))
329 arg[pos++] = *ptr2;
330 if (ptr2 == 0) // Unexpected EOL
331 {
332 bResult = FALSE;
333 state = -1;
334 }
335 break;
336 case 0:
337 state = -1; // Finish processing
338 bResult = FALSE; // Set error flag
339 break;
340 default:
341 if ((currIndex == index) && (pos < maxSize - 1))
342 arg[pos++] = *ptr2;
343 }
344 break;
345 }
346 }
347
348 if (bResult)
349 StrStrip(arg);
350 return bResult;
351 }
352
353
354 //
355 // Get current time in milliseconds
356 // Based on timeval.h by Wu Yongwei
357 //
358
359 INT64 LIBNETXMS_EXPORTABLE GetCurrentTimeMs(void)
360 {
361 #ifdef _WIN32
362 FILETIME ft;
363 LARGE_INTEGER li;
364 __int64 t;
365
366 GetSystemTimeAsFileTime(&ft);
367 li.LowPart = ft.dwLowDateTime;
368 li.HighPart = ft.dwHighDateTime;
369 t = li.QuadPart; // In 100-nanosecond intervals
370 t -= EPOCHFILETIME; // Offset to the Epoch time
371 t /= 10000; // Convert to milliseconds
372 #else
373 struct timeval tv;
374 INT64 t;
375
376 gettimeofday(&tv, NULL);
377 t = (INT64)tv.tv_sec * 1000 + (INT64)(tv.tv_usec / 10000);
378 #endif
379
380 return t;
381 }
382
383
384 //
385 // Extract word from line. Extracted word will be placed in buffer.
386 // Returns pointer to the next word or to the null character if end
387 // of line reached.
388 //
389
390 char LIBNETXMS_EXPORTABLE *ExtractWord(char *line, char *buffer)
391 {
392 char *ptr,*bptr;
393
394 for(ptr=line;(*ptr==' ')||(*ptr=='\t');ptr++); // Skip initial spaces
395 // Copy word to buffer
396 for(bptr=buffer;(*ptr!=' ')&&(*ptr!='\t')&&(*ptr!=0);ptr++,bptr++)
397 *bptr=*ptr;
398 *bptr=0;
399 return ptr;
400 }
401
402
403 //
404 // Get system error string by call to FormatMessage
405 // (Windows only)
406 //
407
408 #ifdef _WIN32
409
410 char LIBNETXMS_EXPORTABLE *GetSystemErrorText(DWORD dwError, char *pszBuffer, int iBufSize)
411 {
412 char *msgBuf;
413
414 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
415 FORMAT_MESSAGE_FROM_SYSTEM |
416 FORMAT_MESSAGE_IGNORE_INSERTS,
417 NULL, dwError,
418 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
419 (LPSTR)&msgBuf, 0, NULL) > 0)
420 {
421 msgBuf[strcspn(msgBuf, "\r\n")] = 0;
422 strncpy(pszBuffer, msgBuf, iBufSize);
423 LocalFree(msgBuf);
424 }
425 else
426 {
427 sprintf(pszBuffer, "MSG 0x%08X - Unable to find message text", dwError);
428 }
429 return pszBuffer;
430 }
431
432 #endif
433
434
435 //
436 // daemon() implementation for systems which doesn't have one
437 //
438
439 #if !(HAVE_DAEMON) && !defined(_NETWARE)
440
441 int daemon(int nochdir, int noclose)
442 {
443 return 0;
444 }
445
446 #endif
447