f54e92a12a62e7b88e1ec11e08e604931ef060c9
[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 // Duplicate memory block
75 //
76
77 void LIBNETXMS_EXPORTABLE *nx_memdup(const void *pData, DWORD dwSize)
78 {
79 void *pNewData;
80
81 pNewData = malloc(dwSize);
82 memcpy(pNewData, pData, dwSize);
83 return pNewData;
84 }
85
86
87 //
88 // Match string against pattern with * and ? metasymbols
89 //
90
91 static BOOL MatchStringEngine(const char *pattern, const char *string)
92 {
93 const char *SPtr,*MPtr,*BPtr;
94
95 SPtr = string;
96 MPtr = pattern;
97
98 while(*MPtr!=0)
99 {
100 switch(*MPtr)
101 {
102 case '?':
103 if (*SPtr!=0)
104 {
105 SPtr++;
106 MPtr++;
107 }
108 else
109 return FALSE;
110 break;
111 case '*':
112 while(*MPtr=='*')
113 MPtr++;
114 if (*MPtr==0)
115 return TRUE;
116 if (*MPtr=='?') // Handle "*?" case
117 {
118 if (*SPtr!=0)
119 SPtr++;
120 else
121 return FALSE;
122 break;
123 }
124 BPtr=MPtr; // Text block begins here
125 while((*MPtr!=0)&&(*MPtr!='?')&&(*MPtr!='*'))
126 MPtr++; // Find the end of text block
127 while(1)
128 {
129 while((*SPtr!=0)&&(*SPtr!=*BPtr))
130 SPtr++;
131 if (strlen(SPtr)<(size_t)(MPtr-BPtr))
132 return FALSE; // Length of remained text less than remaining pattern
133 if (!memcmp(BPtr,SPtr,MPtr-BPtr))
134 break;
135 SPtr++;
136 }
137 SPtr+=(MPtr-BPtr); // Increment SPtr because we alredy match current fragment
138 break;
139 default:
140 if (*MPtr==*SPtr)
141 {
142 SPtr++;
143 MPtr++;
144 }
145 else
146 return FALSE;
147 break;
148 }
149 }
150
151 return *SPtr==0 ? TRUE : FALSE;
152 }
153
154 BOOL LIBNETXMS_EXPORTABLE MatchString(const char *pattern, const char *string, BOOL matchCase)
155 {
156 if (matchCase)
157 return MatchStringEngine(pattern, string);
158 else
159 {
160 char *tp, *ts;
161 BOOL bResult;
162
163 tp = strdup(pattern);
164 ts = strdup(string);
165 strupr(tp);
166 strupr(ts);
167 bResult = MatchStringEngine(tp, ts);
168 free(tp);
169 free(ts);
170 return bResult;
171 }
172 }
173
174
175 //
176 // Strip whitespaces and tabs off the string
177 //
178
179 void LIBNETXMS_EXPORTABLE StrStrip(char *str)
180 {
181 int i;
182
183 for(i=0;(str[i]!=0)&&((str[i]==' ')||(str[i]=='\t'));i++);
184 if (i>0)
185 memmove(str,&str[i],strlen(&str[i])+1);
186 for(i=strlen(str)-1;(i>=0)&&((str[i]==' ')||(str[i]=='\t'));i--);
187 str[i+1]=0;
188 }
189
190
191 //
192 // Add string to enumeration result set
193 //
194
195 void LIBNETXMS_EXPORTABLE NxAddResultString(NETXMS_VALUES_LIST *pList, char *pszString)
196 {
197 pList->ppStringList = (char **)realloc(pList->ppStringList, sizeof(char *) * (pList->dwNumStrings + 1));
198 pList->ppStringList[pList->dwNumStrings] = strdup(pszString);
199 pList->dwNumStrings++;
200 }
201
202
203 //
204 // Get arguments for parameters like name(arg1,...)
205 // Returns FALSE on processing error
206 //
207
208 BOOL LIBNETXMS_EXPORTABLE NxGetParameterArg(char *param, int index, char *arg, int maxSize)
209 {
210 char *ptr1, *ptr2;
211 int state, currIndex, pos;
212 BOOL bResult = TRUE;
213
214 arg[0] = 0; // Default is empty string
215 ptr1 = strchr(param,'(');
216 if (ptr1 == NULL)
217 return TRUE; // No arguments at all
218 for(ptr2 = ptr1 + 1, currIndex = 1, state = 0, pos = 0; state != -1; ptr2++)
219 {
220 switch(state)
221 {
222 case 0: // Normal
223 switch(*ptr2)
224 {
225 case ')':
226 if (currIndex == index)
227 arg[pos] = 0;
228 state = -1; // Finish processing
229 break;
230 case '"':
231 state = 1; // String
232 break;
233 case '\'': // String, type 2
234 state = 2;
235 break;
236 case ',':
237 if (currIndex == index)
238 {
239 arg[pos] = 0;
240 state = -1;
241 }
242 else
243 {
244 currIndex++;
245 }
246 break;
247 case 0:
248 state = -1; // Finish processing
249 bResult = FALSE; // Set error flag
250 break;
251 default:
252 if ((currIndex == index) && (pos < maxSize - 1))
253 arg[pos++] = *ptr2;
254 }
255 break;
256 case 1: // String in ""
257 switch(*ptr2)
258 {
259 case '"':
260 state = 0; // Normal
261 break;
262 case '\\': // Escape
263 ptr2++;
264 if ((currIndex == index) && (pos < maxSize - 1))
265 arg[pos++] = *ptr2;
266 if (ptr2 == 0) // Unexpected EOL
267 {
268 bResult = FALSE;
269 state = -1;
270 }
271 break;
272 case 0:
273 state = -1; // Finish processing
274 bResult = FALSE; // Set error flag
275 break;
276 default:
277 if ((currIndex == index) && (pos < maxSize - 1))
278 arg[pos++] = *ptr2;
279 }
280 break;
281 case 2: // String in ''
282 switch(*ptr2)
283 {
284 case '\'':
285 state = 0; // Normal
286 break;
287 case '\\': // Escape
288 ptr2++;
289 if ((currIndex == index) && (pos < maxSize - 1))
290 arg[pos++] = *ptr2;
291 if (ptr2 == 0) // Unexpected EOL
292 {
293 bResult = FALSE;
294 state = -1;
295 }
296 break;
297 case 0:
298 state = -1; // Finish processing
299 bResult = FALSE; // Set error flag
300 break;
301 default:
302 if ((currIndex == index) && (pos < maxSize - 1))
303 arg[pos++] = *ptr2;
304 }
305 break;
306 }
307 }
308
309 if (bResult)
310 StrStrip(arg);
311 return bResult;
312 }
313
314
315 //
316 // Get current time in milliseconds
317 // Based on timeval.h by Wu Yongwei
318 //
319
320 INT64 LIBNETXMS_EXPORTABLE GetCurrentTimeMs(void)
321 {
322 #ifdef _WIN32
323 FILETIME ft;
324 LARGE_INTEGER li;
325 __int64 t;
326
327 GetSystemTimeAsFileTime(&ft);
328 li.LowPart = ft.dwLowDateTime;
329 li.HighPart = ft.dwHighDateTime;
330 t = li.QuadPart; // In 100-nanosecond intervals
331 t -= EPOCHFILETIME; // Offset to the Epoch time
332 t /= 10000; // Convert to milliseconds
333 #else
334 struct timeval tv;
335 INT64 t;
336
337 gettimeofday(&tv, NULL);
338 t = (INT64)tv.tv_sec * 1000 + (INT64)(tv.tv_usec / 10000);
339 #endif
340
341 return t;
342 }
343
344
345 //
346 // Extract word from line. Extracted word will be placed in buffer.
347 // Returns pointer to the next word or to the null character if end
348 // of line reached.
349 //
350
351 char LIBNETXMS_EXPORTABLE *ExtractWord(char *line, char *buffer)
352 {
353 char *ptr,*bptr;
354
355 for(ptr=line;(*ptr==' ')||(*ptr=='\t');ptr++); // Skip initial spaces
356 // Copy word to buffer
357 for(bptr=buffer;(*ptr!=' ')&&(*ptr!='\t')&&(*ptr!=0);ptr++,bptr++)
358 *bptr=*ptr;
359 *bptr=0;
360 return ptr;
361 }
362
363
364 //
365 // Get system error string by call to FormatMessage
366 // (Windows only)
367 //
368
369 #ifdef _WIN32
370
371 char LIBNETXMS_EXPORTABLE *GetSystemErrorText(DWORD dwError, char *pszBuffer, int iBufSize)
372 {
373 char *msgBuf;
374
375 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
376 FORMAT_MESSAGE_FROM_SYSTEM |
377 FORMAT_MESSAGE_IGNORE_INSERTS,
378 NULL, dwError,
379 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
380 (LPSTR)&msgBuf, 0, NULL) > 0)
381 {
382 msgBuf[strcspn(msgBuf, "\r\n")] = 0;
383 strncpy(pszBuffer, msgBuf, iBufSize);
384 LocalFree(msgBuf);
385 }
386 else
387 {
388 sprintf(pszBuffer, "MSG 0x%08X - Unable to find message text", dwError);
389 }
390 return pszBuffer;
391 }
392
393 #endif
394
395
396 //
397 // daemon() implementation for systems which doesn't have one
398 //
399
400 #if !(HAVE_DAEMON) && !defined(_NETWARE)
401
402 int LIBNETXMS_EXPORTABLE daemon(int nochdir, int noclose)
403 {
404 return 0;
405 }
406
407 #endif
408
409
410 //
411 // Check if given name is a valid object name
412 //
413
414 BOOL LIBNETXMS_EXPORTABLE IsValidObjectName(char *pszName)
415 {
416 static char szValidCharacters[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_- @()./";
417 return (pszName[0] != 0) && (strspn(pszName, szValidCharacters) == strlen(pszName));
418 }