#!/usr/bin/perl
#
# Attaches user's input and output to a local terminal device (/dev/tty*).
#
# Usage:
#
# PortTest tty_device
#

use strict;
use POSIX ();
use Fcntl ();

my $in;
my $termios = POSIX::Termios->new;
my $ttydev = $ARGV[ 0 ];
my $stdin_oldiflag;
my $stdin_oldlflag;
my $tty_oldlflag;
my $tty_oldiflag;

die 'Terminal device not specified' unless $ttydev;

# install signal handler:
$SIG{'INT'}    = \&handler;
$SIG{'QUIT'}   = \&handler;
$SIG{'HUP'}    = \&handler; 
$SIG{'ILL'}    = \&handler; 
$SIG{'TRAP'}   = \&handler; 
$SIG{'ABRT'}   = \&handler; 
$SIG{'EMT'}    = \&handler; 
$SIG{'FPE'}    = \&handler;
$SIG{'BUS'}    = \&handler;
$SIG{'SEGV'}   = \&handler;
$SIG{'SYS'}    = \&handler;
$SIG{'PIPE'}   = \&handler;
$SIG{'ALRM'}   = \&handler;
$SIG{'TERM'}   = \&handler;
$SIG{'TSTP'}   = \&handler;
$SIG{'TTIN'}   = \&handler;
$SIG{'TTOU'}   = \&handler;
$SIG{'XCPU'}   = \&handler;
$SIG{'XFSZ'}   = \&handler; 
$SIG{'VTALRM'} = \&handler;
$SIG{'PROF'}   = \&handler;
$SIG{'USR1'}   = \&handler;

sysopen( DEV, $ttydev, &Fcntl::O_RDWR ) || die( "Can't open $ttydev: $!" );

# Make tty line unbuffered and timeout-blocking on STDIN and TTY:
$termios->getattr( fileno( DEV ) ); 
$tty_oldlflag = $termios->getlflag();
$tty_oldiflag = $termios->getiflag();
$termios->setlflag( $tty_oldlflag & ~&POSIX::ECHO & ~&POSIX::ICANON );
$termios->setiflag( $tty_oldiflag & ~&POSIX::ICRNL );
$termios->setcc( &POSIX::VMIN, 0 );
$termios->setcc( &POSIX::VTIME, 1 );
$termios->setattr( fileno( DEV ), &POSIX::TCSANOW );
$termios->getattr( fileno( STDIN ) ); 
$stdin_oldlflag = $termios->getlflag();
$stdin_oldiflag = $termios->getiflag();
$termios->setlflag( $stdin_oldlflag & ~&POSIX::ECHO & ~&POSIX::ICANON );
$termios->setiflag( $stdin_oldiflag & ~&POSIX::ICRNL | &POSIX::BRKINT | &POSIX::IGNBRK );
$termios->setcc( &POSIX::VMIN, 0 );
$termios->setcc( &POSIX::VTIME, 1 );
$termios->setattr( fileno( STDIN ), &POSIX::TCSANOW );

while( 1 ){
	while( sysread( STDIN, $in, 1024 ) > 0 ){
                syswrite( DEV, $in, length $in );   
	}
	while( sysread( DEV, $in, 1024 ) > 0 ){
                syswrite( STDOUT, $in, length $in );   
	}
}
handler();

sub handler
{
        close DEV;
	# Turning STDIN back
	$termios->setlflag( $stdin_oldlflag );
	$termios->setiflag( $stdin_oldiflag );
	$termios->setcc( &POSIX::VMIN, 1 );
	$termios->setcc( &POSIX::VTIME, 0 );
	$termios->setattr( fileno( STDIN ), &POSIX::TCSANOW );
	# Turning TTY device back
	$termios->getattr( fileno( DEV ) ); 
	$termios->setlflag( $tty_oldlflag );
	$termios->setiflag( $tty_oldiflag );
	$termios->setcc( &POSIX::VMIN, 1 );
	$termios->setcc( &POSIX::VTIME, 0 );
	$termios->setattr( fileno( DEV ), &POSIX::TCSANOW );
        exit;
}
