#!/usr/bin/perl # Checks a Solaris host patchlevel against requirements for DST 2007 # remediation. # Annoyed? Write your Congressman today and demand the repeal of DST # entirely! It's outdated, and causes far more trouble than it's worth. # Written by J.D. Baldwin , March 2007, v 1.1 # Redistribute this script freely. If you modify it, note that in # comments before redistributing it. # Thanks to Sergey Galitskiy for pointing out a needed fix to account # for 'i386' returned from uname -p use warnings; use strict; use Data::Dumper; my $SHOWREV = '/usr/bin/showrev -p'; my $UNAME_R = '/usr/bin/uname -r'; my $UNAME_P = '/usr/bin/uname -p'; my %this_sys_patches = ( ); my %superseding_patches = ( # If one of these patches is found, it's the same as if # the referenced patch (at least) is found, too -- # e.g., if 118833-17 is found, it obsoletes 119689-07. '118833' => '17,119689-07', '118855' => '15,121208-03' ); my %patches_of_interest = ( '109809' => 1, '108993' => 1, '109810' => 1, '108994' => 1, '113225' => 1, '112874' => 1, '116545' => 1, '114432' => 1, '122032' => 1, '119689' => 1, '122033' => 1, '121208' => 1 ); # Patches are delineated SPARC / i386 my %best_patches = ( sparc_8 => '109809-06,108993-52', i386_8 => '109810-06,108994-52', sparc_9 => '113225-08,112874-33', i386_9 => '116545-06,114432-23', sparc_10 => '122032-04,119689-07', i386_10 => '122033-04,121208-03' ); my %us_patches = ( sparc_8 => '109809-02,108993-52', i386_8 => '109810-02,108994-52', sparc_9 => '113225-03,112874-33', i386_9 => '116545-02,114432-23', sparc_10 => '122032-01,119689-07', i386_10 => '122033-01,121208-03' ); my %canada_patches = ( sparc_8 => '109809-04', i386_8 => '109810-04', sparc_9 => '113225-05', i386_9 => '116545-04', sparc_10 => '122032-03', i386_10 => '122033-03' ); my %w_aus_patches = ( sparc_8 => '109809-05', i386_8 => '109810-05', sparc_9 => '113225-07', i386_9 => '116545-05', sparc_10 => '122032-03', i386_10 => '122033-03' ); my %bahamas_patches = ( sparc_8 => '109809-06', i386_8 => '109810-06', sparc_9 => '113225-08', i386_9 => '116545-06', sparc_10 => '122032-04', i386_10 => '122033-04' ); sub max { my ( $a, $b ) = @_; return $a if ( $a > $b ); return $b; } sub check_patches { my ( $t, $this_sys_hash_ref, $tz_of_interest_hash_ref, $tzoutstr ) = @_; my $reasons = ''; my @required = split /,/, $$tz_of_interest_hash_ref{$t}; foreach ( @required ) { my ( $pnum, $prev ) = split /\-/; $prev =~ s/^0*//; if ( ! defined $$this_sys_hash_ref{$pnum} ) { $reasons .= sprintf " missing patch %d, need revision %02d\n", $pnum, $prev; } elsif ( $prev > $$this_sys_hash_ref{$pnum} ) { $reasons .= sprintf " need revision %02d of patch %d, found only %02d\n", $prev, $pnum, $$this_sys_hash_ref{$pnum}; } } if ( length($reasons) > 0 ) { print "This system is NOT patched for $tzoutstr, because:\n"; print $reasons, "\n"; return 0; } else { print "This system is patched for $tzoutstr\n\n"; return 1; } } ############### MAIN PROGRAM ############# open(PATCHES, "$SHOWREV |") or die "Could not open pipe from showrev binary: $!"; open(REV, "$UNAME_R |") or die "Could not open pipe from uname -r binary: $!"; open(ARCH, "$UNAME_P |") or die "Could not open pipe from uname -p binary: $!"; my $revision = ; chomp $revision; my $arch = ; chomp $arch; close REV; close ARCH; if ( $revision !~ m/^5\.[0-9]/ ) { die "Revision $revision is not a valid Solaris revision\n"; } if ( $arch =~ m/^i386/i ) { $arch = 'i386'; } elsif ( $arch =~ m/^x86/i ) { $arch = 'i386'; } elsif ( $arch =~ m/^sparc$/i ) { $arch = 'sparc'; } else { die "Unknown architecture $arch, should be x86, i386 or sparc\n"; } my ( $dummy, $oslevel ) = split /\./, $revision; unless ( ( $oslevel >= 8 ) && ( $oslevel <= 10 ) ) { die "OS level $oslevel is not supported for DST\n"; } while ( ) { my $patch_id; ( $dummy, $patch_id ) = split; my ( $patchnum, $patchrev ) = split /\-/, $patch_id; $patchrev =~ s/^0*//; if ( defined $superseding_patches{$patchnum} ) { my ( $ssp_rev, $patch_superseded ) = split /,/, $superseding_patches{$patchnum}; my ( $pnum, $prev ) = split /\-/, $patch_superseded; $prev =~ s/^0*//; $ssp_rev =~ s/^0*//; if ( $patchrev >= $ssp_rev ) { $this_sys_patches{$pnum} = 0 if ( ! defined $this_sys_patches{$pnum} ); $this_sys_patches{$pnum} = max($prev, $this_sys_patches{$pnum}); } } next if ( ! defined $patches_of_interest{$patchnum} ); $this_sys_patches{$patchnum} = 0 if ( ! defined $this_sys_patches{$patchnum} ); $this_sys_patches{$patchnum} = max($patchrev, $this_sys_patches{$patchnum}); } close PATCHES; my $this_sys = "${arch}_${oslevel}"; # Now check the found patches against what we hope to have: if ( check_patches($this_sys, \%this_sys_patches, \%best_patches, "all known timezones") ) { exit 0; } check_patches($this_sys, \%this_sys_patches, \%us_patches, "all USA timezones"); check_patches($this_sys, \%this_sys_patches, \%canada_patches, "all Canadian timezones"); check_patches($this_sys, \%this_sys_patches, \%w_aus_patches, "all Western Australia timezones"); check_patches($this_sys, \%this_sys_patches, \%bahamas_patches, "the Bahamas timezone");