argv_split.c (1721B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Helper function for splitting a string into an argv-like array. 4 */ 5 6#include <stdlib.h> 7#include <linux/kernel.h> 8#include <linux/ctype.h> 9#include <linux/string.h> 10 11static const char *skip_arg(const char *cp) 12{ 13 while (*cp && !isspace(*cp)) 14 cp++; 15 16 return cp; 17} 18 19static int count_argc(const char *str) 20{ 21 int count = 0; 22 23 while (*str) { 24 str = skip_spaces(str); 25 if (*str) { 26 count++; 27 str = skip_arg(str); 28 } 29 } 30 31 return count; 32} 33 34/** 35 * argv_free - free an argv 36 * @argv - the argument vector to be freed 37 * 38 * Frees an argv and the strings it points to. 39 */ 40void argv_free(char **argv) 41{ 42 char **p; 43 for (p = argv; *p; p++) { 44 free(*p); 45 *p = NULL; 46 } 47 48 free(argv); 49} 50 51/** 52 * argv_split - split a string at whitespace, returning an argv 53 * @str: the string to be split 54 * @argcp: returned argument count 55 * 56 * Returns an array of pointers to strings which are split out from 57 * @str. This is performed by strictly splitting on white-space; no 58 * quote processing is performed. Multiple whitespace characters are 59 * considered to be a single argument separator. The returned array 60 * is always NULL-terminated. Returns NULL on memory allocation 61 * failure. 62 */ 63char **argv_split(const char *str, int *argcp) 64{ 65 int argc = count_argc(str); 66 char **argv = calloc(argc + 1, sizeof(*argv)); 67 char **argvp; 68 69 if (argv == NULL) 70 goto out; 71 72 if (argcp) 73 *argcp = argc; 74 75 argvp = argv; 76 77 while (*str) { 78 str = skip_spaces(str); 79 80 if (*str) { 81 const char *p = str; 82 char *t; 83 84 str = skip_arg(str); 85 86 t = strndup(p, str-p); 87 if (t == NULL) 88 goto fail; 89 *argvp++ = t; 90 } 91 } 92 *argvp = NULL; 93 94out: 95 return argv; 96 97fail: 98 argv_free(argv); 99 return NULL; 100}