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