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