#!/bin/sh -- # A comment mentioning perl, indented bash's sake. eval 'exec perl -S $0 ${1+"$@"}' if 0; $Term = 'xterm'; chop($term = `basename $Term`); $Term_Args_Needed = '-title %TITLE -geometry %GEOMETRY -display %DISPLAY'; $Term_Args_Options = '-bg %BG -fg %FG -fn %FONT'; chop($Hostname = `hostname`); if ( $Hostname eq '' ) { $Hostname = 'localhost'; } $Master_Cmd = "rlogin $Hostname | tee -a %TAILFILE"; $Master_Term_Cmd = "-e sh -c \'%CMD\'"; $Master_Extra_Opts = 1; $Slave_Extra_Opts = 1; $tail = 'tail'; foreach $dir (split(/:/, $ENV{PATH})) { if ( -x "$dir/fast_tail" ) { $tail = "$dir/fast_tail"; last; } } $Slave_Cmd = "$tail -f %TAILFILE"; $Slave_Term_Cmd = '-e %CMD'; $Test_Display = 'xdpyinfo -d %DISPLAY'; $Split_VT_Cmd = 'splitvt'; $Split = 0; $Rlogin = 0; $Rsh = 'rsh -n'; $Master_Term = 1; $Bg = 'floralwhite'; $Fg = 'black'; $Geometry = '80x55'; $Slave_Position = '+30+30'; $Read_Geometry = ''; $Font = '6x13'; $Master_Display = ''; $Debug = 0; chop($Program = `basename $0`); $PROGRAM = $Program; $PROGRAM =~ y/a-z/A-Z/; $Tail_File = "$ENV{HOME}/$Program.$$"; $Usage = <<"END"; $Program: Start up a master $term along with slave's on other displays showing what is happening on the master. Usage: $Program [] [ ...] Options: -f Use for tty output. (instead of $Tail_File) -r Use rlogin instead of xhosting, (unless display matches an X display with ":n", hack - use "::n" to force it back to rlogin). Once rlogin'ed $term is started on that local display (or "::n"). -t Don't start a separate $term for master, use the current terminal. -s Split the $term into 2 windows using the "$Split_VT_Cmd" program. This is like the "talk" command where communication is symmetrical. -d Set master's display. -g Set $term geometry ($Geometry) -p Set optional +X+Y position (useful with -n) -F Set $term font. ($Font) -bg set bg color. ($Bg) -fg set fg color. ($Fg) -nm Shut off font and color choices for master. -ns Shut off font and color choices for slaves. -D Turn on debugging output. END LOOP: while (@ARGV) { $_ = shift; CASE: { /^-D$/ && ($Debug = 1, last CASE); /^-r$/ && ($Rlogin = 1, last CASE); /^-t$/ && ($Master_Term = 0, last CASE); /^-s$/ && ($Split = 1, last CASE); /^-f$/ && ($Tail_File = shift, last CASE); /^-fg$/ && ($Fg = shift, last CASE); /^-bg$/ && ($Bg = shift, last CASE); /^-g/ && ($Geometry = shift, $Read_Geometry = 1, last CASE); /^-p/ && ($Position = shift, last CASE); /^-d/ && ($Master_Display = shift, last CASE); /^-ns$/ && ($Slave_Extra_Opts = 0, last CASE); /^-nm$/ && ($Master_Extra_Opts = 0, last CASE); /^--$/ && (last LOOP); # -- means end of switches /^-(-.*)$/ && (unshift(@ARGV, $1), last CASE); /^(-h|-help)$/ && ((print $Usage), exit 0, last CASE); if ( /^-(..+)$/ ) { # split bundled switches: local($y, $x) = ($1, ''); foreach $x (reverse(split(//, $y))) { unshift(@ARGV,"-$x") }; last CASE; } /^-/ && ((print "Invalid arg: $_\n$Usage"), exit 1, last CASE); unshift(@ARGV,$_); last LOOP; } } if ( $Master_Display eq '' ) { if ( $ENV{DISPLAY} ne '' ) { $Master_Display = $ENV{DISPLAY}; } else { $Master_Display = ':0.0'; } } $ENV{DISPLAY} = $Master_Display; $Tail_File2 = "$Tail_File.2"; open(TAIL, ">$Tail_File") || die "Could not open tail file: $Tail_File: $!"; $msg = "** START of \"$Program\" tracing... (tailing $Tail_File) **\n** Press CTRL-C when you want to Quit. **\n"; if ($Split) { $msg .= "** And log out of login session in above window **\n"; $msg .= "** Press CTRL-W to switch between windows **\n"; $msg .= "** Press CTRL-O then 'h' for splitvt help **\n"; } $msg .= "\n"; print TAIL $msg; close(TAIL); if ( $Split ) { open(TAIL, ">$Tail_File2") || die "Could not open tail file: $Tail_File2: $!"; print TAIL $msg; close(TAIL); } if ( ! $Master_Term && ! $Read_Geometry ) { &Setup_Rows_Columns(); } if ( $Position ne '' ) { $Geometry .= $Position; $Slave_Geometry = $Geometry; $Master_Geometry = $Geometry; } else { $Slave_Geometry = $Geometry . $Slave_Position; $Master_Geometry = $Geometry . "-30-30"; } # Start slaves $Slave_Count = 0; foreach $slave (@ARGV) { &Start_Slave($slave); } print STDERR "$Program: $Slave_Count slaves launched.\n"; &Start_Master(); $msg = "\n** END of \"$Program\" tracing ... Press CTRL-C to Exit. **\n"; if ( $Split ) { $msg .= "** And also log out of login session in above window **\n"; } open(TAIL, ">>$Tail_File") || die "Could not open tail file: $Tail_File: $!"; print TAIL $msg; close(TAIL); sleep 1; if ( $Split ) { open(TAIL, ">>$Tail_File2") || die "Could not open tail file: $Tail_File2: $!"; print TAIL $msg; close(TAIL); } unlink($Tail_File); unlink($Tail_File2); exit 0; sub Start_Slave { local($slave) = @_; local($targs) = $Term_Args_Options; if ( ! $Slave_Extra_Opts ) { $targs = ''; } local($cmd); $cmd = "$Term $Term_Args_Needed $targs $Slave_Term_Cmd"; local($tc) = ''; if ( $Split ) { local($top) = $Master_Cmd; $top =~ s/%TAILFILE/$Tail_File2/g; $top = &Shell_Wrap_Cmd($top); local($bot) = $Slave_Cmd; $bot =~ s/%TAILFILE/$Tail_File/g; $bot = &Shell_Wrap_Cmd($bot); $tc = "$Split_VT_Cmd -upper $top -lower $bot"; } else { $tc = $Slave_Cmd; $tc =~ s/%TAILFILE/$Tail_File/g; } $cmd =~ s/%CMD/$tc/g; local($display) = ''; local($remotehost) = ''; local($rlogin) = 0; if ( $Rlogin ) { if ( $slave =~ /^(.*):(:\d+)/ ) { $remotehost = $1; $display = $2; $rlogin = 1; } elsif ( $slave =~ /^(.*)(:\d+)/ ) { $rlogin = 0; } else { $remotehost = $slave; $rlogin = 1; } } else { if ( $slave =~ /:\d+/ ) { $display = $slave; } else { $display = "$slave:0.0"; } } if ( ! $rlogin ) { if ( ! &Test_Display($display) ) { print STDERR "$Program: Could not open display: $display, skipping.\n"; return; } } $Slave_Count++; $cmd =~ s/%TITLE/${PROGRAM}-slave-#$Slave_Count/g; $cmd =~ s/%BG/$Bg/g; $cmd =~ s/%FG/$Fg/g; $cmd =~ s/%GEOMETRY/$Slave_Geometry/g; $cmd =~ s/%FONT/$Font/g; $cmd =~ s/%TAILFILE/$Tail_File/g; $cmd =~ s/%DISPLAY/$display/g; if ( $rlogin ) { $cmd =~ s/#/\\#/g; $cmd = "$Rsh $remotehost \"$cmd\" &"; } else { $cmd = "$cmd &"; } print STDERR "$Program: Slave: $cmd\n" if $Debug; system($cmd); sleep 1; } sub Start_Master { local($cmd); local($targs) = $Term_Args_Options; if ( ! $Master_Extra_Opts ) { $targs = ''; } local($cmd); if ( $Master_Term ) { $cmd = "$Term $Term_Args_Needed $targs $Master_Term_Cmd"; } local($tc) = ''; if ( $Split ) { local($top) = $Master_Cmd; $top =~ s/%TAILFILE/$Tail_File/g; $top = &Shell_Wrap_Cmd($top); local($bot) = $Slave_Cmd; $bot =~ s/%TAILFILE/$Tail_File2/g; $bot = &Shell_Wrap_Cmd($bot); $tc = "$Split_VT_Cmd -upper $top -lower $bot"; } else { $tc = $Master_Cmd; $tc =~ s/%TAILFILE/$Tail_File/g; } if ( ! $Master_Term ) { $cmd = $tc; } else { $cmd =~ s/%CMD/$tc/g; } $cmd =~ s/%TITLE/${PROGRAM}-master/g; $cmd =~ s/%BG/$Bg/g; $cmd =~ s/%FG/$Fg/g; $cmd =~ s/%GEOMETRY/$Master_Geometry/g; $cmd =~ s/%FONT/$Font/g; $cmd =~ s/%TAILFILE/$Tail_File/g; $cmd =~ s/%DISPLAY/$Master_Display/g; print STDERR "$Program: Master: $cmd\n" if $Debug; local($rc) = system($cmd); if ( $rc == 0 ) { print STDERR "$Program: Finished: $cmd\n" if $Debug; } else { print STDERR "$Program: Problem running: $cmd\n"; return 0; } return 1; } sub Test_Display { local($display) = @_; local($cmd) = $Test_Display; $cmd =~ s/%DISPLAY/$display/g; local($rc) = system("$cmd 1>/dev/null 2>&1"); if ( $rc != 0 ) { print STDERR "$Program: Could not open display: $display\n" if $Debug; return 0; } else { return 1; } } sub Setup_Rows_Columns { open(STTY, "stty -a|"); local($rows) = ''; local($cols) = ''; while () { if ( /rows\s*=\s*(\d+)\b/ ) { $rows = $1; } if ( /columns\s*=\s*(\d+)\b/ ) { $cols = $1; } } if ($rows eq '' ) { $rows = $ENV{LINES}; } if ($rows eq '' ) { $rows = '25'; } if ($cols eq '' ) { $cols = $ENV{COLUMNS}; } if ($cols eq '' ) { $cols = '80'; } $Geometry = "${cols}x${rows}"; } sub Shell_Wrap_Cmd { local($cmd) = @_; $Tmp_Count++; local($tmp) = "/tmp/$Program.$$.$Tmp_Count"; open(TMP, ">$tmp"); chmod(0700,$tmp); print TMP "#!/bin/sh\n"; print TMP "(sleep 5; rm -f $tmp) &\n"; print TMP "$cmd\n"; print TMP "exit 0\n"; close(TMP); return $tmp; }