Terry found this problem with running the expr2 parser on OSX. Make the #defines...
[asterisk/asterisk.git] / main / strcompat.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * See http://www.asterisk.org for more information about
7  * the Asterisk project. Please do not directly contact
8  * any of the maintainers of this project for assistance;
9  * the project provides a web site, mailing lists and IRC
10  * channels for your use.
11  *
12  * This program is free software, distributed under the terms of
13  * the GNU General Public License Version 2. See the LICENSE file
14  * at the top of the source tree.
15  */
16
17 /*! \file
18  *
19  * \brief Compatibility functions for strsep and strtoq missing on Solaris 
20  */
21
22 #include "asterisk.h"
23
24 #include <ctype.h>
25
26 #ifndef HAVE_STRSEP
27 char *strsep(char **str, const char *delims)
28 {
29     char *token;
30
31     if (!*str) {
32         /* No more tokens */
33         return NULL;
34     }
35
36     token = *str;
37     while (**str != '\0') {
38         if (strchr(delims, **str)) {
39             **str = '\0';
40             (*str)++;
41             return token;
42         }
43         (*str)++;
44     }
45
46     /* There is no other token */
47     *str = NULL;
48
49     return token;
50 }
51 #endif
52
53 #ifndef HAVE_SETENV
54 int setenv(const char *name, const char *value, int overwrite)
55 {
56         unsigned char *buf;
57         int buflen;
58
59         buflen = strlen(name) + strlen(value) + 2;
60         buf = alloca(buflen);
61
62         if (!overwrite && getenv(name))
63                 return 0;
64
65         snprintf(buf, buflen, "%s=%s", name, value);
66
67         return putenv(buf);
68 }
69 #endif
70
71 #ifndef HAVE_UNSETENV
72 int unsetenv(const char *name)
73 {
74         return setenv(name, "", 0);
75 }
76 #endif
77
78 #ifndef HAVE_STRCASESTR
79 static char *upper(const char *orig, char *buf, int bufsize)
80 {
81         int i = 0;
82
83         while (i < (bufsize - 1) && orig[i]) {
84                 buf[i] = toupper(orig[i]);
85                 i++;
86         }
87
88         buf[i] = '\0';
89
90         return buf;
91 }
92
93 char *strcasestr(const char *haystack, const char *needle)
94 {
95         char *u1, *u2;
96         int u1len = strlen(haystack) + 1, u2len = strlen(needle) + 1;
97
98         u1 = alloca(u1len);
99         u2 = alloca(u2len);
100         if (u1 && u2) {
101                 char *offset;
102                 if (u2len > u1len) {
103                         /* Needle bigger than haystack */
104                         return NULL;
105                 }
106                 offset = strstr(upper(haystack, u1, u1len), upper(needle, u2, u2len));
107                 if (offset) {
108                         /* Return the offset into the original string */
109                         return ((char *)((unsigned long)haystack + (unsigned long)(offset - u1)));
110                 } else {
111                         return NULL;
112                 }
113         } else {
114                 return NULL;
115         }
116 }
117 #endif /* !HAVE_STRCASESTR */
118
119 #ifndef HAVE_STRNLEN
120 size_t strnlen(const char *s, size_t n)
121 {
122         size_t len;
123
124         for (len = 0; len < n; len++)
125                 if (s[len] == '\0')
126                         break;
127
128         return len;
129 }
130 #endif /* !HAVE_STRNLEN */
131
132 #if !defined(HAVE_STRNDUP) && !defined(__AST_DEBUG_MALLOC)
133 char *strndup(const char *s, size_t n)
134 {
135         size_t len = strnlen(s, n);
136         char *new = malloc(len + 1);
137
138         if (!new)
139                 return NULL;
140
141         new[len] = '\0';
142         return memcpy(new, s, len);
143 }
144 #endif /* !defined(HAVE_STRNDUP) && !defined(__AST_DEBUG_MALLOC) */
145
146 #if !defined(HAVE_VASPRINTF) && !defined(__AST_DEBUG_MALLOC)
147 int vasprintf(char **strp, const char *fmt, va_list ap)
148 {
149         int size;
150         va_list ap2;
151         char s;
152
153         *strp = NULL;
154         va_copy(ap2, ap);
155         size = vsnprintf(&s, 1, fmt, ap2);
156         va_end(ap2);
157         *strp = malloc(size + 1);
158         if (!*strp)
159                 return -1;
160         vsnprintf(*strp, size + 1, fmt, ap);
161
162         return size;
163 }
164 #endif /* !defined(HAVE_VASPRINTF) && !defined(__AST_DEBUG_MALLOC) */
165
166 /*
167  * Based on Code from bsd-asprintf from OpenSSH
168  * Copyright (c) 2004 Darren Tucker.
169  *
170  * Based originally on asprintf.c from OpenBSD:
171  * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
172  *
173  * Permission to use, copy, modify, and distribute this software for any
174  * purpose with or without fee is hereby granted, provided that the above
175  * copyright notice and this permission notice appear in all copies.
176  *
177  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
178  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
179  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
180  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
181  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
182  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
183  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
184  */
185 #if !defined(HAVE_ASPRINTF) && !defined(__AST_DEBUG_MALLOC) 
186 int asprintf(char **str, const char *fmt, ...)
187 {
188         va_list ap;
189         int ret;
190
191         *str = NULL;
192         va_start(ap, fmt);
193         ret = vasprintf(str, fmt, ap);
194         va_end(ap);
195
196         return ret;
197 }
198 #endif /* !defined(HAVE_ASPRINTF) && !defined(__AST_DEBUG_MALLOC) */
199
200 #ifndef HAVE_STRTOQ
201 #ifndef LONG_MIN
202 #define LONG_MIN        (-9223372036854775807L-1L)
203                                          /* min value of a "long int" */
204 #endif
205 #ifndef LONG_MAX
206 #define LONG_MAX        9223372036854775807L
207                                          /* max value of a "long int" */
208 #endif
209
210 /*! \brief
211  * Convert a string to a quad integer.
212  *
213  * \note Ignores `locale' stuff.  Assumes that the upper and lower case
214  * alphabets and digits are each contiguous.
215  */
216 uint64_t strtoq(const char *nptr, char **endptr, int base)
217 {
218          const char *s;
219          uint64_t acc;
220          unsigned char c;
221          uint64_t qbase, cutoff;
222          int neg, any, cutlim;
223
224          /*
225           * Skip white space and pick up leading +/- sign if any.
226           * If base is 0, allow 0x for hex and 0 for octal, else
227           * assume decimal; if base is already 16, allow 0x.
228           */
229          s = nptr;
230          do {
231                  c = *s++;
232          } while (isspace(c));
233          if (c == '-') {
234                  neg = 1;
235                  c = *s++;
236          } else {
237                  neg = 0;
238                  if (c == '+')
239                          c = *s++;
240          }
241          if ((base == 0 || base == 16) &&
242              c == '\0' && (*s == 'x' || *s == 'X')) {
243                  c = s[1];
244                  s += 2;
245                  base = 16;
246          }
247          if (base == 0)
248                  base = c == '\0' ? 8 : 10;
249
250          /*
251           * Compute the cutoff value between legal numbers and illegal
252           * numbers.  That is the largest legal value, divided by the
253           * base.  An input number that is greater than this value, if
254           * followed by a legal input character, is too big.  One that
255           * is equal to this value may be valid or not; the limit
256           * between valid and invalid numbers is then based on the last
257           * digit.  For instance, if the range for quads is
258           * [-9223372036854775808..9223372036854775807] and the input base
259           * is 10, cutoff will be set to 922337203685477580 and cutlim to
260           * either 7 (neg==0) or 8 (neg==1), meaning that if we have
261           * accumulated a value > 922337203685477580, or equal but the
262           * next digit is > 7 (or 8), the number is too big, and we will
263           * return a range error.
264           *
265           * Set any if any `digits' consumed; make it negative to indicate
266           * overflow.
267           */
268          qbase = (unsigned)base;
269          cutoff = neg ? (uint64_t)-(LONG_MIN + LONG_MAX) + LONG_MAX : LONG_MAX;
270          cutlim = cutoff % qbase;
271          cutoff /= qbase;
272          for (acc = 0, any = 0;; c = *s++) {
273                  if (!isascii(c))
274                          break;
275                  if (isdigit(c))
276                          c -= '\0';
277                  else if (isalpha(c))
278                          c -= isupper(c) ? 'A' - 10 : 'a' - 10;
279                  else
280                          break;
281                  if (c >= base)
282                          break;
283                  if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
284                          any = -1;
285                  else {
286                          any = 1;
287                          acc *= qbase;
288                          acc += c;
289                  }
290          }
291          if (any < 0) {
292                  acc = neg ? LONG_MIN : LONG_MAX;
293          } else if (neg)
294                  acc = -acc;
295          if (endptr != 0)
296                  *((const char **)endptr) = any ? s - 1 : nptr;
297          return acc;
298 }
299 #endif /* !HAVE_STRTOQ */
300
301 #ifndef HAVE_GETLOADAVG
302 #ifdef linux
303 /*! \brief Alternative method of getting load avg on Linux only */
304 int getloadavg(double *list, int nelem)
305 {
306         FILE *LOADAVG;
307         double avg[3] = { 0.0, 0.0, 0.0 };
308         int i, res = -1;
309
310         if ((LOADAVG = fopen("/proc/loadavg", "r"))) {
311                 fscanf(LOADAVG, "%lf %lf %lf", &avg[0], &avg[1], &avg[2]);
312                 res = 0;
313                 fclose(LOADAVG);
314         }
315
316         for (i = 0; (i < nelem) && (i < 3); i++) {
317                 list[i] = avg[i];
318         }
319
320         return res;
321 }
322 #else /* !linux */
323 /*! \brief Return something that won't cancel the call, but still return -1, in case
324  * we correct the implementation to check return value */
325 int getloadavg(double *list, int nelem)
326 {
327         int i;
328
329         for (i = 0; i < nelem; i++) {
330                 list[i] = 0.1;
331         }
332         return -1;
333 }
334 #endif /* linux */
335 #endif /* !HAVE_GETLOADAVG */
336
337
338 /*
339  * For strlcat()
340  *
341  * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
342  * All rights reserved.
343  *
344  * Redistribution and use in source and binary forms, with or without
345  * modification, are permitted provided that the following conditions
346  * are met:
347  * 1. Redistributions of source code must retain the above copyright
348  *    notice, this list of conditions and the following disclaimer.
349  * 2. Redistributions in binary form must reproduce the above copyright
350  *    notice, this list of conditions and the following disclaimer in the
351  *    documentation and/or other materials provided with the distribution.
352  * 3. The name of the author may not be used to endorse or promote products
353  *    derived from this software without specific prior written permission.
354  *
355  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
356  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
357  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
358  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
359  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
360  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
361  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
362  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
363  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
364  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
365  */
366
367 /*
368  * Appends src to string dst of size siz (unlike strncat, siz is the
369  * full size of dst, not space left).  At most siz-1 characters
370  * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
371  * Returns strlen(src) + MIN(siz, strlen(initial dst)).
372  * If retval >= siz, truncation occurred.
373  */
374 #ifndef HAVE_STRLCAT
375 size_t strlcat(char *dst, const char *src, size_t siz)
376 {
377         register char *d = dst;
378         register const char *s = src;
379         register size_t n = siz;
380         size_t dlen;
381
382         /* Find the end of dst and adjust bytes left but don't go past end */
383         while (n-- != 0 && *d != '\0')
384                 d++;
385         dlen = d - dst;
386         n = siz - dlen;
387
388         if (n == 0)
389                 return dlen + strlen(s);
390
391         while (*s != '\0') {
392                 if (n != 1) {
393                         *d++ = *s;
394                         n--;
395                 }
396                 s++;
397         }
398         *d = '\0';
399
400         return dlen + (s - src);        /* count does not include NUL */
401 }
402 #endif /* HAVE_STRLCAT */
403
404 /*
405  * For strlcpy()
406  *
407  * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
408  * All rights reserved.
409  *
410  * Redistribution and use in source and binary forms, with or without
411  * modification, are permitted provided that the following conditions
412  * are met:
413  * 1. Redistributions of source code must retain the above copyright
414  *    notice, this list of conditions and the following disclaimer.
415  * 2. Redistributions in binary form must reproduce the above copyright
416  *    notice, this list of conditions and the following disclaimer in the
417  *    documentation and/or other materials provided with the distribution.
418  * 3. The name of the author may not be used to endorse or promote products
419  *    derived from this software without specific prior written permission.
420  *
421  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
422  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
423  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
424  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
425  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
426  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
427  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
428  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
429  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
430  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
431  */
432
433 /*
434  * Copy src to string dst of size siz.  At most siz-1 characters
435  * will be copied.  Always NUL terminates (unless siz == 0).
436  * Returns strlen(src); if retval >= siz, truncation occurred.
437  */
438 #ifndef HAVE_STRLCPY
439 size_t strlcpy(char *dst, const char *src, size_t siz)
440 {
441         register char *d = dst;
442         register const char *s = src;
443         register size_t n = siz;
444
445         /* Copy as many bytes as will fit */
446         if (n != 0 && --n != 0) {
447                 do {
448                         if ((*d++ = *s++) == 0)
449                                 break;
450                 } while (--n != 0);
451         }
452
453         /* Not enough room in dst, add NUL and traverse rest of src */
454         if (n == 0) {
455                 if (siz != 0)
456                         *d = '\0';              /* NUL-terminate dst */
457                 while (*s++)
458                         ;
459         }
460
461         return s - src - 1;     /* count does not include NUL */
462 }
463 #endif /* HAVE_STRLCPY */