a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#!/usr/bin/perl -w
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync=head1 NAME
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncserial-console
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync=head1 SYNOPSIS
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncserial-console [options]
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncOptions:
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync -h,--help Display brief help message
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync -v,--verbose Increase verbosity
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync -q,--quiet Decrease verbosity
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync -l,--log FILE Log output to file
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync -r,--rcfile FILE Modify specified bochsrc file
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync=head1 DESCRIPTION
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncC<serial-console> provides a virtual serial console for use with
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncBochs. Running C<serial-console> creates a pseudo-tty. The master
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncside of this pty is made available to the user for interaction; the
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncslave device is written to the Bochs configuration file
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync(C<bochsrc.txt>) for use by a subsequent Bochs session.
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync=head1 EXAMPLES
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync=over 4
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync=item C<serial-console>
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncCreate a virtual serial console for Bochs, modify C<bochsrc.txt>
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncappropriately.
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync=item C<serial-console -r ../.bochsrc -l serial.log>
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncCreate a virtual serial console for Bochs, modify C<../.bochsrc>
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncappropriately, log output to C<serial.log>.
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync=back
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync=head1 INVOCATION
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncBefore starting Bochs, run C<serial-console> in a different session
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync(e.g. a different xterm window). When you subsequently start Bochs,
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncanything that the emulated machine writes to its serial port will
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncappear in the window running C<serial-console>, and anything typed in
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncthe C<serial-console> window will arrive on the emulated machine's
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncserial port.
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncYou do B<not> need to rerun C<serial-console> afresh for each Bochs
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncsession.
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync=head1 OPTIONS
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync=over 4
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync=item B<-l,--log FILE>
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncLog all output (i.e. everything that is printed in the
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncC<serial-console> window) to the specified file.
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync=item B<-r,--rcfile FILE>
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncModify the specified bochsrc file. The file will be updated to
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsynccontain the path to the slave side of the psuedo tty that we create.
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncThe original file will be restored when C<serial-console> exits. The
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncdefault is to modify the file C<bochsrc.txt> in the current directory.
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncTo avoid modifying any bochsrc file, use C<--norcfile>.
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync=back
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync=cut
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncuse IO::Pty;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncuse IO::Select;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncuse File::Spec::Functions qw ( :ALL );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncuse Getopt::Long;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncuse Pod::Usage;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncuse POSIX qw ( :termios_h );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncuse strict;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncuse warnings;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncmy $o;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncmy $restore_file = {};
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncmy $restore_termios;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncuse constant BLOCKSIZE => 8192;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync##############################################################################
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync# Parse command line options into options hash ($o)
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync# $o = parse_opts();
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncsub parse_opts {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync # $o is the hash that will hold the options
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync my $o = {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync verbosity => 1,
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync rcfile => 'bochsrc.txt',
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync };
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync # Special handlers for some options
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync my $opt_handlers = {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync verbose => sub { $o->{verbosity}++; },
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync quiet => sub { $o->{verbosity}--; },
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync help => sub { pod2usage(1); },
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync norcfile => sub { delete $o->{rcfile}; },
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync };
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync # Merge handlers into main options hash (so that Getopt::Long can find them)
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync $o->{$_} = $opt_handlers->{$_} foreach keys %$opt_handlers;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync # Option specifiers for Getopt::Long
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync my @optspec = ( 'help|h|?',
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync 'quiet|q+',
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync 'verbose|v+',
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync 'log|l=s',
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync 'rcfile|r=s',
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync 'norcfile',
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync # Do option parsing
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync Getopt::Long::Configure ( 'bundling' );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync pod2usage("Error parsing command-line options") unless GetOptions (
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync $o, @optspec );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync # Clean up $o by removing the handlers
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync delete $o->{$_} foreach keys %$opt_handlers;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync return $o;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync}
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync##############################################################################
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync# Modify bochsrc file
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncsub patch_bochsrc {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync my $active = shift;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync my $pty = shift;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync # Rename active file to backup file
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync ( my $vol, my $dir, my $file ) = splitpath ( $active );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync $file = '.'.$file.".serial-console";
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync my $backup = catpath ( $vol, $dir, $file );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync rename $active, $backup
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync or die "Could not back up $active to $backup: $!\n";
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync # Derive line to be inserted
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync my $patch = "com1: enabled=1, mode=term, dev=$pty\n";
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync # Modify file
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync open my $old, "<$backup" or die "Could not open $backup: $!\n";
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync open my $new, ">$active" or die "Could not open $active: $!\n";
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync print $new <<"EOF";
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync##################################################
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync# This file has been modified by serial-console.
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync# Do not modify this file; it will be erased when
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync# serial-console (pid $$) exits and will be
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync# replaced with the backup copy held in
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync# $backup.
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync##################################################
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncEOF
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync my $patched;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync while ( my $line = <$old> ) {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync if ( $line =~ /^\s*\#?\s*com1:\s*\S/ ) {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync if ( ! $patched ) {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync $line = $patch;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync $patched = 1;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync } else {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync $line = '# '.$line unless $line =~ /^\s*\#/;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync }
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync }
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync print $new $line;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync }
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync print $new $patch unless $patched;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync close $old;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync close $new;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync return $backup;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync}
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync##############################################################################
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync# Attach/detach message printing and terminal settings
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncsub bochs_attached {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync print STDERR "Bochs attached.\n\n\n"
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync if $o->{verbosity} >= 1;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync}
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncsub bochs_detached {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync print STDERR "\n\nWaiting for bochs to attach...\n"
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync if $o->{verbosity} >= 1;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync}
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync##############################################################################
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync# Main program
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync$o = parse_opts();
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncpod2usage(1) if @ARGV;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync# Catch signals
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncmy $sigdie = sub { die "Exiting via signal\n"; };
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync$SIG{INT} = $sigdie;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync# Create Pty, close slave side
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncmy $pty = IO::Pty->new();
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync$pty->close_slave();
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync$pty->set_raw();
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncprint STDERR "Slave pty is ".$pty->ttyname."\n" if $o->{verbosity} >= 1;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync# Open logfile
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncmy $log;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncif ( $o->{log} ) {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync open $log, ">$o->{log}" or die "Could not open $o->{log}: $!\n";
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync}
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync# Set up terminal
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncmy $termios;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncif ( -t STDIN ) {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync $termios = POSIX::Termios->new;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync $restore_termios = POSIX::Termios->new;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync $termios->getattr ( fileno(STDIN) );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync $restore_termios->getattr ( fileno(STDIN) );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync $termios->setlflag ( $termios->getlflag & ~(ICANON) & ~(ECHO) );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync $termios->setiflag ( $termios->getiflag & ~(ICRNL) );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync $termios->setattr ( fileno(STDIN), TCSANOW );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync}
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync# Modify bochsrc file
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync$restore_file = { $o->{rcfile} =>
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync patch_bochsrc ( $o->{rcfile}, $pty->ttyname ) }
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync if $o->{rcfile};
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync# Start character shunt
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncmy $attached = 1;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncmy $select = IO::Select->new ( \*STDIN, $pty );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncwhile ( 1 ) {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync my %can_read = map { $_ => 1 }
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync $select->can_read ( $attached ? undef : 1 );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync if ( $can_read{\*STDIN} ) {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync sysread ( STDIN, my $data, BLOCKSIZE )
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync or die "Cannot read from STDIN: $!\n";
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync $pty->syswrite ( $data );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync }
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync if ( $can_read{$pty} ) {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync if ( $pty->sysread ( my $data, BLOCKSIZE ) ) {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync # Actual data available
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync bochs_attached() if $attached == 0;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync $attached = 1;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync syswrite ( STDOUT, $data );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync $log->syswrite ( $data ) if $log;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync } else {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync # No data available but select() says we can read. This almost
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync # certainly indicates that nothing is attached to the slave.
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync bochs_detached() if $attached == 1;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync $attached = 0;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync sleep ( 1 );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync }
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync } else {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync bochs_attached() if $attached == 0;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync $attached = 1;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync }
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync}
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncEND {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync # Restore bochsrc file if applicable
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync if ( ( my $orig_file, my $backup_file ) = %$restore_file ) {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync unlink $orig_file;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync rename $backup_file, $orig_file;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync }
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync # Restore terminal settings if applicable
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync if ( $restore_termios ) {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync $restore_termios->setattr ( fileno(STDIN), TCSANOW );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync }
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync}