1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Helper function for splitting a string into an argv-like array. 4 */ 5 6 #include <stdlib.h> 7 #include <linux/kernel.h> 8 #include <linux/ctype.h> 9 #include <linux/string.h> 10 11 static const char *skip_arg(const char *cp) 12 { 13 while (*cp && !isspace(*cp)) 14 cp++; 15 16 return cp; 17 } 18 19 static int count_argc(const char *str) 20 { 21 int count = 0; 22 23 while (*str) { 24 str = skip_spaces(str); 25 if (*str) { 26 count++; 27 str = skip_arg(str); 28 } 29 } 30 31 return count; 32 } 33 34 /** 35 * argv_free - free an argv 36 * @argv - the argument vector to be freed 37 * 38 * Frees an argv and the strings it points to. 39 */ 40 void argv_free(char **argv) 41 { 42 char **p; 43 for (p = argv; *p; p++) { 44 free(*p); 45 *p = NULL; 46 } 47 48 free(argv); 49 } 50 51 /** 52 * argv_split - split a string at whitespace, returning an argv 53 * @str: the string to be split 54 * @argcp: returned argument count 55 * 56 * Returns an array of pointers to strings which are split out from 57 * @str. This is performed by strictly splitting on white-space; no 58 * quote processing is performed. Multiple whitespace characters are 59 * considered to be a single argument separator. The returned array 60 * is always NULL-terminated. Returns NULL on memory allocation 61 * failure. 62 */ 63 char **argv_split(const char *str, int *argcp) 64 { 65 int argc = count_argc(str); 66 char **argv = calloc(argc + 1, sizeof(*argv)); 67 char **argvp; 68 69 if (argv == NULL) 70 goto out; 71 72 if (argcp) 73 *argcp = argc; 74 75 argvp = argv; 76 77 while (*str) { 78 str = skip_spaces(str); 79 80 if (*str) { 81 const char *p = str; 82 char *t; 83 84 str = skip_arg(str); 85 86 t = strndup(p, str-p); 87 if (t == NULL) 88 goto fail; 89 *argvp++ = t; 90 } 91 } 92 *argvp = NULL; 93 94 out: 95 return argv; 96 97 fail: 98 argv_free(argv); 99 return NULL; 100 } 101