Files
asterisk/main/strcompat.c
Russell Bryant 0a9750ef9f Merged revisions 60603 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r60603 | russell | 2007-04-06 15:58:43 -0500 (Fri, 06 Apr 2007) | 13 lines

To be able to achieve the things that we would like to achieve with the
Asterisk GUI project, we need a fully functional HTTP interface with access
to the Asterisk manager interface.  One of the things that was intended to be
a part of this system, but was never actually implemented, was the ability for
the GUI to be able to upload files to Asterisk.  So, this commit adds this in
the most minimally invasive way that we could come up with.

A lot of work on minimime was done by Steve Murphy.  He fixed a lot of bugs in
the parser, and updated it to be thread-safe.  The ability to check
permissions of active manager sessions was added by Dwayne Hubbard.  Then,
hacking this all together and do doing the modifications necessary to the HTTP
interface was done by me.

........


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@60604 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-06 21:16:38 +00:00

472 lines
13 KiB
C

/*
* 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 "asterisk.h"
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.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 */
/*
* For strlcat()
*
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Appends src to string dst of size siz (unlike strncat, siz is the
* full size of dst, not space left). At most siz-1 characters
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
* If retval >= siz, truncation occurred.
*/
#ifndef HAVE_STRLCAT
size_t strlcat(char *dst, const char *src, size_t siz)
{
register char *d = dst;
register const char *s = src;
register size_t n = siz;
size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end */
while (n-- != 0 && *d != '\0')
d++;
dlen = d - dst;
n = siz - dlen;
if (n == 0)
return dlen + strlen(s);
while (*s != '\0') {
if (n != 1) {
*d++ = *s;
n--;
}
s++;
}
*d = '\0';
return dlen + (s - src); /* count does not include NUL */
}
#endif /* HAVE_STRLCAT */
/*
* For strlcpy()
*
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copy src to string dst of size siz. At most siz-1 characters
* will be copied. Always NUL terminates (unless siz == 0).
* Returns strlen(src); if retval >= siz, truncation occurred.
*/
#ifndef HAVE_STRLCPY
size_t strlcpy(char *dst, const char *src, size_t siz)
{
register char *d = dst;
register const char *s = src;
register size_t n = siz;
/* Copy as many bytes as will fit */
if (n != 0 && --n != 0) {
do {
if ((*d++ = *s++) == 0)
break;
} while (--n != 0);
}
/* Not enough room in dst, add NUL and traverse rest of src */
if (n == 0) {
if (siz != 0)
*d = '\0'; /* NUL-terminate dst */
while (*s++)
;
}
return s - src - 1; /* count does not include NUL */
}
#endif /* HAVE_STRLCPY */