Pull dock-bay into release branch
[sfrench/cifs-2.6.git] / lib / argv_split.c
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/bug.h>
8
9 static const char *skip_sep(const char *cp)
10 {
11         while (*cp && isspace(*cp))
12                 cp++;
13
14         return cp;
15 }
16
17 static const char *skip_arg(const char *cp)
18 {
19         while (*cp && !isspace(*cp))
20                 cp++;
21
22         return cp;
23 }
24
25 static int count_argc(const char *str)
26 {
27         int count = 0;
28
29         while (*str) {
30                 str = skip_sep(str);
31                 if (*str) {
32                         count++;
33                         str = skip_arg(str);
34                 }
35         }
36
37         return count;
38 }
39
40 /**
41  * argv_free - free an argv
42  * @argv - the argument vector to be freed
43  *
44  * Frees an argv and the strings it points to.
45  */
46 void argv_free(char **argv)
47 {
48         char **p;
49         for (p = argv; *p; p++)
50                 kfree(*p);
51
52         kfree(argv);
53 }
54 EXPORT_SYMBOL(argv_free);
55
56 /**
57  * argv_split - split a string at whitespace, returning an argv
58  * @gfp: the GFP mask used to allocate memory
59  * @str: the string to be split
60  * @argcp: returned argument count
61  *
62  * Returns an array of pointers to strings which are split out from
63  * @str.  This is performed by strictly splitting on white-space; no
64  * quote processing is performed.  Multiple whitespace characters are
65  * considered to be a single argument separator.  The returned array
66  * is always NULL-terminated.  Returns NULL on memory allocation
67  * failure.
68  */
69 char **argv_split(gfp_t gfp, const char *str, int *argcp)
70 {
71         int argc = count_argc(str);
72         char **argv = kzalloc(sizeof(*argv) * (argc+1), gfp);
73         char **argvp;
74
75         if (argv == NULL)
76                 goto out;
77
78         *argcp = argc;
79         argvp = argv;
80
81         while (*str) {
82                 str = skip_sep(str);
83
84                 if (*str) {
85                         const char *p = str;
86                         char *t;
87
88                         str = skip_arg(str);
89
90                         t = kstrndup(p, str-p, gfp);
91                         if (t == NULL)
92                                 goto fail;
93                         *argvp++ = t;
94                 }
95         }
96         *argvp = NULL;
97
98   out:
99         return argv;
100
101   fail:
102         argv_free(argv);
103         return NULL;
104 }
105 EXPORT_SYMBOL(argv_split);