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