Skip to content

Commit

Permalink
add argv_split()
Browse files Browse the repository at this point in the history
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
Jeremy Fitzhardinge authored and jsgf committed Jul 18, 2007
1 parent 1e66df3 commit d84d1cc
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 1 deletion.
3 changes: 3 additions & 0 deletions include/linux/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ extern char *kstrdup(const char *s, gfp_t gfp);
extern char *kstrndup(const char *s, size_t len, gfp_t gfp);
extern void *kmemdup(const void *src, size_t len, gfp_t gfp);

extern char **argv_split(gfp_t gfp, const char *str, int *argcp);
extern void argv_free(char **argv);

#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
lib-y := ctype.o string.o vsprintf.o cmdline.o \
rbtree.o radix-tree.o dump_stack.o \
idr.o int_sqrt.o bitmap.o extable.o prio_tree.o \
sha1.o irq_regs.o reciprocal_div.o
sha1.o irq_regs.o reciprocal_div.o argv_split.o

lib-$(CONFIG_MMU) += ioremap.o
lib-$(CONFIG_SMP) += cpumask.o
Expand Down
105 changes: 105 additions & 0 deletions lib/argv_split.c
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);

0 comments on commit d84d1cc

Please sign in to comment.