diff --git a/log/log2sql b/log/log2sql index cd1f4f3..fa8010e 100755 --- a/log/log2sql +++ b/log/log2sql @@ -22,11 +22,11 @@ my (%plugins, %os, %message_ids); my $has_cleanup; my $db = get_db(); -foreach my $file ( @logfiles ) { +foreach my $file (@logfiles) { my ($fid, $offset) = check_logfile($file); $fid or next; - parse_logfile( $file, $fid, $offset ); -}; + parse_logfile($file, $fid, $offset); +} exit; @@ -47,14 +47,14 @@ sub trim_message { return '' if $mess eq 'TLS setup returning'; return $mess; -}; +} sub get_os_id { my $p0f_string = shift or return; $p0f_string =~ s/\s+$//; $p0f_string =~ s/^\s+//; - return if ! $p0f_string; + return if !$p0f_string; return if $p0f_string =~ /no match/; return if $p0f_string =~ /^skip/; return if $p0f_string =~ /^\d/; @@ -62,266 +62,267 @@ sub get_os_id { return if $p0f_string !~ /\w/; return if $p0f_string =~ /no longer in the cache/; - if ( ! scalar keys %os ) { - my $ref = exec_query( 'SELECT * FROM os' ); - foreach my $o ( @$ref ) { - $os{ $o->{name} } = $o->{id}; - }; - }; + if (!scalar keys %os) { + my $ref = exec_query('SELECT * FROM os'); + foreach my $o (@$ref) { + $os{$o->{name}} = $o->{id}; + } + } - if ( ! defined $os{$p0f_string} ) { + if (!defined $os{$p0f_string}) { warn "missing OS for $p0f_string\n"; - }; + } return $os{$p0f_string}; -}; +} sub get_plugin_id { my $plugin = shift; - if ( ! scalar keys %plugins ) { - my $ref = exec_query( 'SELECT * FROM plugin' ); - foreach my $p ( @$ref ) { - $plugins{ $p->{name} } = $p->{id}; - $plugins{ $p->{id} } = $p->{name}; - }; - $ref = exec_query( 'SELECT * FROM plugin_aliases' ); - foreach my $pa ( @$ref ) { - $plugins{ $pa->{name} } = $pa->{plugin_id}; - }; - }; + if (!scalar keys %plugins) { + my $ref = exec_query('SELECT * FROM plugin'); + foreach my $p (@$ref) { + $plugins{$p->{name}} = $p->{id}; + $plugins{$p->{id}} = $p->{name}; + } + $ref = exec_query('SELECT * FROM plugin_aliases'); + foreach my $pa (@$ref) { + $plugins{$pa->{name}} = $pa->{plugin_id}; + } + } + + if (!defined $plugins{$plugin}) { - if ( ! defined $plugins{$plugin} ) { #warn Dumper(\%plugins); die "missing DB plugin $plugin\n"; - }; + } return $plugins{$plugin}; -}; +} sub get_msg_id { - my ( $fid, $pid ) = @_; + my ($fid, $pid) = @_; - return $message_ids{ "$fid-$pid" } if $message_ids{ "$fid-$pid" }; + return $message_ids{"$fid-$pid"} if $message_ids{"$fid-$pid"}; #print "searching for message $pid..."; - my $msgs = exec_query( - 'SELECT * FROM message WHERE file_id=? AND qp_pid=?', - [ $fid, $pid ] - ); + my $msgs = exec_query('SELECT * FROM message WHERE file_id=? AND qp_pid=?', + [$fid, $pid]); + #print scalar @$msgs ? "y\n" : "n\n"; - if ( $msgs->[0]{id} ) { - $message_ids{ "$fid-$pid" } = $msgs->[0]{id}; - }; + if ($msgs->[0]{id}) { + $message_ids{"$fid-$pid"} = $msgs->[0]{id}; + } return $msgs->[0]{id}; -}; +} sub create_message { - my ( $fid, $ts, $pid, $message ) = @_; + my ($fid, $ts, $pid, $message) = @_; my ($host, $ip) = split /\s/, $message; - $ip = substr $ip, 1, -1; # remove brackets + $ip = substr $ip, 1, -1; # remove brackets my $id = exec_query( - "INSERT INTO message SET file_id=?, connect_start=FROM_UNIXTIME(?), qp_pid=?, ip=INET_ATON(?)", - [ $fid, $ts, $pid, $ip ] +"INSERT INTO message SET file_id=?, connect_start=FROM_UNIXTIME(?), qp_pid=?, ip=INET_ATON(?)", + [$fid, $ts, $pid, $ip] ); - if ( $host && $host ne 'Unknown' ) { - exec_query( "UPDATE message SET hostname=? WHERE id=?", [ $host, $id ] ); - }; + if ($host && $host ne 'Unknown') { + exec_query("UPDATE message SET hostname=? WHERE id=?", [$host, $id]); + } + #warn "host updated: $host\n"; -}; +} sub insert_plugin { - my ( $msg_id, $plugin, $message ) = @_; + my ($msg_id, $plugin, $message) = @_; - my $plugin_id = get_plugin_id( $plugin ); + my $plugin_id = get_plugin_id($plugin); - if ( $plugin eq 'ident::geoip' ) { + if ($plugin eq 'ident::geoip') { my ($gip, $distance) = $message =~ /(.*?),\s+([\d]+)\skm/; - if ( $distance ) { - exec_query( 'UPDATE message SET distance=? WHERE id=?', [ $distance, $msg_id ] ); + if ($distance) { + exec_query('UPDATE message SET distance=? WHERE id=?', + [$distance, $msg_id]); $message = $gip; } } - elsif ( $plugin =~ /^ident::p0f/ ) { - my $os_id = get_os_id( $message ); - if ( $os_id ) { - exec_query( 'UPDATE message SET os_id=? WHERE id=?', [ $os_id, $msg_id ] ); + elsif ($plugin =~ /^ident::p0f/) { + my $os_id = get_os_id($message); + if ($os_id) { + exec_query('UPDATE message SET os_id=? WHERE id=?', + [$os_id, $msg_id]); $message = 'pass'; } } - elsif ( $plugin eq 'connection_time' ) { + elsif ($plugin eq 'connection_time') { my ($seconds) = $message =~ /\s*([\d\.]+)\s/; - if ( $seconds ) { - exec_query( 'UPDATE message SET time=? WHERE id=?', [ $seconds, $msg_id ] ); + if ($seconds) { + exec_query('UPDATE message SET time=? WHERE id=?', + [$seconds, $msg_id]); $message = 'pass'; } } - my $result = get_score( $message ); - if ( $result ) { + my $result = get_score($message); + if ($result) { $message = trim_message($message); - }; + } - exec_query( 'INSERT INTO message_plugin SET msg_id=?, plugin_id=?, result=?, string=?', - [ $msg_id, $plugin_id, $result, $message ] + exec_query( +'INSERT INTO message_plugin SET msg_id=?, plugin_id=?, result=?, string=?', + [$msg_id, $plugin_id, $result, $message] ); -}; +} sub parse_logfile { - my $file = shift; - my $fid = shift; + my $file = shift; + my $fid = shift; my $offset = shift || 0; - my $path = "$logdir/$file"; + my $path = "$logdir/$file"; print "parsing file $file (id: $fid) from offset $offset\n"; open my $F, '<', $path or die "could not open $path: $!"; - seek( $F, $offset, 0 ) if $offset; + seek($F, $offset, 0) if $offset; - while ( defined (my $line = <$F> ) ) { + while (defined(my $line = <$F>)) { chomp $line; - next if ! $line; - my ( $type, $pid, $hook, $plugin, $message ) = parse_line( $line ); + next if !$line; + my ($type, $pid, $hook, $plugin, $message) = parse_line($line); - next if ! $type; + next if !$type; next if $type eq 'info'; next if $type eq 'unknown'; next if $type eq 'response'; - next if $type eq 'init'; # doesn't occur in all deployment models + next if $type eq 'init'; # doesn't occur in all deployment models next if $type eq 'cleanup'; next if $type eq 'error'; - my $ts = tai2unix( (split /\s/, $line)[0] ); # print "ts: $ts\n"; + my $ts = tai2unix((split /\s/, $line)[0]); # print "ts: $ts\n"; - my $msg_id = get_msg_id( $fid, $pid ) or do { - create_message( $fid, $ts, $pid, $message ) if $type eq 'connect'; + my $msg_id = get_msg_id($fid, $pid) or do { + create_message($fid, $ts, $pid, $message) if $type eq 'connect'; next; }; #warn "type: $type\n"; - if ( $type eq 'plugin' ) { - next if $plugin eq 'naughty'; # housekeeping only - insert_plugin( $msg_id, $plugin, $message ); + if ($type eq 'plugin') { + next if $plugin eq 'naughty'; # housekeeping only + insert_plugin($msg_id, $plugin, $message); } - elsif ( $type eq 'queue' ) { - exec_query('UPDATE message SET result=? WHERE id=?', [ 3, $msg_id ] ); + elsif ($type eq 'queue') { + exec_query('UPDATE message SET result=? WHERE id=?', [3, $msg_id]); } - elsif ( $type eq 'reject' ) { - exec_query('UPDATE message SET result=? WHERE id=?', [ -3, $msg_id ] ); + elsif ($type eq 'reject') { + exec_query('UPDATE message SET result=? WHERE id=?', [-3, $msg_id]); } - elsif ( $type eq 'close' ) { - if ( $message eq 'Connection Timed Out' ) { - exec_query('UPDATE message SET result=? WHERE id=?', [ -1, $msg_id ] ); - }; - } - elsif ( $type eq 'connect' ) { } - elsif ( $type eq 'dispatch' ) { - if ( substr($message, 0, 21) eq 'dispatching MAIL FROM' ) { - my ($from) = $message =~ /<(.*?)>/; - exec_query('UPDATE message SET mail_from=? WHERE id=?', [ $from, $msg_id ] ); + elsif ($type eq 'close') { + if ($message eq 'Connection Timed Out') { + exec_query('UPDATE message SET result=? WHERE id=?', + [-1, $msg_id]); } - elsif ( substr($message, 0, 19) eq 'dispatching RCPT TO' ) { - my ($to) = $message =~ /<(.*?)>/; - exec_query('UPDATE message SET rcpt_to=? WHERE id=? AND rcpt_to IS NULL', [ $to, $msg_id ] ); + } + elsif ($type eq 'connect') { } + elsif ($type eq 'dispatch') { + if (substr($message, 0, 21) eq 'dispatching MAIL FROM') { + my ($from) = $message =~ /<(.*?)>/; + exec_query('UPDATE message SET mail_from=? WHERE id=?', + [$from, $msg_id]); } - elsif ( $message =~ m/dispatching (EHLO|HELO) (.*)/ ) { - exec_query('UPDATE message SET helo=? WHERE id=?', [ $2, $msg_id ] ); + elsif (substr($message, 0, 19) eq 'dispatching RCPT TO') { + my ($to) = $message =~ /<(.*?)>/; + exec_query( +'UPDATE message SET rcpt_to=? WHERE id=? AND rcpt_to IS NULL', + [$to, $msg_id] + ); } - elsif ( $message eq 'dispatching DATA' ) { } - elsif ( $message eq 'dispatching QUIT' ) { } - elsif ( $message eq 'dispatching STARTTLS' ) { } - elsif ( $message eq 'dispatching RSET' ) { } + elsif ($message =~ m/dispatching (EHLO|HELO) (.*)/) { + exec_query('UPDATE message SET helo=? WHERE id=?', + [$2, $msg_id]); + } + elsif ($message eq 'dispatching DATA') { } + elsif ($message eq 'dispatching QUIT') { } + elsif ($message eq 'dispatching STARTTLS') { } + elsif ($message eq 'dispatching RSET') { } else { # anything here is likely an unrecognized command #print "$message\n"; - }; + } } else { print "$type $pid $hook $plugin $message\n"; - }; - }; + } + } close $F; -}; +} sub check_logfile { my $file = shift; my $path = "$logdir/$file"; - die "missing file $logdir/$file" if ! -f "$logdir/$file"; + die "missing file $logdir/$file" if !-f "$logdir/$file"; - my $inode = stat($path)->ino or die "unable to get inode for $path\n"; + my $inode = stat($path)->ino or die "unable to get inode for $path\n"; my $size = stat($path)->size or die "unable to get size for $path\n"; my $exists; #warn "check if file $file is in the DB as 'current'\n"; - if ( $file =~ /^\@/ ) { - $exists = exec_query( - 'SELECT * FROM log WHERE inode=? AND name=?', - [ $inode, 'current' ] - ); - if ( @$exists ) { + if ($file =~ /^\@/) { + $exists = exec_query('SELECT * FROM log WHERE inode=? AND name=?', + [$inode, 'current']); + if (@$exists) { print "Updating current -> $file\n"; - exec_query( - 'UPDATE log SET name=? WHERE inode=? AND name=?', - [ $file, $inode, 'current' ] - ); - return ( $exists->[0]{id}, $exists->[0]{size} ); # continue parsing - }; - }; + exec_query('UPDATE log SET name=? WHERE inode=? AND name=?', + [$file, $inode, 'current']); + return ($exists->[0]{id}, $exists->[0]{size}); # continue parsing + } + } - if ( $file eq 'current' ) { - $exists = exec_query( - 'SELECT * FROM log WHERE inode=? AND name=?', - [ $inode, $file ] - ); - if ( @$exists ) { - exec_query( - 'UPDATE log SET size=? WHERE inode=? AND name=?', - [ $size, $inode, 'current' ] - ); - return ( $exists->[0]{id}, $exists->[0]{size} ); # continue parsing - }; - }; + if ($file eq 'current') { + $exists = exec_query('SELECT * FROM log WHERE inode=? AND name=?', + [$inode, $file]); + if (@$exists) { + exec_query('UPDATE log SET size=? WHERE inode=? AND name=?', + [$size, $inode, 'current']); + return ($exists->[0]{id}, $exists->[0]{size}); # continue parsing + } + } - $exists = exec_query( - 'SELECT * FROM log WHERE name=? AND size=?', - [ $file, $size ] - ); + $exists = + exec_query('SELECT * FROM log WHERE name=? AND size=?', [$file, $size]); return if @$exists; # log file hasn't changed, ignore it - #print Dumper($exists); + #print Dumper($exists); # file is a new one we haven't seen, add to DB and parse my $id = exec_query( 'INSERT INTO log SET inode=?, size=?, name=?, created=FROM_UNIXTIME(?)', - [ $inode, $size, $file, stat($path)->ctime ] + [$inode, $size, $file, stat($path)->ctime] ); print "new file id: $id\n"; - return ( $id ); -}; + return ($id); +} sub get_log_dir { - if ( -d "log/main" ) { + if (-d "log/main") { my $wd = Cwd::cwd(); return "$wd/log/main"; - }; + } - foreach my $user ( qw/ qpsmtpd smtpd / ) { + foreach my $user (qw/ qpsmtpd smtpd /) { - my ($homedir) = (getpwnam( $user ))[7] or next; + my ($homedir) = (getpwnam($user))[7] or next; - if ( -d "$homedir/log" ) { + if (-d "$homedir/log") { return "$homedir/log/main"; - }; - if ( -d "$homedir/smtpd/log" ) { + } + if (-d "$homedir/smtpd/log") { return "$homedir/smtpd/log/main"; - }; - }; + } + } -}; +} sub get_logfiles { my $dir = shift; @@ -329,134 +330,159 @@ sub get_logfiles { opendir my $D, $dir or die "unable to open log dir $dir\n"; my @files; - while ( defined( my $f = readdir($D) ) ) { - next if ! -f "$dir/$f"; # ignore anything that's not a file - if ( $f =~ /^\@.*s$/ ) { + while (defined(my $f = readdir($D))) { + next if !-f "$dir/$f"; # ignore anything that's not a file + if ($f =~ /^\@.*s$/) { push @files, $f; - }; + } } - push @files, "current"; # always have this one last + push @files, "current"; # always have this one last closedir $D; return @files; -}; +} sub parse_line { my $line = shift; my ($tai, $pid, $message) = split /\s+/, $line, 3; - return if ! $message; # garbage in the log file + return if !$message; # garbage in the log file # lines seen many times per connection - return parse_line_plugin( $line ) if substr($message, 0, 1) eq '('; - return ( 'dispatch', $pid, undef, undef, $message ) if substr($message, 0, 12) eq 'dispatching '; - return ( 'queue', $pid, undef, undef, $message ) if substr($message, 0, 11) eq '250 Queued!'; - return ( 'response', $pid, undef, undef, $message ) if $message =~ /^[2|3]\d\d/; + return parse_line_plugin($line) if substr($message, 0, 1) eq '('; + return ('dispatch', $pid, undef, undef, $message) + if substr($message, 0, 12) eq 'dispatching '; + return ('queue', $pid, undef, undef, $message) + if substr($message, 0, 11) eq '250 Queued!'; + return ('response', $pid, undef, undef, $message) + if $message =~ /^[2|3]\d\d/; # lines seen about once per connection - return ( 'init', $pid, undef, undef, $message ) if substr($message, 0, 19) eq 'Accepted connection'; - return ( 'connect', $pid, undef, undef, substr( $message, 16) ) if substr($message, 0, 15) eq 'Connection from'; - return ( 'connect', $pid, undef, undef, substr( $message, 16) ) if substr($message, 0, 8) eq 'connect '; - return ( 'close', $pid, undef, undef, $message ) if substr($message, 0, 6) eq 'close '; - return ( 'close', $pid, undef, undef, $message ) if $message eq 'Connection Timed Out'; - return ( 'close', $pid, undef, undef, $message ) if substr($message, 0, 20) eq 'click, disconnecting'; - return parse_line_cleanup( $line ) if substr($message, 0, 11) eq 'cleaning up'; + return ('init', $pid, undef, undef, $message) + if substr($message, 0, 19) eq 'Accepted connection'; + return ('connect', $pid, undef, undef, substr($message, 16)) + if substr($message, 0, 15) eq 'Connection from'; + return ('connect', $pid, undef, undef, substr($message, 16)) + if substr($message, 0, 8) eq 'connect '; + return ('close', $pid, undef, undef, $message) + if substr($message, 0, 6) eq 'close '; + return ('close', $pid, undef, undef, $message) + if $message eq 'Connection Timed Out'; + return ('close', $pid, undef, undef, $message) + if substr($message, 0, 20) eq 'click, disconnecting'; + return parse_line_cleanup($line) + if substr($message, 0, 11) eq 'cleaning up'; # lines seen less than once per connection - return ( 'info', $pid, undef, undef, $message ) if $message eq 'spooling message to disk'; - return ( 'reject', $pid, undef, undef, $message ) if $message =~ /^[4|5]\d\d/; - return ( 'reject', $pid, undef, undef, $message ) if substr($message, 0, 14) eq 'deny mail from'; - return ( 'reject', $pid, undef, undef, $message ) if substr($message, 0, 18) eq 'denysoft mail from'; - return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 15) eq 'Lost connection'; - return ( 'info', $pid, undef, undef, $message ) if $message eq 'auth success cleared naughty'; - return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 15) eq 'Running as user'; - return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 16) eq 'Loaded Qpsmtpd::'; - return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 24) eq 'Permissions on spool_dir'; - return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 13) eq 'Listening on '; - return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 18) eq 'size_threshold set'; - return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 12) eq 'tls: ciphers'; - return ( 'error', $pid, undef, undef, $message ) if substr($message, 0, 22) eq 'of uninitialized value'; - return ( 'error', $pid, undef, undef, $message ) if substr($message, 0, 8) eq 'symbol "'; - return ( 'error', $pid, undef, undef, $message ) if substr($message, 0, 9) eq 'error at '; - return ( 'error', $pid, undef, undef, $message ) if substr($message, 0, 15) eq 'Could not print'; + return ('info', $pid, undef, undef, $message) + if $message eq 'spooling message to disk'; + return ('reject', $pid, undef, undef, $message) if $message =~ /^[4|5]\d\d/; + return ('reject', $pid, undef, undef, $message) + if substr($message, 0, 14) eq 'deny mail from'; + return ('reject', $pid, undef, undef, $message) + if substr($message, 0, 18) eq 'denysoft mail from'; + return ('info', $pid, undef, undef, $message) + if substr($message, 0, 15) eq 'Lost connection'; + return ('info', $pid, undef, undef, $message) + if $message eq 'auth success cleared naughty'; + return ('info', $pid, undef, undef, $message) + if substr($message, 0, 15) eq 'Running as user'; + return ('info', $pid, undef, undef, $message) + if substr($message, 0, 16) eq 'Loaded Qpsmtpd::'; + return ('info', $pid, undef, undef, $message) + if substr($message, 0, 24) eq 'Permissions on spool_dir'; + return ('info', $pid, undef, undef, $message) + if substr($message, 0, 13) eq 'Listening on '; + return ('info', $pid, undef, undef, $message) + if substr($message, 0, 18) eq 'size_threshold set'; + return ('info', $pid, undef, undef, $message) + if substr($message, 0, 12) eq 'tls: ciphers'; + return ('error', $pid, undef, undef, $message) + if substr($message, 0, 22) eq 'of uninitialized value'; + return ('error', $pid, undef, undef, $message) + if substr($message, 0, 8) eq 'symbol "'; + return ('error', $pid, undef, undef, $message) + if substr($message, 0, 9) eq 'error at '; + return ('error', $pid, undef, undef, $message) + if substr($message, 0, 15) eq 'Could not print'; print "UNKNOWN LINE: $line\n"; - return ( 'unknown', $pid, undef, undef, $message ); -}; + return ('unknown', $pid, undef, undef, $message); +} sub parse_line_plugin { my ($line) = @_; - # @tai 13486 (connect) ident::p0f: Windows (XP/2000 (RFC1323+, w, tstamp-)) - # @tai 13681 (connect) dnsbl: fail, NAUGHTY - # @tai 15787 (connect) karma: pass, no penalty (0 naughty, 3 nice, 3 connects) - # @tai 27500 (queue) queue::qmail_2dqueue: (for 27481) Queuing to /var/qmail/bin/qmail-queue - my ($tai, $pid, $hook, $plugin, $message ) = split /\s/, $line, 5; +# @tai 13486 (connect) ident::p0f: Windows (XP/2000 (RFC1323+, w, tstamp-)) +# @tai 13681 (connect) dnsbl: fail, NAUGHTY +# @tai 15787 (connect) karma: pass, no penalty (0 naughty, 3 nice, 3 connects) +# @tai 27500 (queue) queue::qmail_2dqueue: (for 27481) Queuing to /var/qmail/bin/qmail-queue + my ($tai, $pid, $hook, $plugin, $message) = split /\s/, $line, 5; $plugin =~ s/:$//; - return parse_line_plugin_p0f( $line ) if $plugin =~ /^ident::p0f/; - return parse_line_plugin_dspam( $line ) if $plugin =~ /^dspam/; - return parse_line_plugin_spamassassin( $line ) if $plugin =~ /^spamassassin/; + return parse_line_plugin_p0f($line) if $plugin =~ /^ident::p0f/; + return parse_line_plugin_dspam($line) if $plugin =~ /^dspam/; + return parse_line_plugin_spamassassin($line) if $plugin =~ /^spamassassin/; - if ( $plugin eq 'sender_permitted_from' ) { + if ($plugin eq 'sender_permitted_from') { $message = 'pass' if $message =~ /^pass/; $message = 'fail' if $message =~ /^fail/; $message = 'skip' if $message =~ /^none/; } - elsif ( $plugin eq 'queue::qmail_2dqueue' ) { + elsif ($plugin eq 'queue::qmail_2dqueue') { ($pid) = $message =~ /\(for ([\d]+)\)/; $message = 'pass' if $message =~ /Queuing/; } - elsif ( $plugin =~ /(?:early|karma|helo|rcpt_ok)/ ) { + elsif ($plugin =~ /(?:early|karma|helo|rcpt_ok)/) { $message = 'pass' if $message =~ /^pass/; } - elsif ( $plugin =~ /resolvable_fromhost/ ) { + elsif ($plugin =~ /resolvable_fromhost/) { $message = 'pass' if $message =~ /^pass/; - }; + } - return ( 'plugin', $pid, $hook, $plugin, $message ); -}; + return ('plugin', $pid, $hook, $plugin, $message); +} sub parse_line_plugin_dspam { my $line = shift; - my ($tai, $pid, $hook, $plugin, $message ) = split /\s/, $line, 5; + my ($tai, $pid, $hook, $plugin, $message) = split /\s/, $line, 5; $plugin =~ s/:$//; - if ( $message =~ /Innocent, (\d\.\d\d c)/ ) { + if ($message =~ /Innocent, (\d\.\d\d c)/) { $message = "pass, $1"; - }; - if ( $message =~ /Spam, (\d\.\d\d c)/ ) { + } + if ($message =~ /Spam, (\d\.\d\d c)/) { $message = "fail, $1"; - }; + } - return ( 'plugin', $pid, $hook, $plugin, $message ); -}; + return ('plugin', $pid, $hook, $plugin, $message); +} sub parse_line_plugin_spamassassin { my $line = shift; - my ($tai, $pid, $hook, $plugin, $message ) = split /\s/, $line, 5; + my ($tai, $pid, $hook, $plugin, $message) = split /\s/, $line, 5; $plugin =~ s/:$//; - if ( $message =~ /pass, Ham, ([\d\-\.]+)\s/ ) { + if ($message =~ /pass, Ham, ([\d\-\.]+)\s/) { $message = "pass, $1"; - }; - if ( $message =~ /^fail, Spam,\s([\d\.]+)\s< 100/ ) { + } + if ($message =~ /^fail, Spam,\s([\d\.]+)\s< 100/) { $message = "fail, $1"; - }; + } - return ( 'plugin', $pid, $hook, $plugin, $message ); -}; + return ('plugin', $pid, $hook, $plugin, $message); +} sub parse_line_plugin_p0f { my $line = shift; - my ($tai, $pid, $hook, $plugin, $message ) = split /\s/, $line, 5; + my ($tai, $pid, $hook, $plugin, $message) = split /\s/, $line, 5; $plugin =~ s/:$//; - if ( substr( $message, -5, 5) eq 'hops)' ) { - ($message) = split( /\s\(/, $message ); - }; + if (substr($message, -5, 5) eq 'hops)') { + ($message) = split(/\s\(/, $message); + } $message = 'iOS' if $message =~ /^iOS/; $message = 'Solaris' if $message =~ /^Solaris/; @@ -478,68 +504,68 @@ sub parse_line_plugin_p0f { $message = 'Cisco' if $message =~ /^Cisco/i; $message = 'Netware' if $message =~ /Netware/i; - return ( 'plugin', $pid, $hook, $plugin, $message ); -}; + return ('plugin', $pid, $hook, $plugin, $message); +} sub parse_line_cleanup { my ($line) = @_; + # @tai 85931 cleaning up after 3210 my $pid = (split /\s+/, $line)[-1]; $has_cleanup++; - return ( 'cleanup', $pid, undef, undef, $line ); -}; + return ('cleanup', $pid, undef, undef, $line); +} sub get_score { my $mess = shift; - return 3 if $mess eq 'TLS setup returning'; - return 3 if $mess =~ /^pass/; - return -3 if $mess =~ /^fail/; - return -2 if $mess =~ /^negative/; - return 2 if $mess =~ /^positive/; - return 1 if $mess =~ /^skip/; + return 3 if $mess eq 'TLS setup returning'; + return 3 if $mess =~ /^pass/; + return -3 if $mess =~ /^fail/; + return -2 if $mess =~ /^negative/; + return 2 if $mess =~ /^positive/; + return 1 if $mess =~ /^skip/; return 0; -}; - +} sub get_db { - my $db = DBIx::Simple->connect( $dsn, $user, $pass ) - or die DBIx::Simple->error; + my $db = DBIx::Simple->connect($dsn, $user, $pass) + or die DBIx::Simple->error; return $db; -}; +} sub exec_query { - my $query = shift; + my $query = shift; my $params = shift; die "invalid arguments to exec_query!" if @_; my @params; - if ( defined $params ) { + if (defined $params) { @params = ref $params eq 'ARRAY' ? @$params : $params; - }; + } my $err = "query failed: $query\n"; - if ( scalar @params ) { + if (scalar @params) { $err .= join(',', @params); - }; + } #warn "err: $err\n"; - if ( $query =~ /INSERT INTO/ ) { - my ( $table ) = $query =~ /INSERT INTO (\w+)\s/; - $db->query( $query, @params ); + if ($query =~ /INSERT INTO/) { + my ($table) = $query =~ /INSERT INTO (\w+)\s/; + $db->query($query, @params); die "$db->error\n$err" if $db->error ne 'DBI error: '; - my $id = $db->last_insert_id(undef,undef,$table,undef) or die $err; + my $id = $db->last_insert_id(undef, undef, $table, undef) or die $err; return $id; } - elsif ( $query =~ /^UPDATE/i ) { - return $db->query( $query, @params ); + elsif ($query =~ /^UPDATE/i) { + return $db->query($query, @params); } - elsif ( $query =~ /DELETE/ ) { - $db->query( $query, @params ) or die $err; + elsif ($query =~ /DELETE/) { + $db->query($query, @params) or die $err; return $db->query("SELECT ROW_COUNT()")->list; - }; + } - my $r = $db->query( $query, @params )->hashes or die $err; + my $r = $db->query($query, @params)->hashes or die $err; return $r; -}; +} diff --git a/log/show_message b/log/show_message index 9ee2ef1..c677d01 100755 --- a/log/show_message +++ b/log/show_message @@ -5,68 +5,68 @@ use warnings; use Data::Dumper; -my $QPDIR = get_qp_dir(); +my $QPDIR = get_qp_dir(); my $logfile = "$QPDIR/log/main/current"; my $is_ip = 0; my $search = $ARGV[0]; -if ( ! $search ) { +if (!$search) { die "\nusage: $0 [ ip_address | PID ]\n\n"; -}; +} + +if ($search =~ /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/) { -if ( $search =~ /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/ ) { #print "it's an IP\n"; $is_ip++; -}; +} open my $LOG, '<', $logfile or die "unable to open $logfile\n"; -if ( $is_ip ) { # look for the connection start message for the IP +if ($is_ip) { # look for the connection start message for the IP my $ip_matches; - while ( defined (my $line = <$LOG>) ) { - next if ! $line; - my ( $tai, $pid, $mess ) = split /\s/, $line, 3; - if ( 'Connection from ' eq substr( $mess, 0, 16 ) ) { - my ( $ip ) = (split /\s+/, $mess)[-1]; # IP is last word + while (defined(my $line = <$LOG>)) { + next if !$line; + my ($tai, $pid, $mess) = split /\s/, $line, 3; + if ('Connection from ' eq substr($mess, 0, 16)) { + my ($ip) = (split /\s+/, $mess)[-1]; # IP is last word $ip = substr $ip, 1, -1; # trim off brackets - if ( $ip eq $search ) { + if ($ip eq $search) { $ip_matches++; $search = $pid; - $is_ip = 0; - }; - }; - }; + $is_ip = 0; + } + } + } seek $LOG, 0, 0; die "no pid found for ip $search\n" if $is_ip; print "showing the last of $ip_matches connnections from $ARGV[0]\n"; -}; +} print "showing QP message PID $search\n"; -while ( defined (my $line = <$LOG>) ) { - next if ! $line; - my ( $tai, $pid, $mess ) = split /\s/, $line, 3; - next if ! $pid; - print $mess if ( $pid eq $search ); -}; +while (defined(my $line = <$LOG>)) { + next if !$line; + my ($tai, $pid, $mess) = split /\s/, $line, 3; + next if !$pid; + print $mess if ($pid eq $search); +} close $LOG; - sub get_qp_dir { - foreach my $user ( qw/ qpsmtpd smtpd / ) { - my ($homedir) = (getpwnam( $user ))[7] or next; + foreach my $user (qw/ qpsmtpd smtpd /) { + my ($homedir) = (getpwnam($user))[7] or next; - if ( -d "$homedir/plugins" ) { + if (-d "$homedir/plugins") { return "$homedir"; - }; - foreach my $s ( qw/ smtpd qpsmtpd qpsmtpd-dev / ) { - if ( -d "$homedir/$s/plugins" ) { + } + foreach my $s (qw/ smtpd qpsmtpd qpsmtpd-dev /) { + if (-d "$homedir/$s/plugins") { return "$homedir/$s"; - }; - }; - }; - if ( -d "./plugins" ) { + } + } + } + if (-d "./plugins") { return Cwd::getcwd(); - }; -}; + } +} diff --git a/log/summarize b/log/summarize index cca2651..b72cef9 100755 --- a/log/summarize +++ b/log/summarize @@ -15,210 +15,238 @@ my %hide_plugins = map { $_ => 1 } qw/ hostname /; my $qpdir = get_qp_dir(); my $file = "$qpdir/log/main/current"; populate_plugins_from_registry(); -my @sorted_plugins = sort { $plugins{$a}{id} <=> $plugins{$b}{id} } keys %plugins; +my @sorted_plugins = + sort { $plugins{$a}{id} <=> $plugins{$b}{id} } keys %plugins; -my $fh = File::Tail->new(name=>$file, interval=>1, maxinterval=>1, debug =>1, tail =>1000 ); +my $fh = File::Tail->new( + name => $file, + interval => 1, + maxinterval => 1, + debug => 1, + tail => 1000 + ); my $printed = 0; my $has_cleanup; my %formats = ( - ip => "%-15.15s", - hostname => "%-20.20s", - distance => "%5.5s", - 'ident::geoip' => "%-20.20s", - 'ident::p0f' => "%-10.10s", - count_unrecognized_commands => "%-5.5s", - unrecognized_commands => "%-5.5s", - dnsbl => "%-3.3s", - rhsbl => "%-3.3s", - relay => "%-3.3s", - karma => "%-3.3s", - fcrdns => "%-3.3s", - earlytalker => "%-3.3s", - check_earlytalker => "%-3.3s", - helo => "%-3.3s", - tls => "%-3.3s", - 'auth::auth_vpopmail' => "%-3.3s", - 'auth::auth_vpopmaild' => "%-3.3s", - 'auth::auth_vpopmail_sql' => "%-3.3s", - 'auth::auth_checkpassword' => "%-3.3s", - badmailfrom => "%-3.3s", - check_badmailfrom => "%-3.3s", - sender_permitted_from => "%-3.3s", - resolvable_fromhost => "%-3.3s", - 'queue::qmail-queue' => "%-3.3s", - connection_time => "%-4.4s", -); + ip => "%-15.15s", + hostname => "%-20.20s", + distance => "%5.5s", + 'ident::geoip' => "%-20.20s", + 'ident::p0f' => "%-10.10s", + count_unrecognized_commands => "%-5.5s", + unrecognized_commands => "%-5.5s", + dnsbl => "%-3.3s", + rhsbl => "%-3.3s", + relay => "%-3.3s", + karma => "%-3.3s", + fcrdns => "%-3.3s", + earlytalker => "%-3.3s", + check_earlytalker => "%-3.3s", + helo => "%-3.3s", + tls => "%-3.3s", + 'auth::auth_vpopmail' => "%-3.3s", + 'auth::auth_vpopmaild' => "%-3.3s", + 'auth::auth_vpopmail_sql' => "%-3.3s", + 'auth::auth_checkpassword' => "%-3.3s", + badmailfrom => "%-3.3s", + check_badmailfrom => "%-3.3s", + sender_permitted_from => "%-3.3s", + resolvable_fromhost => "%-3.3s", + 'queue::qmail-queue' => "%-3.3s", + connection_time => "%-4.4s", + ); my %formats3 = ( - %formats, - badrcptto => "%-3.3s", - check_badrcptto => "%-3.3s", - qmail_deliverable => "%-3.3s", - rcpt_ok => "%-3.3s", - check_basicheaders => "%-3.3s", - headers => "%-3.3s", - uribl => "%-3.3s", - bogus_bounce => "%-3.3s", - check_bogus_bounce => "%-3.3s", - domainkeys => "%-3.3s", - dkim => "%-3.3s", - dmarc => "%-3.3s", - spamassassin => "%-3.3s", - dspam => "%-3.3s", - 'virus::clamdscan' => "%-3.3s", -); + %formats, + badrcptto => "%-3.3s", + check_badrcptto => "%-3.3s", + qmail_deliverable => "%-3.3s", + rcpt_ok => "%-3.3s", + check_basicheaders => "%-3.3s", + headers => "%-3.3s", + uribl => "%-3.3s", + bogus_bounce => "%-3.3s", + check_bogus_bounce => "%-3.3s", + domainkeys => "%-3.3s", + dkim => "%-3.3s", + dmarc => "%-3.3s", + spamassassin => "%-3.3s", + dspam => "%-3.3s", + 'virus::clamdscan' => "%-3.3s", + ); - -while ( defined (my $line = $fh->read) ) { +while (defined(my $line = $fh->read)) { chomp $line; - next if ! $line; - my ( $type, $pid, $hook, $plugin, $message ) = parse_line( $line ); - next if ! $type; + next if !$line; + my ($type, $pid, $hook, $plugin, $message) = parse_line($line); + next if !$type; next if $type =~ /^(info|unknown|response|tcpserver)$/; - next if $type eq 'init'; # doesn't occur in all deployment models + next if $type eq 'init'; # doesn't occur in all deployment models - if ( ! $pids{$pid} ) { # haven't seen this pid + if (!$pids{$pid}) { # haven't seen this pid next if $type ne 'connect'; # ignore unless connect my ($host, $ip) = split /\s/, $message; $ip = substr $ip, 1, -1; - foreach ( keys %seen_plugins, qw/ helo_host from to / ) { $pids{$pid}{$_} = ''; }; - $pids{$pid}{ip} = $ip; + foreach (keys %seen_plugins, qw/ helo_host from to /) { + $pids{$pid}{$_} = ''; + } + $pids{$pid}{ip} = $ip; $pids{$pid}{hostname} = $host if $host ne 'Unknown'; - }; + } - if ( $type eq 'close' ) { - next if $has_cleanup; # it'll get handled later + if ($type eq 'close') { + next if $has_cleanup; # it'll get handled later print_auto_format($pid, $line); delete $pids{$pid}; } - elsif ( $type eq 'cleanup' ) { + elsif ($type eq 'cleanup') { print_auto_format($pid, $line); delete $pids{$pid}; } - elsif ( $type eq 'plugin' ) { + elsif ($type eq 'plugin') { next if $plugin eq 'naughty'; # housekeeping only - if ( ! $pids{$pid}{$plugin} ) { # first entry for this plugin + if (!$pids{$pid}{$plugin}) { # first entry for this plugin $pids{$pid}{$plugin} = $message; } else { # subsequent log entry for this plugin - if ( $pids{$pid}{$plugin} !~ /^(?:pass|fail|skip)/i ) { - $pids{$pid}{$plugin} = $message; # overwrite 1st + if ($pids{$pid}{$plugin} !~ /^(?:pass|fail|skip)/i) { + $pids{$pid}{$plugin} = $message; # overwrite 1st } else { #print "ignoring subsequent hit on $plugin: $message\n"; - }; - }; + } + } - if ( $plugin eq 'ident::geoip' ) { - if ( length $message < 3 ) { - $formats{'ident::geoip'} = "%-3.3s"; + if ($plugin eq 'ident::geoip') { + if (length $message < 3) { + $formats{'ident::geoip'} = "%-3.3s"; $formats3{'ident::geoip'} = "%-3.3s"; } else { my ($gip, $distance) = $message =~ /(.*?),\s+([\d]+)\skm/; - if ( $distance ) { - $pids{$pid}{$plugin} = $gip; + if ($distance) { + $pids{$pid}{$plugin} = $gip; $pids{$pid}{distance} = $distance; - }; - }; - }; + } + } + } } - elsif ( $type eq 'reject' ) { } - elsif ( $type eq 'connect' ) { } - elsif ( $type eq 'dispatch' ) { - if ( $message =~ /^dispatching MAIL FROM/i ) { - my ($from) = $message =~ /<(.*?)>/; + elsif ($type eq 'reject') { } + elsif ($type eq 'connect') { } + elsif ($type eq 'dispatch') { + if ($message =~ /^dispatching MAIL FROM/i) { + my ($from) = $message =~ /<(.*?)>/; $pids{$pid}{from} = $from; } - elsif ( $message =~ /^dispatching RCPT TO/i ) { - my ($to) = $message =~ /<(.*?)>/; + elsif ($message =~ /^dispatching RCPT TO/i) { + my ($to) = $message =~ /<(.*?)>/; $pids{$pid}{to} = $to; } - elsif ( $message =~ m/dispatching (EHLO|HELO) (.*)/ ) { + elsif ($message =~ m/dispatching (EHLO|HELO) (.*)/) { $pids{$pid}{helo_host} = $2; } - elsif ( $message eq 'dispatching DATA' ) { } - elsif ( $message eq 'dispatching QUIT' ) { } - elsif ( $message eq 'dispatching STARTTLS' ) { } - elsif ( $message eq 'dispatching RSET' ) { + elsif ($message eq 'dispatching DATA') { } + elsif ($message eq 'dispatching QUIT') { } + elsif ($message eq 'dispatching STARTTLS') { } + elsif ($message eq 'dispatching RSET') { print_auto_format($pid, $line); } else { # anything here is likely an unrecognized command #print "$message\n"; - }; + } } else { print "$type $pid $hook $plugin $message\n"; - }; -}; + } +} sub parse_line { my $line = shift; my ($tai, $pid, $message) = split /\s+/, $line, 3; - return if ! $message; # garbage in the log file + return if !$message; # garbage in the log file # lines seen many times per connection - return parse_line_plugin( $line ) if substr($message, 0, 1) eq '('; - return ( 'dispatch', $pid, undef, undef, $message ) if substr($message, 0, 12) eq 'dispatching '; - return ( 'response', $pid, undef, undef, $message ) if $message =~ /^[2|3]\d\d/; - return ( 'tcpserver', $pid, undef, undef, undef ) if substr($pid, 0, 10) eq 'tcpserver:'; + return parse_line_plugin($line) if substr($message, 0, 1) eq '('; + return ('dispatch', $pid, undef, undef, $message) + if substr($message, 0, 12) eq 'dispatching '; + return ('response', $pid, undef, undef, $message) + if $message =~ /^[2|3]\d\d/; + return ('tcpserver', $pid, undef, undef, undef) + if substr($pid, 0, 10) eq 'tcpserver:'; # lines seen about once per connection - return ( 'init', $pid, undef, undef, $message ) if substr($message, 0, 19) eq 'Accepted connection'; - return ( 'connect', $pid, undef, undef, substr( $message, 16) ) if substr($message, 0, 15) eq 'Connection from'; - return ( 'close', $pid, undef, undef, $message ) if substr($message, 0, 6) eq 'close '; - return ( 'close', $pid, undef, undef, $message ) if substr($message, 0, 20) eq 'click, disconnecting'; - return parse_line_cleanup( $line ) if substr($message, 0, 11) eq 'cleaning up'; + return ('init', $pid, undef, undef, $message) + if substr($message, 0, 19) eq 'Accepted connection'; + return ('connect', $pid, undef, undef, substr($message, 16)) + if substr($message, 0, 15) eq 'Connection from'; + return ('close', $pid, undef, undef, $message) + if substr($message, 0, 6) eq 'close '; + return ('close', $pid, undef, undef, $message) + if substr($message, 0, 20) eq 'click, disconnecting'; + return parse_line_cleanup($line) + if substr($message, 0, 11) eq 'cleaning up'; # lines seen less than once per connection - return ( 'info', $pid, undef, undef, $message ) if $message eq 'spooling message to disk'; - return ( 'reject', $pid, undef, undef, $message ) if $message =~ /^[4|5]\d\d/; - return ( 'reject', $pid, undef, undef, $message ) if substr($message, 0, 14) eq 'deny mail from'; - return ( 'reject', $pid, undef, undef, $message ) if substr($message, 0, 18) eq 'denysoft mail from'; - return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 15) eq 'Lost connection'; - return ( 'info', $pid, undef, undef, $message ) if $message eq 'auth success cleared naughty'; - return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 15) eq 'Running as user'; - return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 16) eq 'Loaded Qpsmtpd::'; - return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 24) eq 'Permissions on spool_dir'; - return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 13) eq 'Listening on '; + return ('info', $pid, undef, undef, $message) + if $message eq 'spooling message to disk'; + return ('reject', $pid, undef, undef, $message) if $message =~ /^[4|5]\d\d/; + return ('reject', $pid, undef, undef, $message) + if substr($message, 0, 14) eq 'deny mail from'; + return ('reject', $pid, undef, undef, $message) + if substr($message, 0, 18) eq 'denysoft mail from'; + return ('info', $pid, undef, undef, $message) + if substr($message, 0, 15) eq 'Lost connection'; + return ('info', $pid, undef, undef, $message) + if $message eq 'auth success cleared naughty'; + return ('info', $pid, undef, undef, $message) + if substr($message, 0, 15) eq 'Running as user'; + return ('info', $pid, undef, undef, $message) + if substr($message, 0, 16) eq 'Loaded Qpsmtpd::'; + return ('info', $pid, undef, undef, $message) + if substr($message, 0, 24) eq 'Permissions on spool_dir'; + return ('info', $pid, undef, undef, $message) + if substr($message, 0, 13) eq 'Listening on '; - return ( 'err', $pid, undef, undef, $message ) if $line =~ /at [\S]+ line \d/; # generic perl error + return ('err', $pid, undef, undef, $message) + if $line =~ /at [\S]+ line \d/; # generic perl error print "UNKNOWN LINE: $line\n"; - return ( 'unknown', $pid, undef, undef, $message ); -}; + return ('unknown', $pid, undef, undef, $message); +} sub parse_line_plugin { my ($line) = @_; - # @tai 13486 (connect) ident::p0f: Windows (XP/2000 (RFC1323+, w, tstamp-)) - # @tai 13681 (connect) dnsbl: fail, NAUGHTY - # @tai 15787 (connect) karma: pass, no penalty (0 naughty, 3 nice, 3 connects) - # @tai 77603 (queue) queue::qmail_2dqueue: (for 77590) Queuing to /var/qmail/bin/qmail-queue - my ($tai, $pid, $hook, $plugin, $message ) = split /\s/, $line, 5; +# @tai 13486 (connect) ident::p0f: Windows (XP/2000 (RFC1323+, w, tstamp-)) +# @tai 13681 (connect) dnsbl: fail, NAUGHTY +# @tai 15787 (connect) karma: pass, no penalty (0 naughty, 3 nice, 3 connects) +# @tai 77603 (queue) queue::qmail_2dqueue: (for 77590) Queuing to /var/qmail/bin/qmail-queue + my ($tai, $pid, $hook, $plugin, $message) = split /\s/, $line, 5; $plugin =~ s/:$//; - if ( $plugin =~ /_3a/ ) { - ($plugin) = split /_3a/, $plugin; # trim :N off the plugin log entry - }; + if ($plugin =~ /_3a/) { + ($plugin) = split /_3a/, $plugin; # trim :N off the plugin log entry + } $plugin =~ s/_2d/-/g; - $plugin = $plugin_aliases{$plugin} if $plugin_aliases{$plugin}; # map alias to master - if ( $hook eq '(queue)' ) { + $plugin = $plugin_aliases{$plugin} + if $plugin_aliases{$plugin}; # map alias to master + if ($hook eq '(queue)') { ($pid) = $message =~ /\(for ([\d]+)\)\s/; $message = 'pass'; - }; + } - return ( 'plugin', $pid, $hook, $plugin, $message ); -}; + return ('plugin', $pid, $hook, $plugin, $message); +} sub parse_line_cleanup { my ($line) = @_; + # @tai 85931 cleaning up after 3210 - my $pid = (split /\s+/, $line)[-1]; + my $pid = (split /\s+/, $line)[-1]; $has_cleanup++; - return ( 'cleanup', $pid, undef, undef, $line ); -}; + return ('cleanup', $pid, undef, undef, $line); +} sub print_auto_format { my ($pid, $line) = @_; @@ -227,52 +255,53 @@ sub print_auto_format { my @headers; my @values; - foreach my $plugin ( qw/ ip hostname distance /, @sorted_plugins ) { - if ( defined $pids{$pid}{$plugin} ) { - if ( ! $seen_plugins{$plugin} ) { # first time seeing this plugin + foreach my $plugin (qw/ ip hostname distance /, @sorted_plugins) { + if (defined $pids{$pid}{$plugin}) { + if (!$seen_plugins{$plugin}) { # first time seeing this plugin $printed = 0; # force header print - }; + } $seen_plugins{$plugin}++; - }; + } - next if ! $seen_plugins{$plugin}; # hide unused plugins - if ( $hide_plugins{$plugin} ) { # user doesn't want to see + next if !$seen_plugins{$plugin}; # hide unused plugins + if ($hide_plugins{$plugin}) { # user doesn't want to see delete $pids{$pid}{$plugin}; next; - }; + } - if ( defined $pids{$pid}{helo_host} && $plugin =~ /helo/ ) { + if (defined $pids{$pid}{helo_host} && $plugin =~ /helo/) { $format .= " %-18.18s"; - push @values, substr( delete $pids{$pid}{helo_host}, -18, 18); + push @values, substr(delete $pids{$pid}{helo_host}, -18, 18); push @headers, 'HELO'; } - elsif ( defined $pids{$pid}{from} && $plugin =~ /from/ ) { + elsif (defined $pids{$pid}{from} && $plugin =~ /from/) { $format .= " %-20.20s"; - push @values, substr( delete $pids{$pid}{from}, -20, 20); + push @values, substr(delete $pids{$pid}{from}, -20, 20); push @headers, 'MAIL FROM'; } - elsif ( defined $pids{$pid}{to} && $plugin =~ /to|rcpt|recipient/ ) { + elsif (defined $pids{$pid}{to} && $plugin =~ /to|rcpt|recipient/) { $format .= " %-20.20s"; - push @values, delete $pids{$pid}{to}; + push @values, delete $pids{$pid}{to}; push @headers, 'RCPT TO'; - }; + } $format .= $formats3{$plugin} ? " $formats3{$plugin}" : " %-10.10s"; - if ( defined $pids{$pid}{$plugin} ) { - push @values, show_symbol( delete $pids{$pid}{$plugin} ); + if (defined $pids{$pid}{$plugin}) { + push @values, show_symbol(delete $pids{$pid}{$plugin}); } else { push @values, ''; - }; - push @headers, ($plugins{$plugin}{abb3} ? $plugins{$plugin}{abb3} : $plugin); + } + push @headers, + ($plugins{$plugin}{abb3} ? $plugins{$plugin}{abb3} : $plugin); } $format .= "\n"; - printf( "\n$format", @headers ) if ( ! $printed || $printed % 20 == 0 ); - printf( $format, @values ); - print Data::Dumper::Dumper( $pids{$pid} ) if keys %{$pids{$pid}}; + printf("\n$format", @headers) if (!$printed || $printed % 20 == 0); + printf($format, @values); + print Data::Dumper::Dumper($pids{$pid}) if keys %{$pids{$pid}}; $printed++; -}; +} sub show_symbol { my $mess = shift; @@ -288,46 +317,46 @@ sub show_symbol { return ' !' if $mess =~ /^error[,:\s]/i; $mess =~ s/\s\s/ /g; return $mess; -}; +} sub get_qp_dir { - foreach my $user ( qw/ qpsmtpd smtpd / ) { - my ($homedir) = (getpwnam( $user ))[7] or next; + foreach my $user (qw/ qpsmtpd smtpd /) { + my ($homedir) = (getpwnam($user))[7] or next; - if ( -d "$homedir/plugins" ) { + if (-d "$homedir/plugins") { return "$homedir"; - }; - foreach my $s ( qw/ smtpd qpsmtpd qpsmtpd-dev / ) { - if ( -d "$homedir/$s/plugins" ) { + } + foreach my $s (qw/ smtpd qpsmtpd qpsmtpd-dev /) { + if (-d "$homedir/$s/plugins") { return "$homedir/$s"; - }; - }; - }; - if ( -d "./plugins" ) { + } + } + } + if (-d "./plugins") { return Cwd::getcwd(); - }; -}; + } +} sub populate_plugins_from_registry { my $file = "$qpdir/plugins/registry.txt"; - if ( ! -f $file ) { + if (!-f $file) { die "unable to find plugin registry\n"; - }; + } open my $F, '<', $file; - while ( defined ( my $line = <$F> ) ) { - next if $line =~ /^#/; # discard comments + while (defined(my $line = <$F>)) { + next if $line =~ /^#/; # discard comments my ($id, $name, $abb3, $abb5, $aliases) = split /\s+/, $line; - next if ! defined $name; - $plugins{$name} = { id=>$id, abb3=>$abb3, abb5=>$abb5 }; + next if !defined $name; + $plugins{$name} = {id => $id, abb3 => $abb3, abb5 => $abb5}; - next if ! $aliases; + next if !$aliases; $aliases =~ s/\s+//g; $plugins{$name}{aliases} = $aliases; - foreach my $a ( split /,/, $aliases ) { + foreach my $a (split /,/, $aliases) { $plugin_aliases{$a} = $name; - }; - }; -}; + } + } +} diff --git a/log/watch b/log/watch index 6ba3cdd..3e8c398 100755 --- a/log/watch +++ b/log/watch @@ -3,7 +3,7 @@ use strict; use warnings; -$|++; # OUTPUT_AUTOFLUSH +$|++; # OUTPUT_AUTOFLUSH use Cwd; use Data::Dumper; @@ -11,28 +11,34 @@ use File::Tail; my $dir = get_qp_dir() or die "unable to find QP home dir"; my $file = "$dir/log/main/current"; -my $fh = File::Tail->new(name=>$file, interval=>1, maxinterval=>1, debug =>1, tail =>300 ); +my $fh = File::Tail->new( + name => $file, + interval => 1, + maxinterval => 1, + debug => 1, + tail => 300 + ); -while ( defined (my $line = $fh->read) ) { - my (undef, $line) = split /\s/, $line, 2; # strip off tai timestamps +while (defined(my $line = $fh->read)) { + my (undef, $line) = split /\s/, $line, 2; # strip off tai timestamps print $line; -}; +} sub get_qp_dir { - foreach my $user ( qw/ qpsmtpd smtpd / ) { - my ($homedir) = (getpwnam( $user ))[7] or next; + foreach my $user (qw/ qpsmtpd smtpd /) { + my ($homedir) = (getpwnam($user))[7] or next; - if ( -d "$homedir/plugins" ) { + if (-d "$homedir/plugins") { return "$homedir"; - }; - foreach my $s ( qw/ smtpd qpsmtpd qpsmtpd-dev / ) { - if ( -d "$homedir/$s/plugins" ) { + } + foreach my $s (qw/ smtpd qpsmtpd qpsmtpd-dev /) { + if (-d "$homedir/$s/plugins") { return "$homedir/$s"; - }; - }; - }; - if ( -d "./plugins" ) { + } + } + } + if (-d "./plugins") { return Cwd::getcwd(); - }; -}; + } +}