Merged revisions 116463 via svnmerge from
[asterisk-bristuff.git] / main / strcompat.c
bloba3f0e14975c840be5ced7e974baf5e8a9d2c6071
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 <ctype.h>
26 #ifndef HAVE_STRSEP
27 char *strsep(char **str, const char *delims)
29 char *token;
31 if (!*str) {
32 /* No more tokens */
33 return NULL;
36 token = *str;
37 while (**str != '\0') {
38 if (strchr(delims, **str)) {
39 **str = '\0';
40 (*str)++;
41 return token;
43 (*str)++;
46 /* There is no other token */
47 *str = NULL;
49 return token;
51 #endif
53 #ifndef HAVE_SETENV
54 int setenv(const char *name, const char *value, int overwrite)
56 unsigned char *buf;
57 int buflen;
59 buflen = strlen(name) + strlen(value) + 2;
60 buf = alloca(buflen);
62 if (!overwrite && getenv(name))
63 return 0;
65 snprintf(buf, buflen, "%s=%s", name, value);
67 return putenv(buf);
69 #endif
71 #ifndef HAVE_UNSETENV
72 int unsetenv(const char *name)
74 return setenv(name, "", 0);
76 #endif
78 #ifndef HAVE_STRCASESTR
79 static char *upper(const char *orig, char *buf, int bufsize)
81 int i = 0;
83 while (i < (bufsize - 1) && orig[i]) {
84 buf[i] = toupper(orig[i]);
85 i++;
88 buf[i] = '\0';
90 return buf;
93 char *strcasestr(const char *haystack, const char *needle)
95 char *u1, *u2;
96 int u1len = strlen(haystack) + 1, u2len = strlen(needle) + 1;
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;
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;
113 } else {
114 return NULL;
117 #endif /* !HAVE_STRCASESTR */
119 #ifndef HAVE_STRNLEN
120 size_t strnlen(const char *s, size_t n)
122 size_t len;
124 for (len = 0; len < n; len++)
125 if (s[len] == '\0')
126 break;
128 return len;
130 #endif /* !HAVE_STRNLEN */
132 #if !defined(HAVE_STRNDUP) && !defined(__AST_DEBUG_MALLOC)
133 char *strndup(const char *s, size_t n)
135 size_t len = strnlen(s, n);
136 char *new = malloc(len + 1);
138 if (!new)
139 return NULL;
141 new[len] = '\0';
142 return memcpy(new, s, len);
144 #endif /* !defined(HAVE_STRNDUP) && !defined(__AST_DEBUG_MALLOC) */
146 #if !defined(HAVE_VASPRINTF) && !defined(__AST_DEBUG_MALLOC)
147 int vasprintf(char **strp, const char *fmt, va_list ap)
149 int size;
150 va_list ap2;
151 char s;
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);
162 return size;
164 #endif /* !defined(HAVE_VASPRINTF) && !defined(__AST_DEBUG_MALLOC) */
167 * Based on Code from bsd-asprintf from OpenSSH
168 * Copyright (c) 2004 Darren Tucker.
170 * Based originally on asprintf.c from OpenBSD:
171 * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
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.
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.
185 #if !defined(HAVE_ASPRINTF) && !defined(__AST_DEBUG_MALLOC)
186 int asprintf(char **str, const char *fmt, ...)
188 va_list ap;
189 int ret;
191 *str = NULL;
192 va_start(ap, fmt);
193 ret = vasprintf(str, fmt, ap);
194 va_end(ap);
196 return ret;
198 #endif /* !defined(HAVE_ASPRINTF) && !defined(__AST_DEBUG_MALLOC) */
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
210 /*! \brief
211 * Convert a string to a quad integer.
213 * \note Ignores `locale' stuff. Assumes that the upper and lower case
214 * alphabets and digits are each contiguous.
216 uint64_t strtoq(const char *nptr, char **endptr, int base)
218 const char *s;
219 uint64_t acc;
220 unsigned char c;
221 uint64_t qbase, cutoff;
222 int neg, any, cutlim;
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.
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++;
241 if ((base == 0 || base == 16) &&
242 c == '\0' && (*s == 'x' || *s == 'X')) {
243 c = s[1];
244 s += 2;
245 base = 16;
247 if (base == 0)
248 base = c == '\0' ? 8 : 10;
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.
265 * Set any if any `digits' consumed; make it negative to indicate
266 * overflow.
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;
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;
299 #endif /* !HAVE_STRTOQ */
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)
306 FILE *LOADAVG;
307 double avg[3] = { 0.0, 0.0, 0.0 };
308 int i, res = -1;
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);
316 for (i = 0; (i < nelem) && (i < 3); i++) {
317 list[i] = avg[i];
320 return res;
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)
327 int i;
329 for (i = 0; i < nelem; i++) {
330 list[i] = 0.1;
332 return -1;
334 #endif /* linux */
335 #endif /* !HAVE_GETLOADAVG */
339 * For strlcat()
341 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
342 * All rights reserved.
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.
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.
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.
374 #ifndef HAVE_STRLCAT
375 size_t strlcat(char *dst, const char *src, size_t siz)
377 register char *d = dst;
378 register const char *s = src;
379 register size_t n = siz;
380 size_t dlen;
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;
388 if (n == 0)
389 return dlen + strlen(s);
391 while (*s != '\0') {
392 if (n != 1) {
393 *d++ = *s;
394 n--;
396 s++;
398 *d = '\0';
400 return dlen + (s - src); /* count does not include NUL */
402 #endif /* HAVE_STRLCAT */
405 * For strlcpy()
407 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
408 * All rights reserved.
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.
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.
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.
438 #ifndef HAVE_STRLCPY
439 size_t strlcpy(char *dst, const char *src, size_t siz)
441 register char *d = dst;
442 register const char *s = src;
443 register size_t n = siz;
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);
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++)
461 return s - src - 1; /* count does not include NUL */
463 #endif /* HAVE_STRLCPY */