File check_zypper.pl of Package nagios-plugins-zypper

#!/usr/bin/perl -w
# nagios: -epn
#
# check_zypper - nagios plugin
#
# Copyright (C) 2008-2010, Novell, Inc.
# Author: Lars Vogdt
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
#   list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
#   this list of conditions and the following disclaimer in the documentation
#   and/or other materials provided with the distribution.
#
# * Neither the name of the Novell nor the names of its contributors may be
#   used to endorse or promote products derived from this software without
#   specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# $Id$
#

use strict;
use warnings;
use Getopt::Long;
use vars qw($PROGNAME $VERSION $DEBUG);

# cleanup the environment
$ENV{'PATH'}     = '/bin:/usr/bin:/sbin:/usr/sbin:';
$ENV{'BASH_ENV'} = '';
$ENV{'ENV'}      = '';

# constants
$PROGNAME = "check_zypper";
$VERSION  = '1.40';
$DEBUG    = 0;

# variables
our ( $opt_V, $opt_h, $opt_i, $opt_w, $opt_c, $opt_f, $opt_o, $opt_p, $opt_r, $opt_s, $opt_t, $opt_u, $opt_v );
our $zypper          = '/usr/bin/zypper';
our $zypperopt       = '--non-interactive --no-gpg-checks xml-updates';
our $sudo            = '/usr/bin/sudo';
our $refresh_wrapper = '/usr/sbin/zypp-refresh-wrapper';
our $use_sudo        = 'unset LANG; ';
our $releasefile     = '/etc/SuSE-release';
our $rpm             = '/bin/rpm';
our $awk             = '/bin/awk';
our $grep            = '/bin/grep';
our $TIMEOUT         = 120;
our @patchignore     = ();
our @packageignore   = ();
our @packagewhitelist= ();
our $patchlevel      = 0;
our $exitcode        = 0;
our %ERRORS          = (
    'OK'        => 0,
    'WARNING'   => 1,
    'CRITICAL'  => 2,
    'UNKNOWN'   => 3,
    'DEPENDENT' => 4,
);
our %REVERSE = (
    4 => 'DEPENDENT',
    3 => 'UNKNOWN',
    2 => 'CRITICAL',
    1 => 'WARNING',
    0 => 'OK',
);
our %supported_release = (
    'openSUSE' => [ '11.2', '11.3', '11.4', '12.1' ],
    'SLE'      => [ '10.4', '11.1', '11.2' ],
);
$opt_w = 'recommended,optional,unsupported';
$opt_c = 'security';
$opt_f = "$releasefile";
$opt_t = '120';
$opt_v = 0;
$opt_o = 0;
$opt_p = 1;
$opt_s = 0;

#######################################################################
# Functions
#######################################################################

sub print_myrevision ($$) {
    my $commandName    = shift;
    my $pluginRevision = shift;
    print "$commandName v$pluginRevision\n";
}

sub mysupport () {
    print "Please use https://bugzilla.novell.com to submit patches or suggest improvements.\n";
    print "Please include version information with all correspondence (when possible,\n";
    print "use output from the --version option of the plugin itself).\n";
}

sub usage ($) {
    my $format = shift;
    printf( $format, @_ );
    exit $ERRORS{'UNKNOWN'};
}

sub get_distribution($) {
    my ($file) = @_;
	my %dist   = (
		'name'    => '',
		'version' => '',
		'release' => '0',
	);
    open( RELEASE, "<$file" ) || warn("Could not open $file\n");
    while (<RELEASE>) {
        if (/^SUSE Linux Enterprise/) {
            $dist{'name'} = 'SLE';
        }
		elsif (/^openSUSE/){
			$dist{'name'} = 'openSUSE';
		}
        if (/^VERSION/) {
            my ($version) = $_ =~ m/VERSION = (.*)/;
			$dist{'version'}=trim($version);
        }
        if (/^PATCHLEVEL/) {
            my ($release) = $_ =~ m/PATCHLEVEL = (.*)/;
			$dist{'release'}=trim($release);
        }
    }
    close(RELEASE);
    return ( \%dist );
}

sub print_usage () {
    print "This plugin checks for software updates on systems that use package\n";
    print "management systems based on the zypper command found in openSUSE.\n\n";
    print "It checks for security, recommended and optional patches and also for\n";
    print "optional package updates.\n\n";
    print "You can define the status by patch category. Use a commata to list more\n";
    print "than one category to a state. Possible values are recommended,optional,security\n";
    print "and packages\n\n";
    print "If you like to know the names of available patches and packages, use\n";
    print "the \"-v\" option.\n\n";
    print "Usage:\n";
    print "  $PROGNAME [-w <category>] [-c <category>] [-t <timeout>] [-v]\n";
    print "  $PROGNAME [-h | --help]\n";
    print "  $PROGNAME [-V | --version]\n";
    print "\n\nOptions:\n";
    print "  -c, --critical\n";
    print "      A patch with this category result in critical status.\n";
    print "      Default: $opt_c\n";
    print "  -f, --releasefile\n";
    print "      Use the given file to get informations about the distribution.\n";
    print "      Default: $releasefile\n";
    print "  -h, --help\n";
    print "      Print detailed help screen\n";
    print "  -i, --ignore <file>\n";
    print "      Ignore patches/packages that are mentioned in <file>\n";
    print "      Just list one patch/package per line - example:\n\n";
    print "      patch:libtiff-devel\n";
    print "      # comment\n";
    print "      package:libtiff3\n";
    print "      package:libtiff-devel\n";
    print "      # comment\n";
    print "      whitelist:aaa_base\n\n";
    print "  -o, --ignore_outdated\n";
    print "      Don't warn if a repository is outdated.\n";
    print "  -p, --no_perfdata\n";
    print "      Print no perfdata\n";
    print "  -r, --refresh_repos\n";
    print "      Tries to refresh the repositories before checking for updates.\n";
    print "      Note: this maybe needs an entry in /etc/sudoers like:\n";
    print "          nagios ALL = NOPASSWD: /usr/bin/zypper ref\n";
    print "      (and additional lines for the \'-s\' Option) if no check-zypp-wrapper is available.\n";
    print "  -s, --use_sudo\n";
    print "      Zypper needs root privileges on some distributions (known: 10.1 and SLE10).\n";
    print "      You can enable the script to use $sudo to start zypper.\n";
    print "      But don't forget to enable nopasswd sudo for the user starting $PROGNAME\n";
    print "      Via lines like the two below on in /etc/sudoers:\n";
    print "          nagios ALL = NOPASSWD: /usr/bin/zypper sl, \\ \n";
    print "                       /usr/bin/zypper $zypperopt\n";
    print "  -t, --timeout\n";
    print "      Just in case of problems, let's not hang Nagios and define a timeout.\n";
    print "      Default value is: $opt_t seconds\n";
    print "  -v, --verbose_output\n";
    print "      Print more information (useful only with Nagios v3.x).\n";
    print "  -w, --warning\n";
    print "      A patch with this category result in warning status.\n";
    print "      Default: $opt_w\n";
    print "\n";
    print "  -V, --version\n";
    print "      Print version information\n";
    print "\n";
    print "  -d, --debug\n";
    print "      Print debug output to STDERR\n";
}

sub print_help {
    my $exit = shift || undef;
    print "Copyright (c) 2009, Novell, Inc.\n\n";
    print_usage();
    print "\n";
    mysupport();
    exit $exit if ( defined($exit) );
}

sub check_zypper() {
    if ( -x "$zypper" ) {
        print STDERR "INFO: Trying $use_sudo $zypper sl 2>/dev/null 1>&2\n" if ($DEBUG);
        return ( system("$use_sudo $zypper sl 2>/dev/null 1>&2") );
    }
    else {
        return 1;
    }
}

sub refresh_zypper($) {
	my ($dist) = @_;
    if ( -x "$refresh_wrapper" ) {
        print STDERR "Trying: $refresh_wrapper 2>/dev/null 1>&2\n" if ($DEBUG);
        if ( open( WRAPPER, "$refresh_wrapper 2>&1 |" ) ) {
            my @wrapper_out = <WRAPPER>;
            close(WRAPPER);
            foreach my $line (@wrapper_out) {
                chomp $line;
                print STDERR "LINE: $line\n" if ($DEBUG);
                # error handling
                return ( "ERROR: " . xml_re_escape($line), $ERRORS{'ERROR'} ) if ( $line =~ /Could not refresh repository.*/ );
                return ( "ERROR: " . xml_re_escape($line), $ERRORS{'ERROR'} ) if ( $line =~ /Digest verification failed.*/ );
                return ( "ERROR: " . xml_re_escape($line), $ERRORS{'ERROR'} ) if ( $line =~ /refusing file.*wrong digest.*/ );
            }
            return ( "Refresh OK", $ERRORS{'OK'} );
        }
    }
    elsif ( -x "$zypper" ) {
        print STDERR "Trying: $sudo $zypper ref 2>/dev/null 1>&2\n" if ($DEBUG);
        if ( ( ( "$dist->{'name'}" eq "openSUSE" ) && ( "$dist->{'version'}" eq "10.2" ) ) 
          || ( ( "$dist->{'name'}" eq "SLE" ) && ( "$dist->{'version'}" eq "10" ) ) ) {
            my $res = system("$sudo $zypper ref 2>/dev/null 1>&2");
            return ( "ERROR: Unable to refresh the repositories", $ERRORS{'ERROR'} ) if !($res);
        }
        elsif ( open( ZYPPER, "$sudo $zypper ref 2>&1 |" ) ) {
            my @wrapper_out = <ZYPPER>;
            close(ZYPPER);
            foreach my $line (@wrapper_out) {
                chomp $line;
                print STDERR "LINE: $line\n" if ($DEBUG);
                return ( "ERROR: " . xml_re_escape($line), $ERRORS{'ERROR'} ) if ( $line =~ /Could not refresh repository.*/ );
            }
            return ( "Refresh OK", $ERRORS{'OK'} );
        }
    }
    else {
        return ( "ERROR: Could not refresh the repositories - binary not found", $ERRORS{'ERROR'} );
    }
}

sub check_errorcode($) {
    my $status      = shift;
    my $level       = 0;
    my $returnvalue = 'OK';
    $returnvalue = 'WARNING'  if ( "$opt_w" =~ /$status/ );
    $returnvalue = 'CRITICAL' if ( "$opt_c" =~ /$status/ );
    $level       = $ERRORS{"$returnvalue"};
    $exitcode = $level if ( $level gt $exitcode );
    $returnvalue = $REVERSE{"$exitcode"};
    return "$returnvalue";
}

sub xml_re_escape($) {
    my ($text) = @_;
    $text =~ s/&amp;/&/sg;
    $text =~ s/&lt;/</sg;
    $text =~ s/&gt;/>/sg;
    $text =~ s/&quot;/"/sg;
    $text =~ s/&apos;/'/sg;
    return $text;
}

sub trim($) {
    my ($text) = @_;
    $text =~ s/^\s+//;
    $text =~ s/\s+$//;
    return $text;
}

sub check($) {
	my ($dist) = @_;
    my ( $status, $ret_str, $error );
    my $secstr       = '';
    my $recstr       = '';
    my $optstr       = '';
    my $pacstr       = '';
    my $warnstr      = '';
    my $unsupstr     = '';
    my $update_avail = 0;
    my %packagelist;
    my @unsup_packagelist = ();

    if ($opt_u) {
        @unsup_packagelist = `$rpm -qa --qf "%{NAME} %{VENDOR}\n" | $grep -v 'SUSE LINUX Products GmbH, Nuernberg, Germany' | $grep -v gpg-pubkey | $awk '" " { print \$1 }'`;
        my $category = 'unsupported';
        my $status   = 'new';
        foreach my $name ( sort(@unsup_packagelist) ) {
            chomp($name);
            if ( grep {/\Q$name\E/} @packagewhitelist ) {
                print STDERR "WARINING: ignoring $name as it is in \@packagewhitelist\n" if ($DEBUG);
                next;
            }
            $packagelist{"$category"}{"$name"}{'category'} = "$category";
            $packagelist{"$category"}{"$name"}{'name'}     = "$name";
            $packagelist{"$category"}{"$name"}{'status'}   = "$status";
        }
    }
    print STDERR "INFO: Trying $use_sudo $zypper $zypperopt\n" if ($DEBUG);

    if ( open( FH, "$use_sudo $zypper $zypperopt 2>&1 |" ) ) {
        while (<FH>) {
            chomp;
            my $category = 'unknown';
            print STDERR "LINE: $_\n" if ($DEBUG);

            # error handling
            return ( 'UNKNOWN: ' . xml_re_escape($_), 'UNKNOWN' ) if (/not found on medium/);
            return ( 'UNKNOWN: ' . xml_re_escape($_), 'UNKNOWN' ) if (/I\/O error: Can't provide/);
            return ( 'UNKNOWN: ' . xml_re_escape($_), 'UNKNOWN' ) if (/Error message:/);
            return ( 'UNKNOWN: ' . xml_re_escape($_), 'UNKNOWN' ) if (/A ZYpp transaction is already in progress./);
            return ( 'UNKNOWN: ' . xml_re_escape($_), 'UNKNOWN' ) if (/System management is locked/);
            if (/out-of-date/) {
                print STDERR "WARNING: outdated repository found\n" if ($DEBUG);
                if ( !$opt_o ) {
                    $error   = check_errorcode('security');
                    $warnstr = "At least one of your Repositories is out of date. Please run \"zypper refresh\" as root to update it. ";
                    $warnstr .= "\n" if ($opt_v);
                }
            }
            if (/<message type=\"warning\">(.*)<\/message>/) {
                $update_avail = 1;
                $error        = check_errorcode('security');
                $warnstr      = xml_re_escape($1) . ' ';
                $warnstr .= "\n" if ($opt_v);
            }
            if ( ( ( "$dist->{'name'}" eq "SLE" ) && ( "$dist->{'version'}" eq "10.2" ) ) 
              || ( ( "$dist->{'name'}" eq "SLE" ) && ( "$dist->{'version'}" eq "10" ) ) ) {
                my ( $url, $name, $version, $category, $status ) = split( '\s*\|\s*', $_, 5 );    # just for reference - perhaps we need the variables later
                if ( defined($name) ) {
                    if ( grep {/\Q$name\E/} @patchignore ) {
                        print STDERR "WARNING: ignoring $name as it is in \@patchignore\n" if ($DEBUG);
                        next;
                    }
                }
                $category                                      = 'optional'    if (/\|\s*optional\s*\|\s*Needed/);
                $category                                      = 'recommended' if (/\|\s*recommended\s*\|\s*Needed/);
                $category                                      = 'security'    if (/\|\s*security\s*\|\s*Needed/);
                $packagelist{"$category"}{"$name"}{'category'} = "$category"   if defined($category);
                $packagelist{"$category"}{"$name"}{'status'}   = "$status"     if defined($status);
                $packagelist{"$category"}{"$name"}{'name'}     = "$name"       if defined($name);
            }
            else {
                if (/<update /) {
                    my ($name) = $_ =~ /name="(.*?)"/;
                    if (/kind="patch"/) {    # line contains patch
                        if ( grep {/\Q$name\E/} @patchignore ) {
                            print STDERR "WARNING: ignoring $name as it is in \@patchignore\n" if ($DEBUG);
                            next;
                        }
                        $category = 'optional'    if (/category="optional"/);
                        $category = 'recommended' if (/category="recommended"/);
                        $category = 'security'    if (/category="security"/);
                    }
                    elsif (/kind="package"/) {
                        if ( grep {/\Q$name\E/} @packageignore ) {
                            print STDERR "WARNING: ignoring $name as it is in \@packageignore\n" if ($DEBUG);
                            next;
                        }
                        $category = 'package';
                    }
                    $packagelist{"$category"}{"$name"}{'category'} = "$category";
                    $packagelist{"$category"}{"$name"}{'name'}     = "$name";
                    $packagelist{"$category"}{"$name"}{'status'}   = "Needed";
                }
            }
        }
        if ($DEBUG) {
            print STDERR 'INFO: Packages    (paccount): ' . scalar( keys %{ ( $packagelist{'package'} ) } ) . "\n";
            print STDERR 'INFO: Optional    (optcount): ' . scalar( keys %{ ( $packagelist{'optional'} ) } ) . "\n";
            print STDERR 'INFO: Recommended (reccount): ' . scalar( keys %{ ( $packagelist{'recommended'} ) } ) . "\n";
            print STDERR 'INFO: Security    (seccount): ' . scalar( keys %{ ( $packagelist{'security'} ) } ) . "\n";
            print STDERR 'INFO: Unsupported (uspcount): ' . scalar( keys %{ ( $packagelist{'unsupported'} ) } ) . "\n";
            use Data::Dumper;
            print STDERR Data::Dumper->Dump( [ \%packagelist ] );
        }
        if ( defined( $packagelist{'package'} ) && ( scalar( keys %{ ( $packagelist{'package'} ) } ) ne 0 ) ) {
            $update_avail = 1;
            $error        = check_errorcode('packages');
            $pacstr       = scalar( keys %{ ( $packagelist{'package'} ) } ) . " package update(s);";
        }
        if ( defined( $packagelist{'optional'} ) && ( scalar( keys %{ ( $packagelist{'optional'} ) } ) ne 0 ) ) {
            $update_avail = 1;
            $error        = check_errorcode('optional');
            $optstr       = scalar( keys %{ ( $packagelist{'optional'} ) } ) . " optional update(s);";
        }
        if ( defined( $packagelist{'recommended'} ) && ( scalar( keys %{ ( $packagelist{'recommended'} ) } ) ne 0 ) ) {
            $update_avail = 1;
            $error        = check_errorcode('recommended');
            $recstr       = scalar( keys %{ ( $packagelist{'recommended'} ) } ) . " recommended update(s);";
        }
        if ( defined( $packagelist{'security'} ) && ( scalar( keys %{ ( $packagelist{'security'} ) } ) ne 0 ) ) {
            $update_avail = 1;
            $error        = check_errorcode('security');
            $secstr       = scalar( keys %{ ( $packagelist{'security'} ) } ) . " security update(s);";
        }
        if ( defined( $packagelist{'unsupported'} ) && ( scalar( keys %{ ( $packagelist{'unsupported'} ) } ) ne 0 ) ) {
            $update_avail = 1;
            $error        = check_errorcode('unsupported');
            $unsupstr     = scalar( keys %{ ( $packagelist{'unsupported'} ) } ) . " unsupported package(s);";
        }
        if ($update_avail) {
            $ret_str .= trim("$warnstr $secstr $recstr $optstr $pacstr $unsupstr") . " ";
            my @packagelist             = ();
            my @unsupported_packagelist = ();
            if ($opt_v) {
                foreach my $cat ( 'security', 'recommended', 'optional', 'package', 'unsupported' ) {
                    for my $key ( sort( keys %packagelist ) ) {
                        if ( "$key" eq "$cat" ) {
                            for my $name ( sort( keys %{ $packagelist{$key} } ) ) {
                                if ( "$cat" eq "package" ) {
                                    push @packagelist, $packagelist{$key}{$name}{'name'};
                                }
                                elsif ( "$cat" eq "unsupported" ) {
                                    push @unsupported_packagelist, $packagelist{$key}{$name}{'name'};
                                }
                                else {
                                    $ret_str .= "\n$cat patch: " . $packagelist{$key}{$name}{'name'};
                                }
                            }
                        }
                    }
                }
                $ret_str .= "\npackages: " . join( ' ', @packagelist ) if @packagelist;
                $ret_str .= "\nunsupported Packages: " . join( ' ', @unsupported_packagelist ) if @unsupported_packagelist;
                $ret_str .= "\nIgnored Patches : " . join( ' ', @patchignore ) . " "   if @patchignore;
                $ret_str .= "\nIgnored Packages: " . join( ' ', @packageignore ) . " " if @packageignore;
                if ( $#packagewhitelist lt 11 ) {
                    $ret_str .= "\nUnsupported, ignored Packages: " . join( ' ', @packagewhitelist ) . " " if @packagewhitelist;
                }
                else {
                    $ret_str .= "\nUnsupported, ignored Packages: $#packagewhitelist ";
                }
            }
        }
        else {
            $error   = "OK";
            $ret_str = "no updates available ";
            if ($opt_v) {
                $ret_str .= "\nIgnored Patches : " . join( ' ', @patchignore ) . " "   if @patchignore;
                $ret_str .= "\nIgnored Packages: " . join( ' ', @packageignore ) . " " if @packageignore;
                if ( $#packagewhitelist lt 11 ) {
                    $ret_str .= "\nUnsupported, ignored Packages: " . join( ' ', @packagewhitelist ) . " " if @packagewhitelist;
                }
                else {
                    $ret_str .= "\nUnsupported, ignored Packages: $#packagewhitelist ";
                }
            }
        }
        $ret_str
            .= "| security="
            . scalar( keys %{ ( $packagelist{'security'} ) } )
            . ";;;; recommended="
            . scalar( keys %{ ( $packagelist{'recommended'} ) } )
            . ";;;; optional="
            . scalar( keys %{ ( $packagelist{'optional'} ) } )
            . ";;;; packages="
            . scalar( keys %{ ( $packagelist{'package'} ) } )
            . ";;;;\n"
            if ($opt_p);
    }
    close(FH);
    return ( "$ret_str", "$error" );
}

#######################################################################
# Main
#######################################################################

Getopt::Long::Configure('bundling');
GetOptions(
    "V"               => \$opt_V,
    "version"         => \$opt_V,
    "h"               => \$opt_h,
    "help"            => \$opt_h,
    "d"               => \$DEBUG,
    "debug"           => \$DEBUG,
    "i=s"             => \$opt_i,
    "ignore=s"        => \$opt_i,
    "w=s"             => \$opt_w,
    "warning=s"       => \$opt_w,
    "c=s"             => \$opt_c,
    "critical=s"      => \$opt_c,
    "f=s"             => \$opt_f,
    "releasefile=s"   => \$opt_f,
    "o"               => \$opt_o,
    "ignore_outdated" => \$opt_o,
    "p:0"             => \$opt_p,
    "no_perfdata:0"   => \$opt_p,
    "r"               => \$opt_r,
    "refresh_repos"   => \$opt_r,
    "t=i"             => \$opt_t,
    "timeout=i"       => \$opt_t,
    "u"               => \$opt_u,
    "check-vendor"    => \$opt_u,
    "v"               => \$opt_v,
    "verbose_output"  => \$opt_v,
    "s"               => \$opt_s,
    "use_sudo"        => \$opt_s,
) or print_help(2);

$TIMEOUT = $opt_t if ($opt_t);

# Just in case of problems, let's not hang Nagios
$SIG{'ALRM'} = sub {
    print "UNKNOWN - Plugin timed out\n";
    exit $ERRORS{'UNKNOWN'};
};
alarm($TIMEOUT);

if ($opt_V) {
    print_myrevision( $PROGNAME, "$VERSION" );
    exit $ERRORS{'OK'};
}

my $dist = get_distribution("$opt_f");

if ($DEBUG) {
    use English;
    use Data::Dumper;
    print STDERR "INFO: check_zypper version: $VERSION\n";
    print STDERR "INFO: userid : " . getlogin() . "\n";
    foreach my $gid ( split( / /, "$GID" ) ) {
        print STDERR "INFO: groupid: " . getgrgid("$gid") . "\n";
    }
    print STDERR "INFO: $dist->{'name'},$dist->{'version'},$dist->{'release'}\n";
    print STDERR "INFO: " . Data::Dumper->Dump( [ \%supported_release ] );
}

my $version_release = $dist->{'version'};

$zypperopt = '--non-interactive --no-gpg-checks list-updates' if ( "$dist->{'version'}" eq "10.2" );
$zypperopt = '--xmlout --non-interactive list-updates -t package -t patch' if ( $dist->{'version'} gt 11.0 );

if ( "$dist->{'name'}" eq "SLE" ) {
    $version_release = "$dist->{'version'}.$dist->{'release'}";
    if ( ( "$dist->{'version'}" eq "10" ) && ( $dist->{'release'} gt 0 ) ) {
        $zypperopt = '--non-interactive --no-gpg-checks --terse list-updates';
    }
    else {
        $zypperopt = '--xmlout --non-interactive list-updates -t package -t patch';
    }
}

$use_sudo .= "$sudo" if ($opt_s);

if ($opt_h) {
    print_help();
    exit $ERRORS{'OK'};
}

if ($opt_i) {
    if ( !-r "$opt_i" ) {
        print "Updates CRITICAL - can't find file '$opt_i' - perhaps you should not use option '-i'?\n";
        exit $ERRORS{'CRITICAL'};
    }
    else {
        open( IGNORES, "<$opt_i" ) or die "Could not open $opt_i: $!\n";
        print "INFO: Ignoring the following patches/packages:\n" if ($DEBUG);
        while (<IGNORES>) {
            next if /^#/;
            next if /^\s*$/;
            chomp;
            if ( (/^patch:/) || (/^Patch:/) ) {
                my ( $foo, $toadd ) = split( ':', $_, 2 );
                $toadd =~ s/\s*//g;    # Patch names have no whitespaces
                print "INFO: + Patch  : $toadd\n" if ($DEBUG);
                push @patchignore, "$toadd";
            }
            elsif ( (/^package:/) || (/^Package:/) ) {
                my ( $foo, $toadd ) = split( ':', $_, 2 );
                $toadd =~ s/\s*//g;    # Package names have no whitespaces
                print "INFO: + Package: $toadd\n" if ($DEBUG);
                push @packageignore, "$toadd";
            }
            elsif ( (/^whitelist:/) || (/^Whitelist:/) ) {
                my ( $foo, $toadd ) = split( ':', $_, 2 );
                $toadd =~ s/\s*//g;    # Package names have no whitespaces
                print "INFO: + Whitelisting Package: $toadd\n" if ($DEBUG);
                push @packagewhitelist, "$toadd";
            }
        }
        close(IGNORES);
    }
}

if ($opt_r) {
    my ( $ret_str, $error ) = refresh_zypper($dist);
    if ($error) {
        print "$ret_str\n";
        exit $ERRORS{'UNKNOWN'};
    }
}

alarm(0);

if ( check_zypper() ) {
    print "Updates UNKNOWN - system does not allow to execute zypper\n";
    exit $ERRORS{'UNKNOWN'};
}
else {
    my ( $ret_str, $error ) = check($dist);
    if ( grep {/\Q$dist->{'name'}\E/} keys %supported_release ) {
        print STDERR "INFO: found $dist->{'name'} - checking supportstatus\n" if ($DEBUG);
        if ( grep {/\Q$version_release\E/} @{ $supported_release{$dist->{'name'}} } ) {
            print STDERR "INFO: found $version_release for $dist->{'name'} in \%supported_release - OK\n" if ($DEBUG);
        }
        else {
            $ret_str = "discontinued OS Release $dist->{'name'} $version_release; " . $ret_str;
            $error   = 'CRITICAL';
        }
    }
    else {
        $ret_str = "unknown OS Release $dist->{'name'}-$version_release; " . $ret_str;
        $error   = 'UNKNOWN';
    }
    print "Updates $error : $ret_str";
    $exitcode = $ERRORS{$error};
    print STDERR "INFO: Exit-Code: " . $exitcode . "\n" if ($DEBUG);
    exit $exitcode;
}
openSUSE Build Service is sponsored by