forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
argv_split() is a helper function which takes a string, splits it at whitespace, and returns a NULL-terminated argv vector. This is deliberately simple - it does no quote processing of any kind. [ Seems to me that this is something which is already being done in the kernel, but I couldn't find any other implementations, either to steal or replace. Keep an eye out. ] Signed-off-by: Jeremy Fitzhardinge <[email protected]> Signed-off-by: Chris Wright <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Randy Dunlap <[email protected]>
- Loading branch information
Showing
3 changed files
with
109 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/* | ||
* Helper function for splitting a string into an argv-like array. | ||
*/ | ||
|
||
#include <linux/kernel.h> | ||
#include <linux/ctype.h> | ||
#include <linux/bug.h> | ||
|
||
static const char *skip_sep(const char *cp) | ||
{ | ||
while (*cp && isspace(*cp)) | ||
cp++; | ||
|
||
return cp; | ||
} | ||
|
||
static const char *skip_arg(const char *cp) | ||
{ | ||
while (*cp && !isspace(*cp)) | ||
cp++; | ||
|
||
return cp; | ||
} | ||
|
||
static int count_argc(const char *str) | ||
{ | ||
int count = 0; | ||
|
||
while (*str) { | ||
str = skip_sep(str); | ||
if (*str) { | ||
count++; | ||
str = skip_arg(str); | ||
} | ||
} | ||
|
||
return count; | ||
} | ||
|
||
/** | ||
* argv_free - free an argv | ||
* @argv - the argument vector to be freed | ||
* | ||
* Frees an argv and the strings it points to. | ||
*/ | ||
void argv_free(char **argv) | ||
{ | ||
char **p; | ||
for (p = argv; *p; p++) | ||
kfree(*p); | ||
|
||
kfree(argv); | ||
} | ||
EXPORT_SYMBOL(argv_free); | ||
|
||
/** | ||
* argv_split - split a string at whitespace, returning an argv | ||
* @gfp: the GFP mask used to allocate memory | ||
* @str: the string to be split | ||
* @argcp: returned argument count | ||
* | ||
* Returns an array of pointers to strings which are split out from | ||
* @str. This is performed by strictly splitting on white-space; no | ||
* quote processing is performed. Multiple whitespace characters are | ||
* considered to be a single argument separator. The returned array | ||
* is always NULL-terminated. Returns NULL on memory allocation | ||
* failure. | ||
*/ | ||
char **argv_split(gfp_t gfp, const char *str, int *argcp) | ||
{ | ||
int argc = count_argc(str); | ||
char **argv = kzalloc(sizeof(*argv) * (argc+1), gfp); | ||
char **argvp; | ||
|
||
if (argv == NULL) | ||
goto out; | ||
|
||
*argcp = argc; | ||
argvp = argv; | ||
|
||
while (*str) { | ||
str = skip_sep(str); | ||
|
||
if (*str) { | ||
const char *p = str; | ||
char *t; | ||
|
||
str = skip_arg(str); | ||
|
||
t = kstrndup(p, str-p, gfp); | ||
if (t == NULL) | ||
goto fail; | ||
*argvp++ = t; | ||
} | ||
} | ||
*argvp = NULL; | ||
|
||
out: | ||
return argv; | ||
|
||
fail: | ||
argv_free(argv); | ||
return NULL; | ||
} | ||
EXPORT_SYMBOL(argv_split); |