[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,37 +506,54 @@ BOOL freerdp_client_print_command_line_help(int argc, char** argv)
return freerdp_client_print_command_line_help_ex(argc, argv, NULL);
}
static COMMAND_LINE_ARGUMENT_A* create_merged_args(const COMMAND_LINE_ARGUMENT_A* custom,
SSIZE_T count, size_t* pcount)
{
WINPR_ASSERT(pcount);
if (count < 0)
{
const COMMAND_LINE_ARGUMENT_A* cur = custom;
count = 0;
while (cur && cur->Name)
{
count++;
cur++;
}
}
COMMAND_LINE_ARGUMENT_A* largs =
calloc(count + ARRAYSIZE(global_cmd_args), sizeof(COMMAND_LINE_ARGUMENT_A));
*pcount = 0;
if (!largs)
NULL;
size_t lcount = 0;
const COMMAND_LINE_ARGUMENT_A* cur = custom;
while (cur && cur->Name)
{
largs[lcount++] = *cur++;
}
cur = global_cmd_args;
while (cur && cur->Name)
{
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";
size_t count = 0;
const COMMAND_LINE_ARGUMENT_A* cur = custom;
while (cur && cur->Name)
{
count++;
cur++;
}
/* allocate a merged copy of implementation defined and default arguments */
COMMAND_LINE_ARGUMENT_A* largs =
calloc(count + ARRAYSIZE(global_cmd_args), sizeof(COMMAND_LINE_ARGUMENT_A));
size_t lcount = 0;
COMMAND_LINE_ARGUMENT_A* largs = create_merged_args(custom, -1, &lcount);
if (!largs)
return FALSE;
count = 0;
cur = custom;
while (cur && cur->Name)
{
largs[count++] = *cur++;
}
cur = global_cmd_args;
while (cur && cur->Name)
{
largs[count++] = *cur++;
}
if (argc > 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("\n");
freerdp_client_print_command_line_args(largs, count);
freerdp_client_print_command_line_args(largs, lcount);
free(largs);
printf("\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,
char* argv[], BOOL allowUnknown)
static int freerdp_client_settings_parse_command_line_arguments_int(
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* str;
@ -2785,8 +2805,6 @@ static int freerdp_client_settings_parse_command_line_arguments_int(rdpSettings*
BOOL promptForPassword = FALSE;
BOOL compatibility = FALSE;
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
* 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)
{
if (handle_option)
{
const int rc = handle_option(arg, handle_userdata);
if (rc != 0)
return rc;
}
}
CommandLineSwitchEnd(arg)
} while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
@ -4848,10 +4872,19 @@ cleanup:
int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, int oargc,
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;
char** argv = oargv;
int res = -1;
int aargc = 0;
char** aargv = NULL;
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;
}
int res = freerdp_client_settings_parse_command_line_arguments_int(settings, argc, argv,
allowUnknown);
size_t lcount = 0;
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);
return res;
}

View File

@ -31,9 +31,39 @@ extern "C"
{
#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,
int argc, char** argv,
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,
int status, int argc,
char** argv);