#!/usr/bin/perl -w
# Copyright Mark Zealey <mark@itsolve.co.uk> 2001. Released under the GPL.

# This is a very quick hack that allows a gdb server to connect to plex (when
# patched with my serial patch). To use this, you need to edit the $fifos = and
# (possibly) $port = lines. You need to make *2* files using mkfifo, one called
# serial.out and one called serial.out. You must edit the lines in serial.cc in
# plex if you want to change the name from serial... To use, just run this
# script, and then run plex and gdb. In GDB, you should just type 'target remote
# localhost:1234' or whatever and it should connect.
use strict;
use Socket;
use IO::Select;

my $fifos = '/home/mark/compressed/plex86/user/serial';
my $port = 1234;

$|++;
socket S, PF_INET, SOCK_STREAM, getprotobyname 'tcp' or die "socket: $!";
setsockopt S, SOL_SOCKET, SO_REUSEADDR, pack("l", 1) or die "setsockopt: $!";
bind S, sockaddr_in($port, INADDR_ANY) or die "bind: $!";
listen S, SOMAXCONN or die "listen: $!";

while(1) {
	my $paddr = accept Client, S or next;
	&server(\*Client, $paddr);		# Only single-threaded
}

sub server {
	my ($handle, $paddr) = @_;
	my ($inF, $inH);

	open F, "$fifos.out" or die "Can't open $fifos.out for read: $!";
	open G, ">$fifos.in" or die "Can't open $fifos.in for write: $!";

	$inF = IO::Select->new(\*F);
	$inH = IO::Select->new($handle);

	while(1) {
		&do_it($inF, \*F, $handle, '<') or last;
		&do_it($inH, $handle, \*G, '>') or last;
	}
	
	close G;
	close F;
}

sub do_it {
	my ($in, $inH, $out, $dir) = @_;
	my $t;
	my $str;

	while($in->can_read(0.001)) {
		if(!sysread $inH, $t, 1) {
			return &print_err(($dir eq '>')?'gdb':'plex');
		}
		$str .= $t;
		if(!syswrite $out, $t, 1) {
			return &print_err(($dir eq '<')?'gdb':'plex');
		}
	}
	print "$dir $str\n" if $str;
	return 1;
}

sub print_err {
	my $t = shift;
	print "$t closed connection\n";
	return undef;
}
