argv_split: allow argv_split to handle NULL pointer in argcp parameter gracefully
[safe/jmp/linux-2.6] / 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         if (argcp)
79                 *argcp = argc;
80
81         argvp = argv;
82
83         while (*str) {
84                 str = skip_sep(str);
85
86                 if (*str) {
87                         const char *p = str;
88                         char *t;
89
90                         str = skip_arg(str);
91
92                         t = kstrndup(p, str-p, gfp);
93                         if (t == NULL)
94                                 goto fail;
95                         *argvp++ = t;
96                 }
97         }
98         *argvp = NULL;
99
100   out:
101         return argv;
102
103   fail:
104         argv_free(argv);
105         return NULL;
106 }
107 EXPORT_SYMBOL(argv_split);