#!/usr/bin/perl -w
use Term::ANSIColor;
use POSIX qw(strftime);
use Getopt::Long;
Getopt::Long::Configure("no_ignore_case");

$main_version="0.3.0";

# Copyright (C) 2000-2001, KARASZI 'RASZi' Istvan
#                          <raszi@bigfoot.com>
#                          http://nrg.martos.bme.hu/release/colorize/
#
# Released under GPL version 2 or higher,
# http://www.gnu.org/copyleft/gpl.html
#
# Thanks: #linux.hu@ircnet, Andras, fu, Szilva (the Perl book ;)
#         HoFi for many ideas, tompos for the nrg's net connection
#         mhp for packing it into Debian GNU/Linux and ideas

# Words, that we like or hate
@good_words=("activ", "start", "ready", "online", "load", "ok", "register", "detected", "configured", "enable", "listen", "open", "complete", "attempt", "done", "check");
@bad_words=("warn", "restart", "exit", "stop", "end", "shutting", "down", "close", "unreach", "can't", "cannot", "skip", "deny", "disable", "ignored", "miss", "oops", "su", "not", "backdoor", "blocking", "ignoring", "unable", "readonly", "offline");
@error_words=("error", "crit", "invalid", "fail", "false");
@system_words=("ext2-fs", "reiserfs", "vfs", "iso", "isofs", "cslip", "ppp", "bsd", "linux", "ip", "tcp/ip", "mtrr", "pci", "isa", "scsi", "ide", "atapi", "bios", "cpu", "fpu");

# Item names
@items=("default", "unknown", "date", "host", "mac", "pid", "pid-sqbr", "get", "post", "head", "put", "connect", "httpcodes", "ftpcodes", "gettime", "getsize", "debug", "error", "warning", "bad", "good", "repeat", "process", "dir", "prot", "service", "email", "size", "version", "address", "uri", "miss", "parent", "direct", "hit", "deny", "ident", "refresh", "swapfail", "ctype", "clength", "create", "swapin", "swapout", "release", "swapnum", "hdate", "lmdate", "expired", "incoming", "outgoing", "user", "proxyfunction", "numbers", "system", "subject");

# Default output
$default_output="STDOUT";

# Default color
$default_color="white";

# Config file places (order is important, we will override the previous config's values)
@config_files=("/etc/colorizerc", "$ENV{HOME}/.colorizerc");

# Set all item to a default value
sub setdefaults {
	my($item);

	foreach $item(@items) {
		$color{$item}=$default_color;
	}
}

# Read configuration from a file
sub readconfig {
	my($file, $item, $value, $i, $unknown);

	$file=shift;
	if (-e $file) {
		if (!open(CONF, "< $file")) {
			print(STDERR "Can't open config file '$file': $!!"."\n");
			return(1);
		} else {
			while(<CONF>) {
				if (/^([^#]\S+)\s+([^#]+)/) {
					$item=$1;
					$value=$2;

					$unknown=1;

					# cut spaces from end
					$value =~ s/\s+$//;

					if ($value =~ /^'([^']+)'$/) {
						$value=$1;
						if (defined($color{$value})) {
							$color{$item}=$color{$value};
							$unknown=0;
						} else {
							$unknown=2;
						}
					} else {
						foreach $i(@items) {
							if ($i eq $item) {
								$unknown=0;
								$color{$item}=$value;
							}
						}
					}
					print(STDERR "Undefined value in '$file': $item = $value."."\n") if ($unknown == 2);
					print(STDERR "Unknown item in '$file': $item = $value."."\n") if ($unknown == 1);
				}
			}
			close(CONF);
			return(0);
		}
	} else { return(2); }
}

# Print html's head with 'Cascading style sheets'
sub printhtmlheader {
	my($ccolor, $pre, $col, $back);

	&printout('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">');
	&printout("<html><head>"."\n");
	&printout("<title>Generated by colorize.pl $main_version</title>"."\n");
	&printout('<style type="text/css">'."\n");
	foreach $ccolor(keys %color) {
		&printout(".$ccolor { ");

		$color{"$ccolor"} =~ /^(((bold)|(underline)|(underscore)|(blink)|(reverse)|(concealed))\s+)?(\w+)(\s+on_(\w+))?$/;
		$pre=$2;
		$col=$9;
		$back=$11;

		# We must some rewrite, 'cause some ANSIColor's colors isn't equal to css's colors
		if ($col) {
			$col =~ s/cyan/teal/;
			$col =~ s/magenta/purple/;
		}
		if ($back) {
			$back =~ s/cyan/teal/;
			$back =~ s/magenta/purple/;
		}

		if ($pre) {
			&printout("font-weight: bold;") if ($pre =~ /bold/);
			&printout("text-decoration: underline;") if($pre =~ /underline/ || $pre =~ /underscore/);
			&printout("text-decoration: blink;") if ($pre =~ /blink/);
			if ($pre =~ /reverse/) {
				my $x=$col;
				$col=$back;
				$back=$x;
			}
		}

		&printout("background-color: $back;") if ($back);
		&printout("color: $col;") if ($col);

		&printout("}"."\n");
	}

	&printout("body { background-color: #000000; }"."\n");
	&printout('</style>'."\n");
	&printout("</head>"."\n");
	&printout("<body>"."\n");
}

sub endfont {
	&printout("</font>");
	$font=0;
}

sub printenter {
	if (!$html) {
		&printout("\n");
	} else {
		&printout("<br>"."\n");
	}

	&fileclose;
	&fileopen;
}

sub printcolor {
	my($ncolor, $getcolor);

	$getcolor=shift(@_);

	# Just a debug
	$ncolor=$color{"$getcolor"};
	print(STDERR "BUG, unknown color: $getcolor!"."\n") if (!defined($ncolor) or !$ncolor);

	if (!$html) {
		eval("print(FILE color '$ncolor')");
	} else {
		&endfont if ($font);
		&printout('<font class="'.$getcolor.'">');
		$font=1;
	}
}

sub fileopen {
	# Try to open output

	if (($file eq "STDOUT") or ($file eq "STDERR")) {
		open(FILE, ">&".$file) or &error("Can't open output for write: ".$file.", $!!"."\n");
	} else {
		open(FILE, ">> $file") or &error("Can't open output for write: ".$file.", $!!"."\n");
	}
}

sub isexists {
	# Check, the file is exists or not
	# FIXME: if the file name is STDOUT or STDERR isexists return with 0
	if (($file ne "STDOUT") and ($file ne "STDERR") and -e $file) { return(1); } else { return(0); }
}

sub fileclose {
	close(FILE);
}

sub printout {
	my $line=shift;

	print(FILE $line);
}

sub error {
	my $line=shift;

	print(STDERR $line);
	exit;
}

sub quit {
	print(STDERR "Thank you for using colorize..."."\n");

	if (!$html) {
		&clearcol;
	} else {
		&endfont if ($font);

# Removed, 'cause append to an html is bogus, when we close the body and html tag
#		&printout("</body></html>");

	}
	&fileclose;
	exit;
}

sub clearcol {
	print(FILE color 'reset') if (!$html);
}

sub resetcol {
	if (!$html) {
		print(FILE color 'reset'); # Just reset the color
		&printcolor("default"); # Set to default color
	} else {
		&printcolor("default");
	}
}
sub space {
	my $spaces=shift;

	&resetcol();			# Reset the color, and write a space
	if (defined($spaces)) {
		&printout($spaces);
	} else {
		&printout(" ");
	}
}

sub printdate {
	my $line=shift;

	&printcolor("date");
	&printout($line);
	&space();
}

sub http_action {
	$_=shift(@_);

	if    (/GET/)      { &printcolor("get"); }
	elsif (/POST/)     { &printcolor("post"); }
	elsif (/HEAD/)     { &printcolor("head"); }
	elsif (/PUT/)      { &printcolor("put"); }
	elsif (/CONNECT/)  { &printcolor("connect"); }
	else               { &printcolor("unknown"); }
}

sub proxy_hierarchy {
	$_=shift(@_);

	if    (/^NO/)    { &printcolor("warning"); }
	elsif (/DIRECT/) { &printcolor("direct"); }
	elsif (/PARENT/) { &printcolor("parent"); }
	elsif (/MISS/)   { &printcolor("miss"); }
	else             { &printcolor("unknown"); }
}

sub oops_message {
	$_=shift(@_);

	if (/^([^(]+)(\([^)]*\):)(.*)$/) {
		&printcolor("proxyfunction");
		&printout($1);
		&message($2);
		&message($3);
	} else {
		&message($_);
	}
}

sub message {
	my(@line, $word, $post, $pre, $original_word, $j, $color);

	$_=shift(@_);
	if (/^((last message repeated \d+ times)|(-- MARK --))$/) {
		&printcolor("repeat");
		&printout($_);
	}
	else {
		@line=split (/ /);
		for($j=0;$j <= $#line; $j++) {
			$word = $line[$j];

			# Cut start and end characters (like ',", etc)
		 	if ($word =~ /^([`'".,!?:;(\[{<]+)([^`'".,!?:;(\[{<]\S+)$/) {
				$pre=$1;
				$word=$2;
			}
			if ($word =~ /^(\S+[^`'".,!?:;)\]}>])([`'".,!?:;)\]}>]+)$/) {
				$word=$1;
				$post=$2;
			}

			if (defined($pre)) {
				&resetcol();
				&printout($pre);
				undef $pre;
			}

			$original_word=$word;
			$word=lc($word);

			$color="";

			if ($word =~ /^(((\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|(([a-z0-9-_]+\.)+[a-z]{2,3})|(localhost)|(\w*::\w+)+)(:\d{1,5})?)$/) { $color="host"; }
			elsif ($word =~ /^([0-9a-f]{2}:){5}[0-9a-f]{2}$/i) { $color="mac"; }
			elsif ($word =~ /^\/(\S)+$/) { $color="dir"; }
			elsif ($word =~ /^[a-z0-9-_]+@([a-z0-9-_\.]+)+(\.[a-z]{2,3})?$/) { $color="email"; }
			elsif ($word =~ /^\w{2,}:\/\/(\S+\/?)+$/) { $color="uri"; }
			elsif ($word =~ /^\d+(\.\d+)?[k|M|G]{1}B?(ytes?)?$/i) { $color="size"; }
			elsif ($word =~ /^v?(\d+\.){1}((\d|[a-z])+\.)*(\d|[a-z])+$/) { $color="version"; }
			elsif ($word =~ /^0x(\d|[a-f])+$/) { $color="address"; }
			elsif (getservbyname($word, "")) { $color="service"; }
			elsif (getprotobyname($word)) { $color="prot"; }
			elsif (defined(getpwnam($word))) { $color="user"; }
			elsif ($word =~ /^-?\d+$/) { $color="numbers"; }
			else {
				for(my $i=0; $i <= $#good_words; $i++) {
					$color="good" if ($word =~ /^$good_words[$i]/);
				}
				for(my $i=0; $i <= $#bad_words; $i++) {
					$color="bad" if ($word =~ /^$bad_words[$i]/);
				}
				for(my $i=0; $i <= $#error_words; $i++) {
					$color="error" if ($word =~ /^$error_words[$i]/);
				}
				for(my $i=0; $i <= $#system_words; $i++) {
					$color="system" if ($word =~ /^$system_words[$i]/);
				}
			}

			if ($color) {
				&printcolor($color);
			} else {
				&printcolor("unknown");
			}

			&printout($original_word);

			if (defined($post)) {
				&resetcol();
				&printout($post);
				undef $post;
			}
			&space() if ($j != $#line);
		}
	}
}

## Main program ##

# Constants
$html="";
$file=$default_output;
$SIG{'TERM'}="quit";
$SIG{'KILL'}="quit";


GetOptions('file|f=s' => \$file, 'html|h' => \$html, 'help|?' => \$help, 'version|V' => \$version, 'rcfile|F=s' => \$rcfile, 'convert-date|C' => \$convert_date, 'remove-facility|r' => \$remove_facility);
	if ($version) {
		print("Version: ".$main_version."\n");
		exit;
	} elsif ($help) {
		print("colorize.pl version ".$main_version."\n");
		print("Usage: colorize.pl [OPTION]"."\n");
 		print("  -f, --file [file]      print output to a [file]"."\n");
 		print("  -h, --html             generate html output"."\n");
 		print("  -F, --rcfile [file]    read config file from [file]"."\n");
 		print("  -C, --convert-date     convert unix timestamp to readable format"."\n");
 		print("  -r, --remove-facility  remove syslog-ng's facility from start of the lines"."\n");
		print("\n");
 		print("  -?, --help             display this help and exit"."\n");
 		print("  -V, --version          output version information and exit"."\n");
		exit;
	} elsif ($rcfile) {
		@config_files=($rcfile);
		undef($rcfile);
	}

$fileexists=&isexists($file);

# Open output
&fileopen;

# Set default colors
&setdefaults;

# Read all of config files
my $noconfig=1;
foreach my $config (@config_files) {
	$noconfig=0 if (!&readconfig ($config));
}
undef(@config_files);

print(STDERR "Can't read any configuration!"."\n") if ($noconfig);
undef($noconfig);

# Print out html header if file isn't exists and html switch is on
&printhtmlheader() if (!$fileexists && $html);
undef($fileexists);

# main loop
while(<STDIN>) {
	if ($remove_facility) {
		# syslog-ng paste the facility level before log messages, we hate this, cut it off!
		s/^<[0-9]+>//;
	}

	if (/^(>From)\s(\S+)(\s+)(.*)$/) {
		# procmail log (from field)
		$header=$1;
		$mail=$2;
		$space=$3;
		$date=$4;

		&printcolor("default");
		&printout($header);
		
		&space();
		
		&printcolor("email");
		&printout($mail);
		
		&space($space);
		
		&printdate($date);
	}
	elsif (/^\s(Subject:)\s(.*)$/) {
		# procmail log (subject field)
		$header=$1;
		$subject=$2;

		&space();
		
		&printcolor("default");
		&printout($header);

		&space();

		&printcolor("subject");
		&printout($subject);
	}
	elsif (/^(\s+)(Folder:)\s(\S+)(\s+)(\d+)$/) {
		# procmail log (folder field)
		$space1=$1;
		$header=$2;
		$folder=$3;
		$space2=$4;
		$size=$5;

		&space($space1);

		&printcolor("default");
		&printout($header);

		&space();

		&printcolor("dir");
		&printout($folder);

		&space($space2);

		&printcolor("size");
		&printout($size);
	}
	elsif (/^(\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2})\s(.*)$/) {
	# Exim main log
		my($date, $msg, $action, $uniqn, $color);

		$date=$1;
		$msg=$2;

		if ($msg =~ /^(\S{16})\s(<=)\s(\S+.*)$/) {
			$color='incoming';
			$uniqn=$1;
			$action=$2;
			$msg=$3;
		}
		elsif ($msg =~ /^(\S{16})\s(=>)\s(\S+.*)$/) {
			$color='outgoing';
			$uniqn=$1;
			$action=$2;
			$msg=$3;
		}
		elsif ($msg =~ /^(\S{16})\s(==)\s(\S+.*)$/) {
			$color='error';
			$uniqn=$1;
			$action=$2;
			$msg=$3;
		}
		elsif ($msg =~ /^(\S{16})\s(.*)$/) {
			$uniqn=$1;
			$msg=$2;
		}

		# If we know last message id, then we know what is the type of last message
		# (it's send or received or something else)
		if (defined($exim_last_uniqn) && defined($uniqn)) {
			if ($exim_last_uniqn eq $uniqn) {
				$color=$exim_last_color;
			}
		}

		$color="unknown" if (! defined($color));

		&printdate($date);

		if (defined($uniqn)) {
			&printcolor($color);
			&printout($uniqn);

			$exim_last_uniqn=$uniqn;
			$exim_last_color=$color;

			&space();
		}

		if (defined($action)) {
			&printout($action);
			&space();
		}

		&message($msg);
	}
	elsif (/^(\d{9}\.\d{3})(\s+)(\d+)\s(\S+)\s(\w+)\/(\d{3})\s(\d+)\s(\w+)\s(\S+)\s(\S+)\s(\w+)\/(\S+)\s(\S*)$/) {
		# Proxy access.log
		my($date, $space, $elaps, $host, $action, $httpc, $gsize, $method, $uri, $ident, $hierar, $fhost, $content);

		$date=$1;		# timestamp
		$space=$2;		# space between time and elapsed time
		$elaps=$3;		# elapsed time
		$host=$4;		# client
		$action=$5;		# action/code
		$httpc=$6;		# http code
		$gsize=$7;		# get size
		$method=$8;		# method
		$uri=$9;		# requested uri
		$ident=$10;		# ident (disabled default, it's logged as "-")
		$hierar=$11;	# hierarchy
		$fhost=$12;		# from host
		$content=$13;	# Content-type

		if ($convert_date) {
			my $mydate=strftime("%b %e %T", gmtime($date));
			&printdate($mydate);
		} else {
			&printdate($date);
		}

		&printcolor("gettime");
		&printout($elaps);
		&space();

		&printcolor("host");
		&printout($host);
		&space();

		if ($action =~ /^ERR/)        { &printcolor("error"); }
		elsif ($action =~ /MISS/)     { &printcolor("miss"); }
		elsif ($action =~ /HIT/)      { &printcolor("hit"); }
		elsif ($action =~ /DENIED/)   { &printcolor("deny"); }
		elsif ($action =~ /REFRESH/)  { &printcolor("refresh"); }
		elsif ($action =~ /SWAPFAIL/) { &printcolor("swapfail"); }
		elsif ($action =~ /NONE/)     { &printcolor("debug"); }
		else                          { &printcolor("unknown"); }
		&printout($action);
		&resetcol();
		&printout("/");
		&printcolor("httpcodes");
		&printout($httpc);
		&space();

		&printcolor("getsize");
		&printout($gsize);
		&space();

		&http_action($method);
		&printout($method);
		&space();

		&printcolor("uri");
		&printout($uri);
		&space();

		&printcolor("ident");
		&printout($ident);
		&space();

		&proxy_hierarchy($hierar);
		&printout($hierar);
		&resetcol();
		&printout("/");
		&printcolor("host");
		&printout($fhost);
		&space();

		&printcolor("ctype");
		&printout($content);
	}
	elsif (/^(\d{9}\.\d{3})\s(\w+)\s(\w+)(\s+)\s(\d{3})\s(\d{9}|-1)(\s+)(\d{9}|-1)(\s+)(\d{9}|-1)\s(\S+)\s(-1|\d+)\/(\d+)\s(\w+)\s(\S+)$/) {
		# Proxy store.log
		my($date, $tag, $swapnum, $space1, $status, $hdate, $space2, $lmdate, $space3, $expire, $content, $length, $gsize, $method, $uri);

		$date=$1;		# date of the event
		$tag=$2;		# the event :)
		$swapnum=$3;	# swap number
		$space1=$4;		# space between swap number and http reply code
		$status=$5;		# http reply code
		$hdate=$6;		# Time from the HTTP Date reply header
		$space2=$7;		# space between hdate and lmdate
		$lmdate=$8;		# last modification date
		$space3=$9;		# space between lmdate and expire
		$expire=$10;	# expire date
		$content=$11;	# Content-type
		$length=$12;	# Content-Length
		$gsize=$13;		# actually readed bytes
		$method=$14;	# the request method (GET, POST, etc).
		$uri=$15;		# requested uri

		if ($convert_date) {
			my $mydate=strftime("%b %e %T", gmtime($date));
			&printdate($mydate);
		} else {
			&printdate($date);
		}

		if ($tag =~ /CREATE/)     { &printcolor("create"); }
		elsif ($tag =~ /SWAPIN/)  { &printcolor("swapin"); }
		elsif ($tag =~ /SWAPOUT/) { &printcolor("swapout"); }
		elsif ($tag =~ /RELEASE/) { &printcolor("release"); }
		else { &printcolor("unknown"); }
		&printout($tag);
		&space();

		&printcolor("swapnum");
		&printout($swapnum);
		&resetcol();
		&printout($space1);

		&printcolor("httpcodes");
		&printout($status);
		&space();

		&printcolor("hdate");
		&printout($hdate);
		&resetcol();
		&printout($space2);

		&printcolor("lmdate");
		&printout($lmdate);
		&resetcol();
		&printout($space3);

		&printcolor("expired");
		&printout($expire);
		&space();

		&printcolor("ctype");
		&printout($content);
		&space();

		&printcolor("clength");
		&printout($length);
		&resetcol();
		&printout("/");
		&printcolor("getsize");
		&printout($gsize);
		&space();

		&http_action($method);
		&printout($method);
		&space();

		&printcolor("uri");	# I dunno, maybe it must be same color with method (please FIXME with ideas)
		&printout($uri);
	}
	elsif (/^(\d{4}\/\d{2}\/\d{2}\s(\d{2}:){2}\d{2}\|)\s(.*)$/) {
		# Proxy cache.log
		my($date, $msg);

		$date=$1;
		$msg=$3;

		if ($convert_date) {
			my $mydate=strftime("%b %e %T", gmtime($date));
			&printdate($mydate);
		} else {
			&printdate($date);
		}

		&printcolor("debug");	# I think all cache.log message are debug level message
		&printout($msg);
	}
	elsif (/^(\w{3}\s\w{3}\s+\d+\s\d{2}:\d{2}:\d{2}\s\d{4})(\s+)(\[[^\]]+\])(.*)$/) {
		# oops.log
		$date=$1;
		$space=$2;
		$status=$3;
		$msg=$4;

		&printdate($date);
		&space($space);

		&message($status);
		&oops_message($msg);
	}
	elsif (/^(\S*)\s-\s(\S+)\s(\[\d{1,2}\/\S*\/\d{4}:\d{2}:\d{2}:\d{2}.{0,6}\])\s("([A-Z]{3,})\s[^"]+")\s(\d{3})\s(\d+|-)\s(.*)$/) {
		# httpd access.log format found
		my($host, $user, $date, $msg, $method, $full_action, $http_code, $gsize);

		$host=$1;
		$user=$2;
		$date=$3;
		$full_action=$4;
		$method=$5;
		$http_code=$6;
		$gsize=$7;
		$other=$8;

		&printcolor("host");
		&printout($host);
		&space();

		&printout("-");
		&space();

		&printcolor("user");
		&printout($user);
		&space();

		&printdate($date);


		&http_action($method);
		&printout($full_action);
		&space();

		&printcolor("httpcodes");
		&printout($http_code);
		&space();

		&printcolor("getsize");
		&printout($gsize);
		&space();

		&printcolor("default");
		&printout($other);
	}
	elsif (/^(\[\w{3}\s\w{3}\s{1,2}\d{1,2}\s\d{2}:\d{2}:\d{2}\s\d{4}\])\s(\[\w*\])\s(.*)$/) {
		# httpd error.log format found
		my($date, $level, $msg, $color);

		$date=$1;
		$level=$2;
		$msg=$3;

		&printdate($date);

		if ($level =~ /(debug|info|notice)/)         { $color="debug"; }
		elsif ($level =~ /warn/)                     { $color="warning"; }
		elsif ($level =~ /(error|crit|alert|emerg)/) { $color="error"; }
		else { $color="unknown"; }

		&printcolor($color);
		&printout($level);
		&space();

		&printcolor($color);
		&printout($msg);
	}
	elsif (/^(\S{3}\s\S{3}\s{1,2}\S{1,2}\s\d{2}:\d{2}:\d{2}\s\d{4})\s(\d+)\s(\S+)\s(\d+)\s(\S+)\s(.*)/) {
		# xferlog format found
		my($date, $time, $host, $gsiz, $gdir, $ftpc);

		$date=$1;
		$time=$2;
		$host=$3;
		$gsiz=$4;
		$gdir=$5;
		$ftpc=$6;

		&printdate($date);

		&printcolor("gettime");
		&printout($time);
		&space();

		&printcolor("host");
		&printout($host);
		&space();

		&printcolor("getsize");
		&printout($gsiz);
		&space();

		&printcolor("dir");
		&printout($gdir);
		&space();

		&printcolor("ftpcodes");
		&printout($ftpc);
	}
	elsif (/^(\S*\s{1,2}\d{1,2}\s\d\d:\d\d:\d\d)\s(\S+)\s((\S+:?)\s(.*))$/) {
		# It's a system log
		my($date, $host, $send, $process, $msg, $pid);

		$date=$1;
		$host=$2;
		$send=$3;

		# Repeat color
		if ($send !~ /((last message repeated \d+ times)|(-- MARK --))/) {
			$process=$4;
			$msg=$5;
		} else { $msg=$send; }

		&printdate($date);
		&printcolor("host");
		&printout($host);
		&space();

		if (defined($process)) {
			if ($process =~ /\[(\d+)\]/) {
				$process=$`;
				$pid=$1;
			}
		&printcolor("process");
		&printout($process);
		if (defined($pid)) {
			&printcolor("pid-sqbr");
			&printout("[");
			&printcolor("pid");
			&printout($pid);
			&printcolor("pid-sqbr");
			&printout("]");
			undef($pid);
			&resetcol();
			&printcolor("process");
			&printout(":");
		}

		undef($process);

	&space();
	}

	&message($msg);
	}
	else {
		# Print the unknown messages too
		chomp($_);
		&printcolor("unknown");
		&printout($_);
	}

	&clearcol;
	&printenter;
}

&quit;		# Say goodbye

# vi: ts=4 ai
