#!/usr/local/bin/perl
#
# Author:  Petter Reinholdtsen <pere@td.org.uit.no>
# Date:    1997-07-09
# The original was written by Rachel Polanskis <rachel@juno.virago.org.au>
# 
# Fetches output from mailstats(1) either via TCP or via exec and
# feeds changes on smtp to mrtg.
#
# Irix 6.x seems to lack mailstats
#
# Usage mailstats [host]
#  if host is missing, localhost is used

use strict;
use Socket;

my($datafile, $source, $sourceport, @mailstatspaths,
   $oldfrm, $oldto,
   $newfrm, $newto, $uptime);

# Adjust this to your own mailserver.  Uses local `mailstats` if set
# to 'localhost'
$source         = $ARGV[0] || "localhost";
$sourceport     = "7256";

$datafile       = "/tmp/mailstat-$source.old";
@mailstatspaths = ( "/usr/sbin/mailstats", "/usr/bin/mailstats" );

($oldfrm, $oldto) = getOldStats($datafile);

($newfrm, $newto, $uptime) = getStats($source, $sourceport);

putOldStats($datafile, $newfrm, $newto) || warn "$0: Unable to save stats to $datafile";

print $newfrm-$oldfrm,"\n",$newto-$oldto,"\n","$uptime\n$source\n" if ($oldfrm);

##
# Returns first line of file given as param splittet on space
sub getOldStats {
    my($filename) = @_;
    open(OLD, $filename) || warn "$0: Unable to open $filename for reading";
    my($line) = <OLD>;
    close(OLD);
    return split(/ /, $line);
}

sub findFirstExecutable {
    my($filename);
    foreach $filename (@_) {
	return $filename if ( -x $filename && ! -d $filename );
    }
}

sub getStats {
    my($source, $sourceport) = @_;
    my(@output, $port, $proto, $iaddr, $paddr);
    if ( $source eq "localhost" ) {
	my($progpath) = findFirstExecutable(@mailstatspaths);
	@output = `$progpath`;
	chomp(@output);
    } else {
	$port = getservbyname ($sourceport, 'tcp') if ($sourceport =~ /\D/);
	die "$0: Bad port \"$sourceport\"" unless ($port);
	$proto = getprotobyname ('tcp') || die "$0: Bad prototype tcp";

	$iaddr = inet_aton($source) or die "$0: no host \"$source\"";
	$paddr = sockaddr_in($port, $iaddr);

	socket (SOCK, PF_INET, SOCK_STREAM, $proto) or die "$0: socket error $!";
	connect (SOCK, $paddr) or die "$0: connect error $!";

	while (<SOCK>) {
	    push(@output);
	}
	close(SOCK) || warn "$0: socket close error $!";
    }
    my($curfrm, $curto, $uptime);
    foreach (@output) {
	($curfrm, $curto) = (split(/ +/))[2,4] if (/e?smtp/);
	($uptime) = m/Statistics from (.*)/ if (/Stati/);
    }
    return ($curfrm, $curto, $uptime);
}

sub putOldStats {
    my($filename, $frm, $to) = @_;
    open(STAT, ">$filename") || return "";
    print STAT "$frm $to\n";
    close(STAT);
    return "1";
}
