9 serial-console [options]
13 -h,--help Display brief help message
14 -v,--verbose Increase verbosity
15 -q,--quiet Decrease verbosity
16 -l,--log FILE Log output to file
17 -r,--rcfile FILE Modify specified bochsrc file
21 C<serial-console> provides a virtual serial console for use with
22 Bochs. Running C<serial-console> creates a pseudo-tty. The master
23 side of this pty is made available to the user for interaction; the
24 slave device is written to the Bochs configuration file
25 (C<bochsrc.txt>) for use by a subsequent Bochs session.
31 =item C<serial-console>
33 Create a virtual serial console for Bochs, modify C<bochsrc.txt>
36 =item C<serial-console -r ../.bochsrc -l serial.log>
38 Create a virtual serial console for Bochs, modify C<../.bochsrc>
39 appropriately, log output to C<serial.log>.
45 Before starting Bochs, run C<serial-console> in a different session
46 (e.g. a different xterm window). When you subsequently start Bochs,
47 anything that the emulated machine writes to its serial port will
48 appear in the window running C<serial-console>, and anything typed in
49 the C<serial-console> window will arrive on the emulated machine's
52 You do B<not> need to rerun C<serial-console> afresh for each Bochs
59 =item B<-l,--log FILE>
61 Log all output (i.e. everything that is printed in the
62 C<serial-console> window) to the specified file.
64 =item B<-r,--rcfile FILE>
66 Modify the specified bochsrc file. The file will be updated to
67 contain the path to the slave side of the psuedo tty that we create.
68 The original file will be restored when C<serial-console> exits. The
69 default is to modify the file C<bochsrc.txt> in the current directory.
71 To avoid modifying any bochsrc file, use C<--norcfile>.
79 use File
::Spec
::Functions qw
( :ALL
);
82 use POSIX qw
( :termios_h
);
87 my $restore_file = {};
89 use constant BLOCKSIZE
=> 8192;
91 ##############################################################################
93 # Parse command line options into options hash ($o)
98 # $o is the hash that will hold the options
101 rcfile
=> 'bochsrc.txt',
103 # Special handlers for some options
105 verbose
=> sub { $o->{verbosity
}++; },
106 quiet
=> sub { $o->{verbosity
}--; },
107 help
=> sub { pod2usage
(1); },
108 norcfile
=> sub { delete $o->{rcfile
}; },
110 # Merge handlers into main options hash (so that Getopt::Long can find them)
111 $o->{$_} = $opt_handlers->{$_} foreach keys %$opt_handlers;
112 # Option specifiers for Getopt::Long
113 my @optspec = ( 'help|h|?',
121 Getopt
::Long
::Configure
( 'bundling' );
122 pod2usage
("Error parsing command-line options") unless GetOptions
(
124 # Clean up $o by removing the handlers
125 delete $o->{$_} foreach keys %$opt_handlers;
129 ##############################################################################
131 # Modify bochsrc file
137 # Rename active file to backup file
138 ( my $vol, my $dir, my $file ) = splitpath
( $active );
139 $file = '.'.$file.".serial-console";
140 my $backup = catpath
( $vol, $dir, $file );
141 rename $active, $backup
142 or die "Could not back up $active to $backup: $!\n";
144 # Derive line to be inserted
145 my $patch = "com1: enabled=1, mode=term, dev=$pty\n";
148 open my $old, "<$backup" or die "Could not open $backup: $!\n";
149 open my $new, ">$active" or die "Could not open $active: $!\n";
151 ##################################################
153 # This file has been modified by serial-console.
155 # Do not modify this file; it will be erased when
156 # serial-console (pid $$) exits and will be
157 # replaced with the backup copy held in
160 ##################################################
165 while ( my $line = <$old> ) {
166 if ( $line =~ /^\s*\#?\s*com1:\s*\S/ ) {
171 $line = '# '.$line unless $line =~ /^\s*\#/;
176 print $new $patch unless $patched;
183 ##############################################################################
185 # Attach/detach message printing and terminal settings
188 print STDERR
"Bochs attached.\n\n\n"
189 if $o->{verbosity
} >= 1;
193 print STDERR
"\n\nWaiting for bochs to attach...\n"
194 if $o->{verbosity
} >= 1;
197 ##############################################################################
202 pod2usage
(1) if @ARGV;
205 my $sigdie = sub { die "Exiting via signal\n"; };
208 # Create Pty, close slave side
209 my $pty = IO
::Pty
->new();
212 print STDERR
"Slave pty is ".$pty->ttyname."\n" if $o->{verbosity
} >= 1;
217 open $log, ">$o->{log}" or die "Could not open $o->{log}: $!\n";
223 $termios = POSIX
::Termios
->new;
224 $restore_termios = POSIX
::Termios
->new;
225 $termios->getattr ( fileno(STDIN
) );
226 $restore_termios->getattr ( fileno(STDIN
) );
227 $termios->setlflag ( $termios->getlflag & ~(ICANON
) & ~(ECHO
) );
228 $termios->setiflag ( $termios->getiflag & ~(ICRNL
) );
229 $termios->setattr ( fileno(STDIN
), TCSANOW
);
232 # Modify bochsrc file
233 $restore_file = { $o->{rcfile
} =>
234 patch_bochsrc
( $o->{rcfile
}, $pty->ttyname ) }
237 # Start character shunt
239 my $select = IO
::Select
->new ( \
*STDIN
, $pty );
241 my %can_read = map { $_ => 1 }
242 $select->can_read ( $attached ?
undef : 1 );
243 if ( $can_read{\
*STDIN
} ) {
244 sysread ( STDIN
, my $data, BLOCKSIZE
)
245 or die "Cannot read from STDIN: $!\n";
246 $pty->syswrite ( $data );
248 if ( $can_read{$pty} ) {
249 if ( $pty->sysread ( my $data, BLOCKSIZE
) ) {
250 # Actual data available
251 bochs_attached
() if $attached == 0;
253 syswrite ( STDOUT
, $data );
254 $log->syswrite ( $data ) if $log;
256 # No data available but select() says we can read. This almost
257 # certainly indicates that nothing is attached to the slave.
258 bochs_detached
() if $attached == 1;
263 bochs_attached
() if $attached == 0;
269 # Restore bochsrc file if applicable
270 if ( ( my $orig_file, my $backup_file ) = %$restore_file ) {
272 rename $backup_file, $orig_file;
274 # Restore terminal settings if applicable
275 if ( $restore_termios ) {
276 $restore_termios->setattr ( fileno(STDIN
), TCSANOW
);