@cfg_get.<group_name>.<var_name> is documented
[sip-router] / ut.h
1 /*
2  *$Id$
3  *
4  * - various general purpose functions
5  *
6  * Copyright (C) 2001-2003 FhG Fokus
7  *
8  * This file is part of ser, a free SIP server.
9  *
10  * ser is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version
14  *
15  * For a license to use the ser software under conditions
16  * other than those described here, or to purchase support for this
17  * software, please contact iptel.org by e-mail at the following addresses:
18  *    info@iptel.org
19  *
20  * ser is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License 
26  * along with this program; if not, write to the Free Software 
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28  *
29  * History
30  * ------
31  * 2003-01-18 un_escape function introduced for convenience of code needing
32  *            the complex&slow feature of unescaping
33  * 2003-01-28 scratchpad removed (jiri)
34  * 2003-01-29 pathmax added (jiri)
35  * 2003-02-13 strlower added (janakj)
36  * 2003-02-28 scratchpad compatibility abandoned (jiri)
37  * 2003-03-30 str2int and str2float added (janakj)
38  * 2003-04-26 ZSW (jiri)
39  * 2004-03-08 updated int2str (64 bits, INT2STR_MAX_LEN used) (andrei)
40  * 2005-11-29 reverse_hex2int/int2reverse_hex switched to unsigned int (andrei)
41  * 2005-12-09 added msgid_var (andrei)
42  * 2007-05-14 added get_sys_ver() (andrei)
43  * 2007-06-05 added MAX_UVAR_VALUE(), MAX_int(a,b) MIN_int(a,b) (andrei)
44  */
45
46
47 #ifndef ut_h
48 #define ut_h
49
50 #include "comp_defs.h"
51
52 #include <sys/types.h>
53 #include <sys/time.h>
54 #include <limits.h>
55 #include <time.h>
56 #include <unistd.h>
57 #include <ctype.h>
58
59 #include "config.h"
60 #include "dprint.h"
61 #include "str.h"
62
63
64
65 /* zero-string wrapper */
66 #define ZSW(_c) ((_c)?(_c):"")
67
68 /* returns string beginning and length without insignificant chars */
69 #define trim_len( _len, _begin, _mystr ) \
70         do{     static char _c; \
71                 (_len)=(_mystr).len; \
72                 while ((_len) && ((_c=(_mystr).s[(_len)-1])==0 || _c=='\r' || \
73                                         _c=='\n' || _c==' ' || _c=='\t' )) \
74                         (_len)--; \
75                 (_begin)=(_mystr).s; \
76                 while ((_len) && ((_c=*(_begin))==' ' || _c=='\t')) { \
77                         (_len)--;\
78                         (_begin)++; \
79                 } \
80         }while(0)
81
82 #define trim_r( _mystr ) \
83         do{     static char _c; \
84                 while( ((_mystr).len) && ( ((_c=(_mystr).s[(_mystr).len-1]))==0 ||\
85                                                                         _c=='\r' || _c=='\n' ) \
86                                 ) \
87                         (_mystr).len--; \
88         }while(0)
89
90
91 #define  translate_pointer( _new_buf , _org_buf , _p) \
92         ( (_p)?(_new_buf + (_p-_org_buf)):(0) )
93
94 #define via_len(_via) \
95         ((_via)->bsize-((_via)->name.s-\
96                 ((_via)->hdr.s+(_via)->hdr.len)))
97
98
99
100 /* rounds to sizeof(type), but type must have a 2^k size (e.g. short, int,
101  * long, void*) */
102 #define ROUND2TYPE(s, type) \
103         (((s)+(sizeof(type)-1))&(~(sizeof(type)-1)))
104
105
106 /* rounds to sizeof(char*) - the first 4 byte multiple on 32 bit archs
107  * and the first 8 byte multiple on 64 bit archs */
108 #define ROUND_POINTER(s) ROUND2TYPE(s, char*)
109
110 /* rounds to sizeof(long) - the first 4 byte multiple on 32 bit archs
111  * and the first 8 byte multiple on 64 bit archs  (equiv. to ROUND_POINTER)*/
112 #define ROUND_LONG(s)  ROUND2TYPE(s, long)
113
114 /* rounds to sizeof(int) - the first t byte multiple on 32 and 64  bit archs */
115 #define ROUND_INT(s) ROUND2TYPE(s, int)
116
117 /* rounds to sizeof(short) - the first 2 byte multiple */
118 #define ROUND_SHORT(s) ROUND2TYPE(s, short)
119
120
121 /* params: v - either a variable name, structure member or a type
122  * returns an unsigned long containing the maximum possible value that will
123  * fit in v, if v is unsigned or converted to an unsigned version
124  * example: MAX_UVAR_VALUE(unsigned short); MAX_UVAR_VALUE(i);
125  *  MAX_UVAR_VALUE(((struct foo*)0)->bar) */
126 #define MAX_UVAR_VALUE(v) \
127         (((unsigned long)(-1))>>((sizeof(unsigned long)-sizeof(v))*8UL))
128
129
130 #define MIN_int(a, b) (((a)<(b))?(a):(b))
131 #define MAX_int(a, b) (((a)>(b))?(a):(b))
132
133 #define MIN_unsigned(a, b) (unsigned)(((unsigned)(a)<(unsigned)(b))?(a):(b))
134 #define MAX_unsigned(a, b) (unsigned)(((unsigned)(a)>(unsigned)(b))?(a):(b))
135
136 #if 0
137 #define MIN_int(a, b) ((b)+(((a)-(b))& -((a)<(b))))
138 #define MAX_int(a, b) ((a)-(((a)-(b))& -((b)>(a))))
139
140 /* depend on signed right shift result which depends on the compiler */
141 #define MIN_int(a, b) ((b)+(((a)-(b))&(((a)-(b))>>(sizeof(int)*8-1))))
142 #define MAX_int(a, b) ((a)-(((a)-(b))&(((a)-(b))>>(sizeof(int)*8-1))))
143 #endif
144
145
146 /* links a value to a msgid */
147 struct msgid_var{
148         union{
149                 char char_val;
150                 int int_val;
151                 long long_val;
152         }u;
153         unsigned int msgid;
154 };
155
156 /* return the value or 0 if the msg_id doesn't match */
157 #define get_msgid_val(var, id, type)\
158         (type)((type)((var).msgid!=(id))-1)&((var).u.type##_val)
159
160 #define set_msgid_val(var, id, type, value)\
161         do{\
162                 (var).msgid=(id); \
163                 (var).u.type##_val=(value); \
164         }while(0)
165
166 /* char to hex conversion table */
167 static char fourbits2char[16] = { '0', '1', '2', '3', '4', '5',
168         '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
169
170
171 /* converts a str to an u. short, returns the u. short and sets *err on
172  * error and if err!=null
173   */
174 static inline unsigned short str2s(const char* s, unsigned int len,
175                                                                         int *err)
176 {
177         unsigned short ret;
178         int i;
179         unsigned char *limit;
180         unsigned char *init;
181         unsigned char* str;
182
183         /*init*/
184         str=(unsigned char*)s;
185         ret=i=0;
186         limit=str+len;
187         init=str;
188
189         for(;str<limit ;str++){
190                 if ( (*str <= '9' ) && (*str >= '0') ){
191                                 ret=ret*10+*str-'0';
192                                 i++;
193                                 if (i>5) goto error_digits;
194                 }else{
195                                 /* error unknown char */
196                                 goto error_char;
197                 }
198         }
199         if (err) *err=0;
200         return ret;
201
202 error_digits:
203         /*DBG("str2s: ERROR: too many letters in [%.*s]\n", (int)len, init); */
204         if (err) *err=1;
205         return 0;
206 error_char:
207         /*DBG("str2s: ERROR: unexpected char %c in %.*s\n", *str, (int)len, init);
208          * */
209         if (err) *err=1;
210         return 0;
211 }
212
213
214
215 static inline int btostr( char *p,  unsigned char val)
216 {
217         unsigned int a,b,i =0;
218
219         if ( (a=val/100)!=0 )
220                 *(p+(i++)) = a+'0';         /*first digit*/
221         if ( (b=val%100/10)!=0 || a)
222                 *(p+(i++)) = b+'0';        /*second digit*/
223         *(p+(i++)) = '0'+val%10;              /*third digit*/
224
225         return i;
226 }
227
228
229 #define INT2STR_MAX_LEN  (19+1+1) /* 2^64~= 16*10^18 => 19+1 digits + \0 */
230
231 /* 
232  * returns a pointer to a static buffer containing l in asciiz (with base "base") & sets len 
233  * left padded with 0 to "size"
234  */
235 static inline char* int2str_base_0pad(unsigned int l, int* len, int base, int size)
236 {
237         static char r[INT2STR_MAX_LEN];
238         int i, j;
239
240         if (base < 2) {
241                 BUG("base underflow\n");
242                 return NULL;
243         }
244         if (base > 36) {
245                 BUG("base overflow\n");
246                 return NULL;
247         }
248         i=INT2STR_MAX_LEN-2;
249         j=i-size;
250         r[INT2STR_MAX_LEN-1]=0; /* null terminate */
251         do{
252                 r[i]=l%base;
253                 if (r[i]<10)
254                         r[i]+='0';
255                 else
256                         r[i]+='a'-10;
257                 i--;
258                 l/=base;
259         }while((l || i>j) && (i>=0));
260         if (l && (i<0)){
261                 BUG("result buffer overflow\n");
262         }
263         if (len) *len=(INT2STR_MAX_LEN-2)-i;
264         return &r[i+1];
265 }
266
267 /* returns a pointer to a static buffer containing l in asciiz (with base "base") & sets len */
268 static inline char* int2str_base(unsigned int l, int* len, int base)
269 {
270         return int2str_base_0pad(l, len, base, 0);
271 }
272
273
274
275 /* returns a pointer to a static buffer containing l in asciiz & sets len */
276 static inline char* int2str(unsigned int l, int* len)
277 {
278         static char r[INT2STR_MAX_LEN];
279         int i;
280         
281         i=INT2STR_MAX_LEN-2;
282         r[INT2STR_MAX_LEN-1]=0; /* null terminate */
283         do{
284                 r[i]=l%10+'0';
285                 i--;
286                 l/=10;
287         }while(l && (i>=0));
288         if (l && (i<0)){
289                 LOG(L_CRIT, "BUG: int2str: overflow\n");
290         }
291         if (len) *len=(INT2STR_MAX_LEN-2)-i;
292         return &r[i+1];
293 }
294
295
296
297 /* faster memchr version */
298 static inline char* q_memchr(char* p, int c, unsigned int size)
299 {
300         char* end;
301
302         end=p+size;
303         for(;p<end;p++){
304                 if (*p==(unsigned char)c) return p;
305         }
306         return 0;
307 }
308         
309
310 /* returns -1 on error, 1! on success (consistent with int2reverse_hex) */
311 inline static int reverse_hex2int( char *c, int len, unsigned int* res)
312 {
313         char *pc;
314         char mychar;
315
316         *res=0;
317         for (pc=c+len-1; len>0; pc--, len--) {
318                 *res <<= 4 ;
319                 mychar=*pc;
320                 if ( mychar >='0' && mychar <='9') *res+=mychar -'0';
321                 else if (mychar >='a' && mychar <='f') *res+=mychar -'a'+10;
322                 else if (mychar  >='A' && mychar <='F') *res+=mychar -'A'+10;
323                 else return -1;
324         }
325         return 1;
326 }
327
328 inline static int int2reverse_hex( char **c, int *size, unsigned int nr )
329 {
330         unsigned short digit;
331
332         if (*size && nr==0) {
333                 **c = '0';
334                 (*c)++;
335                 (*size)--;
336                 return 1;
337         }
338
339         while (*size && nr ) {
340                 digit = nr & 0xf ;
341                 **c= digit >= 10 ? digit + 'a' - 10 : digit + '0';
342                 nr >>= 4;
343                 (*c)++;
344                 (*size)--;
345         }
346         return nr ? -1 /* number not processed; too little space */ : 1;
347 }
348
349 /* double output length assumed ; does NOT zero-terminate */
350 inline static int string2hex( 
351         /* input */ unsigned char *str, int len,
352         /* output */ char *hex )
353 {
354         int orig_len;
355
356         if (len==0) {
357                 *hex='0';
358                 return 1;
359         }
360
361         orig_len=len;
362         while ( len ) {
363
364                 *hex=fourbits2char[(*str) >> 4];
365                 hex++;
366                 *hex=fourbits2char[(*str) & 0xf];
367                 hex++;
368                 len--;
369                 str++;
370
371         }
372         return orig_len-len;
373 }
374
375 /* portable sleep in microseconds (no interrupt handling now) */
376
377 inline static void sleep_us( unsigned int nusecs )
378 {
379         struct timeval tval;
380         tval.tv_sec =nusecs/1000000;
381         tval.tv_usec=nusecs%1000000;
382         select(0, NULL, NULL, NULL, &tval );
383 }
384
385
386 /* portable determination of max_path */
387 inline static int pathmax()
388 {
389 #ifdef PATH_MAX
390         static int pathmax=PATH_MAX;
391 #else
392         static int pathmax=0;
393 #endif
394         if (pathmax==0) { /* init */
395                 pathmax=pathconf("/", _PC_PATH_MAX);
396                 pathmax=(pathmax<=0)?PATH_MAX_GUESS:pathmax+1;
397         }
398         return pathmax;
399 }
400
401 inline static int hex2int(char hex_digit)
402 {
403         if (hex_digit>='0' && hex_digit<='9')
404                 return hex_digit-'0';
405         if (hex_digit>='a' && hex_digit<='f')
406                 return hex_digit-'a'+10;
407         if (hex_digit>='A' && hex_digit<='F')
408                 return hex_digit-'A'+10;
409         /* no valid hex digit ... */
410         LOG(L_ERR, "ERROR: hex2int: '%c' is no hex char\n", hex_digit );
411         return -1;
412 }
413
414 /* Un-escape URI user  -- it takes a pointer to original user
415    str, as well as the new, unescaped one, which MUST have
416    an allocated buffer linked to the 'str' structure ;
417    (the buffer can be allocated with the same length as
418    the original string -- the output string is always
419    shorter (if escaped characters occur) or same-long
420    as the original one).
421
422    only printable characters are permitted
423
424         <0 is returned on an unescaping error, length of the
425         unescaped string otherwise
426 */
427 inline static int un_escape(str *user, str *new_user ) 
428 {
429         int i, j, value;
430         int hi, lo;
431
432         if( new_user==0 || new_user->s==0) {
433                 LOG(L_CRIT, "BUG: un_escape: called with invalid param\n");
434                 return -1;
435         }
436
437         new_user->len = 0;
438         j = 0;
439
440         for (i = 0; i < user->len; i++) {
441                 if (user->s[i] == '%') {
442                         if (i + 2 >= user->len) {
443                                 LOG(L_ERR, "ERROR: un_escape: escape sequence too short in"
444                                         " '%.*s' @ %d\n",
445                                         user->len, user->s, i );
446                                 goto error;
447                         }
448                         hi=hex2int(user->s[i + 1]);
449                         if (hi<0) {
450                                 LOG(L_ERR, "ERROR: un_escape: non-hex high digit in an escape sequence in"
451                                         " '%.*s' @ %d\n",
452                                         user->len, user->s, i+1 );
453                                 goto error;
454                         }
455                         lo=hex2int(user->s[i + 2]);
456                         if (lo<0) {
457                                 LOG(L_ERR, "ERROR: non-hex low digit in an escape sequence in "
458                                         "'%.*s' @ %d\n",
459                                         user->len, user->s, i+2 );
460                                 goto error;
461                         }
462                         value=(hi<<4)+lo;
463                         if (value < 32 || value > 126) {
464                                 LOG(L_ERR, "ERROR: non-ASCII escaped character in '%.*s' @ %d\n",
465                                         user->len, user->s, i );
466                                 goto error;
467                         }
468                         new_user->s[j] = value;
469                         i+=2; /* consume the two hex digits, for cycle will move to the next char */
470                 } else {
471                         new_user->s[j] = user->s[i];
472                 }
473         j++; /* good -- we translated another character */
474         }
475         new_user->len = j;
476         return j;
477
478 error:
479         new_user->len = j;
480         return -1;
481
482
483
484 /*
485  * Convert a string to lower case
486  */
487 static inline void strlower(str* _s)
488 {
489         int i;
490
491         for(i = 0; i < _s->len; i++) {
492                 _s->s[i] = tolower(_s->s[i]);
493         }
494 }
495
496
497 /*
498  * Convert a str into integer
499  */
500 static inline int str2int(str* _s, unsigned int* _r)
501 {
502         int i;
503         
504         *_r = 0;
505         for(i = 0; i < _s->len; i++) {
506                 if ((_s->s[i] >= '0') && (_s->s[i] <= '9')) {
507                         *_r *= 10;
508                         *_r += _s->s[i] - '0';
509                 } else {
510                         return -1;
511                 }
512         }
513         
514         return 0;
515 }
516
517 /* converts a username into uid:gid,
518  * returns -1 on error & 0 on success */
519 int user2uid(int* uid, int* gid, char* user);
520
521 /* converts a group name into a gid
522  * returns -1 on error, 0 on success */
523 int group2gid(int* gid, char* group);
524
525 /*
526  * Replacement of timegm (does not exists on all platforms
527  * Taken from 
528  * http://lists.samba.org/archive/samba-technical/2002-November/025737.html
529  */
530 time_t _timegm(struct tm* t);
531
532 /* Convert time_t value that is relative to local timezone to UTC */
533 time_t local2utc(time_t in);
534
535 /* Convert time_t value in UTC to to value relative to local time zone */
536 time_t utc2local(time_t in);
537
538 /*
539  * Return str as zero terminated string allocated
540  * using pkg_malloc
541  */
542 char* as_asciiz(str* s);
543
544
545 /* return system version (major.minor.minor2) as
546  *  (major<<16)|(minor)<<8|(minor2)
547  * (if some of them are missing, they are set to 0)
548  * if the parameters are not null they are set to the coresp. part */
549 unsigned int get_sys_version(int* major, int* minor, int* minor2);
550
551 #endif