#! /usr/bin/perl
# anders@aftenposten.no
# 2008-04-05
# Alternative disk space plugin

use Getopt::Std;
use POSIX;

getopts('w:c:p:x:F:emh');
$osname = (POSIX::uname)[0];

sub partout {
	# $_[0]: avail $_[1]: capacity (%) $_[2]: dev $_[3]: mount

	my $avail = $_[0];
	my $cap = $_[1];
	my $dev = $_[2];
	my $mount = $_[3];

	$cap =~ s@%$@@;

	my $txt = "[" . $avail . " KB (" . (100-$cap) . "%) free on ";
	if ($opt_m) {
		$txt .= $mount;
	} else {
		$txt .= $dev;
	}
	$txt .=  "] ";
}

sub usage {
	print "check_diskx 1.0, anders\@aftenposten.no 2006-01-05\n\n";
	print "Usage:\n\n";
	print "-w <warning>%\n";
	print "-c <critical>%\n";
	print "-F <fstype x>,<fstype y..>\n";
	print "-p <part a>,<part b..> (process these)\n";
	print "-x <part c>,<part d..> (exclude these)\n";
	print "-e (include additional partitions (without errors))\n";
	print "-m (print mount, not device)\n";
}

sub ckspace {
	# $_[0]: ckval $_[1]: avail $_[2]: %cap
	my $ckval = $_[0];
	my $avail = $_[1];
	my $cap = $_[2];
	
	if (substr($ckval, length($ckval)-1, 1) eq "%") {
			$cap =~ s@%$@@;
			$ckval =~ s@%$@@;
			if ((100-$cap) <= $ckval) {
				return(1);
			} else {
				return(0);
			}
	} else {
		if ($avail <= $ckval) {
			return(1);
		} else {
			return(0);
		}
	}
}

sub evaldf {
	my $txt = $_[0];
	my $part = $_[1];

	chomp($txt);

	my $dev, $tot, $used, $avail, $cap, $mount;
	($dev, $tot, $used, $avail, $cap, $mount) = split(/\s+/, $txt);
	return if ($dev eq "Filesystem" || exists $exparts{"$dev"} || exists $exparts{"$mount"});
#	print "Sjekker dev=$dev avail=$avail cap=$cap mount=$mount\n";

	if (($avail eq "") || ($cap eq "") && ($part ne "")) {
		$mount = $part;
		$dev = $part;
	}
	if ($avail eq "") { $avail = 0; }
	if ($cap eq "") { $cap = "100%"; }

	if ($opt_c) {
		if (ckspace($opt_c, $avail, $cap)) {
			$critical .= partout($avail, $cap, $dev, $mount);
			return(2);
		}
	}

	if($opt_w) {
		if (ckspace($opt_w, $avail, $cap)) {
			$warning .= partout($avail, $cap, $dev, $mount);
			return(1);
		}
	}

	$info .= partout($avail, $cap, $dev, $mount);
}

sub evalspace {
	if ($opt_F) {
		if ($osname eq "SunOS") {
			$dfcmdfs = "/bin/df -k -F";
		} else {
			$dfcmdfs = "/bin/df -k -t";
		}
	}
	$dfcmd = "/bin/df -k";

	$critical = "";
	$warning = "";
	$info = "";
	%exparts = ();
	my $foo;

	if ($opt_p) {
		$opt_p =~ s@,@\ @g;
		foreach $part (split /\,/, $opt_p) {
			open(DF, "$dfcmd $part 2>/dev/null |");
			if (eof(DF)) {
				$critical .= partout(0, "100%", $part, $part);
			} else {
				$foo = <DF>;
				while (<DF>) {
					evaldf($_, $part);
				}
				close(DF);
			}
		}
	} else {
		foreach $expart (split /\,/, $opt_x) {
			$exparts{"$expart"} = $expart;
		}
		if ($opt_F) {
			foreach $fs (split /\,/, $opt_F) {
				open(DF, "$dfcmdfs $fs 2>/dev/null |");
				$foo = <DF>;
				while (<DF>) {
					evaldf($_);
				}
				close(DF);
			}
		} else {
			open(DF, "$dfcmd 2>/dev/null |");
			$foo = <DF>;
			while (<DF>) {
				evaldf($_);
			}
			close(DF);
		}
	}

	#print "Info: $info\n\n";
	#print "Warning: $warning\n\n";
	#print "Critical: $critical\n\n";

	if ($critical) {
		print "DISK CRITICAL";
	} elsif	($warning) {
		print "DISK WARNING";
	} else {
		print "DISK OK";
	}

	if ($critical) {
		$critical =~ s@\ $@@;
		print " " . $critical;
	}
	if ($warning) {
		$warning =~ s@\ $@@;
		print " " . $warning;
	}
	if ($info && ($opt_e)) {
		$info =~ s@\ $@@;
		print " " . $info;
	}
	print "\n";

	if ($critical) {
		exit(2);
	} elsif($warning) {
		exit(1);
	} else {
		exit(0);
	}
}

if ($opt_h) {
	usage;
} else {
	evalspace;
}
