Back to home page

LXR

 
 

    


0001 /*
0002  * Helper function for splitting a string into an argv-like array.
0003  */
0004 
0005 #include <linux/kernel.h>
0006 #include <linux/ctype.h>
0007 #include <linux/string.h>
0008 #include <linux/slab.h>
0009 #include <linux/export.h>
0010 
0011 static int count_argc(const char *str)
0012 {
0013     int count = 0;
0014     bool was_space;
0015 
0016     for (was_space = true; *str; str++) {
0017         if (isspace(*str)) {
0018             was_space = true;
0019         } else if (was_space) {
0020             was_space = false;
0021             count++;
0022         }
0023     }
0024 
0025     return count;
0026 }
0027 
0028 /**
0029  * argv_free - free an argv
0030  * @argv - the argument vector to be freed
0031  *
0032  * Frees an argv and the strings it points to.
0033  */
0034 void argv_free(char **argv)
0035 {
0036     argv--;
0037     kfree(argv[0]);
0038     kfree(argv);
0039 }
0040 EXPORT_SYMBOL(argv_free);
0041 
0042 /**
0043  * argv_split - split a string at whitespace, returning an argv
0044  * @gfp: the GFP mask used to allocate memory
0045  * @str: the string to be split
0046  * @argcp: returned argument count
0047  *
0048  * Returns an array of pointers to strings which are split out from
0049  * @str.  This is performed by strictly splitting on white-space; no
0050  * quote processing is performed.  Multiple whitespace characters are
0051  * considered to be a single argument separator.  The returned array
0052  * is always NULL-terminated.  Returns NULL on memory allocation
0053  * failure.
0054  *
0055  * The source string at `str' may be undergoing concurrent alteration via
0056  * userspace sysctl activity (at least).  The argv_split() implementation
0057  * attempts to handle this gracefully by taking a local copy to work on.
0058  */
0059 char **argv_split(gfp_t gfp, const char *str, int *argcp)
0060 {
0061     char *argv_str;
0062     bool was_space;
0063     char **argv, **argv_ret;
0064     int argc;
0065 
0066     argv_str = kstrndup(str, KMALLOC_MAX_SIZE - 1, gfp);
0067     if (!argv_str)
0068         return NULL;
0069 
0070     argc = count_argc(argv_str);
0071     argv = kmalloc(sizeof(*argv) * (argc + 2), gfp);
0072     if (!argv) {
0073         kfree(argv_str);
0074         return NULL;
0075     }
0076 
0077     *argv = argv_str;
0078     argv_ret = ++argv;
0079     for (was_space = true; *argv_str; argv_str++) {
0080         if (isspace(*argv_str)) {
0081             was_space = true;
0082             *argv_str = 0;
0083         } else if (was_space) {
0084             was_space = false;
0085             *argv++ = argv_str;
0086         }
0087     }
0088     *argv = NULL;
0089 
0090     if (argcp)
0091         *argcp = argc;
0092     return argv_ret;
0093 }
0094 EXPORT_SYMBOL(argv_split);