#!/usr/bin/perl -w

####################################################
##
## Author: Bruno Miranda
## E-mail: bruno.miranda@opservices.com.br
##
## Date: 07/07/2012
## Alterado - 30/04/15 - Cleber Campanel
#Correcao do ; nos perfdata
##
####################################################

use strict;
use IPC::Open3;
use Getopt::Long;
use File::Basename;
use bignum ( p => -2 );

my $VERSION=1.1;

####################################################
##
##   Display help
##
####################################################
sub help () {
    print "  This plugin uses the command 'ps' to check how much memory (VmRSS) is being\n";
    print "used by a process.\n";
        usage();
    print << 'HELP';
-p | --pname            Process name to check for memory consumption
-w | --warning          warning threshold in KB or MB, depends on the unit '-u'
                    used.
-c | --critical         Critical threshold in KB or MB, depends on the unit
                    '-u' used.
-h | --help             Display this help.
-u | --unit             Unit used to measure the memory in use (kB or MB).
                    Deafult is kB.
-V | --version          Shows the version of this plugin.
-v | --verbose          Verbose level [0,2,3]. Default is 0.
HELP
}

###################################################
##
##   Display usage
##
####################################################
sub usage {
    print "Usage:\n";
    print " ", basename($0), " -p <processname> [-w <warning> -c <crtical>]\n";
}

###################################################
##
##   Display version
##
####################################################
sub version {
    print "Version: ", $VERSION, "\n";
}

####################################################
##
##   Get arguments
##
####################################################
sub getOptions  {
    my ($opt_crit, $opt_warn, $opt_help, $opt_process, $opt_version, $opt_verbose, $opt_unit);

    Getopt::Long::Configure('bundling');
    GetOptions(
            'c|critical=f'          => \$opt_crit,
            'w|warning=f'           => \$opt_warn,
            'h|help'                => \$opt_help,
            'p|process=s'           => \$opt_process,
            'u|unit=s'              => \$opt_unit,
            'V|version'             => \$opt_version,
            'v|verbose=i'           => \$opt_verbose
    );

    $opt_verbose = 0 if (!defined($opt_verbose));

    if (defined($opt_help)) {
            help();
            exit(0);
    }

    if (defined($opt_version)){
            version();
            exit(0);
    }

    if (!defined($opt_process)) {
            usage();
            exit(3);
    }

    if (!defined($opt_unit)){
        $opt_unit="kB";
    }

    if (($opt_unit ne "kB") && ($opt_unit ne "MB")) {
        usage();
        exit(3);
    }

    if (($opt_verbose != 0) && ($opt_verbose != 2) && ($opt_verbose != 3)) {
            help();
            exit(3);
    }

    if (((!defined($opt_crit)) && (defined($opt_warn))) || ((defined($opt_crit)) && (!defined($opt_warn)))){
            help();
            exit(3);
    }

    return ($opt_crit, $opt_warn, $opt_help, $opt_process, $opt_version, $opt_verbose, $opt_unit);
}

####################################################
##
##   Get the memory in use by the requested process
##
####################################################
sub getMemUsage {
        my $name = shift;
    my $opt_verbose = shift;
        my @args = ("-o", "rss", "-C", $name);
        my $memory;
        my($wtr, $rdr, $err);

    print "Output of the command \'ps @args\':\n" if ($opt_verbose >= 2);
        open3($wtr, $rdr, $err, "/bin/ps",@args);
    while (<$rdr>) {
        print "    $_" if ($opt_verbose >= 2);
                chomp ($_);
                $memory += $_ if !($_ =~ /RSS/);
        }

    print "\nSum of memory in use by the list of processes: ",
            $memory, "kB ", $memory / 1024,"MB\n\n" if (($opt_verbose >= 3) && (defined($memory)));

        return $memory;
}


####################################################
##
##   Defines the status returned by the plugin
## (OK, WARNING or CRITICAL).
##
####################################################
sub defineStatus {
    my $opt_crit = shift;
    my $opt_warn = shift;
    my $memory   = shift;

    if ((defined($opt_crit)) && (defined($opt_warn))) {
        if ($memory >= $opt_crit) {
            return "CRITICAL";
        } elsif ($memory >= $opt_warn){
            return "WARNING";
        }
    }
        return "OK";
}

####################################################
###
###   Returns the information collected to OpMon.
###
####################################################
sub displayInfo {
    my $opt_crit    = shift;
    my $opt_warn    = shift;
        my $status      = shift;
    my $memory      = shift;
    my $opt_process = shift;
    my $opt_unit    = shift;
    my $total;
        my($wtr, $rdr, $err);

        open3($wtr, $rdr, $err, "/usr/bin/free -kt");
    while (<$rdr>) {
                $total = $1 if ($_ =~ /^Total:\s+([0-9]+).*/);
        }

    $total /= 1024 if ($opt_unit eq "MB");

        $opt_warn=0 if (!defined($opt_warn));
        $opt_crit=0 if (!defined($opt_crit));

        print $status, ": $memory$opt_unit in use by the \"$opt_process\". | ";
    print "Memory_Usage=$memory$opt_unit;$opt_warn;$opt_crit;0;$total\n";
}

sub main {
    my ($opt_crit, $opt_warn, $opt_help, $opt_process, $opt_version, $opt_verbose, $opt_unit) = getOptions();
        my $memory = getMemUsage($opt_process, $opt_verbose);
    my $status;

        if (!defined($memory)){
                print "UNKNOWN: No process in execution with the name \"$opt_process\".\n";
        exit (3);
    }

    $memory /= 1024 if ($opt_unit eq "MB");
    $status = defineStatus($opt_crit, $opt_warn, $memory);

    displayInfo($opt_crit, $opt_warn, $status, $memory, $opt_process, $opt_unit);

    if ($status eq "CRITICAL") {
        exit (2);
    } elsif ($status eq "WARNING") {
        exit (1);
    }

        exit (0);
} &main
