=over 4
=back
serial port.
You do B<not> need to rerun C<serial-console> afresh for each Bochs
session.
=head1 OPTIONS
=over 4
=item B<-l,--log FILE>
Log all output (i.e. everything that is printed in the
C<serial-console> window) to the specified file.
=item B<-r,--rcfile FILE>
Modify the specified bochsrc file. The file will be updated to
contain the path to the slave side of the psuedo tty that we create.
The original file will be restored when C<serial-console> exits. The
default is to modify the file C<bochsrc.txt> in the current directory.
To avoid modifying any bochsrc file, use C<--norcfile>.
=back
=cut
use IO::Pty;
use IO::Select;
use File::Spec::Functions qw ( :ALL );
use Getopt::Long;
use Pod::Usage;
use POSIX qw ( :termios_h );
use strict;
use warnings;
my $o;
my $restore_file = {};
my $restore_termios;
use constant BLOCKSIZE => 8192;
##############################################################################
#
# Parse command line options into options hash ($o)
#
# $o = parse_opts();
sub parse_opts {
# $o is the hash that will hold the options
my $o = {
verbosity => 1,
};
# Special handlers for some options
my $opt_handlers = {
verbose => sub { $o->{verbosity}++; },
quiet => sub { $o->{verbosity}--; },
help => sub { pod2usage(1); },
norcfile => sub { delete $o->{rcfile}; },
};
# Merge handlers into main options hash (so that Getopt::Long can find them)
$o->{$_} = $opt_handlers->{$_} foreach keys %$opt_handlers;
# Option specifiers for Getopt::Long
);
# Do option parsing
pod2usage("Error parsing command-line options") unless GetOptions (
$o, @optspec );
# Clean up $o by removing the handlers
delete $o->{$_} foreach keys %$opt_handlers;
return $o;
}
##############################################################################
#
# Modify bochsrc file
sub patch_bochsrc {
my $active = shift;
my $pty = shift;
# Rename active file to backup file
( my $vol, my $dir, my $file ) = splitpath ( $active );
$file = '.'.$file.".serial-console";
my $backup = catpath ( $vol, $dir, $file );
rename $active, $backup
or die "Could not back up $active to $backup: $!\n";
# Derive line to be inserted
my $patch = "com1: enabled=1, mode=term, dev=$pty\n";
# Modify file
open my $old, "<$backup" or die "Could not open $backup: $!\n";
open my $new, ">$active" or die "Could not open $active: $!\n";
print $new <<"EOF";
##################################################
#
# This file has been modified by serial-console.
#
# Do not modify this file; it will be erased when
# serial-console (pid $$) exits and will be
# replaced with the backup copy held in
# $backup.
#
##################################################
EOF
my $patched;
while ( my $line = <$old> ) {
if ( $line =~ /^\s*\#?\s*com1:\s*\S/ ) {
if ( ! $patched ) {
$line = $patch;
$patched = 1;
} else {
$line = '# '.$line unless $line =~ /^\s*\#/;
}
}
}
return $backup;
}
##############################################################################
#
print STDERR "Bochs attached.\n\n\n"
if $o->{verbosity} >= 1;
}
print STDERR "\n\nWaiting for bochs to attach...\n"
if $o->{verbosity} >= 1;
}
##############################################################################
#
# Main program
$o = parse_opts();
# Catch signals
# Create Pty, close slave side
# Open logfile
my $log;
if ( $o->{log} ) {
}
# Set up terminal
my $termios;
if ( -t STDIN ) {
$restore_termios = POSIX::Termios->new;
}
# Modify bochsrc file
$restore_file = { $o->{rcfile} =>
if $o->{rcfile};
# Start character shunt
my $attached = 1;
while ( 1 ) {
}
# Actual data available
$attached = 1;
} else {
# No data available but select() says we can read. This almost
# certainly indicates that nothing is attached to the slave.
$attached = 0;
}
} else {
$attached = 1;
}
}
END {
# Restore bochsrc file if applicable
}
# Restore terminal settings if applicable
}
}