From b250cce496b785db92042b6c7e7c6ef764cad229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sun, 4 Nov 2012 16:09:43 -0500 Subject: [PATCH] libwinpr-utils: improved command-line API --- winpr/include/winpr/cmdline.h | 15 +++- winpr/libwinpr/utils/cmdline.c | 37 ++++++++- winpr/libwinpr/utils/test/TestCmdLine.c | 101 +++++++++++++++++++++--- 3 files changed, 138 insertions(+), 15 deletions(-) diff --git a/winpr/include/winpr/cmdline.h b/winpr/include/winpr/cmdline.h index 359965bf0..4ae8fe5f4 100644 --- a/winpr/include/winpr/cmdline.h +++ b/winpr/include/winpr/cmdline.h @@ -33,9 +33,9 @@ #define COMMAND_LINE_VALUE_FLAG 0x00000001 #define COMMAND_LINE_VALUE_REQUIRED 0x00000002 #define COMMAND_LINE_VALUE_OPTIONAL 0x00000004 -#define COMMAND_LINE_VALUE_BOOLEAN 0x00000008 +#define COMMAND_LINE_VALUE_BOOL 0x00000008 -#define COMMAND_LINE_ALIAS 0x00000100 +#define COMMAND_LINE_FINAL_ARGUMENT 0x00000100 /* Command-Line Argument Output Flags */ @@ -65,6 +65,13 @@ #define COMMAND_LINE_ERROR_9 -1009 #define COMMAND_LINE_ERROR_10 -1010 +/* Command-Line Macros */ + +#define CommandLineSwitchStart(_arg) if (0) { } +#define CommandLineSwitchCase(_arg, _name) else if (strcmp(_arg->Name, _name) == 0) +#define CommandLineSwitchDefault(_arg) else +#define CommandLineSwitchEnd(_arg) + typedef struct _COMMAND_LINE_ARGUMENT_A COMMAND_LINE_ARGUMENT_A; typedef struct _COMMAND_LINE_ARGUMENT_W COMMAND_LINE_ARGUMENT_W; @@ -74,6 +81,7 @@ struct _COMMAND_LINE_ARGUMENT_A DWORD Flags; LPSTR Value; LPCSTR Alias; + LPCSTR Text; }; struct _COMMAND_LINE_ARGUMENT_W @@ -82,6 +90,7 @@ struct _COMMAND_LINE_ARGUMENT_W DWORD Flags; LPWSTR Value; LPCWSTR Alias; + LPCWSTR Text; }; #ifdef UNICODE @@ -99,6 +108,8 @@ WINPR_API int CommandLineParseArgumentsW(int argc, LPCWSTR* argv, COMMAND_LINE_A WINPR_API COMMAND_LINE_ARGUMENT_A* CommandLineFindArgumentA(COMMAND_LINE_ARGUMENT_A* options, LPCSTR Name); WINPR_API COMMAND_LINE_ARGUMENT_W* CommandLineFindArgumentW(COMMAND_LINE_ARGUMENT_W* options, LPCWSTR Name); +WINPR_API COMMAND_LINE_ARGUMENT_A* CommandLineFindNextArgumentA(COMMAND_LINE_ARGUMENT_A* argument); + #ifdef UNICODE #define CommandLineClearArguments CommandLineClearArgumentsW #define CommandLineParseArguments CommandLineParseArgumentsW diff --git a/winpr/libwinpr/utils/cmdline.c b/winpr/libwinpr/utils/cmdline.c index 237913287..bc9235d05 100644 --- a/winpr/libwinpr/utils/cmdline.c +++ b/winpr/libwinpr/utils/cmdline.c @@ -108,11 +108,19 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* sigil = (char*) &argv[i][sigil_index]; length = strlen(argv[i]); - if ((sigil[sigil_index] == '/') && (flags & COMMAND_LINE_SIGIL_SLASH)) + if ((sigil[0] == '/') && (flags & COMMAND_LINE_SIGIL_SLASH)) { sigil_length = 1; } - else if ((sigil[sigil_index] == '-') && (flags & COMMAND_LINE_SIGIL_DASH)) + else if ((sigil[0] == '-') && (flags & COMMAND_LINE_SIGIL_DASH)) + { + sigil_length = 1; + } + else if ((sigil[0] == '+') && (flags & COMMAND_LINE_SIGIL_PLUS_MINUS)) + { + sigil_length = 1; + } + else if ((sigil[0] == '-') && (flags & COMMAND_LINE_SIGIL_PLUS_MINUS)) { sigil_length = 1; } @@ -143,7 +151,6 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* separator_index = (separator - argv[i]); keyword_length = (separator - keyword); - printf("option: %.*s ", keyword_length, keyword); value_index = separator_index + separator_length; value = (char*) &argv[i][value_index]; @@ -155,7 +162,6 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* separator_index = -1; keyword_length = (length - keyword_index); - printf("option: %.*s ", keyword_length, keyword); value_index = -1; value = NULL; @@ -209,6 +215,17 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* options[j].Value = (LPSTR) 1; options[j].Flags |= COMMAND_LINE_VALUE_PRESENT; } + else if (options[j].Flags & COMMAND_LINE_VALUE_BOOL) + { + if (sigil[0] == '+') + options[j].Value = (LPSTR) 1; + else if (sigil[0] == '-') + options[j].Value = (LPSTR) 0; + else + options[j].Value = (LPSTR) 1; + + options[j].Flags |= COMMAND_LINE_VALUE_PRESENT; + } } } } @@ -285,3 +302,15 @@ COMMAND_LINE_ARGUMENT_W* CommandLineFindArgumentW(COMMAND_LINE_ARGUMENT_W* optio return NULL; } + +COMMAND_LINE_ARGUMENT_A* CommandLineFindNextArgumentA(COMMAND_LINE_ARGUMENT_A* argument) +{ + COMMAND_LINE_ARGUMENT_A* nextArgument; + + nextArgument = &argument[1]; + + if (nextArgument->Name == NULL) + return NULL; + + return nextArgument; +} diff --git a/winpr/libwinpr/utils/test/TestCmdLine.c b/winpr/libwinpr/utils/test/TestCmdLine.c index 07100d131..20c0ccb82 100644 --- a/winpr/libwinpr/utils/test/TestCmdLine.c +++ b/winpr/libwinpr/utils/test/TestCmdLine.c @@ -6,23 +6,51 @@ const char* testArgv[] = { "mstsc.exe", + "+z", "/w:1024", "/h:768", + "/bpp:32", "/admin", "/multimon", + "+fonts", + "-wallpaper", "/v:localhost:3389" }; COMMAND_LINE_ARGUMENT_A args[] = { - { "w", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL }, - { "h", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL }, - { "f", COMMAND_LINE_VALUE_FLAG, NULL, NULL }, - { "admin", COMMAND_LINE_VALUE_FLAG, NULL, "console" }, - { "multimon", COMMAND_LINE_VALUE_FLAG, NULL, NULL }, - { "v", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL }, - { "?", COMMAND_LINE_VALUE_FLAG, NULL, "help" }, - { NULL, 0, NULL, NULL } + { "w", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, "width" }, + { "h", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, "height" }, + { "f", COMMAND_LINE_VALUE_FLAG, NULL, NULL, "fullscreen" }, + { "bpp", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, "session bpp (color depth)" }, + { "v", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, "destination server" }, + { "admin", COMMAND_LINE_VALUE_FLAG, NULL, "console", "admin (or console) session" }, + { "multimon", COMMAND_LINE_VALUE_FLAG, NULL, NULL, "multi-monitor" }, + { "a", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, "addin" }, + { "u", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, "username" }, + { "p", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, "password" }, + { "d", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, "domain" }, + { "z", COMMAND_LINE_VALUE_BOOL, NULL, NULL, "compression" }, + { "audio", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, "audio output mode" }, + { "mic", COMMAND_LINE_VALUE_FLAG, NULL, NULL, "audio input (microphone)" }, + { "fonts", COMMAND_LINE_VALUE_BOOL, NULL, NULL, "smooth fonts (cleartype)" }, + { "aero", COMMAND_LINE_VALUE_BOOL, NULL, NULL, "desktop composition" }, + { "window-drag", COMMAND_LINE_VALUE_BOOL, NULL, NULL, "full window drag" }, + { "menu-anims", COMMAND_LINE_VALUE_BOOL, NULL, NULL, "menu animations" }, + { "themes", COMMAND_LINE_VALUE_BOOL, NULL, NULL, "themes" }, + { "wallpaper", COMMAND_LINE_VALUE_BOOL, NULL, NULL, "wallpaper" }, + { "codec", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, "codec" }, + { "nego", COMMAND_LINE_VALUE_BOOL, NULL, NULL, "protocol security negotiation" }, + { "sec", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, "force specific protocol security" }, + { "sec-rdp", COMMAND_LINE_VALUE_BOOL, NULL, NULL, "rdp protocol security" }, + { "sec-tls", COMMAND_LINE_VALUE_BOOL, NULL, NULL, "tls protocol security" }, + { "sec-nla", COMMAND_LINE_VALUE_BOOL, NULL, NULL, "nla protocol security" }, + { "sec-ext", COMMAND_LINE_VALUE_BOOL, NULL, NULL, "nla extended protocol security" }, + { "cert-name", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, "certificate name" }, + { "cert-ignore", COMMAND_LINE_VALUE_FLAG, NULL, NULL, "ignore certificate" }, + { "ver", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_FINAL_ARGUMENT, NULL, "version", "print version" }, + { "?", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_FINAL_ARGUMENT, NULL, "help", "print help" }, + { NULL, 0, NULL, NULL, NULL } }; #define testArgc (sizeof(testArgv) / sizeof(testArgv[0])) @@ -31,9 +59,10 @@ int TestCmdLine(int argc, char* argv[]) { int status; DWORD flags; + int width, height; COMMAND_LINE_ARGUMENT_A* arg; - flags = COMMAND_LINE_SIGIL_SLASH | COMMAND_LINE_SEPARATOR_COLON; + flags = COMMAND_LINE_SIGIL_SLASH | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_SIGIL_PLUS_MINUS; status = CommandLineParseArgumentsA(testArgc, testArgv, args, flags); if (status != 0) @@ -90,6 +119,22 @@ int TestCmdLine(int argc, char* argv[]) return -1; } + arg = CommandLineFindArgumentA(args, "fonts"); + + if (!arg->Value) + { + printf("CommandLineFindArgumentA: unexpected %s value\n", arg->Name); + return -1; + } + + arg = CommandLineFindArgumentA(args, "wallpaper"); + + if (arg->Value) + { + printf("CommandLineFindArgumentA: unexpected %s value\n", arg->Name); + return -1; + } + arg = CommandLineFindArgumentA(args, "?"); if (arg->Value) @@ -98,5 +143,43 @@ int TestCmdLine(int argc, char* argv[]) return -1; } + arg = args; + + do + { + if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT)) + continue; + + printf("Argument: %s\n", arg->Name); + + CommandLineSwitchStart(arg) + + CommandLineSwitchCase(arg, "v") + { + + } + CommandLineSwitchCase(arg, "w") + { + width = atoi(arg->Value); + } + CommandLineSwitchCase(arg, "h") + { + height = atoi(arg->Value); + } + CommandLineSwitchDefault(arg) + { + + } + + CommandLineSwitchEnd(arg) + } + while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); + + if ((width != 1024) || (height != 768)) + { + printf("Unexpected width and height: Actual: (%dx%d), Expected: (%dx%d)\n", width, height, 1024, 768); + return -1; + } + return 0; }