1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- /*
- * Helper function for splitting a string into an argv-like array.
- */
- #include <linux/kernel.h>
- #include <linux/ctype.h>
- #include <linux/string.h>
- #include <linux/slab.h>
- #include <linux/export.h>
- static int count_argc(const char *str)
- {
- int count = 0;
- bool was_space;
- for (was_space = true; *str; str++) {
- if (isspace(*str)) {
- was_space = true;
- } else if (was_space) {
- was_space = false;
- count++;
- }
- }
- 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)
- {
- argv--;
- kfree(argv[0]);
- 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.
- *
- * The source string at `str' may be undergoing concurrent alteration via
- * userspace sysctl activity (at least). The argv_split() implementation
- * attempts to handle this gracefully by taking a local copy to work on.
- */
- char **argv_split(gfp_t gfp, const char *str, int *argcp)
- {
- char *argv_str;
- bool was_space;
- char **argv, **argv_ret;
- int argc;
- argv_str = kstrndup(str, KMALLOC_MAX_SIZE - 1, gfp);
- if (!argv_str)
- return NULL;
- argc = count_argc(argv_str);
- argv = kmalloc(sizeof(*argv) * (argc + 2), gfp);
- if (!argv) {
- kfree(argv_str);
- return NULL;
- }
- *argv = argv_str;
- argv_ret = ++argv;
- for (was_space = true; *argv_str; argv_str++) {
- if (isspace(*argv_str)) {
- was_space = true;
- *argv_str = 0;
- } else if (was_space) {
- was_space = false;
- *argv++ = argv_str;
- }
- }
- *argv = NULL;
- if (argcp)
- *argcp = argc;
- return argv_ret;
- }
- EXPORT_SYMBOL(argv_split);
|