| /* |
| * 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); |