libfreerdp-utils/args: add argument parser.

This commit is contained in:
Vic Lee 2011-07-22 12:53:54 +08:00
parent de5c0c8e25
commit 2beb49725f
6 changed files with 488 additions and 0 deletions

View File

@ -1,6 +1,8 @@
#ifndef __CONFIG_H
#define __CONFIG_H
#define FREERDP_VERSION_FULL "${FREERDP_VERSION_FULL}"
/* Include files */
#cmakedefine HAVE_SYS_PARAM_H
#cmakedefine HAVE_SYS_SOCKET_H

View File

@ -25,6 +25,7 @@
#include <freerdp/utils/semaphore.h>
#include <freerdp/utils/load_plugin.h>
#include <freerdp/utils/wait_obj.h>
#include <freerdp/utils/args.h>
#include "test_utils.h"
@ -46,6 +47,7 @@ int add_utils_suite(void)
add_test_function(semaphore);
add_test_function(load_plugin);
add_test_function(wait_obj);
add_test_function(args);
return 0;
}
@ -100,3 +102,55 @@ void test_wait_obj(void)
wait_obj_free(wo);
}
static int process_plugin_args(rdpSettings* settings, const char* name,
FRDP_PLUGIN_DATA* plugin_data, void* user_data)
{
/*printf("load plugin: %s\n", name);*/
return 1;
}
static int process_ui_args(rdpSettings* settings, const char* opt,
const char* val, void* user_data)
{
/*printf("ui arg: %s %s\n", opt, val);*/
return 1;
}
void test_args(void)
{
char* argv_c[] =
{
"-a", "8", "-u", "testuser", "-d", "testdomain", "-g", "640x480", "address1:3389",
"-a", "16", "-u", "testuser", "-d", "testdomain", "-g", "1280x960", "address2:3390"
};
char** argv = argv_c;
int argc = sizeof(argv_c) / sizeof(char*);
int i;
int c;
rdpSettings* settings;
i = 0;
while (argc > 0)
{
settings = settings_new();
i++;
c = freerdp_parse_args(settings, argc, argv, process_plugin_args, NULL, process_ui_args, NULL);
CU_ASSERT(c > 0);
if (c == 0)
{
settings_free(settings);
break;
}
CU_ASSERT(settings->color_depth == i * 8);
CU_ASSERT(settings->width == i * 640);
CU_ASSERT(settings->height == i * 480);
CU_ASSERT(settings->port == i + 3388);
settings_free(settings);
argc -= c;
argv += c;
}
CU_ASSERT(i == 2);
}

View File

@ -27,3 +27,4 @@ void test_mutex(void);
void test_semaphore(void);
void test_load_plugin(void);
void test_wait_obj(void);
void test_args(void);

View File

@ -0,0 +1,38 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* Arguments Parsing
*
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __ARGS_UTILS_H
#define __ARGS_UTILS_H
#include <freerdp/types.h>
#include <freerdp/settings.h>
/* Returns 1 if succeed, otherwise returns zero */
typedef int (*ProcessPluginArgs) (rdpSettings* settings, const char* name,
FRDP_PLUGIN_DATA* plugin_data, void* user_data);
/* Returns number of arguments processed (1 or 2), otherwise returns zero */
typedef int (*ProcessUIArgs) (rdpSettings* settings, const char* opt,
const char* val, void* user_data);
int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
ProcessPluginArgs plugin_callback, void* plugin_user_data,
ProcessUIArgs ui_callback, void* ui_user_data);
#endif /* __ARGS_UTILS_H */

View File

@ -18,6 +18,7 @@
# limitations under the License.
set(FREERDP_UTILS_SRCS
args.c
blob.c
event.c
hexdump.c

392
libfreerdp-utils/args.c Normal file
View File

@ -0,0 +1,392 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* Arguments Parsing
*
* Copyright 2009-2011 Jay Sorg
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <freerdp/utils/memory.h>
#include <freerdp/utils/args.h>
#define MAX_PLUGIN_DATA 20
/**
* Parse command-line arguments and update rdpSettings members accordingly.
* @param settings pointer to rdpSettings struct to be updated.
* @param argc number of arguments available.
* @param argv string array of the arguments.
* @param plugin_callback function to be called when a plugin needs to be loaded.
* @param plugin_user_data pointer to be passed to the plugin_callback function.
* @param ui_callback function to be called when a UI-specific argument is being processed.
* @param ui_user_data pointer to be passed to the ui_callback function.
* @return number of arguments that has been parsed, or 0 if error occurred.
*/
int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
ProcessPluginArgs plugin_callback, void* plugin_user_data,
ProcessUIArgs ui_callback, void* ui_user_data)
{
int index = 0;
int num_extensions = 0;
int i, j;
int t;
char* p;
FRDP_PLUGIN_DATA plugin_data[MAX_PLUGIN_DATA + 1];
while (index < argc)
{
if (strcmp("-a", argv[index]) == 0)
{
index++;
if (index == argc)
{
printf("missing color depth\n");
return 0;
}
settings->color_depth = atoi(argv[index]);
}
else if (strcmp("-u", argv[index]) == 0)
{
index++;
if (index == argc)
{
printf("missing username\n");
return 0;
}
settings->username = (uint8*)xstrdup(argv[index]);
}
else if (strcmp("-p", argv[index]) == 0)
{
index++;
if (index == argc)
{
printf("missing password\n");
return 0;
}
settings->password = (uint8*)xstrdup(argv[index]);
settings->autologon = 1;
/*
* Overwrite original password which could be revealed by a simple "ps aux" command.
* This approach won't hide the password length, but it is better than nothing.
*/
memset(argv[index], '*', strlen(argv[index]));
}
else if (strcmp("-d", argv[index]) == 0)
{
index++;
if (index == argc)
{
printf("missing domain\n");
return 0;
}
settings->domain = (uint8*)xstrdup(argv[index]);
}
else if (strcmp("-s", argv[index]) == 0)
{
index++;
if (index == argc)
{
printf("missing shell\n");
return 0;
}
settings->shell = (uint8*)xstrdup(argv[index]);
}
else if (strcmp("-c", argv[index]) == 0)
{
index++;
if (index == argc)
{
printf("missing directory\n");
return 0;
}
settings->directory = (uint8*)xstrdup(argv[index]);
}
else if (strcmp("-g", argv[index]) == 0)
{
index++;
if (index == argc)
{
printf("missing width\n");
return 0;
}
settings->width = strtol(argv[index], &p, 10);
if (*p == 'x')
{
settings->height = strtol(p + 1, &p, 10);
}
else
{
ui_callback(settings, "-g", p, ui_user_data);
}
}
else if (strcmp("-t", argv[index]) == 0)
{
index++;
if (index == argc)
{
printf("missing port number\n");
return 0;
}
settings->port = atoi(argv[index]);
}
else if (strcmp("-n", argv[index]) == 0)
{
index++;
if (index == argc)
{
printf("missing client hostname\n");
return 0;
}
strncpy(settings->client_hostname, argv[index], sizeof(settings->client_hostname) - 1);
settings->client_hostname[sizeof(settings->client_hostname) - 1] = 0;
}
else if (strcmp("-o", argv[index]) == 0)
{
settings->console_audio = 1;
}
else if (strcmp("-0", argv[index]) == 0)
{
settings->console_session = 1;
}
else if (strcmp("-z", argv[index]) == 0)
{
settings->compression = 1;
}
else if (strcmp("--no-osb", argv[index]) == 0)
{
settings->off_screen_bitmaps = 0;
}
else if (strcmp("--rfx", argv[index]) == 0)
{
settings->rfx_flags = 1;
settings->ui_decode_flags = 1;
settings->use_frame_ack = 0;
settings->color_depth = 32;
settings->performance_flags = PERF_FLAG_NONE;
}
else if (strcmp("-m", argv[index]) == 0)
{
settings->mouse_motion = 0;
}
else if (strcmp("--app", argv[index]) == 0)
{
index++;
if (index == argc)
{
printf("missing application name\n");
return 0;
}
strncpy(settings->app_name, argv[index], sizeof(settings->app_name) - 1);
settings->app_name[sizeof(settings->app_name) - 1] = 0;
settings->remote_app = 1;
}
else if (strcmp("-x", argv[index]) == 0)
{
index++;
if (index == argc)
{
printf("missing performance flag\n");
return 0;
}
if (argv[index][0] == 'm') /* modem */
{
settings->performance_flags = PERF_DISABLE_WALLPAPER |
PERF_DISABLE_FULLWINDOWDRAG | PERF_DISABLE_MENUANIMATIONS |
PERF_DISABLE_THEMING;
}
else if (argv[index][0] == 'b') /* broadband */
{
settings->performance_flags = PERF_DISABLE_WALLPAPER;
}
else if (argv[index][0] == 'l') /* lan */
{
settings->performance_flags = PERF_FLAG_NONE;
}
else
{
settings->performance_flags = strtol(argv[index], 0, 16);
}
}
else if (strcmp("--no-rdp", argv[index]) == 0)
{
settings->rdp_security = 0;
}
else if (strcmp("--no-tls", argv[index]) == 0)
{
settings->tls_security = 0;
}
else if (strcmp("--no-nla", argv[index]) == 0)
{
settings->nla_security = 0;
}
else if (strcmp("--sec", argv[index]) == 0)
{
index++;
if (index == argc)
{
printf("missing protocol security\n");
return 0;
}
if (strncmp("rdp", argv[index], 1) == 0) /* Standard RDP */
{
settings->rdp_security = 1;
settings->tls_security = 0;
settings->nla_security = 0;
}
else if (strncmp("tls", argv[index], 1) == 0) /* TLS */
{
settings->rdp_security = 0;
settings->tls_security = 1;
settings->nla_security = 0;
}
else if (strncmp("nla", argv[index], 1) == 0) /* NLA */
{
settings->rdp_security = 0;
settings->tls_security = 0;
settings->nla_security = 1;
}
else
{
printf("unknown protocol security\n");
return 0;
}
}
else if (strcmp("--plugin", argv[index]) == 0)
{
t = index;
index++;
if (index == argc)
{
printf("missing plugin name\n");
return 0;
}
memset(plugin_data, 0, sizeof(plugin_data));
if (index < argc - 1 && strcmp("--data", argv[index + 1]) == 0)
{
index += 2;
i = 0;
while (index < argc && strcmp("--", argv[index]) != 0 && i < MAX_PLUGIN_DATA)
{
plugin_data[i].size = sizeof(FRDP_PLUGIN_DATA);
for (j = 0, p = argv[index]; j < 4 && p != NULL; j++)
{
if (*p == '\'')
{
plugin_data[i].data[j] = p + 1;
p = strchr(p + 1, '\'');
if (p)
*p++ = 0;
}
else
plugin_data[i].data[j] = p;
p = strchr(p, ':');
if (p != NULL)
*p++ = 0;
}
index++;
i++;
}
}
if (!plugin_callback(settings, argv[t], plugin_data, plugin_user_data))
return 0;
}
else if (strcmp("--ext", argv[index]) == 0)
{
index++;
if (index == argc)
{
printf("missing extension name\n");
return 0;
}
if (num_extensions >= sizeof(settings->extensions) / sizeof(struct rdp_ext_set))
{
printf("maximum extensions reached\n");
return 0;
}
snprintf(settings->extensions[num_extensions].name,
sizeof(settings->extensions[num_extensions].name),
"%s", argv[index]);
settings->extensions[num_extensions].data = NULL;
if (index < argc - 1 && strcmp("--data", argv[index + 1]) == 0)
{
index += 2;
settings->extensions[num_extensions].data = argv[index];
i = 0;
while (index < argc && strcmp("--", argv[index]) != 0)
{
index++;
i++;
}
}
num_extensions++;
}
else if (strcmp("--version", argv[index]) == 0)
{
printf("This is FreeRDP version %s\n", FREERDP_VERSION_FULL);
return 0;
}
else if (argv[index][0] != '-')
{
if (argv[index][0] == '[' && (p = strchr(argv[index], ']'))
&& (p[1] == 0 || (p[1] == ':' && !strchr(p + 2, ':'))))
{
/* Either "[...]" or "[...]:..." with at most one : after the brackets */
settings->hostname = (uint8*)xstrdup(argv[index] + 1);
if ((p = strchr((char*)settings->hostname, ']')))
{
*p = 0;
if (p[1] == ':')
settings->port = atoi(p + 2);
}
}
else
{
/* Port number is cut off and used if exactly one : in the string */
settings->hostname = (uint8*)xstrdup(argv[index]);
if ((p = strchr((char*)settings->hostname, ':')) && !strchr(p + 1, ':'))
{
*p = 0;
settings->port = atoi(p + 1);
}
}
/* server is the last argument for the current session. arguments
followed will be parsed for the next session. */
index++;
return index;
}
else
{
t = ui_callback(settings, argv[index], (index + 1 < argc && argv[index + 1][0] != '-' ?
argv[index + 1] : NULL), ui_user_data);
if (t == 0)
{
printf("invalid option: %s\n", argv[index]);
return 0;
}
index += t - 1;
}
index++;
}
printf("missing server name\n");
return 0;
}