[Techtalk] trying to get xmon to work...
Almut Behrens
almut-behrens at gmx.net
Sat Nov 6 06:22:11 EST 2004
On Fri, Nov 05, 2004 at 08:26:09AM +0100, Almut Behrens wrote:
> On Fri, Nov 05, 2004 at 01:34:23AM +0100, Riccarda Cassini wrote:
> > On Linux, the extension is obviously called "MIT-SCREEN-SAVER" (that's
> > also what xdpyinfo lists). So, everything is fine, if that name is
> > requested. OTOH, when AIX asks for "SCREEN-SAVER", Linux just responds
> > with "sorry, haven't got that"...
> > I guess, I'd have to patch either the AIX X libraries (at least in
> > theory), or the X server code on the Linux side, to make them agree on
> > the name.
>
> Well, you could write yet another port forwarder that essentially does
> s/SCREEN-SAVER/MIT-SCREEN-SAVER/ if there's a QueryExtension request,
> passing on everything else unmodified.
...okay, had some spare time, so I just wrote it for you :)
Sorry for spamming the list, but I thought it might also be of use
to someone else sometime, 'cos if you remove the part which edits the
QueryExtension X request, you'd be left with a general purpose port
forwarder for X/HTTP/whatever, which makes it rather easy to capture or
edit any stream sent across the wire...
By default, the proxy listens on :2 and connects to :1, but you can
change that by passing display numbers as options, e.g. "-l 1 -c 0",
or "--listen 1 --connect 0", if you like it verbose.
I haven't tested it exhaustively, though -- just wrote a trivial test
program calling XScreenSaverQueryInfo(), and there were no longer any
errors with the AIX -> Linux setup...
Enjoy!
Almut
#!/usr/bin/perl -w
use IO::Socket;
use IO::Select;
use POSIX ":sys_wait_h";
use Getopt::Long;
my $listen_display = 2; # defaults
my $connect_display = 1;
GetOptions( 'listen=i' => \$listen_display,
'connect=i' => \$connect_display );
xproxy($listen_display, $connect_display);
sub listening_socket {
my $port = shift;
my $sock = IO::Socket::INET->new(
Proto => 'tcp',
LocalAddr => "0.0.0.0:$port", # bind ANY
Listen => SOMAXCONN,
ReuseAddr => 1,
)
or die "$0: can't create listening socket: $!\n";
return $sock;
}
sub connect_X_server {
my $port = shift;
my $sock = IO::Socket::INET->new(
Proto => 'tcp',
PeerAddr => "localhost:$port",
)
or die "$0: can't connect to X server: $!\n";
return $sock;
}
sub xproxy {
my $listen_port = 6000 + shift; # :0 always is port 6000
my $connect_port = 6000 + shift;
$SIG{CHLD} = \&reaper;
my $sock = listening_socket($listen_port);
while (my $client = $sock->accept()) {
my $kidpid = fork(); die "cannot fork" unless defined $kidpid;
if ($kidpid) {
close $client;
next;
}
close $sock;
my $server = connect_X_server($connect_port);
$kidpid = fork(); die "cannot fork" unless defined $kidpid;
if ($kidpid) {
shovel($client, $server, \&edit_QueryExt); # forward requests
kill 'TERM', $kidpid;
} else {
shovel($server, $client); # forward replies
kill 'TERM', getppid();
}
exit;
}
}
sub shovel {
my ($sock_from, $sock_to, $editproc) = @_;
my $slct = IO::Select->new($sock_from);
my $buf;
while($slct->can_read()) { # blocks until socket is ready for reading
sysread $sock_from, $buf, 1000000 or last;
$editproc->(\$buf) if ref($editproc) eq 'CODE';
syswrite $sock_to, $buf, length($buf);
}
}
sub edit_QueryExt {
my $buf = shift; # ref
my $opcode = unpack "C", $$buf;
if ($opcode == 98) { # = QueryExtension
my $targetname = 'MIT-SCREEN-SAVER';
# the following method is a bit crude, but
# it should suffice for the purpose at hand
if ($$buf =~ s/SCREEN-SAVER/$targetname/) {
# okay, this is the ugly part, 'cos if we've modified the
# request, we have to adjust some length-fields...
substr($$buf,4,2) = pack "n", length($targetname);
substr($$buf,2,2) = pack "n", int(length($targetname)/4)+2;
}
} # else pass through unmodified
}
sub reaper { # cleanup subprocesses
while (waitpid(-1,WNOHANG) > 0) {}
$SIG{CHLD} = \&reaper;
}
More information about the Techtalk
mailing list