~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/lib/argv_split.c

Version: ~ [ linux-5.2-rc4 ] ~ [ linux-5.1.9 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.50 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.125 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.181 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.181 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.68 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
 11 static 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  */
 34 void argv_free(char **argv)
 35 {
 36         argv--;
 37         kfree(argv[0]);
 38         kfree(argv);
 39 }
 40 EXPORT_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  */
 59 char **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 }
 94 EXPORT_SYMBOL(argv_split);
 95 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp