[client,common] add custom line parser option

freerdp_client_settings_parse_command_line_arguments_ex allows supplying
user defined options to be parsed with the default ones from
client/common.
A callback must be implemented to handle the supplied arguments.
This commit is contained in:
Armin Novak 2023-10-21 14:39:43 +02:00 committed by Martin Fleisz
parent 925e2bf5f1
commit 16c4ede603
2 changed files with 100 additions and 30 deletions

View File

@ -506,36 +506,53 @@ BOOL freerdp_client_print_command_line_help(int argc, char** argv)
return freerdp_client_print_command_line_help_ex(argc, argv, NULL); return freerdp_client_print_command_line_help_ex(argc, argv, NULL);
} }
BOOL freerdp_client_print_command_line_help_ex(int argc, char** argv, static COMMAND_LINE_ARGUMENT_A* create_merged_args(const COMMAND_LINE_ARGUMENT_A* custom,
const COMMAND_LINE_ARGUMENT_A* custom) SSIZE_T count, size_t* pcount)
{ {
const char* name = "FreeRDP"; WINPR_ASSERT(pcount);
if (count < 0)
size_t count = 0; {
const COMMAND_LINE_ARGUMENT_A* cur = custom; const COMMAND_LINE_ARGUMENT_A* cur = custom;
count = 0;
while (cur && cur->Name) while (cur && cur->Name)
{ {
count++; count++;
cur++; cur++;
} }
}
/* allocate a merged copy of implementation defined and default arguments */
COMMAND_LINE_ARGUMENT_A* largs = COMMAND_LINE_ARGUMENT_A* largs =
calloc(count + ARRAYSIZE(global_cmd_args), sizeof(COMMAND_LINE_ARGUMENT_A)); calloc(count + ARRAYSIZE(global_cmd_args), sizeof(COMMAND_LINE_ARGUMENT_A));
*pcount = 0;
if (!largs) if (!largs)
return FALSE; NULL;
count = 0; size_t lcount = 0;
cur = custom; const COMMAND_LINE_ARGUMENT_A* cur = custom;
while (cur && cur->Name) while (cur && cur->Name)
{ {
largs[count++] = *cur++; largs[lcount++] = *cur++;
} }
cur = global_cmd_args; cur = global_cmd_args;
while (cur && cur->Name) while (cur && cur->Name)
{ {
largs[count++] = *cur++; largs[lcount++] = *cur++;
} }
*pcount = lcount;
return largs;
}
BOOL freerdp_client_print_command_line_help_ex(int argc, char** argv,
const COMMAND_LINE_ARGUMENT_A* custom)
{
const char* name = "FreeRDP";
/* allocate a merged copy of implementation defined and default arguments */
size_t lcount = 0;
COMMAND_LINE_ARGUMENT_A* largs = create_merged_args(custom, -1, &lcount);
if (!largs)
return FALSE;
if (argc > 0) if (argc > 0)
name = argv[0]; name = argv[0];
@ -552,7 +569,8 @@ BOOL freerdp_client_print_command_line_help_ex(int argc, char** argv,
printf(" +toggle -toggle (enables or disables toggle, where '/' is a synonym of '+')\n"); printf(" +toggle -toggle (enables or disables toggle, where '/' is a synonym of '+')\n");
printf("\n"); printf("\n");
freerdp_client_print_command_line_args(largs, count); freerdp_client_print_command_line_args(largs, lcount);
free(largs);
printf("\n"); printf("\n");
printf("Examples:\n"); printf("Examples:\n");
@ -2773,8 +2791,10 @@ static void fill_credential_strings(COMMAND_LINE_ARGUMENT_A* args)
} }
} }
static int freerdp_client_settings_parse_command_line_arguments_int(rdpSettings* settings, int argc, static int freerdp_client_settings_parse_command_line_arguments_int(
char* argv[], BOOL allowUnknown) rdpSettings* settings, int argc, char* argv[], BOOL allowUnknown,
COMMAND_LINE_ARGUMENT_A* largs, size_t count,
int (*handle_option)(const COMMAND_LINE_ARGUMENT* arg, void* custom), void* handle_userdata)
{ {
char* user = NULL; char* user = NULL;
char* str; char* str;
@ -2785,8 +2805,6 @@ static int freerdp_client_settings_parse_command_line_arguments_int(rdpSettings*
BOOL promptForPassword = FALSE; BOOL promptForPassword = FALSE;
BOOL compatibility = FALSE; BOOL compatibility = FALSE;
const COMMAND_LINE_ARGUMENT_A* arg; const COMMAND_LINE_ARGUMENT_A* arg;
COMMAND_LINE_ARGUMENT_A largs[ARRAYSIZE(global_cmd_args)];
memcpy(largs, global_cmd_args, sizeof(global_cmd_args));
/* Command line detection fails if only a .rdp or .msrcIncident file /* Command line detection fails if only a .rdp or .msrcIncident file
* is supplied. Check this case first, only then try to detect * is supplied. Check this case first, only then try to detect
@ -4623,6 +4641,12 @@ static int freerdp_client_settings_parse_command_line_arguments_int(rdpSettings*
} }
CommandLineSwitchDefault(arg) CommandLineSwitchDefault(arg)
{ {
if (handle_option)
{
const int rc = handle_option(arg, handle_userdata);
if (rc != 0)
return rc;
}
} }
CommandLineSwitchEnd(arg) CommandLineSwitchEnd(arg)
} while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
@ -4848,10 +4872,19 @@ cleanup:
int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, int oargc, int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, int oargc,
char* oargv[], BOOL allowUnknown) char* oargv[], BOOL allowUnknown)
{
return freerdp_client_settings_parse_command_line_arguments_ex(
settings, oargc, oargv, allowUnknown, NULL, 0, NULL, NULL);
}
int freerdp_client_settings_parse_command_line_arguments_ex(
rdpSettings* settings, int oargc, char** oargv, BOOL allowUnknown,
COMMAND_LINE_ARGUMENT_A* args, size_t count,
int (*handle_option)(const COMMAND_LINE_ARGUMENT* arg, void* custom), void* handle_userdata)
{ {
int argc = oargc; int argc = oargc;
char** argv = oargv; char** argv = oargv;
int res = -1;
int aargc = 0; int aargc = 0;
char** aargv = NULL; char** aargv = NULL;
if ((argc == 2) && option_starts_with("/args-from:", argv[1])) if ((argc == 2) && option_starts_with("/args-from:", argv[1]))
@ -4888,8 +4921,15 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
argv = aargv; argv = aargv;
} }
int res = freerdp_client_settings_parse_command_line_arguments_int(settings, argc, argv, size_t lcount = 0;
allowUnknown); COMMAND_LINE_ARGUMENT_A* largs = create_merged_args(args, count, &lcount);
if (!largs)
goto fail;
res = freerdp_client_settings_parse_command_line_arguments_int(
settings, argc, argv, allowUnknown, largs, lcount, handle_option, handle_userdata);
fail:
free(largs);
argv_free(aargc, aargv); argv_free(aargc, aargv);
return res; return res;
} }

View File

@ -31,9 +31,39 @@ extern "C"
{ {
#endif #endif
/** \brief parses command line arguments to appropriate settings values.
*
* \param settings The settings instance to store the parsed values to
* \param argc the number of argv values
* \param argv an array of strings (char pointer)
* \param allowUnknown Allow unknown command line arguments or \b FALSE if not.
*
* \return \b 0 in case of success, a negative number in case of failure.
*/
FREERDP_API int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, FREERDP_API int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
int argc, char** argv, int argc, char** argv,
BOOL allowUnknown); BOOL allowUnknown);
/** \brief parses command line arguments to appropriate settings values. Additionally allows
* supplying custom command line arguments and a handler function.
*
* \param settings The settings instance to store the parsed values to
* \param argc the number of argv values
* \param argv an array of strings (char pointer)
* \param allowUnknown Allow unknown command line arguments or \b FALSE if not.
* \param args Pointer to the custom arguments
* \param count The number of custom arguments
* \param handle_option the handler function for custom arguments.
* \param handle_userdata custom data supplied to \b handle_option as context
*
* \return \b 0 in case of success, a negative number in case of failure.
*/
FREERDP_API int freerdp_client_settings_parse_command_line_arguments_ex(
rdpSettings* settings, int argc, char** argv, BOOL allowUnknown,
COMMAND_LINE_ARGUMENT_A* args, size_t count,
int (*handle_option)(const COMMAND_LINE_ARGUMENT* arg, void* custom),
void* handle_userdata);
FREERDP_API int freerdp_client_settings_command_line_status_print(rdpSettings* settings, FREERDP_API int freerdp_client_settings_command_line_status_print(rdpSettings* settings,
int status, int argc, int status, int argc,
char** argv); char** argv);