diff --git a/hook/args.c b/hook/args.c new file mode 100644 index 0000000..5211bd3 --- /dev/null +++ b/hook/args.c @@ -0,0 +1,137 @@ +#include + +#include +#include +#include +#include +#include + +#include "hook/args.h" + +/* This does not handle escaped double quotes inside args correctly yet */ + +static HRESULT args_push( + int *argc, + char ***argv, + const char *begin, + const char *end) +{ + int tmp_argc; + char **tmp_argv; + size_t nchars; + char *str; + + nchars = end - begin; + str = malloc(nchars + 1); + + if (str == NULL) { + goto fail; + } + + memcpy(str, begin, nchars); + str[nchars] = '\0'; + + tmp_argc = *argc + 1; + tmp_argv = realloc(*argv, tmp_argc * sizeof(char **)); + + if (tmp_argv == NULL) { + goto fail; + } + + tmp_argv[tmp_argc - 1] = str; + + *argv = tmp_argv; + *argc = tmp_argc; + + return S_OK; + +fail: + free(str); + + return E_OUTOFMEMORY; +} + +HRESULT args_recover(int *argc_out, char ***argv_out) +{ + int argc; + char **argv; + const char *begin; + const char *pos; + bool quote; + HRESULT hr; + + assert(argc_out != NULL); + assert(argv_out != NULL); + + *argc_out = 0; + *argv_out = NULL; + + argc = 0; + argv = NULL; + quote = false; + + for (begin = pos = GetCommandLine() ; *pos ; pos++) { + switch (*pos) { + case '"': + if (!quote) { + quote = true; + begin = pos + 1; + } else { + hr = args_push(&argc, &argv, begin, pos); + + if (FAILED(hr)) { + goto fail; + } + + quote = false; + begin = NULL; + } + + break; + + case ' ': + if (!quote && begin != NULL) { + args_push(&argc, &argv, begin, pos); + begin = NULL; + } + + break; + + default: + if (begin == NULL) { + begin = pos; + } + + break; + } + } + + if (begin != NULL && !quote) { + hr = args_push(&argc, &argv, begin, pos); + + if (FAILED(hr)) { + goto fail; + } + } + + *argc_out = argc; + *argv_out = argv; + + return S_OK; + +fail: + args_free(argc, argv); + + return hr; +} + +void args_free(int argc, char **argv) +{ + int i; + + for (i = 0 ; i < argc ; i++) { + free(argv[i]); + } + + free(argv); +} diff --git a/hook/args.h b/hook/args.h new file mode 100644 index 0000000..2f4d586 --- /dev/null +++ b/hook/args.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +HRESULT args_recover(int *argc, char ***argv); +void args_free(int argc, char **argv); diff --git a/hook/meson.build b/hook/meson.build index 79f2168..3658456 100644 --- a/hook/meson.build +++ b/hook/meson.build @@ -3,6 +3,8 @@ hook_lib = static_library( include_directories : inc, c_pch : '../precompiled.h', sources : [ + 'args.c', + 'args.h', 'com-proxy.c', 'com-proxy.h', 'hr.c',