--- loco.orig 2005-05-21 16:38:10.000000000 +0200 +++ loco 2005-05-21 17:04:21.000000000 +0200 @@ -10,8 +10,9 @@ # Thanks Jeffrey Paul for several improvements # Cristian Ionescu-Idbohrn for better patterns -use Term::ANSIColor; use strict; +use POSIX qw(floor); +use Term::ANSIColor; $Term::ANSIColor::AUTORESET++; # reset color after each print $SIG{INT} = sub { print "\n"; exit; }; # reset color after Ctrl-C @@ -39,7 +40,7 @@ # color word my $alert = "LOGIN|login|DHCP_OFFER|[Cc]onnect|fatal|[Ss]uccessful|failed"; -my $warn = "dangling|Assum(e|ing)|root|miss(ed|ing)|[Ii]gnore|adminalert|delet(e|ing)"; +my $warn = "dangling|Assum(e|ing)|root|miss(ed|ing)|[Ii]gnore|adminalert|delet(e|ing)|[Aa]djust(ed|ing)"; my $good = "[Ll]isten|[Ss]tart(ed|ing)|[Rr]eady|active|[Rr]eload(ed|ing)"; # 'palette' @@ -55,15 +56,108 @@ my $warn_word_color = "yellow"; my $good_word_color = "green"; +## the aprox. width (in characters) wasted by standard infos on the left. +##TODO: is this faster than calculating? see &stopandgo +##my $widthadjust = 24; -#### Main loop +#### You shouldn't need to modify anything below. # +my ($userchoice, $TERMHEIGHT, $TERMWIDTH, $ignoredi); +my $linecounter = 0; +my $widthexcess = 0; + +BEGIN { + if (eval "use Term::ReadKey; 1"){ + ($TERMWIDTH, $TERMHEIGHT, undef, undef) = GetTerminalSize(); + }else{ + #These should be a sane defaults: + $TERMWIDTH = 80; + $TERMHEIGHT = 25; + } +} -NEWLINE: while (<>) { - ($date,$host,$service,$rest) = /^(.+?\s.+?\s.+?\s)(.+?\s)(.+?:\s)(.*)/; +###### Parse options +# +#TODO: implement getopt, so user can put +#single options together. +my ($opt_a, $opt_i, $opt_s); +($opt_a, $opt_i, $opt_s) = (0, 0, 0); +my $argi=0; +while ($argi < scalar(@ARGV)){ + my $argnow = $ARGV[$argi]; + if( $argnow =~ /^-(h|-help)$/){ + &printhelp; + exit; + }elsif($argnow =~ /^-(i|-interactive)$/){ + $opt_i = 1; + unless (-t STDOUT){ + #We "die" so the user doesn't see + #tons of garbage if s/he + #tries "loco -i|less" + #TODO make it suggest using "loco -i" + #when running "loco |less" + die <<"EOT"; +ERROR: Option -i specified, but output is not to terminal. +See man page for more detail. +EOT + } + unless (-t STDIN){ + $opt_i = 0; + $ignoredi = 1; + #We don't "die" because the program + #passing us data through the pipe + #might be expensive/impossible to be + #run again. OTOH we want to make + #sure the user get's our warning + #(after we finish)! + END{ + if ($ignoredi){ + warn colored("", 'black')."\n"; + warn <<"EOT"; +WARNING! $0: option -i had been IGNORED! +See man page for more detail. +EOT + } + }#END + } + splice(@ARGV, $argi, 1); + }elsif($argnow =~ /^-(a|-all)$/){ + $opt_a = 1; + splice(@ARGV, $argi, 1); + }elsif($argnow =~ /^-(s|-small)$/){ + $opt_s = 1; + splice(@ARGV, $argi, 1); + }elsif($argnow =~ /^-/){ + warn "$0: Unknown option: $argnow\n"; + &printhelp; + exit; + }else{ + #just leave the filenames alone and loop ahead + $argi++; + } +} +#### Main loop +# +NEWLINE: while (<>) { + if ($opt_a){ + ($date,$host,$service,$rest) = /^(.+?\s.+?\s.+?\s)(.+?\s)(\S+?\s)(.*)/; + if (! defined($date)){#This data is really weird. + #TODO: should this have it's own colour + # instead of service's? + ($service) = /^(.*)/; + ($date,$host,$rest) = ("","",""); + } + }else{ + ($date,$host,$service,$rest) = /^(.+?\s.+?\s.+?\s)(.+?\s)(.+?:\s)(.*)/; + } # Anything interesting to show? - next NEWLINE if ! defined($rest) or (length($rest) < 1); + next NEWLINE unless $opt_a or (defined($rest) and (length($rest) > 0)); + + if ($opt_s){ + $date =~ s/^(.*:.*)(:.*)(\s)/$1$3/; + $host = ""; + } # ignore if.. $service_ignore && next NEWLINE if ($service =~ /$service_ignore/); @@ -76,14 +170,17 @@ # color the whole message if.. if ($rest =~ /$line_alert/) { print colored("$rest\n", $alert_color); + &stopandgo; next NEWLINE; } if ($rest =~ /$line_warn/) { print colored("$rest\n", $warn_color); + &stopandgo; next NEWLINE; } if ($rest =~ /$line_good/) { print colored("$rest\n", $good_color); + &stopandgo; next NEWLINE; } @@ -105,6 +202,54 @@ } } print "\n"; + &stopandgo; +} + +#### If requested, stop every screen-full and ask user for keypress +# +sub stopandgo { + return unless $opt_i; + $linecounter++; + #TODO: is this fast enough?! + $widthexcess += floor( (length($date) +length($host) + +length($service) +length($rest)) + / $TERMWIDTH); + #alternative: + ##$widthexcess++ if (length($rest) > $TERMWIDTH - $widthadjust); + unless ($linecounter < $TERMHEIGHT - (3+$widthexcess)){ + print " ===>Press to continue."; + #DBG:. + #print "\tW:$TERMWIDTH,H:$TERMHEIGHT,L:$linecounter,E:$widthexcess"; + $userchoice = ; + $linecounter = 0; + $widthexcess = 0; + } +} + +#### +# +sub printhelp { + my $perldocfailure = 0; + + {#the block where to suppress warnings + local $SIG{__WARN__} = sub {}; + if(system("perldoc $0")){ $perldocfailure = 1;} + }#warnings are on again. + + if($perldocfailure){ + #TODO: this is "/"-filesystems-only! + #OTOH, who does syslogs on "\" ones?! ;-) + my ($basename) = $0 =~ m/([^\/]*)$/; + print << "EOT"; +usage: + $0 [-iash] file1 [file2 ...] + or + anotherprogram | $0 [-ash] [file1 [file2 ...]] + +For further information try 'man $basename' or install perldoc +and run '$0 -h' or '$0 --help' again. +EOT + } } =pod @@ -117,28 +262,83 @@ =head1 SYNOPSIS -B [I]... +B [I] [I]... + +program | B [I] [I]... =head1 DESCRIPTION -Colorize FILES(s), or standard input and print on the +Colorize FILE(s), or standard input and print on the standard output. With no FILE, read standard input. -To produce colors, loco uses the B -module. +To produce colors, loco uses the B module. +To get terminal dimensions, B is used if +available, I a terminal size of I<80x25> is +assumed. + +=head1 +OPTIONS + +B refers to any combination of the options listed +below. B denotes a subset of ALLOPTIONS, where +-i (and resp. --interactive) is missing. + +=over 8 + +=item B<-h>, B<--help> + +Use perldoc to display this page or print basic usage information. + +=item B<-a>, B<--all> + +Print B lines of B. (If I<$service_ignore> and +I<$line_ignore> are defined - by default they are not -, +they I this setting.) + +=item B<-s>, B<--small> + +Hostname(s) and seconds are removed from output to save space. + +=item B<-i>, B<--interactive> + +After B of information B and waits until the user presses +BEnterE> to continue. + +This option can B when I or I are B and will cause B to + +=over 2 + +=item * + +B with a warning, if standard B is B (to protect the user from special character flood.) + +=item * + +issue a I to I and B this +option if standard B is B. + +=back + +=back =head1 EXAMPLES - loco /var/log/messages + loco -i /var/log/messages tail -f /var/log/messages | loco + loco -a -i -s /var/log/messages + + loco + =head1 AUTHOR -Jules Stuifbergen . Basically, I +Jules Stuifbergen Ejules@zjuul.netE. Basically, I was bored, and rewrote 'logcolorise.pl' from Michael Babcock from scratch. Feel free to mail me patches, improvements, or fixes.