Sat Nov 1 06:30:39 2008

Asterisk developer's documentation


utils.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Digium, Inc.
00005  *
00006  * See http://www.asterisk.org for more information about
00007  * the Asterisk project. Please do not directly contact
00008  * any of the maintainers of this project for assistance;
00009  * the project provides a web site, mailing lists and IRC
00010  * channels for your use.
00011  *
00012  * This program is free software, distributed under the terms of
00013  * the GNU General Public License Version 2. See the LICENSE file
00014  * at the top of the source tree.
00015  */
00016 
00017 /*! \file
00018  *
00019  * \brief Utility functions
00020  *
00021  * \note These are important for portability and security,
00022  * so please use them in favour of other routines.
00023  * Please consult the CODING GUIDELINES for more information.
00024  */
00025 
00026 #include <ctype.h>
00027 #include <string.h>
00028 #include <unistd.h>
00029 #include <stdlib.h>
00030 #include <errno.h>
00031 #include <stdarg.h>
00032 #include <stdio.h>
00033 #include <sys/types.h>
00034 #include <sys/socket.h>
00035 #include <netinet/in.h>
00036 #include <arpa/inet.h>
00037 
00038 #include "asterisk.h"
00039 
00040 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 56729 $")
00041 
00042 #define AST_API_MODULE
00043 #include "asterisk/lock.h"
00044 
00045 #include "asterisk/io.h"
00046 #include "asterisk/logger.h"
00047 #include "asterisk/md5.h"
00048 #include "asterisk/options.h"
00049 #include "asterisk/compat.h"
00050 
00051 #define AST_API_MODULE     /* ensure that inlinable API functions will be built in this module if required */
00052 #include "asterisk/strings.h"
00053 
00054 #define AST_API_MODULE     /* ensure that inlinable API functions will be built in this module if required */
00055 #include "asterisk/time.h"
00056 
00057 #define AST_API_MODULE     /* ensure that inlinable API functions will be built in this module if required */
00058 #include "asterisk/utils.h"
00059 
00060 static char base64[64];
00061 static char b2a[256];
00062 
00063 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__) || defined(__CYGWIN__)
00064 
00065 /* duh? ERANGE value copied from web... */
00066 #define ERANGE 34
00067 #undef gethostbyname
00068 
00069 AST_MUTEX_DEFINE_STATIC(__mutex);
00070 
00071 /* Recursive replacement for gethostbyname for BSD-based systems.  This
00072 routine is derived from code originally written and placed in the public 
00073 domain by Enzo Michelangeli <em@em.no-ip.com> */
00074 
00075 static int gethostbyname_r (const char *name, struct hostent *ret, char *buf,
00076             size_t buflen, struct hostent **result, 
00077             int *h_errnop) 
00078 {
00079    int hsave;
00080    struct hostent *ph;
00081    ast_mutex_lock(&__mutex); /* begin critical area */
00082    hsave = h_errno;
00083 
00084    ph = gethostbyname(name);
00085    *h_errnop = h_errno; /* copy h_errno to *h_herrnop */
00086    if (ph == NULL) {
00087       *result = NULL;
00088    } else {
00089       char **p, **q;
00090       char *pbuf;
00091       int nbytes=0;
00092       int naddr=0, naliases=0;
00093       /* determine if we have enough space in buf */
00094 
00095       /* count how many addresses */
00096       for (p = ph->h_addr_list; *p != 0; p++) {
00097          nbytes += ph->h_length; /* addresses */
00098          nbytes += sizeof(*p); /* pointers */
00099          naddr++;
00100       }
00101       nbytes += sizeof(*p); /* one more for the terminating NULL */
00102 
00103       /* count how many aliases, and total length of strings */
00104       for (p = ph->h_aliases; *p != 0; p++) {
00105          nbytes += (strlen(*p)+1); /* aliases */
00106          nbytes += sizeof(*p);  /* pointers */
00107          naliases++;
00108       }
00109       nbytes += sizeof(*p); /* one more for the terminating NULL */
00110 
00111       /* here nbytes is the number of bytes required in buffer */
00112       /* as a terminator must be there, the minimum value is ph->h_length */
00113       if(nbytes > buflen) {
00114          *result = NULL;
00115          ast_mutex_unlock(&__mutex); /* end critical area */
00116          return ERANGE; /* not enough space in buf!! */
00117       }
00118 
00119       /* There is enough space. Now we need to do a deep copy! */
00120       /* Allocation in buffer:
00121          from [0] to [(naddr-1) * sizeof(*p)]:
00122          pointers to addresses
00123          at [naddr * sizeof(*p)]:
00124          NULL
00125          from [(naddr+1) * sizeof(*p)] to [(naddr+naliases) * sizeof(*p)] :
00126          pointers to aliases
00127          at [(naddr+naliases+1) * sizeof(*p)]:
00128          NULL
00129          then naddr addresses (fixed length), and naliases aliases (asciiz).
00130       */
00131 
00132       *ret = *ph;   /* copy whole structure (not its address!) */
00133 
00134       /* copy addresses */
00135       q = (char **)buf; /* pointer to pointers area (type: char **) */
00136       ret->h_addr_list = q; /* update pointer to address list */
00137       pbuf = buf + ((naddr+naliases+2)*sizeof(*p)); /* skip that area */
00138       for (p = ph->h_addr_list; *p != 0; p++) {
00139          memcpy(pbuf, *p, ph->h_length); /* copy address bytes */
00140          *q++ = pbuf; /* the pointer is the one inside buf... */
00141          pbuf += ph->h_length; /* advance pbuf */
00142       }
00143       *q++ = NULL; /* address list terminator */
00144 
00145       /* copy aliases */
00146       ret->h_aliases = q; /* update pointer to aliases list */
00147       for (p = ph->h_aliases; *p != 0; p++) {
00148          strcpy(pbuf, *p); /* copy alias strings */
00149          *q++ = pbuf; /* the pointer is the one inside buf... */
00150          pbuf += strlen(*p); /* advance pbuf */
00151          *pbuf++ = 0; /* string terminator */
00152       }
00153       *q++ = NULL; /* terminator */
00154 
00155       strcpy(pbuf, ph->h_name); /* copy alias strings */
00156       ret->h_name = pbuf;
00157       pbuf += strlen(ph->h_name); /* advance pbuf */
00158       *pbuf++ = 0; /* string terminator */
00159 
00160       *result = ret;  /* and let *result point to structure */
00161 
00162    }
00163    h_errno = hsave;  /* restore h_errno */
00164    ast_mutex_unlock(&__mutex); /* end critical area */
00165 
00166    return (*result == NULL); /* return 0 on success, non-zero on error */
00167 }
00168 
00169 
00170 #endif
00171 
00172 /*! \brief Re-entrant (thread safe) version of gethostbyname that replaces the 
00173    standard gethostbyname (which is not thread safe)
00174 */
00175 struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp)
00176 {
00177    int res;
00178    int herrno;
00179    int dots=0;
00180    const char *s;
00181    struct hostent *result = NULL;
00182    /* Although it is perfectly legitimate to lookup a pure integer, for
00183       the sake of the sanity of people who like to name their peers as
00184       integers, we break with tradition and refuse to look up a
00185       pure integer */
00186    s = host;
00187    res = 0;
00188    while(s && *s) {
00189       if (*s == '.')
00190          dots++;
00191       else if (!isdigit(*s))
00192          break;
00193       s++;
00194    }
00195    if (!s || !*s) {
00196       /* Forge a reply for IP's to avoid octal IP's being interpreted as octal */
00197       if (dots != 3)
00198          return NULL;
00199       memset(hp, 0, sizeof(struct ast_hostent));
00200       hp->hp.h_addrtype = AF_INET;
00201       hp->hp.h_addr_list = (void *) hp->buf;
00202       hp->hp.h_addr = hp->buf + sizeof(void *);
00203       if (inet_pton(AF_INET, host, hp->hp.h_addr) > 0)
00204          return &hp->hp;
00205       return NULL;
00206       
00207    }
00208 #ifdef SOLARIS
00209    result = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &herrno);
00210 
00211    if (!result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
00212       return NULL;
00213 #else
00214    res = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &result, &herrno);
00215 
00216    if (res || !result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
00217       return NULL;
00218 #endif
00219    return &hp->hp;
00220 }
00221 
00222 
00223 
00224 AST_MUTEX_DEFINE_STATIC(test_lock);
00225 AST_MUTEX_DEFINE_STATIC(test_lock2);
00226 static pthread_t test_thread; 
00227 static int lock_count = 0;
00228 static int test_errors = 0;
00229 
00230 /*! \brief This is a regression test for recursive mutexes.
00231    test_for_thread_safety() will return 0 if recursive mutex locks are
00232    working properly, and non-zero if they are not working properly. */
00233 static void *test_thread_body(void *data) 
00234 { 
00235    ast_mutex_lock(&test_lock);
00236    lock_count += 10;
00237    if (lock_count != 10) 
00238       test_errors++;
00239    ast_mutex_lock(&test_lock);
00240    lock_count += 10;
00241    if (lock_count != 20) 
00242       test_errors++;
00243    ast_mutex_lock(&test_lock2);
00244    ast_mutex_unlock(&test_lock);
00245    lock_count -= 10;
00246    if (lock_count != 10) 
00247       test_errors++;
00248    ast_mutex_unlock(&test_lock);
00249    lock_count -= 10;
00250    ast_mutex_unlock(&test_lock2);
00251    if (lock_count != 0) 
00252       test_errors++;
00253    return NULL;
00254 } 
00255 
00256 int test_for_thread_safety(void)
00257 { 
00258    ast_mutex_lock(&test_lock2);
00259    ast_mutex_lock(&test_lock);
00260    lock_count += 1;
00261    ast_mutex_lock(&test_lock);
00262    lock_count += 1;
00263    ast_pthread_create(&test_thread, NULL, test_thread_body, NULL); 
00264    usleep(100);
00265    if (lock_count != 2) 
00266       test_errors++;
00267    ast_mutex_unlock(&test_lock);
00268    lock_count -= 1;
00269    usleep(100); 
00270    if (lock_count != 1) 
00271       test_errors++;
00272    ast_mutex_unlock(&test_lock);
00273    lock_count -= 1;
00274    if (lock_count != 0) 
00275       test_errors++;
00276    ast_mutex_unlock(&test_lock2);
00277    usleep(100);
00278    if (lock_count != 0) 
00279       test_errors++;
00280    pthread_join(test_thread, NULL);
00281    return(test_errors);          /* return 0 on success. */
00282 }
00283 
00284 /*! \brief ast_md5_hash: Produce 16 char MD5 hash of value. ---*/
00285 void ast_md5_hash(char *output, char *input)
00286 {
00287    struct MD5Context md5;
00288    unsigned char digest[16];
00289    char *ptr;
00290    int x;
00291 
00292    MD5Init(&md5);
00293    MD5Update(&md5, (unsigned char *)input, strlen(input));
00294    MD5Final(digest, &md5);
00295    ptr = output;
00296    for (x=0; x<16; x++)
00297       ptr += sprintf(ptr, "%2.2x", digest[x]);
00298 }
00299 
00300 int ast_base64decode(unsigned char *dst, const char *src, int max)
00301 {
00302    int cnt = 0;
00303    unsigned int byte = 0;
00304    unsigned int bits = 0;
00305    int incnt = 0;
00306 #if 0
00307    unsigned char *odst = dst;
00308 #endif
00309    while(*src && (cnt < max)) {
00310       /* Shift in 6 bits of input */
00311       byte <<= 6;
00312       byte |= (b2a[(int)(*src)]) & 0x3f;
00313       bits += 6;
00314 #if 0
00315       printf("Add: %c %s\n", *src, binary(b2a[(int)(*src)] & 0x3f, 6));
00316 #endif
00317       src++;
00318       incnt++;
00319       /* If we have at least 8 bits left over, take that character 
00320          off the top */
00321       if (bits >= 8)  {
00322          bits -= 8;
00323          *dst = (byte >> bits) & 0xff;
00324 #if 0
00325          printf("Remove: %02x %s\n", *dst, binary(*dst, 8));
00326 #endif
00327          dst++;
00328          cnt++;
00329       }
00330    }
00331 #if 0
00332    dump(odst, cnt);
00333 #endif
00334    /* Dont worry about left over bits, they're extra anyway */
00335    return cnt;
00336 }
00337 
00338 int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
00339 {
00340    int cnt = 0;
00341    unsigned int byte = 0;
00342    int bits = 0;
00343    int index;
00344    int cntin = 0;
00345 #if 0
00346    char *odst = dst;
00347    dump(src, srclen);
00348 #endif
00349    /* Reserve one bit for end */
00350    max--;
00351    while((cntin < srclen) && (cnt < max)) {
00352       byte <<= 8;
00353 #if 0
00354       printf("Add: %02x %s\n", *src, binary(*src, 8));
00355 #endif
00356       byte |= *(src++);
00357       bits += 8;
00358       cntin++;
00359       while((bits >= 6) && (cnt < max)) {
00360          bits -= 6;
00361          /* We want only the top */
00362          index = (byte >> bits) & 0x3f;
00363          *dst = base64[index];
00364 #if 0
00365          printf("Remove: %c %s\n", *dst, binary(index, 6));
00366 #endif
00367          dst++;
00368          cnt++;
00369       }
00370    }
00371    if (bits && (cnt < max)) {
00372       /* Add one last character for the remaining bits, 
00373          padding the rest with 0 */
00374       byte <<= (6 - bits);
00375       index = (byte) & 0x3f;
00376       *(dst++) = base64[index];
00377       cnt++;
00378    }
00379    *dst = '\0';
00380    return cnt;
00381 }
00382 
00383 static void base64_init(void)
00384 {
00385    int x;
00386    memset(b2a, -1, sizeof(b2a));
00387    /* Initialize base-64 Conversion table */
00388    for (x=0;x<26;x++) {
00389       /* A-Z */
00390       base64[x] = 'A' + x;
00391       b2a['A' + x] = x;
00392       /* a-z */
00393       base64[x + 26] = 'a' + x;
00394       b2a['a' + x] = x + 26;
00395       /* 0-9 */
00396       if (x < 10) {
00397          base64[x + 52] = '0' + x;
00398          b2a['0' + x] = x + 52;
00399       }
00400    }
00401    base64[62] = '+';
00402    base64[63] = '/';
00403    b2a[(int)'+'] = 62;
00404    b2a[(int)'/'] = 63;
00405 }
00406 
00407 /*! \brief  ast_uri_encode: Turn text string to URI-encoded %XX version ---*/
00408 /*    At this point, we're converting from ISO-8859-x (8-bit), not UTF8
00409    as in the SIP protocol spec 
00410    If doreserved == 1 we will convert reserved characters also.
00411    RFC 2396, section 2.4
00412    outbuf needs to have more memory allocated than the instring
00413    to have room for the expansion. Every char that is converted
00414    is replaced by three ASCII characters.
00415 
00416    Note: The doreserved option is needed for replaces header in
00417    SIP transfers.
00418 */
00419 char *ast_uri_encode(char *string, char *outbuf, int buflen, int doreserved) 
00420 {
00421    char *reserved = ";/?:@&=+$, ";  /* Reserved chars */
00422 
00423    char *ptr  = string; /* Start with the string */
00424    char *out = NULL;
00425    char *buf = NULL;
00426 
00427    strncpy(outbuf, string, buflen);
00428 
00429    /* If there's no characters to convert, just go through and don't do anything */
00430    while (*ptr) {
00431       if (((unsigned char) *ptr) > 127 || (doreserved && strchr(reserved, *ptr)) ) {
00432          /* Oops, we need to start working here */
00433          if (!buf) {
00434             buf = outbuf;
00435             out = buf + (ptr - string) ;  /* Set output ptr */
00436          }
00437          out += sprintf(out, "%%%02x", (unsigned char) *ptr);
00438       } else if (buf) {
00439          *out = *ptr;   /* Continue copying the string */
00440          out++;
00441       } 
00442       ptr++;
00443    }
00444    if (buf)
00445       *out = '\0';
00446    return outbuf;
00447 }
00448 
00449 /*! \brief  ast_uri_decode: Decode SIP URI, URN, URL (overwrite the string)  ---*/
00450 void ast_uri_decode(char *s) 
00451 {
00452    char *o;
00453    unsigned int tmp;
00454 
00455    for (o = s; *s; s++, o++) {
00456       if (*s == '%' && strlen(s) > 2 && sscanf(s + 1, "%2x", &tmp) == 1) {
00457          /* have '%', two chars and correct parsing */
00458          *o = tmp;
00459          s += 2;  /* Will be incremented once more when we break out */
00460       } else /* all other cases, just copy */
00461          *o = *s;
00462    }
00463    *o = '\0';
00464 }
00465 
00466 /*! \brief  ast_inet_ntoa: Recursive thread safe replacement of inet_ntoa */
00467 const char *ast_inet_ntoa(char *buf, int bufsiz, struct in_addr ia)
00468 {
00469    return inet_ntop(AF_INET, &ia, buf, bufsiz);
00470 }
00471 
00472 int ast_utils_init(void)
00473 {
00474    base64_init();
00475    return 0;
00476 }
00477 
00478 #ifndef __linux__
00479 #undef pthread_create /* For ast_pthread_create function only */
00480 #endif /* !__linux__ */
00481 
00482 int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *data, size_t stacksize)
00483 {
00484    pthread_attr_t lattr;
00485    if (!attr) {
00486       pthread_attr_init(&lattr);
00487       attr = &lattr;
00488    }
00489 #ifdef __linux__
00490    /* On Linux, pthread_attr_init() defaults to PTHREAD_EXPLICIT_SCHED,
00491       which is kind of useless. Change this here to
00492       PTHREAD_INHERIT_SCHED; that way the -p option to set realtime
00493       priority will propagate down to new threads by default.
00494       This does mean that callers cannot set a different priority using
00495       PTHREAD_EXPLICIT_SCHED in the attr argument; instead they must set
00496       the priority afterwards with pthread_setschedparam(). */
00497    errno = pthread_attr_setinheritsched(attr, PTHREAD_INHERIT_SCHED);
00498    if (errno)
00499       ast_log(LOG_WARNING, "pthread_attr_setinheritsched returned non-zero: %s\n", strerror(errno));
00500 #endif
00501 
00502    if (!stacksize)
00503       stacksize = AST_STACKSIZE;
00504    errno = pthread_attr_setstacksize(attr, stacksize);
00505    if (errno)
00506       ast_log(LOG_WARNING, "pthread_attr_setstacksize returned non-zero: %s\n", strerror(errno));
00507    return pthread_create(thread, attr, start_routine, data); /* We're in ast_pthread_create, so it's okay */
00508 }
00509 
00510 int ast_wait_for_input(int fd, int ms)
00511 {
00512    struct pollfd pfd[1];
00513    memset(pfd, 0, sizeof(pfd));
00514    pfd[0].fd = fd;
00515    pfd[0].events = POLLIN|POLLPRI;
00516    return poll(pfd, 1, ms);
00517 }
00518 
00519 char *ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
00520 {
00521    char *e;
00522    char *q;
00523 
00524    s = ast_strip(s);
00525    if ((q = strchr(beg_quotes, *s)) && *q != '\0') {
00526       e = s + strlen(s) - 1;
00527       if (*e == *(end_quotes + (q - beg_quotes))) {
00528          s++;
00529          *e = '\0';
00530       }
00531    }
00532 
00533    return s;
00534 }
00535 
00536 int ast_build_string_va(char **buffer, size_t *space, const char *fmt, va_list ap)
00537 {
00538    int result;
00539 
00540    if (!buffer || !*buffer || !space || !*space)
00541       return -1;
00542 
00543    result = vsnprintf(*buffer, *space, fmt, ap);
00544 
00545    if (result < 0)
00546       return -1;
00547    else if (result > *space)
00548       result = *space;
00549 
00550    *buffer += result;
00551    *space -= result;
00552    return 0;
00553 }
00554 
00555 int ast_build_string(char **buffer, size_t *space, const char *fmt, ...)
00556 {
00557    va_list ap;
00558    int result;
00559 
00560    va_start(ap, fmt);
00561    result = ast_build_string_va(buffer, space, fmt, ap);
00562    va_end(ap);
00563 
00564    return result;
00565 }
00566 
00567 int ast_true(const char *s)
00568 {
00569    if (ast_strlen_zero(s))
00570       return 0;
00571 
00572    /* Determine if this is a true value */
00573    if (!strcasecmp(s, "yes") ||
00574        !strcasecmp(s, "true") ||
00575        !strcasecmp(s, "y") ||
00576        !strcasecmp(s, "t") ||
00577        !strcasecmp(s, "1") ||
00578        !strcasecmp(s, "on"))
00579       return -1;
00580 
00581    return 0;
00582 }
00583 
00584 int ast_false(const char *s)
00585 {
00586    if (ast_strlen_zero(s))
00587       return 0;
00588 
00589    /* Determine if this is a false value */
00590    if (!strcasecmp(s, "no") ||
00591        !strcasecmp(s, "false") ||
00592        !strcasecmp(s, "n") ||
00593        !strcasecmp(s, "f") ||
00594        !strcasecmp(s, "0") ||
00595        !strcasecmp(s, "off"))
00596       return -1;
00597 
00598    return 0;
00599 }
00600 
00601 #define ONE_MILLION  1000000
00602 /*
00603  * put timeval in a valid range. usec is 0..999999
00604  * negative values are not allowed and truncated.
00605  */
00606 static struct timeval tvfix(struct timeval a)
00607 {
00608    if (a.tv_usec >= ONE_MILLION) {
00609       ast_log(LOG_WARNING, "warning too large timestamp %ld.%ld\n",
00610          a.tv_sec, (long int) a.tv_usec);
00611       a.tv_sec += a.tv_usec / ONE_MILLION;
00612       a.tv_usec %= ONE_MILLION;
00613    } else if (a.tv_usec < 0) {
00614       ast_log(LOG_WARNING, "warning negative timestamp %ld.%ld\n",
00615          a.tv_sec, (long int) a.tv_usec);
00616       a.tv_usec = 0;
00617    }
00618    return a;
00619 }
00620 
00621 struct timeval ast_tvadd(struct timeval a, struct timeval b)
00622 {
00623    /* consistency checks to guarantee usec in 0..999999 */
00624    a = tvfix(a);
00625    b = tvfix(b);
00626    a.tv_sec += b.tv_sec;
00627    a.tv_usec += b.tv_usec;
00628    if (a.tv_usec >= ONE_MILLION) {
00629       a.tv_sec++;
00630       a.tv_usec -= ONE_MILLION;
00631    }
00632    return a;
00633 }
00634 
00635 struct timeval ast_tvsub(struct timeval a, struct timeval b)
00636 {
00637    /* consistency checks to guarantee usec in 0..999999 */
00638    a = tvfix(a);
00639    b = tvfix(b);
00640    a.tv_sec -= b.tv_sec;
00641    a.tv_usec -= b.tv_usec;
00642    if (a.tv_usec < 0) {
00643       a.tv_sec-- ;
00644       a.tv_usec += ONE_MILLION;
00645    }
00646    return a;
00647 }
00648 #undef ONE_MILLION
00649 
00650 #ifndef HAVE_STRCASESTR
00651 static char *upper(const char *orig, char *buf, int bufsize)
00652 {
00653    int i = 0;
00654 
00655    while (i < (bufsize - 1) && orig[i]) {
00656       buf[i] = toupper(orig[i]);
00657       i++;
00658    }
00659 
00660    buf[i] = '\0';
00661 
00662    return buf;
00663 }
00664 
00665 char *strcasestr(const char *haystack, const char *needle)
00666 {
00667    char *u1, *u2;
00668    int u1len = strlen(haystack) + 1, u2len = strlen(needle) + 1;
00669 
00670    u1 = alloca(u1len);
00671    u2 = alloca(u2len);
00672    if (u1 && u2) {
00673       char *offset;
00674       if (u2len > u1len) {
00675          /* Needle bigger than haystack */
00676          return NULL;
00677       }
00678       offset = strstr(upper(haystack, u1, u1len), upper(needle, u2, u2len));
00679       if (offset) {
00680          /* Return the offset into the original string */
00681          return ((char *)((unsigned long)haystack + (unsigned long)(offset - u1)));
00682       } else {
00683          return NULL;
00684       }
00685    } else {
00686       ast_log(LOG_ERROR, "Out of memory\n");
00687       return NULL;
00688    }
00689 }
00690 #endif /* !HAVE_STRCASESTR */
00691 
00692 #ifndef HAVE_STRNLEN
00693 size_t strnlen(const char *s, size_t n)
00694 {
00695    size_t len;
00696 
00697    for (len=0; len < n; len++)
00698       if (s[len] == '\0')
00699          break;
00700 
00701    return len;
00702 }
00703 #endif /* !HAVE_STRNLEN */
00704 
00705 #if !defined(HAVE_STRNDUP) && !defined(__AST_DEBUG_MALLOC)
00706 char *strndup(const char *s, size_t n)
00707 {
00708    size_t len = strnlen(s, n);
00709    char *new = malloc(len + 1);
00710 
00711    if (!new)
00712       return NULL;
00713 
00714    new[len] = '\0';
00715    return memcpy(new, s, len);
00716 }
00717 #endif /* !defined(HAVE_STRNDUP) && !defined(__AST_DEBUG_MALLOC) */
00718 
00719 #if !defined(HAVE_VASPRINTF) && !defined(__AST_DEBUG_MALLOC)
00720 int vasprintf(char **strp, const char *fmt, va_list ap)
00721 {
00722    int size;
00723    va_list ap2;
00724    char s;
00725 
00726    *strp = NULL;
00727    va_copy(ap2, ap);
00728    size = vsnprintf(&s, 1, fmt, ap2);
00729    va_end(ap2);
00730    *strp = malloc(size + 1);
00731    if (!*strp)
00732       return -1;
00733    vsnprintf(*strp, size + 1, fmt, ap);
00734 
00735    return size;
00736 }
00737 #endif /* !defined(HAVE_VASPRINTF) && !defined(__AST_DEBUG_MALLOC) */
00738 
00739 #ifndef HAVE_STRTOQ
00740 #ifndef LONG_MIN
00741 #define LONG_MIN        (-9223372036854775807L-1L)
00742                                     /* min value of a "long int" */
00743 #endif
00744 #ifndef LONG_MAX
00745 #define LONG_MAX        9223372036854775807L
00746                                     /* max value of a "long int" */
00747 #endif
00748 
00749 /*
00750  * Convert a string to a quad integer.
00751  *
00752  * Ignores `locale' stuff.  Assumes that the upper and lower case
00753  * alphabets and digits are each contiguous.
00754  */
00755 uint64_t strtoq(const char *nptr, char **endptr, int base)
00756 {
00757     const char *s;
00758     uint64_t acc;
00759     unsigned char c;
00760     uint64_t qbase, cutoff;
00761     int neg, any, cutlim;
00762 
00763     /*
00764      * Skip white space and pick up leading +/- sign if any.
00765      * If base is 0, allow 0x for hex and 0 for octal, else
00766      * assume decimal; if base is already 16, allow 0x.
00767      */
00768     s = nptr;
00769     do {
00770             c = *s++;
00771     } while (isspace(c));
00772     if (c == '-') {
00773             neg = 1;
00774             c = *s++;
00775     } else {
00776             neg = 0;
00777             if (c == '+')
00778                     c = *s++;
00779     }
00780     if ((base == 0 || base == 16) &&
00781         c == '\0' && (*s == 'x' || *s == 'X')) {
00782             c = s[1];
00783             s += 2;
00784             base = 16;
00785     }
00786     if (base == 0)
00787             base = c == '\0' ? 8 : 10;
00788 
00789     /*
00790      * Compute the cutoff value between legal numbers and illegal
00791      * numbers.  That is the largest legal value, divided by the
00792      * base.  An input number that is greater than this value, if
00793      * followed by a legal input character, is too big.  One that
00794      * is equal to this value may be valid or not; the limit
00795      * between valid and invalid numbers is then based on the last
00796      * digit.  For instance, if the range for quads is
00797      * [-9223372036854775808..9223372036854775807] and the input base
00798      * is 10, cutoff will be set to 922337203685477580 and cutlim to
00799      * either 7 (neg==0) or 8 (neg==1), meaning that if we have
00800      * accumulated a value > 922337203685477580, or equal but the
00801      * next digit is > 7 (or 8), the number is too big, and we will
00802      * return a range error.
00803      *
00804      * Set any if any `digits' consumed; make it negative to indicate
00805      * overflow.
00806      */
00807     qbase = (unsigned)base;
00808     cutoff = neg ? (uint64_t)-(LONG_MIN + LONG_MAX) + LONG_MAX : LONG_MAX;
00809     cutlim = cutoff % qbase;
00810     cutoff /= qbase;
00811     for (acc = 0, any = 0;; c = *s++) {
00812             if (!isascii(c))
00813                     break;
00814             if (isdigit(c))
00815                     c -= '\0';
00816             else if (isalpha(c))
00817                     c -= isupper(c) ? 'A' - 10 : 'a' - 10;
00818             else
00819                     break;
00820             if (c >= base)
00821                     break;
00822             if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
00823                     any = -1;
00824             else {
00825                     any = 1;
00826                     acc *= qbase;
00827                     acc += c;
00828             }
00829     }
00830     if (any < 0) {
00831             acc = neg ? LONG_MIN : LONG_MAX;
00832     } else if (neg)
00833             acc = -acc;
00834     if (endptr != 0)
00835             *((const char **)endptr) = any ? s - 1 : nptr;
00836     return acc;
00837 }
00838 #endif /* !HAVE_STRTOQ */
00839 
00840 #ifndef HAVE_GETLOADAVG
00841 #ifdef linux
00842 /* Alternative method of getting load avg on Linux only */
00843 int getloadavg(double *list, int nelem)
00844 {
00845    FILE *LOADAVG;
00846    double avg[3] = { 0.0, 0.0, 0.0 };
00847    int i, res = -1;
00848 
00849    if ((LOADAVG = fopen("/proc/loadavg", "r"))) {
00850       fscanf(LOADAVG, "%lf %lf %lf", &avg[0], &avg[1], &avg[2]);
00851       res = 0;
00852       fclose(LOADAVG);
00853    }
00854 
00855    for (i = 0; (i < nelem) && (i < 3); i++) {
00856       list[i] = avg[i];
00857    }
00858 
00859    return res;
00860 }
00861 #else /* !linux */
00862 /* Return something that won't cancel the call, but still return -1, in case
00863  * we correct the implementation to check return value */
00864 int getloadavg(double *list, int nelem)
00865 {
00866    int i;
00867 
00868    for (i = 0; i < nelem; i++) {
00869       list[i] = 0.1;
00870    }
00871    return -1;
00872 }
00873 #endif /* linux */
00874 #endif /* !defined(_BSD_SOURCE) */
00875 
00876 char *ast_process_quotes_and_slashes(char *start, char find, char replace_with)
00877 {
00878    char *dataPut = start;
00879    int inEscape = 0;
00880    int inQuotes = 0;
00881 
00882    for (; *start; start++) {
00883       if (inEscape) {
00884          *dataPut++ = *start;       /* Always goes verbatim */
00885          inEscape = 0;
00886          } else {
00887          if (*start == '\\') {
00888             inEscape = 1;      /* Do not copy \ into the data */
00889          } else if (*start == '\'') {
00890             inQuotes = 1-inQuotes;   /* Do not copy ' into the data */
00891          } else {
00892             /* Replace , with |, unless in quotes */
00893             *dataPut++ = inQuotes ? *start : ((*start==find) ? replace_with : *start);
00894          }
00895       }
00896    }
00897    if (start != dataPut)
00898       *dataPut = 0;
00899    return dataPut;
00900 }
00901 
00902 void ast_enable_packet_fragmentation(int sock)
00903 {
00904 #ifdef __linux__
00905    int val = IP_PMTUDISC_DONT;
00906    
00907    if (setsockopt(sock, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val)))
00908       ast_log(LOG_WARNING, "Unable to disable PMTU discovery. Large UDP packets may fail to be delivered when sent from this socket.\n");
00909 #endif
00910 }
00911 
00912 AST_MUTEX_DEFINE_STATIC(fetchadd_m); /* used for all fetc&add ops */
00913 
00914 int ast_atomic_fetchadd_int_slow(volatile int *p, int v)
00915 {
00916         int ret;
00917         ast_mutex_lock(&fetchadd_m);
00918         ret = *p;
00919         *p += v;
00920         ast_mutex_unlock(&fetchadd_m);
00921         return ret;
00922 }

Generated on Sat Nov 1 06:30:39 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.1