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  
skip_arg(const char * cp)11  static const char *skip_arg(const char *cp)
12  {
13  	while (*cp && !isspace(*cp))
14  		cp++;
15  
16  	return cp;
17  }
18  
count_argc(const char * str)19  static 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   */
argv_free(char ** argv)40  void 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   */
argv_split(const char * str,int * argcp)63  char **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  
94  out:
95  	return argv;
96  
97  fail:
98  	argv_free(argv);
99  	return NULL;
100  }
101