Beispiel #1
0
/* Client program */
int
main(int argc, char *argv[])
{
	char server[256];
	char fullhostname[64];
	char domain[256];
	char shell[256];
	char directory[256];
	RD_BOOL prompt_password, deactivated;
	struct passwd *pw;
	uint32 flags, ext_disc_reason = 0;
	char *p;
	int c;
	char *locale = NULL;
	int username_option = 0;
	RD_BOOL geometry_option = False;
#ifdef WITH_RDPSND
	char *rdpsnd_optarg = NULL;
#endif

#ifdef HAVE_LOCALE_H
	/* Set locale according to environment */
	locale = setlocale(LC_ALL, "");
	if (locale)
	{
		locale = xstrdup(locale);
	}

#endif

	/* Ignore SIGPIPE, since we are using popen() */
	struct sigaction act;
	memset(&act, 0, sizeof(act));
	act.sa_handler = SIG_IGN;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	sigaction(SIGPIPE, &act, NULL);

	/* setup default flags for TS_INFO_PACKET */
	flags = RDP_INFO_MOUSE | RDP_INFO_DISABLECTRLALTDEL
		| RDP_INFO_UNICODE | RDP_INFO_MAXIMIZESHELL | RDP_INFO_ENABLEWINDOWSKEY;

	prompt_password = False;
	g_seamless_spawn_cmd[0] = domain[0] = g_password[0] = shell[0] = directory[0] = 0;
	g_embed_wnd = 0;

	g_num_devices = 0;

#ifdef RDP2VNC
#define VNCOPT "V:Q:"
#else
#define VNCOPT
#endif
	while ((c = getopt(argc, argv,
			   VNCOPT "A:u:L:d:s:c:p:n:k:g:o:fbBeEitmzCDKS:T:UNX:a:x:Pr:045h?")) != -1)
	{
		switch (c)
		{
#ifdef RDP2VNC
			case 'V':
				rfb_port = strtol(optarg, NULL, 10);
				if (rfb_port < 100)
					rfb_port += 5900;
				break;

			case 'Q':
				defer_time = strtol(optarg, NULL, 10);
				if (defer_time < 0)
					defer_time = 0;
				break;
#endif

			case 'A':
				g_seamless_rdp = True;
				STRNCPY(g_seamless_shell, optarg, sizeof(g_seamless_shell));
				break;

			case 'u':
				g_username = (char *) xmalloc(strlen(optarg) + 1);
				STRNCPY(g_username, optarg, strlen(optarg) + 1);
				username_option = 1;
				break;

			case 'L':
#ifdef HAVE_ICONV
				STRNCPY(g_codepage, optarg, sizeof(g_codepage));
#else
				error("iconv support not available\n");
#endif
				break;

			case 'd':
				STRNCPY(domain, optarg, sizeof(domain));
				break;

			case 's':
				STRNCPY(shell, optarg, sizeof(shell));
				g_seamless_persistent_mode = False;
				break;

			case 'c':
				STRNCPY(directory, optarg, sizeof(directory));
				break;

			case 'p':
				if ((optarg[0] == '-') && (optarg[1] == 0))
				{
					prompt_password = True;
					break;
				}

				STRNCPY(g_password, optarg, sizeof(g_password));
				flags |= RDP_INFO_AUTOLOGON;

				/* try to overwrite argument so it won't appear in ps */
				p = optarg;
				while (*p)
					*(p++) = 'X';
				break;
#ifdef WITH_SCARD
			case 'i':
				flags |= RDP_INFO_PASSWORD_IS_SC_PIN;
				g_use_password_as_pin = True;
				break;
#endif
			case 't':
				g_use_ctrl = False;
				break;

			case 'n':
				STRNCPY(g_hostname, optarg, sizeof(g_hostname));
				break;

			case 'k':
				STRNCPY(g_keymapname, optarg, sizeof(g_keymapname));
				break;

			case 'g':
				geometry_option = True;
				g_fullscreen = False;
				if (!strcmp(optarg, "workarea"))
				{
					g_sizeopt = 1;
					break;
				}

				g_width = strtol(optarg, &p, 10);
				if (g_width <= 0)
				{
					error("invalid geometry\n");
					return EX_USAGE;
				}

				if (*p == 'x')
					g_height = strtol(p + 1, &p, 10);

				if (g_height <= 0)
				{
					error("invalid geometry\n");
					return EX_USAGE;
				}

				if (*p == '%')
				{
					g_sizeopt = -g_width;
					g_width = 800;
					p++;
				}

				if (*p == '+' || *p == '-')
				{
					g_pos |= (*p == '-') ? 2 : 1;
					g_xpos = strtol(p, &p, 10);

				}
				if (*p == '+' || *p == '-')
				{
					g_pos |= (*p == '-') ? 4 : 1;
					g_ypos = strtol(p, NULL, 10);
				}

				break;

			case 'f':
				g_fullscreen = True;
				break;

			case 'b':
				g_bitmap_cache = False;
				break;

			case 'B':
				g_ownbackstore = False;
				break;

			case 'e':
				g_encryption_initial = g_encryption = False;
				break;
			case 'E':
				g_packet_encryption = False;
				break;
			case 'm':
				g_sendmotion = False;
				break;

			case 'C':
				g_owncolmap = True;
				break;

			case 'D':
				g_hide_decorations = True;
				break;

			case 'K':
				g_grab_keyboard = False;
				break;

			case 'U':
				g_ungrab_on_ctrlalt = True;
				break;

			case 'S':
				if (!strcmp(optarg, "standard"))
				{
					g_win_button_size = 18;
					break;
				}

				g_win_button_size = strtol(optarg, &p, 10);

				if (*p)
				{
					error("invalid button size\n");
					return EX_USAGE;
				}

				break;

			case 'T':
				STRNCPY(g_title, optarg, sizeof(g_title));
				break;

			case 'N':
				g_numlock_sync = True;
				break;

			case 'X':
				g_embed_wnd = strtol(optarg, NULL, 0);
				break;

			case 'a':
				g_server_depth = strtol(optarg, NULL, 10);
				if (g_server_depth != 8 &&
				    g_server_depth != 16 &&
				    g_server_depth != 15 && g_server_depth != 24
				    && g_server_depth != 32)
				{
					error("Invalid server colour depth.\n");
					return EX_USAGE;
				}
				break;

			case 'z':
				DEBUG(("rdp compression enabled\n"));
				flags |= (RDP_INFO_COMPRESSION | RDP_INFO_COMPRESSION2);
				break;

			case 'x':
				if (str_startswith(optarg, "m"))	/* modem */
				{
					g_rdp5_performanceflags = RDP5_NO_CURSOR_SHADOW |
						RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG |
						RDP5_NO_MENUANIMATIONS | RDP5_NO_THEMING;
				}
				else if (str_startswith(optarg, "b"))	/* broadband */
				{
					g_rdp5_performanceflags =
						RDP5_NO_CURSOR_SHADOW | RDP5_NO_WALLPAPER;
				}
				else if (str_startswith(optarg, "l"))	/* lan */
				{
					g_rdp5_performanceflags =
						RDP5_NO_CURSOR_SHADOW | RDP5_DISABLE_NOTHING;
				}
				else
				{
					g_rdp5_performanceflags =
						RDP5_NO_CURSOR_SHADOW | strtol(optarg, NULL, 16);
				}
				break;

			case 'P':
				g_bitmap_cache_persist_enable = True;
				break;

			case 'r':

				if (str_startswith(optarg, "sound"))
				{
					optarg += 5;

					if (*optarg == ':')
					{
						optarg++;
						while ((p = next_arg(optarg, ',')))
						{
							if (str_startswith(optarg, "remote"))
								flags |= RDP_INFO_REMOTE_CONSOLE_AUDIO;

							if (str_startswith(optarg, "local"))
#ifdef WITH_RDPSND
							{
								rdpsnd_optarg =
									next_arg(optarg, ':');
								g_rdpsnd = True;
							}

#else
								warning("Not compiled with sound support\n");
#endif

							if (str_startswith(optarg, "off"))
#ifdef WITH_RDPSND
								g_rdpsnd = False;
#else
								warning("Not compiled with sound support\n");
#endif

							optarg = p;
						}
					}
					else
					{
#ifdef WITH_RDPSND
						g_rdpsnd = True;
#else
						warning("Not compiled with sound support\n");
#endif
					}
				}
				else if (str_startswith(optarg, "disk"))
				{
					/* -r disk:h:=/mnt/floppy */
					disk_enum_devices(&g_num_devices, optarg + 4);
				}
				else if (str_startswith(optarg, "comport"))
				{
					serial_enum_devices(&g_num_devices, optarg + 7);
				}
				else if (str_startswith(optarg, "lspci"))
				{
					g_lspci_enabled = True;
				}
				else if (str_startswith(optarg, "lptport"))
				{
					parallel_enum_devices(&g_num_devices, optarg + 7);
				}
				else if (str_startswith(optarg, "printer"))
				{
					printer_enum_devices(&g_num_devices, optarg + 7);
				}
				else if (str_startswith(optarg, "clientname"))
				{
					g_rdpdr_clientname = xmalloc(strlen(optarg + 11) + 1);
					strcpy(g_rdpdr_clientname, optarg + 11);
				}
				else if (str_startswith(optarg, "clipboard"))
				{
					optarg += 9;

					if (*optarg == ':')
					{
						optarg++;

						if (str_startswith(optarg, "off"))
							g_rdpclip = False;
						else
							cliprdr_set_mode(optarg);
					}
					else
						g_rdpclip = True;
				}
				else if (strncmp("scard", optarg, 5) == 0)
				{
#ifdef WITH_SCARD
					scard_enum_devices(&g_num_devices, optarg + 5);
#else
					warning("Not compiled with smartcard support\n");
#endif
				}
				else
				{
					warning("Unknown -r argument\n\n\tPossible arguments are: comport, disk, lptport, printer, sound, clipboard, scard\n");
				}
				break;

			case '0':
				g_console_session = True;
				break;

			case '4':
				g_rdp_version = RDP_V4;
				break;

			case '5':
				g_rdp_version = RDP_V5;
				break;
#if WITH_SCARD
			case 'o':
				{
					char *p = strchr(optarg, '=');
					if (p == NULL)
					{
						warning("Skipping option '%s' specified, lacks name=value format.\n");
						continue;
					}

					if (strncmp(optarg, "sc-csp-name", strlen("sc-scp-name")) ==
					    0)
						g_sc_csp_name = strdup(p + 1);
					else if (strncmp
						 (optarg, "sc-reader-name",
						  strlen("sc-reader-name")) == 0)
						g_sc_reader_name = strdup(p + 1);
					else if (strncmp
						 (optarg, "sc-card-name",
						  strlen("sc-card-name")) == 0)
						g_sc_card_name = strdup(p + 1);
					else if (strncmp
						 (optarg, "sc-container-name",
						  strlen("sc-container-name")) == 0)
						g_sc_container_name = strdup(p + 1);

				}
				break;
#endif
			case 'h':
			case '?':
			default:
				usage(argv[0]);
				return EX_USAGE;
		}
	}

	if (argc - optind != 1)
	{
		usage(argv[0]);
		return EX_USAGE;
	}

	STRNCPY(server, argv[optind], sizeof(server));
	parse_server_and_port(server);

	if (g_seamless_rdp)
	{
		if (shell[0])
			STRNCPY(g_seamless_spawn_cmd, shell, sizeof(g_seamless_spawn_cmd));

		STRNCPY(shell, g_seamless_shell, sizeof(shell));

		if (g_win_button_size)
		{
			error("You cannot use -S and -A at the same time\n");
			return EX_USAGE;
		}
		g_rdp5_performanceflags &= ~RDP5_NO_FULLWINDOWDRAG;
		if (geometry_option)
		{
			error("You cannot use -g and -A at the same time\n");
			return EX_USAGE;
		}
		if (g_fullscreen)
		{
			error("You cannot use -f and -A at the same time\n");
			return EX_USAGE;
		}
		if (g_hide_decorations)
		{
			error("You cannot use -D and -A at the same time\n");
			return EX_USAGE;
		}
		if (g_embed_wnd)
		{
			error("You cannot use -X and -A at the same time\n");
			return EX_USAGE;
		}
		if (g_rdp_version < RDP_V5)
		{
			error("You cannot use -4 and -A at the same time\n");
			return EX_USAGE;
		}
		g_sizeopt = -100;
		g_grab_keyboard = False;
	}

	if (!username_option)
	{
		pw = getpwuid(getuid());
		if ((pw == NULL) || (pw->pw_name == NULL))
		{
			error("could not determine username, use -u\n");
			return EX_OSERR;
		}
		/* +1 for trailing \0 */
		int pwlen = strlen(pw->pw_name) + 1;
		g_username = (char *) xmalloc(pwlen);
		STRNCPY(g_username, pw->pw_name, pwlen);
	}

#ifdef HAVE_ICONV
	if (g_codepage[0] == 0)
	{
		if (setlocale(LC_CTYPE, ""))
		{
			STRNCPY(g_codepage, nl_langinfo(CODESET), sizeof(g_codepage));
		}
		else
		{
			STRNCPY(g_codepage, DEFAULT_CODEPAGE, sizeof(g_codepage));
		}
	}
#endif

	if (g_hostname[0] == 0)
	{
		if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
		{
			error("could not determine local hostname, use -n\n");
			return EX_OSERR;
		}

		p = strchr(fullhostname, '.');
		if (p != NULL)
			*p = 0;

		STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
	}

	if (g_keymapname[0] == 0)
	{
		if (locale && xkeymap_from_locale(locale))
		{
			fprintf(stderr, "Autoselected keyboard map %s\n", g_keymapname);
		}
		else
		{
			STRNCPY(g_keymapname, "en-us", sizeof(g_keymapname));
		}
	}
	if (locale)
		xfree(locale);


	if (prompt_password && read_password(g_password, sizeof(g_password)))
		flags |= RDP_INFO_AUTOLOGON;

	if (g_title[0] == 0)
	{
		strcpy(g_title, "rdesktop - ");
		strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
	}

#ifdef RDP2VNC
	rdp2vnc_connect(server, flags, domain, g_password, shell, directory);
	return EX_OK;
#else

	/* Only startup ctrl functionality is seamless are used for now. */
	if (g_use_ctrl && g_seamless_rdp)
	{
		if (ctrl_init(server, domain, g_username) < 0)
		{
			error("Failed to initialize ctrl mode.");
			exit(1);
		}

		if (ctrl_is_slave())
		{
			fprintf(stdout,
				"rdesktop in slave mode sending command to master process.\n");

			if (g_seamless_spawn_cmd[0])
				return ctrl_send_command("seamless.spawn", g_seamless_spawn_cmd);

			fprintf(stdout, "No command specified to be spawn in seamless mode.\n");
			return EX_USAGE;
		}
	}

	if (!ui_init())
		return EX_OSERR;

#ifdef WITH_RDPSND
	if (!rdpsnd_init(rdpsnd_optarg))
		warning("Initializing sound-support failed!\n");
#endif

	if (g_lspci_enabled)
		lspci_init();

	rdpdr_init();
	g_reconnect_loop = False;
	while (1)
	{
		rdesktop_reset_state();

		if (g_redirect)
		{
			STRNCPY(domain, g_redirect_domain, sizeof(domain));
			xfree(g_username);
			g_username = (char *) xmalloc(strlen(g_redirect_username) + 1);
			STRNCPY(g_username, g_redirect_username, strlen(g_redirect_username) + 1);
			STRNCPY(server, g_redirect_server, sizeof(server));
			flags |= RDP_INFO_AUTOLOGON;

			fprintf(stderr, "Redirected to %s@%s session %d.\n",
				g_redirect_username, g_redirect_server, g_redirect_session_id);

			/* A redirect on SSL from a 2003 WTS will result in a 'connection reset by peer'
			   and therefor we just clear this error before we connect to redirected server.
			 */
			g_network_error = False;
			g_redirect = False;
		}

		ui_init_connection();
		if (!rdp_connect
		    (server, flags, domain, g_password, shell, directory, g_reconnect_loop))
		{

			g_network_error = False;

			if (g_reconnect_loop == False)
				return EX_PROTOCOL;

			/* check if auto reconnect cookie has timed out */
			if (time(NULL) - g_reconnect_random_ts > RECONNECT_TIMEOUT)
			{
				fprintf(stderr, "Tried to reconnect for %d minutes, giving up.\n",
					RECONNECT_TIMEOUT / 60);
				return EX_PROTOCOL;
			}

			sleep(4);
			continue;
		}

		if (g_redirect)
		{
			rdp_disconnect();
			continue;
		}

		/* By setting encryption to False here, we have an encrypted login 
		   packet but unencrypted transfer of other packets */
		if (!g_packet_encryption)
			g_encryption_initial = g_encryption = False;

		DEBUG(("Connection successful.\n"));

		rd_create_ui();
		tcp_run_ui(True);

		deactivated = False;
		g_reconnect_loop = False;
		rdp_main_loop(&deactivated, &ext_disc_reason);

		tcp_run_ui(False);

		DEBUG(("Disconnecting...\n"));
		rdp_disconnect();

		if (g_redirect)
			continue;

		/* handle network error and start autoreconnect */
		if (g_network_error && !deactivated)
		{
			fprintf(stderr,
				"Disconnected due to network error, retrying to reconnect for %d minutes.\n",
				RECONNECT_TIMEOUT / 60);
			g_network_error = False;
			g_reconnect_loop = True;
			continue;
		}

		ui_seamless_end();
		ui_destroy_window();

		/* Enter a reconnect loop if we have a pending resize request */
		if (g_pending_resize)
		{
			g_pending_resize = False;
			g_reconnect_loop = True;
			continue;
		}
		break;
	}

	cache_save_state();
	ui_deinit();

	if (g_user_quit)
		return EXRD_WINDOW_CLOSED;

	return handle_disconnect_reason(deactivated, ext_disc_reason);

#endif
	if (g_redirect_username)
		xfree(g_redirect_username);

	xfree(g_username);
}
Beispiel #2
0
/* Client program */
int
main(int argc, char *argv[])
{
	char server[64];
	char fullhostname[64];
	char domain[16];
	char password[64];
	char shell[256];
	char directory[256];
	RD_BOOL prompt_password, deactivated;
	struct passwd *pw;
	uint32 flags, ext_disc_reason = 0;
	char *p;
	int c;
	char *locale = NULL;
	int username_option = 0;
	RD_BOOL geometry_option = False;
	int run_count = 0;	/* Session Directory support */
	RD_BOOL continue_connect = True;	/* Session Directory support */
#ifdef WITH_RDPSND
	char *rdpsnd_optarg = NULL;
#endif

#ifdef HAVE_LOCALE_H
	/* Set locale according to environment */
	locale = setlocale(LC_ALL, "");
	if (locale)
	{
		locale = xstrdup(locale);
	}

#endif
	flags = RDP_LOGON_NORMAL;
	prompt_password = False;
	domain[0] = password[0] = shell[0] = directory[0] = 0;
	g_embed_wnd = 0;

	g_num_devices = 0;

#ifdef RDP2VNC
#define VNCOPT "V:Q:"
#else
#define VNCOPT
#endif

	while ((c = getopt(argc, argv,
			   VNCOPT "Au:L:d:s:c:p:n:k:g:fbBeEmzCDKS:T:NX:a:x:Pr:045h?")) != -1)
	{
		switch (c)
		{
#ifdef RDP2VNC
			case 'V':
				rfb_port = strtol(optarg, NULL, 10);
				if (rfb_port < 100)
					rfb_port += 5900;
				break;

			case 'Q':
				defer_time = strtol(optarg, NULL, 10);
				if (defer_time < 0)
					defer_time = 0;
				break;
#endif

			case 'A':
				g_seamless_rdp = True;
				break;

			case 'u':
				STRNCPY(g_username, optarg, sizeof(g_username));
				username_option = 1;
				break;

			case 'L':
#ifdef HAVE_ICONV
				STRNCPY(g_codepage, optarg, sizeof(g_codepage));
#else
				error("iconv support not available\n");
#endif
				break;

			case 'd':
				STRNCPY(domain, optarg, sizeof(domain));
				break;

			case 's':
				STRNCPY(shell, optarg, sizeof(shell));
				break;

			case 'c':
				STRNCPY(directory, optarg, sizeof(directory));
				break;

			case 'p':
				if ((optarg[0] == '-') && (optarg[1] == 0))
				{
					prompt_password = True;
					break;
				}

				STRNCPY(password, optarg, sizeof(password));
				flags |= RDP_LOGON_AUTO;

				/* try to overwrite argument so it won't appear in ps */
				p = optarg;
				while (*p)
					*(p++) = 'X';
				break;

			case 'n':
				STRNCPY(g_hostname, optarg, sizeof(g_hostname));
				break;

			case 'k':
				STRNCPY(g_keymapname, optarg, sizeof(g_keymapname));
				break;

			case 'g':
				geometry_option = True;
				g_fullscreen = False;
				if (!strcmp(optarg, "workarea"))
				{
					g_width = g_height = 0;
					break;
				}

				g_width = strtol(optarg, &p, 10);
				if (g_width <= 0)
				{
					error("invalid geometry\n");
					return 1;
				}

				if (*p == 'x')
					g_height = strtol(p + 1, &p, 10);

				if (g_height <= 0)
				{
					error("invalid geometry\n");
					return 1;
				}

				if (*p == '%')
				{
					g_width = -g_width;
					p++;
				}

				if (*p == '+' || *p == '-')
				{
					g_pos |= (*p == '-') ? 2 : 1;
					g_xpos = strtol(p, &p, 10);

				}
				if (*p == '+' || *p == '-')
				{
					g_pos |= (*p == '-') ? 4 : 1;
					g_ypos = strtol(p, NULL, 10);
				}

				break;

			case 'f':
				g_fullscreen = True;
				break;

			case 'b':
				g_bitmap_cache = False;
				break;

			case 'B':
				g_ownbackstore = False;
				break;

			case 'e':
				g_encryption = False;
				break;
			case 'E':
				g_packet_encryption = False;
				break;
			case 'm':
				g_sendmotion = False;
				break;

			case 'C':
				g_owncolmap = True;
				break;

			case 'D':
				g_hide_decorations = True;
				break;

			case 'K':
				g_grab_keyboard = False;
				break;

			case 'S':
				if (!strcmp(optarg, "standard"))
				{
					g_win_button_size = 18;
					break;
				}

				g_win_button_size = strtol(optarg, &p, 10);

				if (*p)
				{
					error("invalid button size\n");
					return 1;
				}

				break;

			case 'T':
				STRNCPY(g_title, optarg, sizeof(g_title));
				break;

			case 'N':
				g_numlock_sync = True;
				break;

			case 'X':
				g_embed_wnd = strtol(optarg, NULL, 0);
				break;

			case 'a':
				g_server_depth = strtol(optarg, NULL, 10);
				if (g_server_depth != 8 &&
				    g_server_depth != 16 &&
				    g_server_depth != 15 && g_server_depth != 24
				    && g_server_depth != 32)
				{
					error("Invalid server colour depth.\n");
					return 1;
				}
				break;

			case 'z':
				DEBUG(("rdp compression enabled\n"));
				flags |= (RDP_LOGON_COMPRESSION | RDP_LOGON_COMPRESSION2);
				break;

			case 'x':
				if (str_startswith(optarg, "m"))	/* modem */
				{
					g_rdp5_performanceflags =
						RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG |
						RDP5_NO_MENUANIMATIONS | RDP5_NO_THEMING;
				}
				else if (str_startswith(optarg, "b"))	/* broadband */
				{
					g_rdp5_performanceflags = RDP5_NO_WALLPAPER;
				}
				else if (str_startswith(optarg, "l"))	/* lan */
				{
					g_rdp5_performanceflags = RDP5_DISABLE_NOTHING;
				}
				else
				{
					g_rdp5_performanceflags = strtol(optarg, NULL, 16);
				}
				break;

			case 'P':
				g_bitmap_cache_persist_enable = True;
				break;

			case 'r':

				if (str_startswith(optarg, "sound"))
				{
					optarg += 5;

					if (*optarg == ':')
					{
						optarg++;
						while ((p = next_arg(optarg, ',')))
						{
							if (str_startswith(optarg, "remote"))
								flags |= RDP_LOGON_LEAVE_AUDIO;

							if (str_startswith(optarg, "local"))
#ifdef WITH_RDPSND
							{
								rdpsnd_optarg =
									next_arg(optarg, ':');
								g_rdpsnd = True;
							}

#else
								warning("Not compiled with sound support\n");
#endif

							if (str_startswith(optarg, "off"))
#ifdef WITH_RDPSND
								g_rdpsnd = False;
#else
								warning("Not compiled with sound support\n");
#endif

							optarg = p;
						}
					}
					else
					{
#ifdef WITH_RDPSND
						g_rdpsnd = True;
#else
						warning("Not compiled with sound support\n");
#endif
					}
				}
				else if (str_startswith(optarg, "disk"))
				{
					/* -r disk:h:=/mnt/floppy */
					disk_enum_devices(&g_num_devices, optarg + 4);
				}
				else if (str_startswith(optarg, "comport"))
				{
					serial_enum_devices(&g_num_devices, optarg + 7);
				}
				else if (str_startswith(optarg, "lspci"))
				{
					g_lspci_enabled = True;
				}
				else if (str_startswith(optarg, "lptport"))
				{
					parallel_enum_devices(&g_num_devices, optarg + 7);
				}
				else if (str_startswith(optarg, "printer"))
				{
					printer_enum_devices(&g_num_devices, optarg + 7);
				}
				else if (str_startswith(optarg, "clientname"))
				{
					g_rdpdr_clientname = xmalloc(strlen(optarg + 11) + 1);
					strcpy(g_rdpdr_clientname, optarg + 11);
				}
				else if (str_startswith(optarg, "clipboard"))
				{
					optarg += 9;

					if (*optarg == ':')
					{
						optarg++;

						if (str_startswith(optarg, "off"))
							g_rdpclip = False;
						else
							cliprdr_set_mode(optarg);
					}
					else
						g_rdpclip = True;
				}
				else if (strncmp("scard", optarg, 5) == 0)
				{
#ifdef WITH_SCARD
					scard_enum_devices(&g_num_devices, optarg + 5);
#else
					warning("Not compiled with smartcard support\n");
#endif
				}
				else
				{
					warning("Unknown -r argument\n\n\tPossible arguments are: comport, disk, lptport, printer, sound, clipboard, scard\n");
				}
				break;

			case '0':
				g_console_session = True;
				break;

			case '4':
				g_use_rdp5 = False;
				break;

			case '5':
				g_use_rdp5 = True;
				break;

			case 'h':
			case '?':
			default:
				usage(argv[0]);
				return 1;
		}
	}

	if (argc - optind != 1)
	{
		usage(argv[0]);
		return 1;
	}

	STRNCPY(server, argv[optind], sizeof(server));
	parse_server_and_port(server);

	if (g_seamless_rdp)
	{
		if (g_win_button_size)
		{
			error("You cannot use -S and -A at the same time\n");
			return 1;
		}
		g_rdp5_performanceflags &= ~RDP5_NO_FULLWINDOWDRAG;
		if (geometry_option)
		{
			error("You cannot use -g and -A at the same time\n");
			return 1;
		}
		if (g_fullscreen)
		{
			error("You cannot use -f and -A at the same time\n");
			return 1;
		}
		if (g_hide_decorations)
		{
			error("You cannot use -D and -A at the same time\n");
			return 1;
		}
		if (g_embed_wnd)
		{
			error("You cannot use -X and -A at the same time\n");
			return 1;
		}
		if (!g_use_rdp5)
		{
			error("You cannot use -4 and -A at the same time\n");
			return 1;
		}
		g_width = -100;
		g_grab_keyboard = False;
	}

	if (!username_option)
	{
		pw = getpwuid(getuid());
		if ((pw == NULL) || (pw->pw_name == NULL))
		{
			error("could not determine username, use -u\n");
			return 1;
		}

		STRNCPY(g_username, pw->pw_name, sizeof(g_username));
	}

#ifdef HAVE_ICONV
	if (g_codepage[0] == 0)
	{
		if (setlocale(LC_CTYPE, ""))
		{
			STRNCPY(g_codepage, nl_langinfo(CODESET), sizeof(g_codepage));
		}
		else
		{
			STRNCPY(g_codepage, DEFAULT_CODEPAGE, sizeof(g_codepage));
		}
	}
#endif

	if (g_hostname[0] == 0)
	{
		if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
		{
			error("could not determine local hostname, use -n\n");
			return 1;
		}

		p = strchr(fullhostname, '.');
		if (p != NULL)
			*p = 0;

		STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
	}

	if (g_keymapname[0] == 0)
	{
		if (locale && xkeymap_from_locale(locale))
		{
			fprintf(stderr, "Autoselected keyboard map %s\n", g_keymapname);
		}
		else
		{
			STRNCPY(g_keymapname, "en-us", sizeof(g_keymapname));
		}
	}
	if (locale)
		xfree(locale);


	if (prompt_password && read_password(password, sizeof(password)))
		flags |= RDP_LOGON_AUTO;

	if (g_title[0] == 0)
	{
		strcpy(g_title, "rdesktop - ");
		strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
	}

#ifdef RDP2VNC
	rdp2vnc_connect(server, flags, domain, password, shell, directory);
	return 0;
#else

	if (!ui_init())
		return 1;

#ifdef WITH_RDPSND
	if (g_rdpsnd)
	{
		if (!rdpsnd_init(rdpsnd_optarg))
		{
			warning("Initializing sound-support failed!\n");
		}
	}
#endif

	if (g_lspci_enabled)
		lspci_init();

	rdpdr_init();

	while (run_count < 2 && continue_connect)	/* add support for Session Directory; only reconnect once */
	{
		if (run_count == 0)
		{
			if (!rdp_connect(server, flags, domain, password, shell, directory))
				return 1;
		}
		else if (!rdp_reconnect
			 (server, flags, domain, password, shell, directory, g_redirect_cookie))
			return 1;

		/* By setting encryption to False here, we have an encrypted login 
		   packet but unencrypted transfer of other packets */
		if (!g_packet_encryption)
			g_encryption = False;


		DEBUG(("Connection successful.\n"));
		memset(password, 0, sizeof(password));

		if (run_count == 0)
			if (!ui_create_window())
				continue_connect = False;

		if (continue_connect)
			rdp_main_loop(&deactivated, &ext_disc_reason);

		DEBUG(("Disconnecting...\n"));
		rdp_disconnect();

		if ((g_redirect == True) && (run_count == 0))	/* Support for Session Directory */
		{
			/* reset state of major globals */
			rdesktop_reset_state();

			STRNCPY(domain, g_redirect_domain, sizeof(domain));
			STRNCPY(g_username, g_redirect_username, sizeof(g_username));
			STRNCPY(password, g_redirect_password, sizeof(password));
			STRNCPY(server, g_redirect_server, sizeof(server));
			flags |= RDP_LOGON_AUTO;

			g_redirect = False;
		}
		else
		{
			continue_connect = False;
			ui_destroy_window();
			break;
		}

		run_count++;
	}

	cache_save_state();
	ui_deinit();

	if (ext_disc_reason >= 2)
		print_disconnect_reason(ext_disc_reason);

	if (deactivated)
	{
		/* clean disconnect */
		return 0;
	}
	else
	{
		if (ext_disc_reason == exDiscReasonAPIInitiatedDisconnect
		    || ext_disc_reason == exDiscReasonAPIInitiatedLogoff)
		{
			/* not so clean disconnect, but nothing to worry about */
			return 0;
		}
		else
		{
			/* return error */
			return 2;
		}
	}

#endif

}