http://www.perlmonks.org?node_id=474423
Category:
Author/Contact Info steven fountain (slf@dreamscape.org) http://dreamscape.org/code/ (http://dreamscape.org/steven-fountain.txt) 1-925-895-1500
Description: --------------------------------------------------------
screenshots @ http://dreamscape.org/code/ilf-war.png
inspiration @ http://dreamscape.org/swim/index.php/article/112089231
++ instant war room ++
(using xterm's) http://dreamscape.org/code/ilf-war
(using eterm's) http://dreamscape.org/code/ilf-war-eterm
this version is capable of much much more:)
--------------------------------------------------------
get it at http://dreamscape.org/code/ilf
-------------------------------------------------------------------- ilf - input line frequency/time event visualization DSC Ops Research Group - http://dreamscape.org/ (slf@) organicly evolved from: http://dreamscape.org/code/tdpc -------------------------------------------------------------------- you will see two things: symbols that show timechanges (also indicating a line was seen), and secondly symbols that happen so quickly a timechange has not happened. you can customize the colors of each of these w/ -c -t -------------------------------------------------------------------- psuedo-math for 'blinky light over time' w/ducttape it all started because I pondered to myself . o O "I wonder how frequently I make my neighbors w/love:) wireless light blink.." ..then it evolved! -------------------------------------------------------------------- screenshots of its predecessor's output can be found at http://dreamscape.org/swim/index.php/article/1120892317 this version is capable of much much more:) screenshots @ http://dreamscape.org/code/ilf-war.png >> instant war room << (using xterm's) http://dreamscape.org/code/ilf-war (using eterm's) http://dreamscape.org/code/ilf-war-eterm -------------------------------------------------------------------- General options: -b 'REGEX' pattern that allways triggers bold -i 'REGEX' pattern that allways triggers reverse -F 'REGEX' pattern that allways triggers blink -r 'REGEX' pattern that triggers reverse ON -R 'REGEX' pattern that triggers reverse OFF -k 'REGEX' pattern that triggers blinking ON -K 'REGEX' pattern that triggers blinking OFF -f 'STR' color choice for "he's on fire!" mode -L INT the limit that triggers "he's on fire!" mode (the default is 50 within .1s (1 ms)) -l enable internal logging to ilf.log (ilf | tee -a ilf.log.color is cooler) -m INT number of lines to represent on each line in our visualization (the default is 50) -c 'STR' color choice for really fast lines -t 'STR' color choice for time changes -h display this help -H drop this help text to ilf.txt and less it -z FLOAT sleep this much time instead of default 1s "builtin" function: -N [-n[O]] [-d] : track output of lsof (network status) -S [-n[O]] [-d] : track output of lsof (system status) -W [-n[0]] [-d] : track output of who (login activity) -s [-n[O]] [-d] : track output of ps auxfw (process activity) -D 'command line' [-n[o]] [-d] : track "command" output Usage: ilf 'command line' ilf -- command [args ...] ilf -d command [args ...] (is equivilant to -- but with debug) ilf builtin {-D|-N|-S|-W|-s} [options ...] ilf builtin -D 'tail -1000 /var/log/*.log' -n ilf -w ilf -H
#!/usr/bin/perl
# ilf - input line frequency/time event visualization (slf@dreamscape.
+org)
#                a steven fountain creation most definitely:) hire me?
#                  i do it all for the praise and the word of mouth
#
# psuedo-math for 'blinky light over time' w/duct tape for general uni
+xy things
#
# screenshots of its predecessor's output at http://dreamscape.org/swi
+m/index.php/article/1120892317
# this version is capable of much much more:)
# >> instant war room <<
#      screenshots @ http://dreamscape.org/code/ilf-war.png
#    (using xterm's) http://dreamscape.org/code/ilf-war
#    (using eterm's) http://dreamscape.org/code/ilf-war-eterm
#
# Come back later and check out this file again at http://dreamscape.o
+rg/code/ilf
# as it may be updated and improved!
#
$usage = "------------------------------------------------------------
+--------
   ilf - input line frequency/time event visualization
  DSC Ops Research Group - http://dreamscape.org/ (slf@)
 organicly evolved from: http://dreamscape.org/code/tdpc
--------------------------------------------------------------------
 you will see two things: symbols that show timechanges
 (also indicating a line was seen), and secondly symbols
 that happen so quickly a timechange has not happened.
 you can customize the colors of each of these w/ -c -t
--------------------------------------------------------------------
  psuedo-math for 'blinky light over time' w/ducttape
          it all started because I pondered to myself
   . o O \"I wonder how frequently I make my neighbors
w/love:)  wireless light blink..\"    ..then it evolved!
--------------------------------------------------------------------
 screenshots of its predecessor's output can be found at
 http://dreamscape.org/swim/index.php/article/1120892317
 this version is capable of much much more:)
 screenshots @ http://dreamscape.org/code/ilf-war.png
 >> instant war room <<
    (using xterm's) http://dreamscape.org/code/ilf-war
    (using eterm's) http://dreamscape.org/code/ilf-war-eterm
--------------------------------------------------------------------
  General options:
   -b 'REGEX' pattern that allways triggers bold
   -i 'REGEX' pattern that allways triggers reverse
   -F 'REGEX' pattern that allways triggers blink
   -r 'REGEX' pattern that triggers reverse ON
   -R 'REGEX' pattern that triggers reverse OFF
   -k 'REGEX' pattern that triggers blinking ON
   -K 'REGEX' pattern that triggers blinking OFF
   -f 'STR'   color choice for \"he's on fire!\" mode
   -L INT     the limit that triggers \"he's on fire!\" mode
              (the default is 50 within .1s (1 ms))
   -l         enable internal logging to ilf.log
              ($0 | tee -a ilf.log.color is cooler)
   -m INT     number of lines to represent on each line in
              our visualization (the default is 50)
   -c 'STR'   color choice for really fast lines
   -t 'STR'   color choice for time changes
   -h         display this help
   -H         drop this help text to ilf.txt and less it
   -z FLOAT   sleep this much time instead of default 1s

  \"builtin\" function:
   -N [-n[O]] [-d] : track output of lsof (network status)
   -S [-n[O]] [-d] : track output of lsof (system status)
   -W [-n[0]] [-d] : track output of who (login activity)
   -s [-n[O]] [-d] : track output of ps auxfw (process activity)
   -D 'command line' [-n[o]] [-d] : track \"command\" output

 Usage:
   $0 'command line'
   $0 -- command [args ...]
   $0 -d command [args ...] (is equivilant to -- but with debug)
   $0 builtin {-D|-N|-S|-W|-s} [options ...]
   $0 builtin -D 'tail -1000 /var/log/*.log' -n
   $0 -w
   $0 -H                                           
";


use Term::ANSIColor;
use Time::HiRes qw(time);
$|=1; # autoflushing (required)
use Getopt::Std;
$specificly = shift || die "$usage";
if ($specificly =~ /^-H/)
{
  open HELP, "> ilf.txt";
  print HELP "$usage";
  close HELP;
  system "less ilf.txt";
  print "The help file exists as ilf.txt if you need to refer to it ag
+ain.\n";
  exit;
}

sub printandorlog
{ # no color for the log, sorry ;) just perl ilf -- blah | tee -a ilf.
+log.color
  my $msg=shift;
  print "$msg";
  print LOG "$msg" if ($l eq 1);
}

if ($specificly eq '-d')
{
  printandorlog "# Letting you get away with ghetto option evading. ;)
+\n";
  $specificly = join ' ', @ARGV;
  printandorlog "# Enabling debugging too. This is the only option you
+ get. ;);)\n";
  $d = 1;
}
elsif ($specificly eq '-w')
{
  print "Retrieving http://dreamscape.org/code/ilf-war to ./ilf-war ..
+\n";
  system "wget -O ilf-war http://dreamscape.org/code/ilf-war";
  
  print "Adding execute bit to ./ilf-war ..\n";
  system "chmod +x ilf-war";
  
  print "Running ./ilf-war ..\n";
  system "./ilf-war &";
  
  exit;
}
elsif ($specificly eq '--')
{
  printandorlog "# Letting you get away with ghetto option evading. ;)
+\n";
  $specificly = join ' ', @ARGV;
}
else
{
  getopts('i:b:K:k:m:c:t:D:F:r:R:L:hlsdSNWnoHwz', \%switches);
  (print "$usage" and exit) if ($specificly =~ /^-(?:h|help|\-help)(?:
+$|\s)/);
  foreach(sort keys %switches) {
    $usedaswitch=1;
    ${$_}= "$switches{$_}";
    (print "$usage" and exit) if ($h eq 1);
    #warn "# * Hint: -D usage is supposed to be something like -D 'tai
+l /var/log/messages' and NOT 'tail -f /var/log/messages'\n *        M
+aybe you might want $0 \'$D\' instead if you dont see changes.\n" if 
+($D && $D =~ /(?:tail|tcpdump|watch)/);
    printandorlog "#  * $_ is \"$switches{$_}\"";
    if ($switches{$_} eq '1') { printandorlog " (ON)"; }
    if ($switches{$_} eq '0') { printandorlog " (OFF)"; }
    printandorlog "\n";
  }
}

if ($l eq 1)
{ 
  system "mv ilf.log.2ago ilf.log.3ago 2>/dev/null";
  system "mv ilf.log.1ago ilf.log.2ago 2>/dev/null";
  system "mv ilf.log      ilf.log.1ago 2>/dev/null";
  die "I tried to move ilf.log out of the way but it's still there?  Y
+o?\n" if (-e "ilf.log");
  open LOG, "+>> ilf.log" or die "Cant create ilf.log, given reason is
+: $!\n";
  printandorlog "# Logging enabled to ilf.log\n";
}

$SLEEP=$z || "1s"; # the number of seconds to sleep when diffing outpu
+t
$max=$m || 50;    # the number of lines to represent on one line
$hesonfire=$L || 50; # the number of lines that trigger the special "h
+e's on fire!" mode
$reallyfastcolor = $c || "blue";  #(items within the same second are d
+isplayed as this color)
$hesonfirecolor  = $f || "red"; #(items that have triggered the "he's 
+on fire!" mode are displayed as this color)
$timechangecolor = $t || "cyan";  #(time changes are represented by th
+is color)
$na = " - - NOT APPLICABLE - - (?: never..) "; #(hopefully you arent r
+unning ilf 'cat ilf' ? ;)
$blinkon = $k || $na;
$blinkoff = $K || $na;
$reverseon = $r || $na;
$reverseoff = $R || $na;
$whenbold = $b || $na;
$whenreverse = $i || $na;
$whenblink = $F || $na;

$blinkon =~ /NOT APPLICABLE/     ? 1 : printandorlog "                
+  pattern that hilights everything bold: /$whenbold/\n";
$blinkoff =~ /NOT APPLICABLE/    ? 1 : printandorlog "               p
+attern that hilights everything reverse: /$whenreverse/\n";
$whenbold =~ /NOT APPLICABLE/    ? 1 : printandorlog " pattern that fl
+ips the blink switch to the ON position: /$blinkon/\n";
$whenreverse =~ /NOT APPLICABLE/ ? 1 : printandorlog "pattern that fli
+ps the blink switch to the OFF position: /$blinkoff/\n";
$c eq '' ? 1 : printandorlog "reallyfastcolor: $reallyfastcolor\n";
$t eq '' ? 1 : printandorlog "timechangecolor: $timechangecolor\n";

$char = ">"; # input lines are flowing character (if you see nothing b
+ut these, we never successfully encoded a symbol)
$otime = " "; # intialize it to something so NEW!=OLD works w/no bs
$oldsize = 0; # initializing the byte-counter & byte-incremental math

if ($n eq 1 && $o eq 1) { $diffmethod = '[<>]'; }
elsif ($n eq 1) { $diffmethod = '>'; }
elsif ($o eq 1) { $diffmethod = '<'; }
else { $diffmethod = '[<>]'; }

# control-C binding
$SIG{INT} = sub { close LOG if $l; die " <- ok, exiting.\n"; };
# open TD, "tcpdump -n -i $device -s 2000 -l $specificly 2>/dev/null |
+" or die "cannot open $specificly because of: $!\n";
sub rndStr{local $"=''; "@_[map{rand$#_} 1 .. shift]"; }
$magic = `mcookie 2> /dev/null && date 2> /dev/null` || rndStr 16, 'A'
+..'Z', 0..9, 'a-z';
$magic =~ s/\n/__/g;
$magic =~ s/ /_/g;
if ($s eq 1 && $specificly eq 'builtin') { $specificly = "while true; 
+do mv /tmp/diff.now.$magic /tmp/.diff.then.$magic ; ps auxfw | grep -
+v auxfw | grep -v grep | grep -v builtin | grep -v sleep > /tmp/diff.
+now.$magic 2> /dev/null ; diff /tmp/.diff.then.$magic /tmp/diff.now.$
+magic 2>/dev/null | grep \"^$diffmethod\" 2> /dev/null ; sleep ${SLEE
+P}; done"; }
if (defined $D && $specificly eq 'builtin') { open DTEST, "$D 2\>\&1 |
+" or die "couldnt execute $D: $!\n"; close DTEST; $specificly = "whil
+e true; do mv /tmp/.custom.now.$magic /tmp/.custom.then.$magic 2> /de
+v/null ; $D > /tmp/.custom.now.$magic 2> /dev/null ; diff /tmp/.custo
+m.then.$magic /tmp/.custom.now.$magic | grep \"^$diffmethod\" 2> /dev
+/null ; sleep ${SLEEP}; done"; }
if (defined $N && $specificly eq 'builtin') { open LSOF, "lsof -n 2\>\
+&1 |" or die "couldnt execute lsof: $!\n"; close LSOF; $specificly = 
+"while true; do mv /tmp/.custom.now.$magic /tmp/.custom.then.$magic 2
+> /dev/null ; lsof -i -n > /tmp/.custom.now.$magic 2> /dev/null ; dif
+f /tmp/.custom.then.$magic /tmp/.custom.now.$magic | grep \"^$diffmet
+hod\" 2> /dev/null ; sleep ${SLEEP}; done"; }
if (defined $S && $specificly eq 'builtin') { open LSOF, "lsof -n 2\>\
+&1 |" or die "couldnt execute lsof: $!\n"; close LSOF; $specificly = 
+"while true; do mv /tmp/.custom.now.$magic /tmp/.custom.then.$magic 2
+> /dev/null ; lsof -n | grep -v $$ | grep -v grep | grep -v lsof > /t
+mp/.custom.now.$magic 2> /dev/null ; diff /tmp/.custom.then.$magic /t
+mp/.custom.now.$magic | grep -E \"^$diffmethod\" 2> /dev/null ; sleep
+ ${SLEEP}; done"; }
if (defined $W && $specificly eq 'builtin') { open WHO, "who -a 2\>\&1
+ |" or die "couldnt execute who: $!\n"; close WHO; $specificly = "whi
+le true; do mv /tmp/.custom.now.$magic /tmp/.custom.then.$magic 2> /d
+ev/null ; who > /tmp/.custom.now.$magic 2> /dev/null ; diff /tmp/.cus
+tom.then.$magic /tmp/.custom.now.$magic | grep \"^$diffmethod\" 2> /d
+ev/null ; sleep ${SLEEP}; done"; }
printandorlog "# Opening: $specificly 2\>\&1\n";
open TD, "$specificly 2\>\&1 |" or die "cannot open $specificly becaus
+e of: $!\n";
printandorlog "# high-res legend: !=0.0-0.1 sec, @=0.1-0.2, #=0.2-0.3 
+... )=0.9-1 seconds\n";
printandorlog "# bulk-res legend: 0=.'s  1..9=1..9  10..35=a..z  >35=C
+  >40=D  >50=E  >60=F\n";
printandorlog "# " . showtime() . "ilf - input line frequency/time eve
+nt visualization (slf\@dreamscape.org)\n";
printandorlog "#(freq/time)";
#printandorlog "# input lines: ";
while(<TD>)
{
  # This will strip out all ANSI characters in your input.
  s/\e\[.*?m//go;
       
  # Store our previous time measurements.
  if (defined $timenow)    {    $oldtime = $timenow;    }
    
  # Take a time measurement.
  $timenow = time;
  $time = $timenow;
    
  # Determine if this is a ordinary line or one that is also a timecha
+nge & then act
  if (defined $time && defined $oldtime)    {
    # how much time has elapsed since the last input line?
    $diff = $time - $oldtime;
    # the sensitivity of this is currently fixed at 1 millisecond.
    if ($diff > 0.01)
    {
      # we dont care about 1.2345 etc...
      if ($diff > 1) { $diff = int($diff); }

      # reset the reallyfastlines counter whenever we do a timechange
      $pcount=0;

      # encode the timechange symbol (could be high resolution)
      $char=whatchar($diff);
            
      # allways reset before changing colors.
      print color 'reset';
      
      # our timechanges are generally allways supposed to be bold.
      print color 'bold';
      
      # change the color to our configured timechangecolor setting.
      print color "$timechangecolor";
      
      # increment the timechanges bean counter.
      $timechanges++;
    }
    else
    {
      $pcount++;
      $OLDdiff = $diff;
      $diff = $pcount;
      
      # encode the character to a symbol (could be high resolution)
      $char=whatchar($diff);
      
      # then begin coloring it.
      
      # allways reset before we add options.
      print color 'reset';
      
      # clean the spoon we will use to feed the options.
      $cmode = ""; ### (clean off the spoon)
      
      # determine if we should be blinking.
      if (/${blinkon}/o) { $blinkswitch = "ON"; }
      if (/${blinkoff}/o) { $blinkswitch = "OFF"; }
      if ($blinkswitch eq 'ON') { $cmode .= "blink "; }
      
      # determine if we should be reversing.
      if (/${reverseon}/o) { $reverseswitch = "ON"; }
      if (/${reverseoff}/o) { $reverseswitch = "OFF"; }
      if ($reverseswitch eq 'ON') { $cmode .= "reverse "; }
      
      # allways blink when we match this pattern
      $cmode .= "blink " if (/$whenblink/o);
      
      # allways reverse when we match this pattern
      $cmode .= "reverse " if (/$whenreverse/o);
      
      # allways bold when we match this pattern
      $cmode .= "bold " if (/$whenbold/o);
      
      # then finally add the color we'll be using.
      $cmode .= "$reallyfastcolor";
      
      # and then eat up! the colors! the colors! ;)
      print color "$cmode";
      
      $reallyfastlines++;
    }
  }
  
  $pnum++;
  
  # if ($char eq '.') { print color 'red'; }
  if ($lastchar eq $char) { $prun++; }
  if ($lastchar ne $char) { $prun=0; }
  
  # he's on fire!    override color decisions when we've seen way too 
+many packets within .1 second
  if ($prun > $hesonfire)  { print color 'reset'; print color "bold $h
+esonfirecolor"; $prun++; }
  if ($prun > ($hesonfire * 2) ) { print color 'reset'; print color "r
+everse blink bold $hesonfirecolor"; }
  #                                                        ^^^ go craz
+y if we're he's on fire 2x! ;)
  # (yes this could have been pnum, but what happens when you wrap lin
+es and are still on fire? ;))
  
  # Actually print the coded character
  printandorlog "$char";
  
  # Reset immediately for good measure (you never know when you might 
+control-C or lose link, eh?)
  print color 'reset';
  
  # To help determine when we're running at ludacris speed.
  $lastchar = "$char";
  
  # How many seconds have elapsed since the last gain on the clock?
  $secondssince = time - $timehere;
  
  $secondssince = $1 if ($secondssince =~ /^(\d+(?:|\.\ddd|\.\d\d|\.\d
+))/o);
  
  # If you want to add something special at the end of each line, make
+ it look like this.
  if ($pnum eq $max) { printandorlog " ${secondssince}s since" if (def
+ined $notthefirstlineplzthxu); }
  
  # when we have filled up your screen (maxxed out the setting in -m),
+ what happens on the next line?
  if ($pnum eq $max)
  {
    if (not defined $notthefirstlineplzthxu) { $notthefirstlineplzthxu
+=1 }
    printandorlog "\n";
    $nclock = showtime();
    if ($otime ne $nclock)
    {
      printandorlog "#\n";
      printandorlog "# Gain since last clockchange: ";
      $timehere = time;
      if (not defined $timechanges) { $timechanges="no" }
      printandorlog " \+${reallyfastlines} within .1s, ${timechanges} 
+timechange";
      if ($timechanges > 1 || $timechanges eq 0) { printandorlog "s"; 
+}
      printandorlog ".\n";
      $reallyfastlines=0;
      $timechanges=0;
    }
    printandorlog "# $nclock" if ($otime ne $nclock);
    printandorlog "# " if ($otime eq $nclock);
    printandorlog " " x 10 if ($otime eq $nclock);
    $otime = $nclock;
    $pnum=0;
  }
  ## $char = "." if ($char ne '.'); # normal printing character
  # normal printing character
  printandorlog " $_" if ($d);    
}
close TD;
printandorlog " The program finished..?\n";
exit;


sub strftime ($@)
{
  my ($format,$second,$minute,$hour,$day,$month,$year) = @_;
  my %convert = (
   Y => $year + 1900,
   m => sprintf( '%02d',$month + 1 ),
   d => sprintf( '%02d',$day ),
   H => sprintf( '%02d',$hour ),
   M => sprintf( '%02d',$minute ),
   S => sprintf( '%02d',$second ),
  );
  $format =~ s#%(.)#$convert{$1}#sg;
  return $format;
}

sub showtime
{
  my ($time2,$time,$hour,$min,$lclock,$clock,$pad,$extra);
  
  $time2 = strftime( '%H%M%S', localtime() );
  $time = $1 if ($time2 =~ /^(\d\d\d\d)\d\d/o);
  $hour = $1 if ($time =~ /^(\d\d)\d\d/o);
  $min = $1 if ($time =~ /^\d\d(\d\d)/o);
  if ($hour > 12) { $extra = "pm"; $hour -= 12; }
  else
  {
    if ($hour < 1) { $hour += 12; }
    $extra = "am";
  }
  
  $clock = "$hour:${min}$extra";     
  $lclock = length $clock;
  $pad = 10 - $lclock;
  $clock .= " " x $pad;
  return $clock;
}

sub whatchar
{
    my $diff = shift;  # pass a parameter rather than checking a globa
+l
    my $char;  # return this value rather than setting a global

    my @zeroto1 = qw/! @ # $ % ^ & * ( )/;  # characters for values <1
        # (the hash mark there will generate a warning, but it's okay)

    if ( $diff <= 0 ) {
        $char = ' ';  # differs from OP code
    }
    elsif ( $diff < 1 ) {
        $char = $zeroto1[int( $diff * 10 )];
    }
    elsif ( $diff < 10 ) {
        $char = ( $diff < 9 ) ? chr( int( $diff ) + ord( '1' )) : '0';
        # are you sure "234567890" is better than "123456789" ??
        # ... $char = chr( int( $diff ) + ord( '0' )) seems okay to me
    }
    elsif ( $diff <= 35 ) {
        $char = chr( int( $diff - 10 ) + ord( 'a' ));
    }
    else {
        $diff = 260 if ( $diff > 260 );
        $char = chr( int( $diff/10 ) - 3 + ord( 'C' ));
    }
    return $char;
}

#--------------------------------------------------------
#wishlist...
#  min..avg-range..max dynamic granular highlighting
#  choose-your-own-adventure legend writing
#--------------------------------------------------------