linux/lib/argv_split.c
<<
>>
Prefs
   1/*
   2 * Helper function for splitting a string into an argv-like array.
   3 */
   4
   5#include <linux/kernel.h>
   6#include <linux/ctype.h>
   7#include <linux/string.h>
   8#include <linux/slab.h>
   9#include <linux/export.h>
  10
  11static int count_argc(const char *str)
  12{
  13        int count = 0;
  14        bool was_space;
  15
  16        for (was_space = true; *str; str++) {
  17                if (isspace(*str)) {
  18                        was_space = true;
  19                } else if (was_space) {
  20                        was_space = false;
  21                        count++;
  22                }
  23        }
  24
  25        return count;
  26}
  27
  28/**
  29 * argv_free - free an argv
  30 * @argv - the argument vector to be freed
  31 *
  32 * Frees an argv and the strings it points to.
  33 */
  34void argv_free(char **argv)
  35{
  36        argv--;
  37        kfree(argv[0]);
  38        kfree(argv);
  39}
  40EXPORT_SYMBOL(argv_free);
  41
  42/**
  43 * argv_split - split a string at whitespace, returning an argv
  44 * @gfp: the GFP mask used to allocate memory
  45 * @str: the string to be split
  46 * @argcp: returned argument count
  47 *
  48 * Returns an array of pointers to strings which are split out from
  49 * @str.  This is performed by strictly splitting on white-space; no
  50 * quote processing is performed.  Multiple whitespace characters are
  51 * considered to be a single argument separator.  The returned array
  52 * is always NULL-terminated.  Returns NULL on memory allocation
  53 * failure.
  54 *
  55 * The source string at `str' may be undergoing concurrent alteration via
  56 * userspace sysctl activity (at least).  The argv_split() implementation
  57 * attempts to handle this gracefully by taking a local copy to work on.
  58 */
  59char **argv_split(gfp_t gfp, const char *str, int *argcp)
  60{
  61        char *argv_str;
  62        bool was_space;
  63        char **argv, **argv_ret;
  64        int argc;
  65
  66        argv_str = kstrndup(str, KMALLOC_MAX_SIZE - 1, gfp);
  67        if (!argv_str)
  68                return NULL;
  69
  70        argc = count_argc(argv_str);
  71        argv = kmalloc(sizeof(*argv) * (argc + 2), gfp);
  72        if (!argv) {
  73                kfree(argv_str);
  74                return NULL;
  75        }
  76
  77        *argv = argv_str;
  78        argv_ret = ++argv;
  79        for (was_space = true; *argv_str; argv_str++) {
  80                if (isspace(*argv_str)) {
  81                        was_space = true;
  82                        *argv_str = 0;
  83                } else if (was_space) {
  84                        was_space = false;
  85                        *argv++ = argv_str;
  86                }
  87        }
  88        *argv = NULL;
  89
  90        if (argcp)
  91                *argcp = argc;
  92        return argv_ret;
  93}
  94EXPORT_SYMBOL(argv_split);
  95