aboutsummaryrefslogtreecommitdiffstats
path: root/menuselect/strcompat.c
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2009-12-16 04:47:16 +0100
committerPatrick McHardy <kaber@trash.net>2011-02-26 22:05:44 +0100
commit7cab80cd3379199f19dbce189f0d4e291e61e6c0 (patch)
treed6a726b2993fdc792a3bbff1035cdf3da9ceb50b /menuselect/strcompat.c
parentf93033b8ee08ad290af1dfdcabf071ef777eb28d (diff)
Import menuselect from asterisk SVN
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'menuselect/strcompat.c')
-rw-r--r--menuselect/strcompat.c344
1 files changed, 344 insertions, 0 deletions
diff --git a/menuselect/strcompat.c b/menuselect/strcompat.c
new file mode 100644
index 000000000..9d7016896
--- /dev/null
+++ b/menuselect/strcompat.c
@@ -0,0 +1,344 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2006, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Compatibility functions for strsep and strtoq missing on Solaris
+ */
+
+#include "autoconfig.h"
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+
+#ifndef HAVE_STRSEP
+char *strsep(char **str, const char *delims)
+{
+ char *token;
+
+ if (!*str) {
+ /* No more tokens */
+ return NULL;
+ }
+
+ token = *str;
+ while (**str != '\0') {
+ if (strchr(delims, **str)) {
+ **str = '\0';
+ (*str)++;
+ return token;
+ }
+ (*str)++;
+ }
+
+ /* There is no other token */
+ *str = NULL;
+
+ return token;
+}
+#endif
+
+#ifndef HAVE_SETENV
+int setenv(const char *name, const char *value, int overwrite)
+{
+ unsigned char *buf;
+ int buflen;
+
+ buflen = strlen(name) + strlen(value) + 2;
+ buf = alloca(buflen);
+
+ if (!overwrite && getenv(name))
+ return 0;
+
+ snprintf(buf, buflen, "%s=%s", name, value);
+
+ return putenv(buf);
+}
+#endif
+
+#ifndef HAVE_UNSETENV
+int unsetenv(const char *name)
+{
+ return setenv(name, "", 0);
+}
+#endif
+
+#ifndef HAVE_STRCASESTR
+static char *upper(const char *orig, char *buf, int bufsize)
+{
+ int i = 0;
+
+ while (i < (bufsize - 1) && orig[i]) {
+ buf[i] = toupper(orig[i]);
+ i++;
+ }
+
+ buf[i] = '\0';
+
+ return buf;
+}
+
+char *strcasestr(const char *haystack, const char *needle)
+{
+ char *u1, *u2;
+ int u1len = strlen(haystack) + 1, u2len = strlen(needle) + 1;
+
+ u1 = alloca(u1len);
+ u2 = alloca(u2len);
+ if (u1 && u2) {
+ char *offset;
+ if (u2len > u1len) {
+ /* Needle bigger than haystack */
+ return NULL;
+ }
+ offset = strstr(upper(haystack, u1, u1len), upper(needle, u2, u2len));
+ if (offset) {
+ /* Return the offset into the original string */
+ return ((char *)((unsigned long)haystack + (unsigned long)(offset - u1)));
+ } else {
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+}
+#endif /* !HAVE_STRCASESTR */
+
+#ifndef HAVE_STRNLEN
+size_t strnlen(const char *s, size_t n)
+{
+ size_t len;
+
+ for (len = 0; len < n; len++)
+ if (s[len] == '\0')
+ break;
+
+ return len;
+}
+#endif /* !HAVE_STRNLEN */
+
+#if !defined(HAVE_STRNDUP) && !defined(__AST_DEBUG_MALLOC)
+char *strndup(const char *s, size_t n)
+{
+ size_t len = strnlen(s, n);
+ char *new = malloc(len + 1);
+
+ if (!new)
+ return NULL;
+
+ new[len] = '\0';
+ return memcpy(new, s, len);
+}
+#endif /* !defined(HAVE_STRNDUP) && !defined(__AST_DEBUG_MALLOC) */
+
+#if !defined(HAVE_VASPRINTF) && !defined(__AST_DEBUG_MALLOC)
+int vasprintf(char **strp, const char *fmt, va_list ap)
+{
+ int size;
+ va_list ap2;
+ char s;
+
+ *strp = NULL;
+ va_copy(ap2, ap);
+ size = vsnprintf(&s, 1, fmt, ap2);
+ va_end(ap2);
+ *strp = malloc(size + 1);
+ if (!*strp)
+ return -1;
+ vsnprintf(*strp, size + 1, fmt, ap);
+
+ return size;
+}
+#endif /* !defined(HAVE_VASPRINTF) && !defined(__AST_DEBUG_MALLOC) */
+
+/*
+ * Based on Code from bsd-asprintf from OpenSSH
+ * Copyright (c) 2004 Darren Tucker.
+ *
+ * Based originally on asprintf.c from OpenBSD:
+ * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#if !defined(HAVE_ASPRINTF) && !defined(__AST_DEBUG_MALLOC)
+int asprintf(char **str, const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ *str = NULL;
+ va_start(ap, fmt);
+ ret = vasprintf(str, fmt, ap);
+ va_end(ap);
+
+ return ret;
+}
+#endif /* !defined(HAVE_ASPRINTF) && !defined(__AST_DEBUG_MALLOC) */
+
+#ifndef HAVE_STRTOQ
+#ifndef LONG_MIN
+#define LONG_MIN (-9223372036854775807L-1L)
+ /* min value of a "long int" */
+#endif
+#ifndef LONG_MAX
+#define LONG_MAX 9223372036854775807L
+ /* max value of a "long int" */
+#endif
+
+/*! \brief
+ * Convert a string to a quad integer.
+ *
+ * \note Ignores `locale' stuff. Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+uint64_t strtoq(const char *nptr, char **endptr, int base)
+{
+ const char *s;
+ uint64_t acc;
+ unsigned char c;
+ uint64_t qbase, cutoff;
+ int neg, any, cutlim;
+
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == '+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == '\0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '\0' ? 8 : 10;
+
+ /*
+ * Compute the cutoff value between legal numbers and illegal
+ * numbers. That is the largest legal value, divided by the
+ * base. An input number that is greater than this value, if
+ * followed by a legal input character, is too big. One that
+ * is equal to this value may be valid or not; the limit
+ * between valid and invalid numbers is then based on the last
+ * digit. For instance, if the range for quads is
+ * [-9223372036854775808..9223372036854775807] and the input base
+ * is 10, cutoff will be set to 922337203685477580 and cutlim to
+ * either 7 (neg==0) or 8 (neg==1), meaning that if we have
+ * accumulated a value > 922337203685477580, or equal but the
+ * next digit is > 7 (or 8), the number is too big, and we will
+ * return a range error.
+ *
+ * Set any if any `digits' consumed; make it negative to indicate
+ * overflow.
+ */
+ qbase = (unsigned)base;
+ cutoff = neg ? (uint64_t)-(LONG_MIN + LONG_MAX) + LONG_MAX : LONG_MAX;
+ cutlim = cutoff % qbase;
+ cutoff /= qbase;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (!isascii(c))
+ break;
+ if (isdigit(c))
+ c -= '\0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= qbase;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? LONG_MIN : LONG_MAX;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *((const char **)endptr) = any ? s - 1 : nptr;
+ return acc;
+}
+#endif /* !HAVE_STRTOQ */
+
+#ifndef HAVE_GETLOADAVG
+#ifdef linux
+/*! \brief Alternative method of getting load avg on Linux only */
+int getloadavg(double *list, int nelem)
+{
+ FILE *LOADAVG;
+ double avg[3] = { 0.0, 0.0, 0.0 };
+ int i, res = -1;
+
+ if ((LOADAVG = fopen("/proc/loadavg", "r"))) {
+ fscanf(LOADAVG, "%lf %lf %lf", &avg[0], &avg[1], &avg[2]);
+ res = 0;
+ fclose(LOADAVG);
+ }
+
+ for (i = 0; (i < nelem) && (i < 3); i++) {
+ list[i] = avg[i];
+ }
+
+ return res;
+}
+#else /* !linux */
+/*! \brief Return something that won't cancel the call, but still return -1, in case
+ * we correct the implementation to check return value */
+int getloadavg(double *list, int nelem)
+{
+ int i;
+
+ for (i = 0; i < nelem; i++) {
+ list[i] = 0.1;
+ }
+ return -1;
+}
+#endif /* linux */
+#endif /* !HAVE_GETLOADAVG */