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