1/* 2 * Copyright (C) 2004-2007, 2011, 2012, 2014 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1999-2001, 2003 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* 19 * Copyright (c) 1990, 1993 20 * The Regents of the University of California. All rights reserved. 21 * 22 * Redistribution and use in source and binary forms, with or without 23 * modification, are permitted provided that the following conditions 24 * are met: 25 * 1. Redistributions of source code must retain the above copyright 26 * notice, this list of conditions and the following disclaimer. 27 * 2. Redistributions in binary form must reproduce the above copyright 28 * notice, this list of conditions and the following disclaimer in the 29 * documentation and/or other materials provided with the distribution. 30 * 3. Neither the name of the University nor the names of its contributors 31 * may be used to endorse or promote products derived from this software 32 * without specific prior written permission. 33 * 34 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 35 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 36 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 37 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 38 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 39 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 40 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 41 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 42 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 43 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 44 * SUCH DAMAGE. 45 */ 46 47/*! \file */ 48 49#include <config.h> 50 51#include <ctype.h> 52 53#include <isc/mem.h> 54#include <isc/print.h> 55#include <isc/region.h> 56#include <isc/string.h> 57#include <isc/util.h> 58 59static char digits[] = "0123456789abcdefghijklmnoprstuvwxyz"; 60 61isc_uint64_t 62isc_string_touint64(char *source, char **end, int base) { 63 isc_uint64_t tmp; 64 isc_uint64_t overflow; 65 char *s = source; 66 char *o; 67 char c; 68 69 if ((base < 0) || (base == 1) || (base > 36)) { 70 *end = source; 71 return (0); 72 } 73 74 while (*s != 0 && isascii(*s&0xff) && isspace(*s&0xff)) 75 s++; 76 if (*s == '+' /* || *s == '-' */) 77 s++; 78 if (base == 0) { 79 if (*s == '0' && (*(s+1) == 'X' || *(s+1) == 'x')) { 80 s += 2; 81 base = 16; 82 } else if (*s == '0') 83 base = 8; 84 else 85 base = 10; 86 } 87 if (*s == 0) { 88 *end = source; 89 return (0); 90 } 91 overflow = ~0; 92 overflow /= base; 93 tmp = 0; 94 95 while ((c = *s) != 0) { 96 c = tolower(c&0xff); 97 /* end ? */ 98 if ((o = strchr(digits, c)) == NULL) { 99 *end = s; 100 return (tmp); 101 } 102 /* end ? */ 103 if ((o - digits) >= base) { 104 *end = s; 105 return (tmp); 106 } 107 /* overflow ? */ 108 if (tmp > overflow) { 109 *end = source; 110 return (0); 111 } 112 tmp *= base; 113 /* overflow ? */ 114 if ((tmp + (o - digits)) < tmp) { 115 *end = source; 116 return (0); 117 } 118 tmp += o - digits; 119 s++; 120 } 121 *end = s; 122 return (tmp); 123} 124 125isc_result_t 126isc_string_copy(char *target, size_t size, const char *source) { 127 REQUIRE(size > 0U); 128 129 if (strlcpy(target, source, size) >= size) { 130 memset(target, ISC_STRING_MAGIC, size); 131 return (ISC_R_NOSPACE); 132 } 133 134 ENSURE(strlen(target) < size); 135 136 return (ISC_R_SUCCESS); 137} 138 139void 140isc_string_copy_truncate(char *target, size_t size, const char *source) { 141 REQUIRE(size > 0U); 142 143 strlcpy(target, source, size); 144 145 ENSURE(strlen(target) < size); 146} 147 148isc_result_t 149isc_string_append(char *target, size_t size, const char *source) { 150 REQUIRE(size > 0U); 151 REQUIRE(strlen(target) < size); 152 153 if (strlcat(target, source, size) >= size) { 154 memset(target, ISC_STRING_MAGIC, size); 155 return (ISC_R_NOSPACE); 156 } 157 158 ENSURE(strlen(target) < size); 159 160 return (ISC_R_SUCCESS); 161} 162 163void 164isc_string_append_truncate(char *target, size_t size, const char *source) { 165 REQUIRE(size > 0U); 166 REQUIRE(strlen(target) < size); 167 168 strlcat(target, source, size); 169 170 ENSURE(strlen(target) < size); 171} 172 173isc_result_t 174isc_string_printf(char *target, size_t size, const char *format, ...) { 175 va_list args; 176 size_t n; 177 178 REQUIRE(size > 0U); 179 180 va_start(args, format); 181 n = vsnprintf(target, size, format, args); 182 va_end(args); 183 184 if (n >= size) { 185 memset(target, ISC_STRING_MAGIC, size); 186 return (ISC_R_NOSPACE); 187 } 188 189 ENSURE(strlen(target) < size); 190 191 return (ISC_R_SUCCESS); 192} 193 194void 195isc_string_printf_truncate(char *target, size_t size, const char *format, ...) 196{ 197 va_list args; 198 199 REQUIRE(size > 0U); 200 201 va_start(args, format); 202 /* check return code? */ 203 (void)vsnprintf(target, size, format, args); 204 va_end(args); 205 206 ENSURE(strlen(target) < size); 207} 208 209char * 210isc_string_regiondup(isc_mem_t *mctx, const isc_region_t *source) { 211 char *target; 212 213 REQUIRE(mctx != NULL); 214 REQUIRE(source != NULL); 215 216 target = (char *) isc_mem_allocate(mctx, source->length + 1); 217 if (target != NULL) { 218 memmove(source->base, target, source->length); 219 target[source->length] = '\0'; 220 } 221 222 return (target); 223} 224 225char * 226isc_string_separate(char **stringp, const char *delim) { 227 char *string = *stringp; 228 char *s; 229 const char *d; 230 char sc, dc; 231 232 if (string == NULL) 233 return (NULL); 234 235 for (s = string; (sc = *s) != '\0'; s++) 236 for (d = delim; (dc = *d) != '\0'; d++) 237 if (sc == dc) { 238 *s++ = '\0'; 239 *stringp = s; 240 return (string); 241 } 242 *stringp = NULL; 243 return (string); 244} 245 246size_t 247isc_string_strlcpy(char *dst, const char *src, size_t size) 248{ 249 char *d = dst; 250 const char *s = src; 251 size_t n = size; 252 253 /* Copy as many bytes as will fit */ 254 if (n != 0U && --n != 0U) { 255 do { 256 if ((*d++ = *s++) == 0) 257 break; 258 } while (--n != 0U); 259 } 260 261 /* Not enough room in dst, add NUL and traverse rest of src */ 262 if (n == 0U) { 263 if (size != 0U) 264 *d = '\0'; /* NUL-terminate dst */ 265 while (*s++) 266 ; 267 } 268 269 return(s - src - 1); /* count does not include NUL */ 270} 271 272size_t 273isc_string_strlcat(char *dst, const char *src, size_t size) 274{ 275 char *d = dst; 276 const char *s = src; 277 size_t n = size; 278 size_t dlen; 279 280 /* Find the end of dst and adjust bytes left but don't go past end */ 281 while (n-- != 0U && *d != '\0') 282 d++; 283 dlen = d - dst; 284 n = size - dlen; 285 286 if (n == 0U) 287 return(dlen + strlen(s)); 288 while (*s != '\0') { 289 if (n != 1U) { 290 *d++ = *s; 291 n--; 292 } 293 s++; 294 } 295 *d = '\0'; 296 297 return(dlen + (s - src)); /* count does not include NUL */ 298} 299 300char * 301isc_string_strcasestr(const char *str, const char *search) { 302 char c, sc, *s; 303 size_t len; 304 305 if ((c = *search++) != 0) { 306 c = tolower((unsigned char) c); 307 len = strlen(search); 308 do { 309 do { 310 if ((sc = *str++) == 0) 311 return (NULL); 312 } while ((char) tolower((unsigned char) sc) != c); 313 } while (strncasecmp(str, search, len) != 0); 314 str--; 315 } 316 DE_CONST(str, s); 317 return (s); 318 319} 320