- new folder src/ to hold the source code for main project applications
- main.c is in src/
- all core files are subfolder are in src/core/
- modules are in src/modules/
- libs are in src/lib/
- application Makefiles are in src/
- application binary is built in src/ (src/kamailio)
1 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,964 +0,0 @@ |
1 |
-/* |
|
2 |
- * - various general purpose functions |
|
3 |
- * |
|
4 |
- * Copyright (C) 2001-2003 FhG Fokus |
|
5 |
- * |
|
6 |
- * Permission to use, copy, modify, and distribute this software for any |
|
7 |
- * purpose with or without fee is hereby granted, provided that the above |
|
8 |
- * copyright notice and this permission notice appear in all copies. |
|
9 |
- * |
|
10 |
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|
11 |
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|
12 |
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
|
13 |
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|
14 |
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
|
15 |
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
|
16 |
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|
17 |
- * |
|
18 |
- */ |
|
19 |
-/** Kamailio core :: various general purpose/helper functions. |
|
20 |
- * @file |
|
21 |
- * @ingroup core |
|
22 |
- */ |
|
23 |
- |
|
24 |
- |
|
25 |
-#ifndef ut_h |
|
26 |
-#define ut_h |
|
27 |
- |
|
28 |
-#include "comp_defs.h" |
|
29 |
- |
|
30 |
-#include <sys/types.h> |
|
31 |
-#include <sys/select.h> |
|
32 |
-#include <sys/time.h> |
|
33 |
-#include <limits.h> |
|
34 |
-#include <time.h> |
|
35 |
-#include <unistd.h> |
|
36 |
-#include <ctype.h> |
|
37 |
-#include <string.h> |
|
38 |
-#include <strings.h> |
|
39 |
- |
|
40 |
-#include "compiler_opt.h" |
|
41 |
-#include "config.h" |
|
42 |
-#include "dprint.h" |
|
43 |
-#include "str.h" |
|
44 |
-#include "mem/mem.h" |
|
45 |
-#include "mem/shm_mem.h" |
|
46 |
- |
|
47 |
- |
|
48 |
- |
|
49 |
-/* zero-string wrapper */ |
|
50 |
-#define ZSW(_c) ((_c)?(_c):"") |
|
51 |
- |
|
52 |
-/* returns string beginning and length without insignificant chars */ |
|
53 |
-#define trim_len( _len, _begin, _mystr ) \ |
|
54 |
- do{ static char _c; \ |
|
55 |
- (_len)=(_mystr).len; \ |
|
56 |
- while ((_len) && ((_c=(_mystr).s[(_len)-1])==0 || _c=='\r' || \ |
|
57 |
- _c=='\n' || _c==' ' || _c=='\t' )) \ |
|
58 |
- (_len)--; \ |
|
59 |
- (_begin)=(_mystr).s; \ |
|
60 |
- while ((_len) && ((_c=*(_begin))==' ' || _c=='\t')) { \ |
|
61 |
- (_len)--;\ |
|
62 |
- (_begin)++; \ |
|
63 |
- } \ |
|
64 |
- }while(0) |
|
65 |
- |
|
66 |
-#define trim_r( _mystr ) \ |
|
67 |
- do{ static char _c; \ |
|
68 |
- while( ((_mystr).len) && ( ((_c=(_mystr).s[(_mystr).len-1]))==0 ||\ |
|
69 |
- _c=='\r' || _c=='\n' ) \ |
|
70 |
- ) \ |
|
71 |
- (_mystr).len--; \ |
|
72 |
- }while(0) |
|
73 |
- |
|
74 |
- |
|
75 |
-#define translate_pointer( _new_buf , _org_buf , _p) \ |
|
76 |
- ( (_p)?(_new_buf + (_p-_org_buf)):(0) ) |
|
77 |
- |
|
78 |
-#define via_len(_via) \ |
|
79 |
- ((_via)->bsize-((_via)->name.s-\ |
|
80 |
- ((_via)->hdr.s+(_via)->hdr.len))) |
|
81 |
- |
|
82 |
- |
|
83 |
- |
|
84 |
-/* rounds to sizeof(type), but type must have a 2^k size (e.g. short, int, |
|
85 |
- * long, void*) */ |
|
86 |
-#define ROUND2TYPE(s, type) \ |
|
87 |
- (((s)+(sizeof(type)-1))&(~(sizeof(type)-1))) |
|
88 |
- |
|
89 |
- |
|
90 |
-/* rounds to sizeof(char*) - the first 4 byte multiple on 32 bit archs |
|
91 |
- * and the first 8 byte multiple on 64 bit archs */ |
|
92 |
-#define ROUND_POINTER(s) ROUND2TYPE(s, char*) |
|
93 |
- |
|
94 |
-/* rounds to sizeof(long) - the first 4 byte multiple on 32 bit archs |
|
95 |
- * and the first 8 byte multiple on 64 bit archs (equiv. to ROUND_POINTER)*/ |
|
96 |
-#define ROUND_LONG(s) ROUND2TYPE(s, long) |
|
97 |
- |
|
98 |
-/* rounds to sizeof(int) - the first t byte multiple on 32 and 64 bit archs */ |
|
99 |
-#define ROUND_INT(s) ROUND2TYPE(s, int) |
|
100 |
- |
|
101 |
-/* rounds to sizeof(short) - the first 2 byte multiple */ |
|
102 |
-#define ROUND_SHORT(s) ROUND2TYPE(s, short) |
|
103 |
- |
|
104 |
- |
|
105 |
-/* params: v - either a variable name, structure member or a type |
|
106 |
- * returns an unsigned long containing the maximum possible value that will |
|
107 |
- * fit in v, if v is unsigned or converted to an unsigned version |
|
108 |
- * example: MAX_UVAR_VALUE(unsigned short); MAX_UVAR_VALUE(i); |
|
109 |
- * MAX_UVAR_VALUE(((struct foo*)0)->bar) */ |
|
110 |
-#define MAX_UVAR_VALUE(v) \ |
|
111 |
- (((unsigned long)(-1))>>((sizeof(unsigned long)-sizeof(v))*8UL)) |
|
112 |
- |
|
113 |
- |
|
114 |
-#define MIN_int(a, b) (((a)<(b))?(a):(b)) |
|
115 |
-#define MAX_int(a, b) (((a)>(b))?(a):(b)) |
|
116 |
- |
|
117 |
-#define MIN_unsigned(a, b) (unsigned)(((unsigned)(a)<(unsigned)(b))?(a):(b)) |
|
118 |
-#define MAX_unsigned(a, b) (unsigned)(((unsigned)(a)>(unsigned)(b))?(a):(b)) |
|
119 |
- |
|
120 |
-#if 0 |
|
121 |
-#define MIN_int(a, b) ((b)+(((a)-(b))& -((a)<(b)))) |
|
122 |
-#define MAX_int(a, b) ((a)-(((a)-(b))& -((b)>(a)))) |
|
123 |
- |
|
124 |
-/* depend on signed right shift result which depends on the compiler */ |
|
125 |
-#define MIN_int(a, b) ((b)+(((a)-(b))&(((a)-(b))>>(sizeof(int)*8-1)))) |
|
126 |
-#define MAX_int(a, b) ((a)-(((a)-(b))&(((a)-(b))>>(sizeof(int)*8-1)))) |
|
127 |
-#endif |
|
128 |
- |
|
129 |
- |
|
130 |
-#define append_str(_dest,_src,_len) \ |
|
131 |
- do{ \ |
|
132 |
- memcpy( (_dest) , (_src) , (_len) ); \ |
|
133 |
- (_dest) += (_len) ; \ |
|
134 |
- }while(0); \ |
|
135 |
- |
|
136 |
- |
|
137 |
-/*! append _c char to _dest string */ |
|
138 |
-#define append_chr(_dest,_c) \ |
|
139 |
- *((_dest)++) = _c; |
|
140 |
- |
|
141 |
- |
|
142 |
-#define is_in_str(p, in) (p < in->s + in->len && *p) |
|
143 |
- |
|
144 |
- |
|
145 |
-/* links a value to a msgid */ |
|
146 |
-struct msgid_var{ |
|
147 |
- union{ |
|
148 |
- char char_val; |
|
149 |
- int int_val; |
|
150 |
- long long_val; |
|
151 |
- }u; |
|
152 |
- unsigned int msgid; |
|
153 |
-}; |
|
154 |
- |
|
155 |
-/* return the value or 0 if the msg_id doesn't match */ |
|
156 |
-#define get_msgid_val(var, id, type)\ |
|
157 |
- ((type)((type)((var).msgid!=(id))-1)&((var).u.type##_val)) |
|
158 |
- |
|
159 |
-#define set_msgid_val(var, id, type, value)\ |
|
160 |
- do{\ |
|
161 |
- (var).msgid=(id); \ |
|
162 |
- (var).u.type##_val=(value); \ |
|
163 |
- }while(0) |
|
164 |
- |
|
165 |
-/* char to hex conversion table */ |
|
166 |
-static char fourbits2char[16] = { '0', '1', '2', '3', '4', '5', |
|
167 |
- '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; |
|
168 |
- |
|
169 |
- |
|
170 |
-/* converts a str to an u. short, returns the u. short and sets *err on |
|
171 |
- * error and if err!=null |
|
172 |
- */ |
|
173 |
-static inline unsigned short str2s(const char* s, unsigned int len, int *err) |
|
174 |
-{ |
|
175 |
- unsigned short ret; |
|
176 |
- int i; |
|
177 |
- unsigned char *limit; |
|
178 |
- unsigned char* str; |
|
179 |
- |
|
180 |
- /*init*/ |
|
181 |
- str=(unsigned char*)s; |
|
182 |
- ret=i=0; |
|
183 |
- limit=str+len; |
|
184 |
- |
|
185 |
- for(;str<limit ;str++){ |
|
186 |
- if ( (*str <= '9' ) && (*str >= '0') ){ |
|
187 |
- ret=ret*10+*str-'0'; |
|
188 |
- i++; |
|
189 |
- if (i>5) goto error_digits; |
|
190 |
- }else{ |
|
191 |
- /* error unknown char */ |
|
192 |
- goto error_char; |
|
193 |
- } |
|
194 |
- } |
|
195 |
- if (err) *err=0; |
|
196 |
- return ret; |
|
197 |
- |
|
198 |
-error_digits: |
|
199 |
- if (err) *err=1; |
|
200 |
- return 0; |
|
201 |
-error_char: |
|
202 |
- if (err) *err=1; |
|
203 |
- return 0; |
|
204 |
-} |
|
205 |
- |
|
206 |
- |
|
207 |
- |
|
208 |
-static inline int btostr( char *p, unsigned char val) |
|
209 |
-{ |
|
210 |
- unsigned int a,b,i =0; |
|
211 |
- |
|
212 |
- if ( (a=val/100)!=0 ) |
|
213 |
- *(p+(i++)) = a+'0'; /*first digit*/ |
|
214 |
- if ( (b=val%100/10)!=0 || a) |
|
215 |
- *(p+(i++)) = b+'0'; /*second digit*/ |
|
216 |
- *(p+(i++)) = '0'+val%10; /*third digit*/ |
|
217 |
- |
|
218 |
- return i; |
|
219 |
-} |
|
220 |
- |
|
221 |
- |
|
222 |
-#define INT2STR_MAX_LEN (19+1+1+1) /* 2^64~= 16*10^18 => |
|
223 |
- 19+1 digits + sign + \0 */ |
|
224 |
- |
|
225 |
-/* |
|
226 |
- * returns a pointer to a static buffer containing l in asciiz (with base "base") & sets len |
|
227 |
- * left padded with 0 to "size" |
|
228 |
- */ |
|
229 |
-static inline char* int2str_base_0pad(unsigned int l, int* len, int base, |
|
230 |
- int size) |
|
231 |
-{ |
|
232 |
- static char r[INT2STR_MAX_LEN]; |
|
233 |
- int i, j; |
|
234 |
- |
|
235 |
- if (base < 2) { |
|
236 |
- BUG("base underflow\n"); |
|
237 |
- return NULL; |
|
238 |
- } |
|
239 |
- if (base > 36) { |
|
240 |
- BUG("base overflow\n"); |
|
241 |
- return NULL; |
|
242 |
- } |
|
243 |
- i=INT2STR_MAX_LEN-2; |
|
244 |
- j=i-size; |
|
245 |
- r[INT2STR_MAX_LEN-1]=0; /* null terminate */ |
|
246 |
- do{ |
|
247 |
- r[i]=l%base; |
|
248 |
- if (r[i]<10) |
|
249 |
- r[i]+='0'; |
|
250 |
- else |
|
251 |
- r[i]+='a'-10; |
|
252 |
- i--; |
|
253 |
- l/=base; |
|
254 |
- }while((l || i>j) && (i>=0)); |
|
255 |
- if (l && (i<0)){ |
|
256 |
- BUG("result buffer overflow\n"); |
|
257 |
- } |
|
258 |
- if (len) *len=(INT2STR_MAX_LEN-2)-i; |
|
259 |
- return &r[i+1]; |
|
260 |
-} |
|
261 |
- |
|
262 |
-/* returns a pointer to a static buffer containing l in asciiz (with base "base") & sets len */ |
|
263 |
-static inline char* int2str_base(unsigned int l, int* len, int base) |
|
264 |
-{ |
|
265 |
- return int2str_base_0pad(l, len, base, 0); |
|
266 |
-} |
|
267 |
- |
|
268 |
- |
|
269 |
- |
|
270 |
-/** unsigned long to str conversion using a provided buffer. |
|
271 |
- * Converts/prints an unsigned long to a string. The result buffer must be |
|
272 |
- * provided and its length must be at least INT2STR_MAX_LEN. |
|
273 |
- * @param l - unsigned long to be converted |
|
274 |
- * @param r - pointer to result buffer |
|
275 |
- * @param r_size - result buffer size, must be at least INT2STR_MAX_LEN. |
|
276 |
- * @param *len - length of the written string, _without_ the terminating 0. |
|
277 |
- * @return pointer _inside_ r, to the converted string (note: the string |
|
278 |
- * is written from the end of the buffer and not from the start and hence |
|
279 |
- * the returned pointer will most likely not be equal to r). In case of error |
|
280 |
- * it returns 0 (the only error being insufficient provided buffer size). |
|
281 |
- */ |
|
282 |
-static inline char* int2strbuf(unsigned long l, char *r, int r_size, int* len) |
|
283 |
-{ |
|
284 |
- int i; |
|
285 |
- |
|
286 |
- if(unlikely(r_size<INT2STR_MAX_LEN)) { |
|
287 |
- if (len) |
|
288 |
- *len = 0; |
|
289 |
- return 0; /* => if someone misuses it => crash (feature no. 1) */ |
|
290 |
- } |
|
291 |
- i=INT2STR_MAX_LEN-2; |
|
292 |
- r[INT2STR_MAX_LEN-1]=0; /* null terminate */ |
|
293 |
- do{ |
|
294 |
- r[i]=l%10+'0'; |
|
295 |
- i--; |
|
296 |
- l/=10; |
|
297 |
- }while(l && (i>=0)); |
|
298 |
- if (l && (i<0)){ |
|
299 |
- LM_CRIT("overflow\n"); |
|
300 |
- } |
|
301 |
- if (len) *len=(INT2STR_MAX_LEN-2)-i; |
|
302 |
- return &r[i+1]; |
|
303 |
-} |
|
304 |
- |
|
305 |
-extern char ut_buf_int2str[INT2STR_MAX_LEN]; |
|
306 |
-/** interger(long) to string conversion. |
|
307 |
- * This version uses a static buffer (shared with sint2str()). |
|
308 |
- * WARNING: other function calls might overwrite the static buffer, so |
|
309 |
- * either always save the result immediately or use int2strbuf(...). |
|
310 |
- * @param l - unsigned long to be converted/printed. |
|
311 |
- * @param *len - will be filled with the final length (without the terminating |
|
312 |
- * 0). |
|
313 |
- * @return a pointer to a static buffer containing l in asciiz & sets len. |
|
314 |
- */ |
|
315 |
-static inline char* int2str(unsigned long l, int* len) |
|
316 |
-{ |
|
317 |
- return int2strbuf(l, ut_buf_int2str, INT2STR_MAX_LEN, len); |
|
318 |
-} |
|
319 |
- |
|
320 |
- |
|
321 |
- |
|
322 |
-/** signed long to str conversion using a provided buffer. |
|
323 |
- * Converts a long to a signed string. The result buffer must be provided |
|
324 |
- * and its length must be at least INT2STR_MAX_LEN. |
|
325 |
- * @param l - long to be converted |
|
326 |
- * @param r - pointer to result buffer |
|
327 |
- * @param r_size - result buffer size, must be at least INT2STR_MAX_LEN. |
|
328 |
- * @param *len - length of the written string, _without_ the terminating 0. |
|
329 |
- * @return pointer _inside_ r, to the converted string (note: the string |
|
330 |
- * is written from the end of the buffer and not from the start and hence |
|
331 |
- * the returned pointer will most likely not be equal to r). In case of error |
|
332 |
- * it returns 0 (the only error being insufficient provided buffer size). |
|
333 |
- */ |
|
334 |
-static inline char* sint2strbuf(long l, char* r, int r_size, int* len) |
|
335 |
-{ |
|
336 |
- int sign; |
|
337 |
- char *p; |
|
338 |
- int p_len; |
|
339 |
- |
|
340 |
- sign = 0; |
|
341 |
- if(l<0) { |
|
342 |
- sign = 1; |
|
343 |
- l = -l; |
|
344 |
- } |
|
345 |
- p = int2strbuf((unsigned long)l, r, r_size, &p_len); |
|
346 |
- if(sign && p_len<(r_size-1)) { |
|
347 |
- *(--p) = '-'; |
|
348 |
- p_len++;; |
|
349 |
- } |
|
350 |
- if (likely(len)) |
|
351 |
- *len = p_len; |
|
352 |
- return p; |
|
353 |
-} |
|
354 |
- |
|
355 |
- |
|
356 |
-/** Signed INTeger-TO-STRing: converts a long to a string. |
|
357 |
- * This version uses a static buffer, shared with int2str(). |
|
358 |
- * WARNING: other function calls might overwrite the static buffer, so |
|
359 |
- * either always save the result immediately or use sint2strbuf(...). |
|
360 |
- * @param l - long to be converted/printed. |
|
361 |
- * @param *len - will be filled with the final length (without the terminating |
|
362 |
- * 0). |
|
363 |
- * @return a pointer to a static buffer containing l in asciiz & sets len. |
|
364 |
- */ |
|
365 |
-static inline char* sint2str(long l, int* len) |
|
366 |
-{ |
|
367 |
- return sint2strbuf(l, ut_buf_int2str, INT2STR_MAX_LEN, len); |
|
368 |
-} |
|
369 |
- |
|
370 |
- |
|
371 |
- |
|
372 |
-#define USHORT2SBUF_MAX_LEN 5 /* 65535*/ |
|
373 |
-/* converts an unsigned short (16 bits) to asciiz |
|
374 |
- * returns bytes written or 0 on error |
|
375 |
- * the passed len must be at least USHORT2SBUF_MAX chars or error |
|
376 |
- * would be returned. |
|
377 |
- * (optimized for port conversion (4 or 5 digits most of the time)*/ |
|
378 |
-static inline int ushort2sbuf(unsigned short u, char* buf, int len) |
|
379 |
-{ |
|
380 |
- int offs; |
|
381 |
- unsigned char a, b, c, d; |
|
382 |
- |
|
383 |
- if (unlikely(len<USHORT2SBUF_MAX_LEN)) |
|
384 |
- return 0; |
|
385 |
- offs=0; |
|
386 |
- a=u/10000; u%=10000; |
|
387 |
- buf[offs]=a+'0'; offs+=(a!=0); |
|
388 |
- b=u/1000; u%=1000; |
|
389 |
- buf[offs]=b+'0'; offs+=((offs|b)!=0); |
|
390 |
- c=u/100; u%=100; |
|
391 |
- buf[offs]=c+'0'; offs+=((offs|c)!=0); |
|
392 |
- d=u/10; u%=10; |
|
393 |
- buf[offs]=d+'0'; offs+=((offs|d)!=0); |
|
394 |
- buf[offs]=(unsigned char)u+'0'; |
|
395 |
- return offs+1; |
|
396 |
-} |
|
397 |
- |
|
398 |
- |
|
399 |
- |
|
400 |
-#define USHORT2STR_MAX_LEN (USHORT2SBUF_MAX_LEN+1) /* 65535\0*/ |
|
401 |
-/* converts an unsigned short (16 bits) to asciiz |
|
402 |
- * (optimized for port conversiob (4 or 5 digits most of the time)*/ |
|
403 |
-static inline char* ushort2str(unsigned short u) |
|
404 |
-{ |
|
405 |
- static char buf[USHORT2STR_MAX_LEN]; |
|
406 |
- int len; |
|
407 |
- |
|
408 |
- len=ushort2sbuf(u, buf, sizeof(buf)-1); |
|
409 |
- buf[len]=0; |
|
410 |
- return buf; |
|
411 |
-} |
|
412 |
- |
|
413 |
- |
|
414 |
- |
|
415 |
-/* fast memchr version */ |
|
416 |
-static inline char* q_memchr(char* p, int c, unsigned int size) |
|
417 |
-{ |
|
418 |
- char* end; |
|
419 |
- |
|
420 |
- end=p+size; |
|
421 |
- for(;p<end;p++){ |
|
422 |
- if (*p==(unsigned char)c) return p; |
|
423 |
- } |
|
424 |
- return 0; |
|
425 |
-} |
|
426 |
- |
|
427 |
- |
|
428 |
-/* fast reverse char search */ |
|
429 |
- |
|
430 |
-static inline char* q_memrchr(char* p, int c, unsigned int size) |
|
431 |
-{ |
|
432 |
- char* end; |
|
433 |
- |
|
434 |
- end=p+size-1; |
|
435 |
- for(;end>=p;end--) { |
|
436 |
- if (*end==(unsigned char)c) return end; |
|
437 |
- } |
|
438 |
- return 0; |
|
439 |
-} |
|
440 |
- |
|
441 |
-/* returns -1 on error, 1! on success (consistent with int2reverse_hex) */ |
|
442 |
-inline static int reverse_hex2int( char *c, int len, unsigned int* res) |
|
443 |
-{ |
|
444 |
- char *pc; |
|
445 |
- char mychar; |
|
446 |
- |
|
447 |
- *res=0; |
|
448 |
- for (pc=c+len-1; len>0; pc--, len--) { |
|
449 |
- *res <<= 4 ; |
|
450 |
- mychar=*pc; |
|
451 |
- if ( mychar >='0' && mychar <='9') *res+=mychar -'0'; |
|
452 |
- else if (mychar >='a' && mychar <='f') *res+=mychar -'a'+10; |
|
453 |
- else if (mychar >='A' && mychar <='F') *res+=mychar -'A'+10; |
|
454 |
- else return -1; |
|
455 |
- } |
|
456 |
- return 1; |
|
457 |
-} |
|
458 |
- |
|
459 |
-inline static int int2reverse_hex( char **c, int *size, unsigned int nr ) |
|
460 |
-{ |
|
461 |
- unsigned short digit; |
|
462 |
- |
|
463 |
- if (*size && nr==0) { |
|
464 |
- **c = '0'; |
|
465 |
- (*c)++; |
|
466 |
- (*size)--; |
|
467 |
- return 1; |
|
468 |
- } |
|
469 |
- |
|
470 |
- while (*size && nr ) { |
|
471 |
- digit = nr & 0xf ; |
|
472 |
- **c= digit >= 10 ? digit + 'a' - 10 : digit + '0'; |
|
473 |
- nr >>= 4; |
|
474 |
- (*c)++; |
|
475 |
- (*size)--; |
|
476 |
- } |
|
477 |
- return nr ? -1 /* number not processed; too little space */ : 1; |
|
478 |
-} |
|
479 |
- |
|
480 |
-/* double output length assumed ; does NOT zero-terminate */ |
|
481 |
-inline static int string2hex( |
|
482 |
- /* input */ unsigned char *str, int len, |
|
483 |
- /* output */ char *hex ) |
|
484 |
-{ |
|
485 |
- int orig_len; |
|
486 |
- |
|
487 |
- if (len==0) { |
|
488 |
- *hex='0'; |
|
489 |
- return 1; |
|
490 |
- } |
|
491 |
- |
|
492 |
- orig_len=len; |
|
493 |
- while ( len ) { |
|
494 |
- |
|
495 |
- *hex=fourbits2char[(*str) >> 4]; |
|
496 |
- hex++; |
|
497 |
- *hex=fourbits2char[(*str) & 0xf]; |
|
498 |
- hex++; |
|
499 |
- len--; |
|
500 |
- str++; |
|
501 |
- |
|
502 |
- } |
|
503 |
- return orig_len-len; |
|
504 |
-} |
|
505 |
- |
|
506 |
-/* portable sleep in microseconds (no interrupt handling now) */ |
|
507 |
- |
|
508 |
-inline static void sleep_us( unsigned int nusecs ) |
|
509 |
-{ |
|
510 |
- struct timeval tval; |
|
511 |
- tval.tv_sec =nusecs/1000000; |
|
512 |
- tval.tv_usec=nusecs%1000000; |
|
513 |
- select(0, NULL, NULL, NULL, &tval ); |
|
514 |
-} |
|
515 |
- |
|
516 |
- |
|
517 |
-/* portable determination of max_path */ |
|
518 |
-inline static int pathmax(void) |
|
519 |
-{ |
|
520 |
-#ifdef PATH_MAX |
|
521 |
- static int pathmax=PATH_MAX; |
|
522 |
-#else |
|
523 |
- static int pathmax=0; |
|
524 |
-#endif |
|
525 |
- if (pathmax==0) { /* init */ |
|
526 |
- pathmax=pathconf("/", _PC_PATH_MAX); |
|
527 |
- pathmax=(pathmax<=0)?PATH_MAX_GUESS:pathmax+1; |
|
528 |
- } |
|
529 |
- return pathmax; |
|
530 |
-} |
|
531 |
- |
|
532 |
-inline static int hex2int(char hex_digit) |
|
533 |
-{ |
|
534 |
- if (hex_digit>='0' && hex_digit<='9') |
|
535 |
- return hex_digit-'0'; |
|
536 |
- if (hex_digit>='a' && hex_digit<='f') |
|
537 |
- return hex_digit-'a'+10; |
|
538 |
- if (hex_digit>='A' && hex_digit<='F') |
|
539 |
- return hex_digit-'A'+10; |
|
540 |
- /* no valid hex digit ... */ |
|
541 |
- LM_ERR("'%c' is no hex char\n", hex_digit ); |
|
542 |
- return -1; |
|
543 |
-} |
|
544 |
- |
|
545 |
-/* Un-escape URI user -- it takes a pointer to original user |
|
546 |
- str, as well as the new, unescaped one, which MUST have |
|
547 |
- an allocated buffer linked to the 'str' structure ; |
|
548 |
- (the buffer can be allocated with the same length as |
|
549 |
- the original string -- the output string is always |
|
550 |
- shorter (if escaped characters occur) or same-long |
|
551 |
- as the original one). |
|
552 |
- |
|
553 |
- only printable characters are permitted |
|
554 |
- |
|
555 |
- <0 is returned on an unescaping error, length of the |
|
556 |
- unescaped string otherwise |
|
557 |
-*/ |
|
558 |
-inline static int un_escape(str *user, str *new_user ) |
|
559 |
-{ |
|
560 |
- int i, j, value; |
|
561 |
- int hi, lo; |
|
562 |
- |
|
563 |
- if( new_user==0 || new_user->s==0) { |
|
564 |
- LM_CRIT("invalid param\n"); |
|
565 |
- return -1; |
|
566 |
- } |
|
567 |
- |
|
568 |
- new_user->len = 0; |
|
569 |
- j = 0; |
|
570 |
- |
|
571 |
- for (i = 0; i < user->len; i++) { |
|
572 |
- if (user->s[i] == '%') { |
|
573 |
- if (i + 2 >= user->len) { |
|
574 |
- LM_ERR("escape sequence too short in '%.*s' @ %d\n", |
|
575 |
- user->len, user->s, i ); |
|
576 |
- goto error; |
|
577 |
- } |
|
578 |
- hi=hex2int(user->s[i + 1]); |
|
579 |
- if (hi<0) { |
|
580 |
- LM_ERR("non-hex high digit in an escape sequence in" |
|
581 |
- " '%.*s' @ %d\n", |
|
582 |
- user->len, user->s, i+1 ); |
|
583 |
- goto error; |
|
584 |
- } |
|
585 |
- lo=hex2int(user->s[i + 2]); |
|
586 |
- if (lo<0) { |
|
587 |
- LM_ERR("non-hex low digit in an escape sequence in " |
|
588 |
- "'%.*s' @ %d\n", |
|
589 |
- user->len, user->s, i+2 ); |
|
590 |
- goto error; |
|
591 |
- } |
|
592 |
- value=(hi<<4)+lo; |
|
593 |
- if (value < 32 || value > 126) { |
|
594 |
- LM_ERR("non-ASCII escaped character in '%.*s' @ %d\n", |
|
595 |
- user->len, user->s, i ); |
|
596 |
- goto error; |
|
597 |
- } |
|
598 |
- new_user->s[j] = value; |
|
599 |
- i+=2; /* consume the two hex digits, for cycle will move to the next char */ |
|
600 |
- } else { |
|
601 |
- new_user->s[j] = user->s[i]; |
|
602 |
- } |
|
603 |
- j++; /* good -- we translated another character */ |
|
604 |
- } |
|
605 |
- new_user->len = j; |
|
606 |
- return j; |
|
607 |
- |
|
608 |
-error: |
|
609 |
- new_user->len = j; |
|
610 |
- return -1; |
|
611 |
-} |
|
612 |
- |
|
613 |
- |
|
614 |
-/* |
|
615 |
- * Convert a string to lower case |
|
616 |
- */ |
|
617 |
-static inline void strlower(str* _s) |
|
618 |
-{ |
|
619 |
- int i; |
|
620 |
- |
|
621 |
- if (_s == NULL) return ; |
|
622 |
- if (_s->len < 0) return ; |
|
623 |
- if (_s->s == NULL) return ; |
|
624 |
- |
|
625 |
- for(i = 0; i < _s->len; i++) { |
|
626 |
- _s->s[i] = tolower(_s->s[i]); |
|
627 |
- } |
|
628 |
-} |
|
629 |
- |
|
630 |
- |
|
631 |
-/* |
|
632 |
- * Convert a str into integer |
|
633 |
- */ |
|
634 |
-static inline int str2int(str* _s, unsigned int* _r) |
|
635 |
-{ |
|
636 |
- int i; |
|
637 |
- |
|
638 |
- if (_s == NULL) return -1; |
|
639 |
- if (_r == NULL) return -1; |
|
640 |
- if (_s->len < 0) return -1; |
|
641 |
- if (_s->s == NULL) return -1; |
|
642 |
- |
|
643 |
- *_r = 0; |
|
644 |
- for(i = 0; i < _s->len; i++) { |
|
645 |
- if ((_s->s[i] >= '0') && (_s->s[i] <= '9')) { |
|
646 |
- *_r *= 10; |
|
647 |
- *_r += _s->s[i] - '0'; |
|
648 |
- } else { |
|
649 |
- return -1; |
|
650 |
- } |
|
651 |
- } |
|
652 |
- |
|
653 |
- return 0; |
|
654 |
-} |
|
655 |
- |
|
656 |
-/* |
|
657 |
- * Convert an str to signed integer |
|
658 |
- */ |
|
659 |
-static inline int str2sint(str* _s, int* _r) |
|
660 |
-{ |
|
661 |
- int i; |
|
662 |
- int sign; |
|
663 |
- |
|
664 |
- if (_s == NULL) return -1; |
|
665 |
- if (_r == NULL) return -1; |
|
666 |
- if (_s->len < 0) return -1; |
|
667 |
- if (_s->s == NULL) return -1; |
|
668 |
- |
|
669 |
- *_r = 0; |
|
670 |
- sign = 1; |
|
671 |
- i = 0; |
|
672 |
- if (_s->s[0] == '+') { |
|
673 |
- i++; |
|
674 |
- } else if (_s->s[0] == '-') { |
|
675 |
- sign = -1; |
|
676 |
- i++; |
|
677 |
- } |
|
678 |
- for(; i < _s->len; i++) { |
|
679 |
- if ((_s->s[i] >= '0') && (_s->s[i] <= '9')) { |
|
680 |
- *_r *= 10; |
|
681 |
- *_r += _s->s[i] - '0'; |
|
682 |
- } else { |
|
683 |
- return -1; |
|
684 |
- } |
|
685 |
- } |
|
686 |
- *_r *= sign; |
|
687 |
- |
|
688 |
- return 0; |
|
689 |
-} |
|
690 |
- |
|
691 |
- |
|
692 |
- |
|
693 |
-#ifdef SHM_MEM |
|
694 |
-/** |
|
695 |
- * \brief Make a copy of a str structure using shm_malloc |
|
696 |
- * \param dst destination |
|
697 |
- * \param src source |
|
698 |
- * \return 0 on success, -1 on failure |
|
699 |
- */ |
|
700 |
-static inline int shm_str_dup(str* dst, const str* src) |
|
701 |
-{ |
|
702 |
- /* NULL checks */ |
|
703 |
- if (dst == NULL || src == NULL) { |
|
704 |
- LM_ERR("NULL src or dst\n"); |
|
705 |
- return -1; |
|
706 |
- } |
|
707 |
- |
|
708 |
- /** |
|
709 |
- * fallback actions: |
|
710 |
- * - dst->len=0 |
|
711 |
- * - dst->s is allocated sizeof(void*) size |
|
712 |
- * - return 0 (i.e. success) |
|
713 |
- */ |
|
714 |
- |
|
715 |
- /* fallback checks */ |
|
716 |
- if (src->len < 0 || src->s == NULL) { |
|
717 |
- LM_WARN("shm_str_dup fallback; dup called for src->s == NULL or src->len < 0\n"); |
|
718 |
- dst->len = 0; |
|
719 |
- } else { |
|
720 |
- dst->len = src->len; |
|
721 |
- } |
|
722 |
- |
|
723 |
- dst->s = (char*)shm_malloc(dst->len); |
|
724 |
- if (dst->s == NULL) { |
|
725 |
- SHM_MEM_ERROR; |
|
726 |
- return -1; |
|
727 |
- } |
|
728 |
- |
|
729 |
- /* avoid memcpy from NULL source - undefined behaviour */ |
|
730 |
- if (src->s == NULL) { |
|
731 |
- LM_WARN("shm_str_dup fallback; skip memcpy for src->s == NULL\n"); |
|
732 |
- return 0; |
|
733 |
- } |
|
734 |
- |
|
735 |
- memcpy(dst->s, src->s, dst->len); |
|
736 |
- |
|
737 |
- return 0; |
|
738 |
-} |
|
739 |
-#endif /* SHM_MEM */ |
|
740 |
- |
|
741 |
- |
|
742 |
- |
|
743 |
-/** |
|
744 |
- * \brief Make a copy of a str structure using pkg_malloc |
|
745 |
- * \param dst destination |
|
746 |
- * \param src source |
|
747 |
- * \return 0 on success, -1 on failure |
|
748 |
- */ |
|
749 |
-static inline int pkg_str_dup(str* dst, const str* src) |
|
750 |
-{ |
|
751 |
- /* NULL checks */ |
|
752 |
- if (dst == NULL || src == NULL) { |
|
753 |
- LM_ERR("NULL src or dst\n"); |
|
754 |
- return -1; |
|
755 |
- } |
|
756 |
- |
|
757 |
- /** |
|
758 |
- * fallback actions: |
|
759 |
- * - dst->len=0 |
|
760 |
- * - dst->s is allocated sizeof(void*) size |
|
761 |
- * - return 0 (i.e. success) |
|
762 |
- */ |
|
763 |
- |
|
764 |
- /* fallback checks */ |
|
765 |
- if (src->len < 0 || src->s == NULL) { |
|
766 |
- LM_WARN("pkg_str_dup fallback; dup called for src->s == NULL or src->len < 0\n"); |
|
767 |
- dst->len = 0; |
|
768 |
- } else { |
|
769 |
- dst->len = src->len; |
|
770 |
- } |
|
771 |
- |
|
772 |
- dst->s = (char*)pkg_malloc(dst->len); |
|
773 |
- if (dst->s == NULL) { |
|
774 |
- PKG_MEM_ERROR; |
|
775 |
- return -1; |
|
776 |
- } |
|
777 |
- |
|
778 |
- /* avoid memcpy from NULL source - undefined behaviour */ |
|
779 |
- if (src->s == NULL) { |
|
780 |
- LM_WARN("pkg_str_dup fallback; skip memcpy for src->s == NULL\n"); |
|
781 |
- return 0; |
|
782 |
- } |
|
783 |
- |
|
784 |
- memcpy(dst->s, src->s, dst->len); |
|
785 |
- |
|
786 |
- return 0; |
|
787 |
-} |
|
788 |
- |
|
789 |
-/** |
|
790 |
- * \brief Compare two str's case sensitive |
|
791 |
- * \param str1 first str |
|
792 |
- * \param str2 second str |
|
793 |
- * \return 0 if both are equal, positive if str1 is greater, negative if str2 is greater, -2 on errors |
|
794 |
- */ |
|
795 |
-static inline int str_strcmp(const str *str1, const str *str2) |
|
796 |
-{ |
|
797 |
- if(str1==NULL || str2==NULL || str1->s ==NULL || str2->s==NULL || str1->len<0 || str2->len<0) |
|
798 |
- { |
|
799 |
- LM_ERR("bad parameters\n"); |
|
800 |
- return -2; |
|
801 |
- } |
|
802 |
- |
|
803 |
- if (str1->len < str2->len) |
|
804 |
- return -1; |
|
805 |
- else if (str1->len > str2->len) |
|
806 |
- return 1; |
|
807 |
- else |
|
808 |
- return strncmp(str1->s, str2->s, str1->len); |
|
809 |
-} |
|
810 |
- |
|
811 |
-/** |
|
812 |
- * \brief Compare two str's case insensitive |
|
813 |
- * \param str1 first str |
|
814 |
- * \param str2 second str |
|
815 |
- * \return 0 if both are equal, positive if str1 is greater, negative if str2 is greater, -2 on errors |
|
816 |
- */ |
|
817 |
-static inline int str_strcasecmp(const str *str1, const str *str2) |
|
818 |
-{ |
|
819 |
- if(str1==NULL || str2==NULL || str1->s ==NULL || str2->s==NULL || str1->len<0 || str2->len<0) |
|
820 |
- { |
|
821 |
- LM_ERR("bad parameters\n"); |
|
822 |
- return -2; |
|
823 |
- } |
|
824 |
- if (str1->len < str2->len) |
|
825 |
- return -1; |
|
826 |
- else if (str1->len > str2->len) |
|
827 |
- return 1; |
|
828 |
- else |
|
829 |
- return strncasecmp(str1->s, str2->s, str1->len); |
|
830 |
-} |
|
831 |
- |
|
832 |
-#ifndef MIN |
|
833 |
-#define MIN(x, y) ((x) < (y) ? (x) : (y)) |
|
834 |
-#endif |
|
835 |
-#ifndef MAX |
|
836 |
-#define MAX(x, y) ((x) > (y) ? (x) : (y)) |
|
837 |
-#endif |
|
838 |
- |
|
839 |
- |
|
840 |
-/* INTeger-TO-Buffer-STRing : convers an unsigned long to a string |
|
841 |
- * IMPORTANT: the provided buffer must be at least INT2STR_MAX_LEN size !! */ |
|
842 |
-static inline char* int2bstr(unsigned long l, char *s, int* len) |
|
843 |
-{ |
|
844 |
- int i; |
|
845 |
- i=INT2STR_MAX_LEN-2; |
|
846 |
- s[INT2STR_MAX_LEN-1]=0; |
|
847 |
- /* null terminate */ |
|
848 |
- do{ |
|
849 |
- s[i]=l%10+'0'; |
|
850 |
- i--; |
|
851 |
- l/=10; |
|
852 |
- }while(l && (i>=0)); |
|
853 |
- if (l && (i<0)){ |
|
854 |
- LM_CRIT("overflow error\n"); |
|
855 |
- } |
|
856 |
- if (len) *len=(INT2STR_MAX_LEN-2)-i; |
|
857 |
- return &s[i+1]; |
|
858 |
-} |
|
859 |
- |
|
860 |
- |
|
861 |
-inline static int hexstr2int(char *c, int len, unsigned int *val) |
|
862 |
-{ |
|
863 |
- char *pc; |
|
864 |
- int r; |
|
865 |
- char mychar; |
|
866 |
- |
|
867 |
- r=0; |
|
868 |
- for (pc=c; pc<c+len; pc++) { |
|
869 |
- r <<= 4 ; |
|
870 |
- mychar=*pc; |
|
871 |
- if ( mychar >='0' && mychar <='9') r+=mychar -'0'; |
|
872 |
- else if (mychar >='a' && mychar <='f') r+=mychar -'a'+10; |
|
873 |
- else if (mychar >='A' && mychar <='F') r+=mychar -'A'+10; |
|
874 |
- else return -1; |
|
875 |
- } |
|
876 |
- *val = r; |
|
877 |
- return 0; |
|
878 |
-} |
|
879 |
- |
|
880 |
- |
|
881 |
- |
|
882 |
-/* |
|
883 |
- * Convert a str (base 10 or 16) into integer |
|
884 |
- */ |
|
885 |
-static inline int strno2int( str *val, unsigned int *mask ) |
|
886 |
-{ |
|
887 |
- /* hexa or decimal*/ |
|
888 |
- if (val->len>2 && val->s[0]=='0' && val->s[1]=='x') { |
|
889 |
- return hexstr2int( val->s+2, val->len-2, mask); |
|
890 |
- } else { |
|
891 |
- return str2int( val, mask); |
|
892 |
- } |
|
893 |
-} |
|
894 |
- |
|
895 |
-/* converts a username into uid:gid, |
|
896 |
- * returns -1 on error & 0 on success */ |
|
897 |
-int user2uid(int* uid, int* gid, char* user); |
|
898 |
- |
|
899 |
-/* converts a group name into a gid |
|
900 |
- * returns -1 on error, 0 on success */ |
|
901 |
-int group2gid(int* gid, char* group); |
|
902 |
- |
|
903 |
-/* |
|
904 |
- * Replacement of timegm (does not exists on all platforms |
|
905 |
- * Taken from |
|
906 |
- * http://lists.samba.org/archive/samba-technical/2002-November/025737.html |
|