diff options
| author | Jeremy Fitzhardinge <jeremy@xensource.com> | 2007-07-17 18:37:02 -0700 | 
|---|---|---|
| committer | Jeremy Fitzhardinge <jeremy@goop.org> | 2007-07-18 08:47:40 -0700 | 
| commit | d84d1cc7647c7e4f77d517e2d87b4a106a0420d9 (patch) | |
| tree | b6ccc40d323998d4ad013c7b05613bc727a8f4e0 | |
| parent | 1e66df3ee301209f4a38df097d7cc5cb9b367a3f (diff) | |
| download | olio-linux-3.10-d84d1cc7647c7e4f77d517e2d87b4a106a0420d9.tar.xz olio-linux-3.10-d84d1cc7647c7e4f77d517e2d87b4a106a0420d9.zip  | |
add argv_split()
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 <jeremy@xensource.com>
Signed-off-by: Chris Wright <chrisw@sous-sol.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Randy Dunlap <randy.dunlap@oracle.com>
| -rw-r--r-- | include/linux/string.h | 3 | ||||
| -rw-r--r-- | lib/Makefile | 2 | ||||
| -rw-r--r-- | lib/argv_split.c | 105 | 
3 files changed, 109 insertions, 1 deletions
diff --git a/include/linux/string.h b/include/linux/string.h index ee5e9ccc4aa..836062b7582 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -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 diff --git a/lib/Makefile b/lib/Makefile index da68b2ca060..61496638740 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -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 diff --git a/lib/argv_split.c b/lib/argv_split.c new file mode 100644 index 00000000000..4096ed42f49 --- /dev/null +++ b/lib/argv_split.c @@ -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);  |