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