#include "tokenize.h" #include #include #define LOG_MODULE "tokenize" #define LOG_ENABLE_DBG 0 #include "log.h" static bool push_argv(char ***argv, size_t *size, char *arg, size_t *argc) { if (arg != NULL && arg[0] == '%') return true; if (*argc >= *size) { size_t new_size = *size > 0 ? 2 * *size : 10; char **new_argv = realloc(*argv, new_size * sizeof(new_argv[0])); if (new_argv == NULL) return false; *argv = new_argv; *size = new_size; } (*argv)[(*argc)++] = arg; return true; } bool tokenize_cmdline(char *cmdline, char ***argv) { *argv = NULL; size_t argv_size = 0; bool first_token_is_quoted = cmdline[0] == '"' || cmdline[0] == '\''; char delim = first_token_is_quoted ? cmdline[0] : ' '; char *p = first_token_is_quoted ? &cmdline[1] : &cmdline[0]; size_t idx = 0; while (*p != '\0') { char *end = strchr(p, delim); if (end == NULL) { if (delim != ' ') { LOG_ERR("unterminated %s quote\n", delim == '"' ? "double" : "single"); free(*argv); return false; } if (!push_argv(argv, &argv_size, p, &idx) || !push_argv(argv, &argv_size, NULL, &idx)) { goto err; } else return true; } *end = '\0'; if (!push_argv(argv, &argv_size, p, &idx)) goto err; p = end + 1; while (*p == delim) p++; while (*p == ' ') p++; if (*p == '"' || *p == '\'') { delim = *p; p++; } else delim = ' '; } if (!push_argv(argv, &argv_size, NULL, &idx)) goto err; return true; err: free(*argv); return false; }