2 * Copyright (c) 1997-2014 Erez Zadok
3 * Copyright (c) 1990 Jan-Simon Pendry
4 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
5 * Copyright (c) 1990 The Regents of the University of California.
8 * This code is derived from software contributed to Berkeley by
9 * Jan-Simon Pendry at Imperial College, London.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * File: am-utils/libamu/strutil.c
46 #endif /* HAVE_CONFIG_H */
52 strnsave(const char *str, int len)
54 char *sp = (char *) xmalloc(len + 1);
55 memmove(sp, str, len);
63 * Concatenate three strings and store the result in the buffer pointed to
64 * by p, making p large enough to hold the strings
67 str3cat(char *p, char *s1, char *s2, char *s3)
73 p = (char *) xrealloc(p, l1 + l2 + l3 + 1);
75 memmove(p + l1, s2, l2);
76 memmove(p + l1 + l2, s3, l3 + 1);
82 * Split s using ch as delimiter and qc as quote character
85 strsplit(char *s, int ch, int qc)
91 ivec = (char **) xmalloc((ic + 1) * sizeof(char *));
99 while (*s && (ch == ' ' ? (isascii((unsigned char)*s) && isspace((unsigned char)*s)) : *s == ch))
109 * remember start of string
116 while (*s && !(ch == ' ' ? (isascii((unsigned char)*s) && isspace((unsigned char)*s)) : *s == ch)) {
122 while (*s && *s != qc)
134 * save string in new ivec slot
137 ivec = (char **) xrealloc((voidp) ivec, (ic + 1) * sizeof(char *));
139 plog(XLOG_DEBUG, "strsplit saved \"%s\"", v);
143 plog(XLOG_DEBUG, "strsplit saved a total of %d strings", ic);
152 * Use generic strlcpy to copy a string more carefully, null-terminating it
153 * as needed. However, if the copied string was truncated due to lack of
154 * space, then warn us.
156 * For now, xstrlcpy returns VOID because it doesn't look like anywhere in
157 * the Amd code do we actually use the return value of strncpy/strlcpy.
161 _xstrlcpy(const char *filename, int lineno, char *dst, const char *src, size_t len)
162 #else /* not DEBUG */
163 xstrlcpy(char *dst, const char *src, size_t len)
164 #endif /* not DEBUG */
168 if (strlcpy(dst, src, len) >= len)
170 plog(XLOG_ERROR, "xstrlcpy(%s:%d): string \"%s\" truncated to \"%s\"",
171 filename, lineno, src, dst);
172 #else /* not DEBUG */
173 plog(XLOG_ERROR, "xstrlcpy: string \"%s\" truncated to \"%s\"", src, dst);
174 #endif /* not DEBUG */
179 * Use generic strlcat to concatenate a string more carefully,
180 * null-terminating it as needed. However, if the copied string was
181 * truncated due to lack of space, then warn us.
183 * For now, xstrlcat returns VOID because it doesn't look like anywhere in
184 * the Amd code do we actually use the return value of strncat/strlcat.
188 _xstrlcat(const char *filename, int lineno, char *dst, const char *src, size_t len)
189 #else /* not DEBUG */
190 xstrlcat(char *dst, const char *src, size_t len)
191 #endif /* not DEBUG */
195 if (strlcat(dst, src, len) >= len) {
196 /* strlcat does not null terminate if the size of src is equal to len. */
197 dst[strlen(dst) - 1] = '\0';
199 plog(XLOG_ERROR, "xstrlcat(%s:%d): string \"%s\" truncated to \"%s\"",
200 filename, lineno, src, dst);
201 #else /* not DEBUG */
202 plog(XLOG_ERROR, "xstrlcat: string \"%s\" truncated to \"%s\"", src, dst);
203 #endif /* not DEBUG */
208 /* our version of snprintf */
210 #if defined(DEBUG) && (defined(HAVE_C99_VARARGS_MACROS) || defined(HAVE_GCC_VARARGS_MACROS))
211 _xsnprintf(const char *filename, int lineno, char *str, size_t size, const char *format, ...)
212 #else /* not DEBUG or no C99/GCC-style vararg cpp macros supported */
213 xsnprintf(char *str, size_t size, const char *format, ...)
214 #endif /* not DEBUG or no C99/GCC-style vararg cpp macros supported */
219 va_start(ap, format);
220 #if defined(DEBUG) && (defined(HAVE_C99_VARARGS_MACROS) || defined(HAVE_GCC_VARARGS_MACROS))
221 ret = _xvsnprintf(filename, lineno, str, size, format, ap);
222 #else /* not DEBUG or no C99/GCC-style vararg cpp macros supported */
223 ret = xvsnprintf(str, size, format, ap);
224 #endif /* not DEBUG or no C99/GCC-style vararg cpp macros supported */
231 /* our version of vsnprintf */
233 #if defined(DEBUG) && (defined(HAVE_C99_VARARGS_MACROS) || defined(HAVE_GCC_VARARGS_MACROS))
234 _xvsnprintf(const char *filename, int lineno, char *str, size_t size, const char *format, va_list ap)
235 #else /* not DEBUG or no C99/GCC-style vararg cpp macros supported */
236 xvsnprintf(char *str, size_t size, const char *format, va_list ap)
237 #endif /* not DEBUG or no C99/GCC-style vararg cpp macros supported */
241 #ifdef HAVE_VSNPRINTF
242 ret = vsnprintf(str, size, format, ap);
243 #else /* not HAVE_VSNPRINTF */
244 ret = vsprintf(str, format, ap); /* less secure version */
245 #endif /* not HAVE_VSNPRINTF */
247 * If error or truncation, plog error.
249 * WARNING: we use the static 'maxtrunc' variable below to break out any
250 * possible infinite recursion between plog() and xvsnprintf(). If it
251 * ever happens, it'd indicate a bug in Amd.
253 if (ret < 0 || (size_t) ret >= size) { /* error or truncation occured */
254 static int maxtrunc; /* hack to avoid inifinite loop */
256 #if defined(DEBUG) && (defined(HAVE_C99_VARARGS_MACROS) || defined(HAVE_GCC_VARARGS_MACROS))
257 plog(XLOG_ERROR, "xvsnprintf(%s:%d): string %p truncated (ret=%d, format=\"%s\")",
258 filename, lineno, str, ret, format);
259 #else /* not DEBUG or no C99/GCC-style vararg cpp macros supported */
260 plog(XLOG_ERROR, "xvsnprintf: string %p truncated (ret=%d, format=\"%s\")",
262 #endif /* not DEBUG or no C99/GCC-style vararg cpp macros supported */
269 vstrlen(const char *src, va_list ap)
271 size_t len = strlen(src);
272 while ((src = va_arg(ap, const char *)) != NULL)
278 vstrcpy(char *dst, const char *src, va_list ap)
281 while ((src = va_arg(ap, const char *)) != NULL)
286 strvcat(const char *src, ...)
293 len = vstrlen(src, ap);
295 dst = xmalloc(len + 1);
297 vstrcpy(dst, src, ap);