diff options
Diffstat (limited to 'contrib/amd/libamu/strutil.c')
-rw-r--r-- | contrib/amd/libamu/strutil.c | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/contrib/amd/libamu/strutil.c b/contrib/amd/libamu/strutil.c new file mode 100644 index 0000000..5a1e759 --- /dev/null +++ b/contrib/amd/libamu/strutil.c @@ -0,0 +1,270 @@ +/* + * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1990 Jan-Simon Pendry + * Copyright (c) 1990 Imperial College of Science, Technology & Medicine + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry at Imperial College, London. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + * + * + * File: am-utils/libamu/strutil.c + * + */ + +/* + * String Utilities. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* HAVE_CONFIG_H */ +#include <am_defs.h> +#include <amu.h> + + +char * +strnsave(const char *str, int len) +{ + char *sp = (char *) xmalloc(len + 1); + memmove(sp, str, len); + sp[len] = '\0'; + + return sp; +} + + +/* + * Concatenate three strings and store the result in the buffer pointed to + * by p, making p large enough to hold the strings + */ +char * +str3cat(char *p, char *s1, char *s2, char *s3) +{ + int l1 = strlen(s1); + int l2 = strlen(s2); + int l3 = strlen(s3); + + p = (char *) xrealloc(p, l1 + l2 + l3 + 1); + memmove(p, s1, l1); + memmove(p + l1, s2, l2); + memmove(p + l1 + l2, s3, l3 + 1); + return p; +} + + +/* + * Split s using ch as delimiter and qc as quote character + */ +char ** +strsplit(char *s, int ch, int qc) +{ + char **ivec; + int ic = 0; + int done = 0; + + ivec = (char **) xmalloc((ic + 1) * sizeof(char *)); + + while (!done) { + char *v; + + /* + * skip to split char + */ + while (*s && (ch == ' ' ? (isascii((unsigned char)*s) && isspace((unsigned char)*s)) : *s == ch)) + *s++ = '\0'; + + /* + * End of string? + */ + if (!*s) + break; + + /* + * remember start of string + */ + v = s; + + /* + * skip to split char + */ + while (*s && !(ch == ' ' ? (isascii((unsigned char)*s) && isspace((unsigned char)*s)) : *s == ch)) { + if (*s++ == qc) { + /* + * Skip past string. + */ + s++; + while (*s && *s != qc) + s++; + if (*s == qc) + s++; + } + } + + if (!*s) + done = 1; + *s++ = '\0'; + + /* + * save string in new ivec slot + */ + ivec[ic++] = v; + ivec = (char **) xrealloc((voidp) ivec, (ic + 1) * sizeof(char *)); + if (amuDebug(D_STR)) + plog(XLOG_DEBUG, "strsplit saved \"%s\"", v); + } + + if (amuDebug(D_STR)) + plog(XLOG_DEBUG, "strsplit saved a total of %d strings", ic); + + ivec[ic] = NULL; + + return ivec; +} + + +/* + * Use generic strlcpy to copy a string more carefully, null-terminating it + * as needed. However, if the copied string was truncated due to lack of + * space, then warn us. + * + * For now, xstrlcpy returns VOID because it doesn't look like anywhere in + * the Amd code do we actually use the return value of strncpy/strlcpy. + */ +void +#ifdef DEBUG +_xstrlcpy(const char *filename, int lineno, char *dst, const char *src, size_t len) +#else /* not DEBUG */ +xstrlcpy(char *dst, const char *src, size_t len) +#endif /* not DEBUG */ +{ + if (len == 0) + return; + if (strlcpy(dst, src, len) >= len) +#ifdef DEBUG + plog(XLOG_ERROR, "xstrlcpy(%s:%d): string \"%s\" truncated to \"%s\"", + filename, lineno, src, dst); +#else /* not DEBUG */ + plog(XLOG_ERROR, "xstrlcpy: string \"%s\" truncated to \"%s\"", src, dst); +#endif /* not DEBUG */ +} + + +/* + * Use generic strlcat to concatenate a string more carefully, + * null-terminating it as needed. However, if the copied string was + * truncated due to lack of space, then warn us. + * + * For now, xstrlcat returns VOID because it doesn't look like anywhere in + * the Amd code do we actually use the return value of strncat/strlcat. + */ +void +#ifdef DEBUG +_xstrlcat(const char *filename, int lineno, char *dst, const char *src, size_t len) +#else /* not DEBUG */ +xstrlcat(char *dst, const char *src, size_t len) +#endif /* not DEBUG */ +{ + if (len == 0) + return; + if (strlcat(dst, src, len) >= len) { + /* strlcat does not null terminate if the size of src is equal to len. */ + dst[strlen(dst) - 1] = '\0'; +#ifdef DEBUG + plog(XLOG_ERROR, "xstrlcat(%s:%d): string \"%s\" truncated to \"%s\"", + filename, lineno, src, dst); +#else /* not DEBUG */ + plog(XLOG_ERROR, "xstrlcat: string \"%s\" truncated to \"%s\"", src, dst); +#endif /* not DEBUG */ + } +} + + +/* our version of snprintf */ +int +#if defined(DEBUG) && (defined(HAVE_C99_VARARGS_MACROS) || defined(HAVE_GCC_VARARGS_MACROS)) +_xsnprintf(const char *filename, int lineno, char *str, size_t size, const char *format, ...) +#else /* not DEBUG or no C99/GCC-style vararg cpp macros supported */ +xsnprintf(char *str, size_t size, const char *format, ...) +#endif /* not DEBUG or no C99/GCC-style vararg cpp macros supported */ +{ + va_list ap; + int ret = 0; + + va_start(ap, format); +#if defined(DEBUG) && (defined(HAVE_C99_VARARGS_MACROS) || defined(HAVE_GCC_VARARGS_MACROS)) + ret = _xvsnprintf(filename, lineno, str, size, format, ap); +#else /* not DEBUG or no C99/GCC-style vararg cpp macros supported */ + ret = xvsnprintf(str, size, format, ap); +#endif /* not DEBUG or no C99/GCC-style vararg cpp macros supported */ + va_end(ap); + + return ret; +} + + +/* our version of vsnprintf */ +int +#if defined(DEBUG) && (defined(HAVE_C99_VARARGS_MACROS) || defined(HAVE_GCC_VARARGS_MACROS)) +_xvsnprintf(const char *filename, int lineno, char *str, size_t size, const char *format, va_list ap) +#else /* not DEBUG or no C99/GCC-style vararg cpp macros supported */ +xvsnprintf(char *str, size_t size, const char *format, va_list ap) +#endif /* not DEBUG or no C99/GCC-style vararg cpp macros supported */ +{ + int ret = 0; + +#ifdef HAVE_VSNPRINTF + ret = vsnprintf(str, size, format, ap); +#else /* not HAVE_VSNPRINTF */ + ret = vsprintf(str, format, ap); /* less secure version */ +#endif /* not HAVE_VSNPRINTF */ + /* + * If error or truncation, plog error. + * + * WARNING: we use the static 'maxtrunc' variable below to break out any + * possible infinite recursion between plog() and xvsnprintf(). If it + * ever happens, it'd indicate a bug in Amd. + */ + if (ret < 0 || (size_t) ret >= size) { /* error or truncation occured */ + static int maxtrunc; /* hack to avoid inifinite loop */ + if (++maxtrunc > 10) +#if defined(DEBUG) && (defined(HAVE_C99_VARARGS_MACROS) || defined(HAVE_GCC_VARARGS_MACROS)) + plog(XLOG_ERROR, "xvsnprintf(%s:%d): string %p truncated (ret=%d, format=\"%s\")", + filename, lineno, str, ret, format); +#else /* not DEBUG or no C99/GCC-style vararg cpp macros supported */ + plog(XLOG_ERROR, "xvsnprintf: string %p truncated (ret=%d, format=\"%s\")", + str, ret, format); +#endif /* not DEBUG or no C99/GCC-style vararg cpp macros supported */ + } + + return ret; +} |