1 /*
2  * SPDX-License-Identifier: ISC
3  *
4  * Copyright (c) 2015 Todd C. Miller <Todd.Miller@sudo.ws>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /*
20  * This is an open source non-commercial project. Dear PVS-Studio, please check it.
21  * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
22  */
23 
24 #include <config.h>
25 
26 #include "sudo_compat.h"
27 #include "sudo_debug.h"
28 #include "sudo_util.h"
29 
30 /*
31  * Like strtok_r but non-destructive and works w/o a NUL terminator.
32  * TODO: Optimize by storing current char in a variable ch
33  */
34 const char *
sudo_strsplit_v1(const char * str,const char * endstr,const char * sep,const char ** last)35 sudo_strsplit_v1(const char *str, const char *endstr, const char *sep, const char **last)
36 {
37     const char *cp, *s;
38     debug_decl(sudo_strsplit, SUDO_DEBUG_UTIL);
39 
40     /* If no str specified, use last ptr (if any). */
41     if (str == NULL)
42 	str = *last;
43 
44     /* Skip leading separator characters. */
45     while (str < endstr) {
46 	for (s = sep; *s != '\0'; s++) {
47 	    if (*str == *s) {
48 		str++;
49 		break;
50 	    }
51 	}
52 	if (*s == '\0')
53 	    break;
54     }
55 
56     /* Empty string? */
57     if (str >= endstr) {
58 	*last = endstr;
59 	debug_return_ptr(NULL);
60     }
61 
62     /* Scan str until we hit a char from sep. */
63     for (cp = str; cp < endstr; cp++) {
64 	for (s = sep; *s != '\0'; s++) {
65 	    if (*cp == *s)
66 		break;
67 	}
68 	if (*s != '\0')
69 	    break;
70     }
71     *last = cp;
72     debug_return_const_ptr(str);
73 }
74