View | Details | Raw Unified | Return to bug 2289
Collapse All | Expand All

(-)rdesktop/doc/rdesktop.1 (+16 lines)
Lines 86-91 Link Here
86
86
87
Example: rdesktop -A -s 'seamlessrdpshell notepad'.
87
Example: rdesktop -A -s 'seamlessrdpshell notepad'.
88
.TP
88
.TP
89
.BR "-M <control socket path>"
90
Enable SeamlessRDP master mode. This mode allows additional applications to be
91
launched from a single SeamlessRDP session as opposed to requiring one session
92
per application. A control socket path must be specified for use by slave mode
93
invocations.
94
95
Example: rdesktop -A -s 'seamlessrdpshell notepad' -M /tmp/rdesktop-socket
96
.TP
97
.BR "-l <command>"
98
Use SeamlessRDP slave mode to execute an additional command within the master
99
SeamlessRDP session. When using this option, a control socket path must be
100
specified instead of a server, and all other options will be ignored. Note
101
that a shell does not have to be specified, only the command to be executed.
102
103
Example: rdesktop -l 'notepad' /tmp/rdesktop-socket
104
.TP
89
.BR "-B"
105
.BR "-B"
90
Use the BackingStore of the Xserver instead of the integrated one in
106
Use the BackingStore of the Xserver instead of the integrated one in
91
rdesktop.
107
rdesktop.
(-)rdesktop/proto.h (+1 lines)
Lines 303-308 Link Here
303
void seamless_select_timeout(struct timeval *tv);
303
void seamless_select_timeout(struct timeval *tv);
304
unsigned int seamless_send_zchange(unsigned long id, unsigned long below, unsigned long flags);
304
unsigned int seamless_send_zchange(unsigned long id, unsigned long below, unsigned long flags);
305
unsigned int seamless_send_focus(unsigned long id, unsigned long flags);
305
unsigned int seamless_send_focus(unsigned long id, unsigned long flags);
306
unsigned int seamless_send_spawn(char *cmdline);
306
/* scard.c */
307
/* scard.c */
307
void scardSetInfo(uint32 device, uint32 id, uint32 bytes_out);
308
void scardSetInfo(uint32 device, uint32 id, uint32 bytes_out);
308
int scard_enum_devices(uint32 * id, char *optarg);
309
int scard_enum_devices(uint32 * id, char *optarg);
(-)rdesktop/rdesktop.c (-1 / +53 lines)
Lines 29-34 Link Here
29
#include <ctype.h>		/* toupper */
29
#include <ctype.h>		/* toupper */
30
#include <errno.h>
30
#include <errno.h>
31
#include "rdesktop.h"
31
#include "rdesktop.h"
32
#include "seamless.h"
32
33
33
#ifdef HAVE_LOCALE_H
34
#ifdef HAVE_LOCALE_H
34
#include <locale.h>
35
#include <locale.h>
Lines 91-96 Link Here
91
BOOL g_owncolmap = False;
92
BOOL g_owncolmap = False;
92
BOOL g_ownbackstore = True;	/* We can't rely on external BackingStore */
93
BOOL g_ownbackstore = True;	/* We can't rely on external BackingStore */
93
BOOL g_seamless_rdp = False;
94
BOOL g_seamless_rdp = False;
95
96
/* Master socket identifier */
97
char *master_socket = NULL;
98
/* Command line to execute in slave mode */
99
char *slave_cmdline = NULL;
100
94
uint32 g_embed_wnd;
101
uint32 g_embed_wnd;
95
uint32 g_rdp5_performanceflags =
102
uint32 g_rdp5_performanceflags =
96
	RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS;
103
	RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS;
Lines 122-127 Link Here
122
rdp2vnc_connect(char *server, uint32 flags, char *domain, char *password,
129
rdp2vnc_connect(char *server, uint32 flags, char *domain, char *password,
123
		char *shell, char *directory);
130
		char *shell, char *directory);
124
#endif
131
#endif
132
133
// Send message to rdesktop running in SeamlessrRDP master mode
134
void send_seamless_slave_message(char *cmdline);
135
125
/* Display usage information */
136
/* Display usage information */
126
static void
137
static void
127
usage(char *program)
138
usage(char *program)
Lines 131-136 Link Here
131
	fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
142
	fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
132
143
133
	fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
144
	fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
145
	fprintf(stderr, "       %s -l <command> <control socket path>\n", program);
134
#ifdef RDP2VNC
146
#ifdef RDP2VNC
135
	fprintf(stderr, "   -V: vnc port\n");
147
	fprintf(stderr, "   -V: vnc port\n");
136
	fprintf(stderr, "   -Q: defer time (ms)\n");
148
	fprintf(stderr, "   -Q: defer time (ms)\n");
Lines 149-154 Link Here
149
	fprintf(stderr, "   -L: local codepage\n");
161
	fprintf(stderr, "   -L: local codepage\n");
150
#endif
162
#endif
151
	fprintf(stderr, "   -A: enable SeamlessRDP mode\n");
163
	fprintf(stderr, "   -A: enable SeamlessRDP mode\n");
164
	fprintf(stderr, "   -M: SeamlessRDP master mode socket path\n");
165
	fprintf(stderr, "   -l: <command> <control socket path>: SeamlessRDP slave mode\n");
152
	fprintf(stderr, "   -B: use BackingStore of X-server (if available)\n");
166
	fprintf(stderr, "   -B: use BackingStore of X-server (if available)\n");
153
	fprintf(stderr, "   -e: disable encryption (French TS)\n");
167
	fprintf(stderr, "   -e: disable encryption (French TS)\n");
154
	fprintf(stderr, "   -E: disable encryption from client to server\n");
168
	fprintf(stderr, "   -E: disable encryption from client to server\n");
Lines 443-448 Link Here
443
457
444
	g_num_devices = 0;
458
	g_num_devices = 0;
445
459
460
	slave_cmdline = NULL;
461
446
#ifdef RDP2VNC
462
#ifdef RDP2VNC
447
#define VNCOPT "V:Q:"
463
#define VNCOPT "V:Q:"
448
#else
464
#else
Lines 450-456 Link Here
450
#endif
466
#endif
451
467
452
	while ((c = getopt(argc, argv,
468
	while ((c = getopt(argc, argv,
453
			   VNCOPT "Au:L:d:s:c:p:n:k:g:fbBeEmzCDKS:T:NX:a:x:Pr:045h?")) != -1)
469
			   VNCOPT "Au:L:d:s:c:p:n:k:g:fbBeEmzCDKS:T:NX:a:x:Pr:045M:l:h?")) != -1)
454
	{
470
	{
455
		switch (c)
471
		switch (c)
456
		{
472
		{
Lines 783-788 Link Here
783
				g_use_rdp5 = True;
799
				g_use_rdp5 = True;
784
				break;
800
				break;
785
801
802
			case 'M':
803
				master_socket = xmalloc(sizeof(char) * (strlen(optarg) + 1));
804
				STRNCPY(master_socket, optarg, sizeof(char) * (strlen(optarg) + 1));
805
				break;
806
807
			case 'l':
808
				slave_cmdline = xmalloc(sizeof(char) * (strlen(optarg) + 1));
809
				STRNCPY(slave_cmdline, optarg, sizeof(char) * (strlen(optarg) + 1));
810
				break;
811
786
			case 'h':
812
			case 'h':
787
			case '?':
813
			case '?':
788
			default:
814
			default:
Lines 800-805 Link Here
800
	STRNCPY(server, argv[optind], sizeof(server));
826
	STRNCPY(server, argv[optind], sizeof(server));
801
	parse_server_and_port(server);
827
	parse_server_and_port(server);
802
828
829
	/* If slave mode is being used, the 'server' variable contains the name
830
	 * of the control socket to use. */
831
	if (slave_cmdline != NULL)
832
	{
833
		seamless_socket_send(server, slave_cmdline);
834
		xfree(slave_cmdline);
835
		return 0;
836
	}
837
803
	if (g_seamless_rdp)
838
	if (g_seamless_rdp)
804
	{
839
	{
805
		if (g_win_button_size)
840
		if (g_win_button_size)
Lines 837-842 Link Here
837
		g_grab_keyboard = False;
872
		g_grab_keyboard = False;
838
	}
873
	}
839
874
875
	/* If we're in master mode, create a socket and listen on it. */
876
	if (master_socket != NULL)
877
		seamless_create_socket(master_socket);
878
840
	if (!username_option)
879
	if (!username_option)
841
	{
880
	{
842
		pw = getpwuid(getuid());
881
		pw = getpwuid(getuid());
Lines 980-985 Link Here
980
1019
981
	cache_save_state();
1020
	cache_save_state();
982
	ui_deinit();
1021
	ui_deinit();
1022
	/* If we opened a socket, clean it up. */
1023
	if (master_socket != NULL)
1024
	{
1025
		seamless_close_socket(master_socket);
1026
		xfree(master_socket);
1027
	}
983
1028
984
	if (ext_disc_reason >= 2)
1029
	if (ext_disc_reason >= 2)
985
		print_disconnect_reason(ext_disc_reason);
1030
		print_disconnect_reason(ext_disc_reason);
Lines 1624-1626 Link Here
1624
		return False;
1669
		return False;
1625
	return True;
1670
	return True;
1626
}
1671
}
1672
1673
// Send message to rdesktop running in SeamlessrRDP master mode
1674
void
1675
send_seamless_slave_message(char *cmdline)
1676
{
1677
	fprintf(stderr, cmdline);
1678
}
(-)rdesktop/rdp.c (-1 / +9 lines)
Lines 22-27 Link Here
22
#include <errno.h>
22
#include <errno.h>
23
#include <unistd.h>
23
#include <unistd.h>
24
#include "rdesktop.h"
24
#include "rdesktop.h"
25
#include "seamless.h"
25
26
26
#ifdef HAVE_ICONV
27
#ifdef HAVE_ICONV
27
#ifdef HAVE_ICONV_H
28
#ifdef HAVE_ICONV_H
Lines 51-56 Link Here
51
extern BOOL g_bitmap_cache_persist_enable;
52
extern BOOL g_bitmap_cache_persist_enable;
52
extern BOOL g_numlock_sync;
53
extern BOOL g_numlock_sync;
53
54
55
/* SeamlessRDP master mode socket */
56
extern char *master_socket;
57
54
uint8 *g_next_packet;
58
uint8 *g_next_packet;
55
uint32 g_rdp_shareid;
59
uint32 g_rdp_shareid;
56
60
Lines 74-79 Link Here
74
static BOOL g_iconv_works = True;
78
static BOOL g_iconv_works = True;
75
#endif
79
#endif
76
80
81
77
/* Receive an RDP packet */
82
/* Receive an RDP packet */
78
static STREAM
83
static STREAM
79
rdp_recv(uint8 * type)
84
rdp_recv(uint8 * type)
Lines 1361-1367 Link Here
1361
rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1366
rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1362
{
1367
{
1363
	while (rdp_loop(deactivated, ext_disc_reason))
1368
	while (rdp_loop(deactivated, ext_disc_reason))
1364
		;
1369
	{
1370
		if (master_socket != NULL)
1371
			seamless_check_socket();
1372
	}
1365
}
1373
}
1366
1374
1367
/* used in uiports and rdp_main_loop, processes the rdp packets waiting */
1375
/* used in uiports and rdp_main_loop, processes the rdp packets waiting */
(-)rdesktop/seamless.c (-1 / +155 lines)
Lines 21-26 Link Here
21
#include "rdesktop.h"
21
#include "rdesktop.h"
22
#include <stdarg.h>
22
#include <stdarg.h>
23
#include <assert.h>
23
#include <assert.h>
24
#include <sys/types.h>
25
#include <sys/socket.h>
26
#include <sys/un.h>
27
#include <unistd.h>
28
#include "seamless.h"
24
29
25
/* #define WITH_DEBUG_SEAMLESS */
30
/* #define WITH_DEBUG_SEAMLESS */
26
31
Lines 30-35 Link Here
30
#define DEBUG_SEAMLESS(args)
35
#define DEBUG_SEAMLESS(args)
31
#endif
36
#endif
32
37
38
// Control socket file descriptor
39
int sock;
40
33
extern BOOL g_seamless_rdp;
41
extern BOOL g_seamless_rdp;
34
static VCHANNEL *seamless_channel;
42
static VCHANNEL *seamless_channel;
35
static unsigned int seamless_serial;
43
static unsigned int seamless_serial;
Lines 442-448 Link Here
442
}
450
}
443
451
444
452
445
446
unsigned int
453
unsigned int
447
seamless_send_focus(unsigned long id, unsigned long flags)
454
seamless_send_focus(unsigned long id, unsigned long flags)
448
{
455
{
Lines 451-453 Link Here
451
458
452
	return seamless_send("FOCUS", "0x%08lx,0x%lx", id, flags);
459
	return seamless_send("FOCUS", "0x%08lx,0x%lx", id, flags);
453
}
460
}
461
462
/* Send client-to-server message to spawn a new process on the server. */
463
unsigned int
464
seamless_send_spawn(char *cmdline)
465
{
466
	if (!g_seamless_rdp)
467
		return (unsigned int) -1;
468
469
	return seamless_send("SPAWN", cmdline);
470
}
471
472
473
/* Check seamless master mode socket and send spawn command if input found.
474
 * Returns 0 if a slave connected and sent command, 1 otherwise.  */
475
int
476
seamless_check_socket()
477
{
478
	fd_set rfds;
479
	struct timeval tv;
480
	int slaves, index, ns;
481
	struct sockaddr_un fsaun;
482
	char cmdline[256];
483
	socklen_t fromlen;
484
	FILE *fp;
485
	char c;
486
487
	FD_ZERO(&rfds);
488
	FD_SET(sock, &rfds);
489
490
	/* Don't wait - set timeout to zero. */
491
	tv.tv_sec = 0;
492
	tv.tv_usec = 0;
493
494
	/* See if any slaves are trying to connect. */
495
	slaves = select(sock + 1, &rfds, NULL, NULL, &tv);
496
497
	if (slaves == -1)
498
	{
499
		perror("Error checking socket: select()");
500
		return 1;
501
	}
502
	/* Return if no waiting slaves */
503
	else if (slaves == 0)
504
	{
505
		return 1;
506
	}
507
508
	/* Accept connection */
509
	fromlen = sizeof(fsaun);
510
	if ((ns = accept(sock, (struct sockaddr *) &fsaun, &fromlen)) < 0)
511
	{
512
		perror("server: accept");
513
		exit(1);
514
	}
515
516
	/* Read command from client socket */
517
	fp = fdopen(ns, "r");
518
	index = 0;
519
	while ((c = fgetc(fp)) != EOF && index < 256)
520
	{
521
		cmdline[index] = c;
522
523
		index++;
524
	}
525
	cmdline[index] = '\0';
526
527
	/* Send spawn command to server-side SeamlessRDP component */
528
	seamless_send_spawn(cmdline);
529
530
	return 0;
531
}
532
533
/* Create control socket */
534
void
535
seamless_create_socket(char *socket_name)
536
{
537
	struct sockaddr_un saun;
538
539
	/* Create socket */
540
	if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
541
	{
542
		perror("Error creating socket: socket");
543
		exit(1);
544
	}
545
546
	/* Bind to the socket. Any older socket with the same name will be
547
	 * unlinked first. */
548
	memset(&saun, 0, sizeof(struct sockaddr_un));
549
	saun.sun_family = AF_UNIX;
550
	strncpy(saun.sun_path, socket_name, sizeof(saun.sun_path));
551
	unlink(socket_name);
552
	if (bind(sock, (struct sockaddr *) &saun, sizeof(struct sockaddr_un)) < 0)
553
	{
554
		perror("Error binding to socket: bind");
555
		exit(1);
556
	}
557
558
	/* Listen on the socket */
559
	if (listen(sock, 5) < 0)
560
	{
561
		perror("Error listening on socket: listen");
562
		exit(1);
563
	}
564
}
565
566
/* Close control socket */
567
void
568
seamless_close_socket(char *socket_name)
569
{
570
	close(sock);
571
	unlink(socket_name);
572
573
	return;
574
}
575
576
/* Send a command line to a master process via a socket. */
577
int
578
seamless_socket_send(char *socket_name, char *cmdline)
579
{
580
	register int s, len;
581
	struct sockaddr_un saun;
582
583
	/* Create socket */
584
	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
585
	{
586
		perror("Error creating socket: socket");
587
		exit(1);
588
	}
589
590
	/* Connect to server */
591
	saun.sun_family = AF_UNIX;
592
	strcpy(saun.sun_path, socket_name);
593
	len = sizeof(saun.sun_family) + strlen(saun.sun_path);
594
	if (connect(s, (struct sockaddr *) &saun, len) < 0)
595
	{
596
		perror("Error connecting to socket: connect");
597
		exit(1);
598
	}
599
600
	/* Send command */
601
	send(s, cmdline, strlen(cmdline), 0);
602
603
	/* Close socket */
604
	close(s);
605
606
	return 0;
607
}
(-)rdesktop/seamless.h (+9 lines)
Lines 17-19 Link Here
17
   along with this program; if not, write to the Free Software
17
   along with this program; if not, write to the Free Software
18
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
*/
19
*/
20
21
/* Check seamless master mode socket and send spawn command if input found. */
22
int seamless_check_socket();
23
/* Create control socket */
24
void seamless_create_socket(char *socket_name);
25
/* Close control socket */
26
void seamless_close_socket(char *socket_name);
27
/* Send a command line to seamless master socket. */
28
int seamless_socket_send(char *socket_name, char *cmdline);

Return to bug 2289