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