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