| /* | |
| * Helper function for splitting a string into an argv-like array. | |
| */ | |
| #include <linux/kernel.h> | |
| #include <linux/ctype.h> | |
| #include <linux/slab.h> | |
| #include <linux/module.h> | |
| static const char *skip_sep(const char *cp) | |
| { | |
| while (*cp && isspace(*cp)) | |
| cp++; | |
| return cp; | |
| } | |
| static const char *skip_arg(const char *cp) | |
| { | |
| while (*cp && !isspace(*cp)) | |
| cp++; | |
| return cp; | |
| } | |
| static int count_argc(const char *str) | |
| { | |
| int count = 0; | |
| while (*str) { | |
| str = skip_sep(str); | |
| if (*str) { | |
| count++; | |
| str = skip_arg(str); | |
| } | |
| } | |
| return count; | |
| } | |
| /** | |
| * argv_free - free an argv | |
| * @argv - the argument vector to be freed | |
| * | |
| * Frees an argv and the strings it points to. | |
| */ | |
| void argv_free(char **argv) | |
| { | |
| char **p; | |
| for (p = argv; *p; p++) | |
| kfree(*p); | |
| kfree(argv); | |
| } | |
| EXPORT_SYMBOL(argv_free); | |
| /** | |
| * argv_split - split a string at whitespace, returning an argv | |
| * @gfp: the GFP mask used to allocate memory | |
| * @str: the string to be split | |
| * @argcp: returned argument count | |
| * | |
| * Returns an array of pointers to strings which are split out from | |
| * @str. This is performed by strictly splitting on white-space; no | |
| * quote processing is performed. Multiple whitespace characters are | |
| * considered to be a single argument separator. The returned array | |
| * is always NULL-terminated. Returns NULL on memory allocation | |
| * failure. | |
| */ | |
| char **argv_split(gfp_t gfp, const char *str, int *argcp) | |
| { | |
| int argc = count_argc(str); | |
| char **argv = kzalloc(sizeof(*argv) * (argc+1), gfp); | |
| char **argvp; | |
| if (argv == NULL) | |
| goto out; | |
| if (argcp) | |
| *argcp = argc; | |
| argvp = argv; | |
| while (*str) { | |
| str = skip_sep(str); | |
| if (*str) { | |
| const char *p = str; | |
| char *t; | |
| str = skip_arg(str); | |
| t = kstrndup(p, str-p, gfp); | |
| if (t == NULL) | |
| goto fail; | |
| *argvp++ = t; | |
| } | |
| } | |
| *argvp = NULL; | |
| out: | |
| return argv; | |
| fail: | |
| argv_free(argv); | |
| return NULL; | |
| } | |
| EXPORT_SYMBOL(argv_split); |