2
* FreeRDP: A Remote Desktop Protocol client.
5
* Copyright 2009-2011 Jay Sorg
6
* Copyright 2011 Vic Lee
8
* Licensed under the Apache License, Version 2.0 (the "License");
9
* you may not use this file except in compliance with the License.
10
* You may obtain a copy of the License at
12
* http://www.apache.org/licenses/LICENSE-2.0
14
* Unless required by applicable law or agreed to in writing, software
15
* distributed under the License is distributed on an "AS IS" BASIS,
16
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
* See the License for the specific language governing permissions and
18
* limitations under the License.
25
#include <freerdp/settings.h>
26
#include <freerdp/utils/print.h>
27
#include <freerdp/utils/memory.h>
28
#include <freerdp/utils/args.h>
31
* Parse command-line arguments and update rdpSettings members accordingly.
32
* @param settings pointer to rdpSettings struct to be updated.
33
* @param argc number of arguments available.
34
* @param argv string array of the arguments.
35
* @param plugin_callback function to be called when a plugin needs to be loaded.
36
* @param plugin_user_data pointer to be passed to the plugin_callback function.
37
* @param ui_callback function to be called when a UI-specific argument is being processed.
38
* @param ui_user_data pointer to be passed to the ui_callback function.
39
* @return number of arguments that were parsed, or FREERDP_ARGS_PARSE_RESULT on failure or --version/--help
41
int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
42
ProcessPluginArgs plugin_callback, void* plugin_user_data,
43
ProcessUIArgs ui_callback, void* ui_user_data)
49
int num_extensions = 0;
50
RDP_PLUGIN_DATA* plugin_data;
54
if ((strcmp("-h", argv[index]) == 0 ) || (strcmp("--help", argv[index]) == 0 ))
57
"FreeRDP - A Free Remote Desktop Protocol Client\n"
58
"See http://www.freerdp.com for more information\n"
60
"Usage: %s [options] server:port\n"
61
" -0: connect to console session\n"
62
" -a: set color depth in bit, default is 16\n"
63
" -c: initial working directory\n"
64
" -D: hide window decorations\n"
67
" -f: fullscreen mode\n"
68
" -g: set geometry, using format WxH or X%% or 'workarea', default is 1024x768\n"
69
" -h: print this help\n"
70
" -k: set keyboard layout ID\n"
71
" -K: do not interfere with window manager bindings\n"
72
" -m: don't send mouse motion events\n"
74
" -o: console audio\n"
76
" -s: set startup-shell\n"
77
" -t: alternative port number, default is 3389\n"
79
" -x: performance flags (m[odem], b[roadband] or l[an])\n"
80
" -X: embed into another window with a given XID.\n"
81
" -z: enable compression\n"
82
" --app: RemoteApp connection. This implies -g workarea\n"
83
" --ext: load an extension\n"
84
" --no-auth: disable authentication\n"
85
" --no-fastpath: disable fast-path\n"
86
" --gdi: graphics rendering (hw, sw)\n"
87
" --no-osb: disable offscreen bitmaps\n"
88
" --no-bmp-cache: disable bitmap cache\n"
89
" --plugin: load a virtual channel plugin\n"
90
" --rfx: enable RemoteFX\n"
91
" --rfx-mode: RemoteFX operational flags (v[ideo], i[mage]), default is video\n"
92
" --nsc: enable NSCodec (experimental)\n"
93
" --disable-wallpaper: disables wallpaper\n"
94
" --composition: enable desktop composition\n"
95
" --disable-full-window-drag: disables full window drag\n"
96
" --disable-menu-animations: disables menu animations\n"
97
" --disable-theming: disables theming\n"
98
" --no-rdp: disable Standard RDP encryption\n"
99
" --no-tls: disable TLS encryption\n"
100
" --no-nla: disable network level authentication\n"
101
" --ntlm: force NTLM authentication protocol version (1 or 2)\n"
102
" --ignore-certificate: ignore verification of logon certificate\n"
103
" --sec: force protocol security (rdp, tls or nla)\n"
104
" --version: print version information\n"
106
return FREERDP_ARGS_PARSE_HELP; //TODO: What is the correct return
108
else if (strcmp("-a", argv[index]) == 0)
113
printf("missing color depth\n");
114
return FREERDP_ARGS_PARSE_FAILURE;
116
settings->color_depth = atoi(argv[index]);
118
else if (strcmp("-u", argv[index]) == 0)
123
printf("missing username\n");
124
return FREERDP_ARGS_PARSE_FAILURE;
126
settings->username = xstrdup(argv[index]);
128
else if (strcmp("-p", argv[index]) == 0)
133
printf("missing password\n");
134
return FREERDP_ARGS_PARSE_FAILURE;
136
settings->password = xstrdup(argv[index]);
137
settings->autologon = 1;
140
* Overwrite original password which could be revealed by a simple "ps aux" command.
141
* This approach won't hide the password length, but it is better than nothing.
144
memset(argv[index], '*', strlen(argv[index]));
146
else if (strcmp("-d", argv[index]) == 0)
151
printf("missing domain\n");
152
return FREERDP_ARGS_PARSE_FAILURE;
154
settings->domain = xstrdup(argv[index]);
156
else if (strcmp("-s", argv[index]) == 0)
161
printf("missing shell\n");
162
return FREERDP_ARGS_PARSE_FAILURE;
164
settings->shell = xstrdup(argv[index]);
166
else if (strcmp("-c", argv[index]) == 0)
171
printf("missing directory\n");
172
return FREERDP_ARGS_PARSE_FAILURE;
174
settings->directory = xstrdup(argv[index]);
176
else if (strcmp("-g", argv[index]) == 0)
181
printf("missing dimensions\n");
182
return FREERDP_ARGS_PARSE_FAILURE;
185
if (strncmp("workarea", argv[index], 1) == 0)
187
settings->workarea = true;
191
settings->width = (uint16) strtol(argv[index], &p, 10);
195
settings->height = (uint16) strtol(p + 1, &p, 10);
199
settings->percent_screen = settings->width;
200
if (settings->percent_screen <= 0 || settings->percent_screen > 100)
202
printf("invalid geometry percentage\n");
203
return FREERDP_ARGS_PARSE_FAILURE;
208
if (ui_callback != NULL)
209
ui_callback(settings, "-g", p, ui_user_data);
213
else if (strcmp("-f", argv[index]) == 0)
215
settings->fullscreen = true;
217
else if (strcmp("-D", argv[index]) == 0)
219
settings->decorations = false;
221
else if (strcmp("-T", argv[index]) == 0)
226
printf("missing window title\n");
227
return FREERDP_ARGS_PARSE_FAILURE;
230
settings->window_title = xstrdup(argv[index]);
232
else if (strcmp("-t", argv[index]) == 0)
237
printf("missing port number\n");
238
return FREERDP_ARGS_PARSE_FAILURE;
240
settings->port = atoi(argv[index]);
242
else if (strcmp("-k", argv[index]) == 0)
247
printf("missing keyboard layout id\n");
248
return FREERDP_ARGS_PARSE_FAILURE;
250
sscanf(argv[index], "%X", &(settings->kbd_layout));
252
else if (strcmp("-K", argv[index]) == 0)
254
settings->grab_keyboard = false;
256
else if (strcmp("-n", argv[index]) == 0)
261
printf("missing client hostname\n");
262
return FREERDP_ARGS_PARSE_FAILURE;
264
strncpy(settings->client_hostname, argv[index], sizeof(settings->client_hostname) - 1);
265
settings->client_hostname[sizeof(settings->client_hostname) - 1] = 0;
267
else if (strcmp("-o", argv[index]) == 0)
269
settings->console_audio = true;
271
else if (strcmp("-0", argv[index]) == 0)
273
settings->console_session = true;
275
else if (strcmp("-z", argv[index]) == 0)
277
settings->compression = true;
279
else if (strcmp("--ntlm", argv[index]) == 0)
283
settings->ntlm_version = atoi(argv[index]);
285
if (settings->ntlm_version != 2)
286
settings->ntlm_version = 1;
288
else if (strcmp("--no-glyph-cache", argv[index]) == 0)
290
settings->glyph_cache = false;
292
else if (strcmp("--no-osb", argv[index]) == 0)
294
settings->offscreen_bitmap_cache = false;
296
else if (strcmp("--no-bmp-cache", argv[index]) == 0)
298
settings->bitmap_cache = false;
300
else if (strcmp("--no-auth", argv[index]) == 0)
302
settings->authentication = false;
304
else if (strcmp("--ignore-certificate", argv[index]) == 0)
306
settings->ignore_certificate = true;
308
else if (strcmp("--no-fastpath", argv[index]) == 0)
310
settings->fastpath_input = false;
311
settings->fastpath_output = false;
313
else if (strcmp("--gdi", argv[index]) == 0)
318
printf("missing GDI backend\n");
319
return FREERDP_ARGS_PARSE_FAILURE;
321
if (strncmp("sw", argv[index], 1) == 0) /* software */
323
settings->sw_gdi = true;
325
else if (strncmp("hw", argv[index], 1) == 0) /* hardware */
327
settings->sw_gdi = false;
331
printf("unknown GDI backend\n");
332
return FREERDP_ARGS_PARSE_FAILURE;
335
else if (strcmp("--rfx", argv[index]) == 0)
337
settings->rfx_codec = true;
338
settings->fastpath_output = true;
339
settings->color_depth = 32;
340
settings->frame_acknowledge = false;
341
settings->performance_flags = PERF_FLAG_NONE;
342
settings->large_pointer = true;
344
else if (strcmp("--rfx-mode", argv[index]) == 0)
349
printf("missing RemoteFX mode flag\n");
350
return FREERDP_ARGS_PARSE_FAILURE;
352
if (argv[index][0] == 'v') /* video */
354
settings->rfx_codec_mode = 0x00;
356
else if (argv[index][0] == 'i') /* image */
358
settings->rfx_codec_mode = 0x02;
362
printf("unknown RemoteFX mode flag\n");
363
return FREERDP_ARGS_PARSE_FAILURE;
366
else if (strcmp("--nsc", argv[index]) == 0)
368
settings->ns_codec = true;
370
else if (strcmp("--dump-rfx", argv[index]) == 0)
375
printf("missing file name\n");
376
return FREERDP_ARGS_PARSE_FAILURE;
378
settings->dump_rfx_file = xstrdup(argv[index]);
379
settings->dump_rfx = true;
381
else if (strcmp("--play-rfx", argv[index]) == 0)
386
printf("missing file name\n");
387
return FREERDP_ARGS_PARSE_FAILURE;
389
settings->play_rfx_file = xstrdup(argv[index]);
390
settings->play_rfx = true;
392
else if (strcmp("--fonts", argv[index]) == 0)
394
settings->smooth_fonts = true;
396
else if (strcmp("--disable-wallpaper", argv[index]) == 0)
398
settings->disable_wallpaper = true;
400
else if (strcmp("--disable-full-window-drag", argv[index]) == 0)
402
settings->disable_full_window_drag = true;
404
else if (strcmp("--disable-menu-animations", argv[index]) == 0)
406
settings->disable_menu_animations = true;
408
else if (strcmp("--disable-theming", argv[index]) == 0)
410
settings->disable_theming = true;
412
else if (strcmp("--composition", argv[index]) == 0)
414
settings->desktop_composition = true;
416
else if (strcmp("--no-motion", argv[index]) == 0)
418
settings->mouse_motion = false;
420
else if (strcmp("--app", argv[index]) == 0)
422
settings->remote_app = true;
423
settings->rail_langbar_supported = true;
424
settings->workarea = true;
425
settings->performance_flags = PERF_DISABLE_WALLPAPER | PERF_DISABLE_FULLWINDOWDRAG;
427
else if (strcmp("-x", argv[index]) == 0)
432
printf("missing performance flag\n");
433
return FREERDP_ARGS_PARSE_FAILURE;
435
if (argv[index][0] == 'm') /* modem */
437
settings->performance_flags = PERF_DISABLE_WALLPAPER |
438
PERF_DISABLE_FULLWINDOWDRAG | PERF_DISABLE_MENUANIMATIONS |
439
PERF_DISABLE_THEMING;
441
settings->connection_type = CONNECTION_TYPE_MODEM;
443
else if (argv[index][0] == 'b') /* broadband */
445
settings->performance_flags = PERF_DISABLE_WALLPAPER;
446
settings->connection_type = CONNECTION_TYPE_BROADBAND_HIGH;
448
else if (argv[index][0] == 'l') /* lan */
450
settings->performance_flags = PERF_FLAG_NONE;
451
settings->connection_type = CONNECTION_TYPE_LAN;
455
settings->performance_flags = strtol(argv[index], 0, 16);
458
else if (strcmp("-X", argv[index]) == 0)
464
printf("missing parent window XID\n");
465
return FREERDP_ARGS_PARSE_FAILURE;
468
settings->parent_window_xid = strtoul(argv[index], NULL, 16);
470
if (settings->parent_window_xid == 0)
472
printf("invalid parent window XID\n");
473
return FREERDP_ARGS_PARSE_FAILURE;
476
else if (strcmp("--no-rdp", argv[index]) == 0)
478
settings->rdp_security = false;
480
else if (strcmp("--no-tls", argv[index]) == 0)
482
settings->tls_security = false;
484
else if (strcmp("--no-nla", argv[index]) == 0)
486
settings->nla_security = false;
488
else if (strcmp("--sec", argv[index]) == 0)
493
printf("missing protocol security\n");
494
return FREERDP_ARGS_PARSE_FAILURE;
496
if (strncmp("rdp", argv[index], 1) == 0) /* Standard RDP */
498
settings->rdp_security = true;
499
settings->tls_security = false;
500
settings->nla_security = false;
501
settings->encryption = true;
502
settings->encryption_method = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
503
settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
505
else if (strncmp("tls", argv[index], 1) == 0) /* TLS */
507
settings->rdp_security = false;
508
settings->tls_security = true;
509
settings->nla_security = false;
511
else if (strncmp("nla", argv[index], 1) == 0) /* NLA */
513
settings->rdp_security = false;
514
settings->tls_security = false;
515
settings->nla_security = true;
519
printf("unknown protocol security\n");
520
return FREERDP_ARGS_PARSE_FAILURE;
523
else if (strcmp("--plugin", argv[index]) == 0)
529
printf("missing plugin name\n");
530
return FREERDP_ARGS_PARSE_FAILURE;
533
if (index < argc - 1 && strcmp("--data", argv[index + 1]) == 0)
537
while (index < argc && strcmp("--", argv[index]) != 0)
539
plugin_data = (RDP_PLUGIN_DATA*)xrealloc(plugin_data, sizeof(RDP_PLUGIN_DATA) * (i + 2));
540
plugin_data[i].size = sizeof(RDP_PLUGIN_DATA);
541
plugin_data[i].data[0] = NULL;
542
plugin_data[i].data[1] = NULL;
543
plugin_data[i].data[2] = NULL;
544
plugin_data[i].data[3] = NULL;
545
plugin_data[i + 1].size = 0;
546
for (j = 0, p = argv[index]; j < 4 && p != NULL; j++)
550
plugin_data[i].data[j] = p + 1;
551
p = strchr(p + 1, '\'');
556
plugin_data[i].data[j] = p;
567
if (plugin_callback != NULL)
569
if (!plugin_callback(settings, argv[t], plugin_data, plugin_user_data))
570
return FREERDP_ARGS_PARSE_FAILURE;
573
else if (strcmp("--ext", argv[index]) == 0)
578
printf("missing extension name\n");
579
return FREERDP_ARGS_PARSE_FAILURE;
581
if (num_extensions >= sizeof(settings->extensions) / sizeof(struct rdp_ext_set))
583
printf("maximum extensions reached\n");
584
return FREERDP_ARGS_PARSE_FAILURE;
586
snprintf(settings->extensions[num_extensions].name,
587
sizeof(settings->extensions[num_extensions].name),
589
settings->extensions[num_extensions].data = NULL;
590
if (index < argc - 1 && strcmp("--data", argv[index + 1]) == 0)
593
settings->extensions[num_extensions].data = argv[index];
595
while (index < argc && strcmp("--", argv[index]) != 0)
603
else if (strcmp("--version", argv[index]) == 0)
605
printf("This is FreeRDP version %s\n", FREERDP_VERSION_FULL);
606
return FREERDP_ARGS_PARSE_VERSION;
608
else if (argv[index][0] != '-')
610
if (argv[index][0] == '[' && (p = strchr(argv[index], ']'))
611
&& (p[1] == 0 || (p[1] == ':' && !strchr(p + 2, ':'))))
613
/* Either "[...]" or "[...]:..." with at most one : after the brackets */
614
settings->hostname = xstrdup(argv[index] + 1);
615
if ((p = strchr((char*)settings->hostname, ']')))
619
settings->port = atoi(p + 2);
624
/* Port number is cut off and used if exactly one : in the string */
625
settings->hostname = xstrdup(argv[index]);
626
if ((p = strchr((char*)settings->hostname, ':')) && !strchr(p + 1, ':'))
629
settings->port = atoi(p + 1);
632
/* server is the last argument for the current session. arguments
633
followed will be parsed for the next session. */
636
if (settings->smooth_fonts)
637
settings->performance_flags |= PERF_ENABLE_FONT_SMOOTHING;
639
if (settings->desktop_composition)
640
settings->performance_flags |= PERF_ENABLE_DESKTOP_COMPOSITION;
642
if (settings->disable_wallpaper)
643
settings->performance_flags |= PERF_DISABLE_WALLPAPER;
645
if (settings->disable_full_window_drag)
646
settings->performance_flags |= PERF_DISABLE_FULLWINDOWDRAG;
648
if (settings->disable_menu_animations)
649
settings->performance_flags |= PERF_DISABLE_MENUANIMATIONS;
651
if (settings->disable_theming)
652
settings->performance_flags |= PERF_DISABLE_THEMING;
658
if (ui_callback != NULL)
660
t = ui_callback(settings, argv[index], (index + 1 < argc && argv[index + 1][0] != '-' ?
661
argv[index + 1] : NULL), ui_user_data);
664
printf("invalid option: %s\n", argv[index]);
665
return FREERDP_ARGS_PARSE_FAILURE;
672
printf("missing server name\n");
673
return FREERDP_ARGS_PARSE_FAILURE;