Sat Sep 16 07:28:10 2006

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

Generated on Sat Sep 16 07:28:10 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7