at v2.6.23 105 lines 1.9 kB view raw
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 9static const char *skip_sep(const char *cp) 10{ 11 while (*cp && isspace(*cp)) 12 cp++; 13 14 return cp; 15} 16 17static const char *skip_arg(const char *cp) 18{ 19 while (*cp && !isspace(*cp)) 20 cp++; 21 22 return cp; 23} 24 25static 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 */ 46void argv_free(char **argv) 47{ 48 char **p; 49 for (p = argv; *p; p++) 50 kfree(*p); 51 52 kfree(argv); 53} 54EXPORT_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 */ 69char **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 *argcp = argc; 79 argvp = argv; 80 81 while (*str) { 82 str = skip_sep(str); 83 84 if (*str) { 85 const char *p = str; 86 char *t; 87 88 str = skip_arg(str); 89 90 t = kstrndup(p, str-p, gfp); 91 if (t == NULL) 92 goto fail; 93 *argvp++ = t; 94 } 95 } 96 *argvp = NULL; 97 98 out: 99 return argv; 100 101 fail: 102 argv_free(argv); 103 return NULL; 104} 105EXPORT_SYMBOL(argv_split);