diff --git a/include/freerdp/server/shadow.h b/include/freerdp/server/shadow.h index af8319815..25bf7a9ed 100644 --- a/include/freerdp/server/shadow.h +++ b/include/freerdp/server/shadow.h @@ -339,7 +339,7 @@ extern "C" COMMAND_LINE_ARGUMENT_A* cargs); FREERDP_API int shadow_server_command_line_status_print(rdpShadowServer* server, int argc, char** argv, int status, - COMMAND_LINE_ARGUMENT_A* cargs); + const COMMAND_LINE_ARGUMENT_A* cargs); FREERDP_API int shadow_server_start(rdpShadowServer* server); FREERDP_API int shadow_server_stop(rdpShadowServer* server); diff --git a/server/shadow/shadow_server.c b/server/shadow/shadow_server.c index 138a5d2c7..97a136d91 100644 --- a/server/shadow/shadow_server.c +++ b/server/shadow/shadow_server.c @@ -59,35 +59,67 @@ static int fail_at_(const COMMAND_LINE_ARGUMENT_A* arg, int rc, const char* file return rc; } -static int shadow_server_print_command_line_help(int argc, char** argv, - COMMAND_LINE_ARGUMENT_A* largs) +static int command_line_compare(const void* pa, const void* pb) +{ + const COMMAND_LINE_ARGUMENT_A* a = pa; + const COMMAND_LINE_ARGUMENT_A* b = pb; + + if (!a && !b) + return 0; + if (!a) + return -1; + if (!b) + return 1; + + return strcmp(a->Name, b->Name); +} + +static int shadow_server_print_command_line_help(int argc, char** argv, + const COMMAND_LINE_ARGUMENT_A* largs) { - char* str = NULL; - size_t length = 0; - const COMMAND_LINE_ARGUMENT_A* arg = NULL; if ((argc < 1) || !largs || !argv) return -1; - char* path = winpr_GetConfigFilePath(TRUE, "SAM"); - printf("Usage: %s [options]\n", argv[0]); - printf("\n"); - printf("Notes: By default NLA security is active.\n"); - printf("\tIn this mode a SAM database is required.\n"); - printf("\tProvide one with /sam-file:\n"); - printf("\telse the default path %s is used.\n", path); - printf("\tIf there is no existing SAM file authentication for all users will fail.\n"); - printf( - "\n\tIf authentication against PAM is desired, start with -sec-nla (requires compiled in " - "support for PAM)\n\n"); - printf("Syntax:\n"); - printf(" /flag (enables flag)\n"); - printf(" /option: (specifies option with value)\n"); - printf(" +toggle -toggle (enables or disables toggle, where '/' is a synonym of '+')\n"); - printf("\n"); - free(path); + { + char* path = winpr_GetConfigFilePath(TRUE, "SAM"); + printf("Usage: %s [options]\n", argv[0]); + printf("\n"); + printf("Notes: By default NLA security is active.\n"); + printf("\tIn this mode a SAM database is required.\n"); + printf("\tProvide one with /sam-file:\n"); + printf("\telse the default path %s is used.\n", path); + printf("\tIf there is no existing SAM file authentication for all users will fail.\n"); + printf("\n\tIf authentication against PAM is desired, start with -sec-nla (requires " + "compiled in " + "support for PAM)\n\n"); + printf("Syntax:\n"); + printf(" /flag (enables flag)\n"); + printf(" /option: (specifies option with value)\n"); + printf(" +toggle -toggle (enables or disables toggle, where '/' is a synonym of '+')\n"); + printf("\n"); + free(path); + } - arg = largs; + // TODO: Sort arguments + size_t nrArgs = 0; + { + const COMMAND_LINE_ARGUMENT_A* arg = largs; + while (arg->Name != NULL) + { + nrArgs++; + arg++; + } + nrArgs++; + } + COMMAND_LINE_ARGUMENT_A* args_copy = calloc(nrArgs, sizeof(COMMAND_LINE_ARGUMENT_A)); + if (!args_copy) + return -1; + memcpy(args_copy, largs, nrArgs * sizeof(COMMAND_LINE_ARGUMENT_A)); + qsort(args_copy, nrArgs - 1, sizeof(COMMAND_LINE_ARGUMENT_A), command_line_compare); + const COMMAND_LINE_ARGUMENT_A* arg = args_copy; + + int rc = -1; do { if (arg->Flags & COMMAND_LINE_VALUE_FLAG) @@ -103,11 +135,11 @@ static int shadow_server_print_command_line_help(int argc, char** argv, if (arg->Format) { - length = (strlen(arg->Name) + strlen(arg->Format) + 2); - str = (char*)malloc(length + 1); + const size_t length = (strlen(arg->Name) + strlen(arg->Format) + 2); + char* str = (char*)calloc(length + 1, sizeof(char)); if (!str) - return -1; + goto fail; (void)sprintf_s(str, length + 1, "%s:%s", arg->Name, arg->Format); (void)printf("%-20s\n", str); @@ -122,26 +154,30 @@ static int shadow_server_print_command_line_help(int argc, char** argv, } else if (arg->Flags & COMMAND_LINE_VALUE_BOOL) { - length = strlen(arg->Name) + 32; - str = (char*)malloc(length + 1); + const size_t length = strlen(arg->Name) + 32; + char* str = calloc(length + 1, sizeof(char)); if (!str) - return -1; + goto fail; (void)sprintf_s(str, length + 1, "%s (default:%s)", arg->Name, arg->Default ? "on" : "off"); (void)printf(" %s", arg->Default ? "-" : "+"); (void)printf("%-20s\n", str); - free(str); (void)printf("\t%s\n", arg->Text); + + free(str); } } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); - return 1; + rc = 1; +fail: + free(args_copy); + return rc; } int shadow_server_command_line_status_print(rdpShadowServer* server, int argc, char** argv, - int status, COMMAND_LINE_ARGUMENT_A* cargs) + int status, const COMMAND_LINE_ARGUMENT_A* cargs) { WINPR_UNUSED(server);