#include "util/cmdline.h" #include "util/mem.h" #include #include #include #include #include static void push_argv(int *argc, char ***argv, const char *begin, const char *end) { size_t nchars; char *str; (*argc)++; *argv = xrealloc(*argv, *argc * sizeof(char **)); nchars = end - begin; str = xmalloc(nchars + 1); memcpy(str, begin, nchars); str[nchars] = '\0'; (*argv)[*argc - 1] = str; } void args_recover(int *argc_out, char ***argv_out) { int argc; char **argv; const char *begin; const char *pos; bool quote; argc = 0; argv = NULL; quote = false; for (begin = pos = GetCommandLine(); *pos; pos++) { switch (*pos) { case '"': if (!quote) { quote = true; begin = pos + 1; } else { push_argv(&argc, &argv, begin, pos); quote = false; begin = NULL; } break; case ' ': if (!quote && begin != NULL) { push_argv(&argc, &argv, begin, pos); begin = NULL; } break; default: if (begin == NULL) { begin = pos; } break; } } if (begin != NULL && !quote) { push_argv(&argc, &argv, begin, pos); } *argc_out = argc; *argv_out = argv; } void args_free(int argc, char **argv) { int i; for (i = 0; i < argc; i++) { free(argv[i]); } free(argv); } char *args_join(int argc, char **argv) { char *pos; char *str; uint32_t nchars; uint32_t part_len; int i; nchars = 0; for (i = 0; i < argc; i++) { /* 3 = leading space plus two surrounding quotes. The first element has no leading space, but this is counterbalanced by the fact that the string needs a NUL terminator. */ nchars += 3 + strlen(argv[i]); } str = xmalloc(nchars); pos = str; for (i = 0; i < argc; i++) { if (i != 0) { *pos++ = ' '; } *pos++ = '"'; part_len = strlen(argv[i]); memcpy(pos, argv[i], part_len); pos += part_len; *pos++ = '"'; } *pos = '\0'; return str; }