RSS feed logo RSS Feed | About Pantz.org
Perl script to check for OpenBSD package updates
Posted on 11-02-2005 21:13:00 EST | Updated on 11-02-2005 21:13:00 EST
Section: /software/openbsd/ | Permanent Link

OpenBSD will do security updates to the software on their distributions when it is deemed necessary. I found that this was the best way to check for the new updated software packages for my release. The security-announce mailing list they have might do this also but I found this eaiser to do.

This script was made to check on OpenBSD package updates by checking a website that has the packages available. These sites would be the normal http distro sites packages directory. This script will need the GNU program "wget" and the ability to write 1 file to disk. If it finds an updated package date from the last time it was run it will e-mail what packages were updated. Have a cron job run this script as often as you like.

#!/usr/bin/perl

# Timestamp filename/path for keeping last time package times were checked
$lastcheck_date_time_filename = "/usr/local/bin/check_date";

# OpenBSD version to check. This is the only thing you have to change
# between OpenBSD version changes. So you don't have to change your url below.
$version = "3.9";

# http URL of site to get packages file list from.
# Usually a OpenBSD mirror site. Use $version var above for easy
# version change in the url. Change your arch at the end to suite your needs.
# Example url:      http://openbsd.secsup.org/3.8/packages/i386/
# Example with var: http://openbsd.secsup.org/$version/packages/i386/
$url_of_filelist = "http://openbsd.mirrors.pair.com/ftp/$version/packages/i386/";

# Path to Wget binary. -q for quite and -T timeout of 15 secs
# -t3 for 3 trys. "-O -" outputs to stdout.
$wget = "wget -q -T5 -t3 -O -";

# Fill out where you want the notification e-mail to go.
# These work with Sendmail/Postfix. Sendmail symlink has to be there for postfix.
# Put commas between multiple e-mail addresses for a to, cc, or bcc list.
$from='openbsd@localhost.localdomain' unless $from;
$to='update@yourdomain.com' unless $to;
$cc='' unless $cc;
$bcc='' unless $bcc;
$sendmail="/usr/sbin/sendmail -oi -t" unless $sendmail;

# Hash for letter to number date conversion
%Month=("Jan" => "01",
        "Feb" => "02",
        "Mar" => "03",
        "Apr" => "04",
        "May" => "05",
        "Jun" => "06",
        "Jul" => "07",
        "Aug" => "08",
        "Sep" => "09",
        "Oct" => "10",
        "Nov" => "11",
        "Dec" => "12" );

# Get current local time
($Cur_Second, $Cur_Minute, $Cur_Hour, $Cur_Day, $Cur_Month, $Cur_Year, $Cur_WeekDay, $Cur_DayOfYear, $IsDaylightSavings) = localtime(time);

# Correct formating of local time with 0 pad's and year and month correction.
$Cur_Month += 1;
$Cur_Year += 1900;
if ($Cur_Month < 10) { $Cur_Month = "0" . $Cur_Month; }
if ($Cur_Hour < 10) { $Cur_Hour = "0" . $Cur_Hour; }
if ($Cur_Minute < 10) { $Cur_Minute = "0" . $Cur_Minute; }
if ($Cur_Second < 10) { $Cur_Second = "0" . $Cur_Second; }
if ($Cur_Day < 10) { $Cur_Day = "0" . $Cur_Day; }

# Assemble a current date/time stamp
$Cur_date_time= $Cur_Year . $Cur_Month . $Cur_Day . $Cur_Hour . $Cur_Minute;

# If date-time check file does not exist create file with current date-time.
if (! -e $lastcheck_date_time_filename) {
  write_current_date();
}

# If date-time last check file exists and is readable get the date-time of last check
if (-e $lastcheck_date_time_filename && -r $lastcheck_date_time_filename) {
  open(LAST_CHECK1, "$lastcheck_date_time_filename") or die("Cannot Open File. Permissions?");
    while ( <LAST_CHECK1> ) {
      if (/^\d{12}$/) {
        $last_check_date_time = $_;
      } else {
      die("File format in date check file: $lastcheck_date_time_filename incorrect.");
      }
    }
  close(LAST_CHECK1);
}

%package_date_hash =();

# Open html file with an index listing of .tgz files from an apache server. Check file
# dates and times. If they are later then the last time we checked then the packages are
# new and the package name and date/time are put in a hash. $? var checks return value from wget.
# <IMG SRC="/icons/compressed.gif" ALT="[   ]"> <A HREF="zope-2.7.4.tgz">zope-2.7.4.tgz</A>          04-Sep-2005 20:29   4.8M
open(IN, "$wget $url_of_filelist |") or die ("Problem getting remote file. Did Wget retrieve the file ok?");
  while ( <IN> ) {
    if (/.tgz/) {
      ($pack_name,$pack_day,$pack_month,$pack_year,$pack_hour,$pack_min) = ($_ =~ /href\=\"(.*\.tgz)\".*\<\/a\>.* (\d+)\-(\w+)\-(\d+) 
(\d+):(\d+)/i);
      $pack_month=$Month{$pack_month};
      $cur_pack_date_time = $pack_year . $pack_month . $pack_day . $pack_hour . $pack_min;
        if ($cur_pack_date_time > $last_check_date_time) {
          ($unpack_year,$unpack_month,$unpack_day,$unpack_hour,$unpack_min) = ($cur_pack_date_time =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})/);
          $cur_pack_date_time = "$unpack_month-$unpack_day-$unpack_year $unpack_hour:$unpack_min";
          $package_date_hash{ $pack_name } = $cur_pack_date_time;
        }
    }
  }
close(IN);

# $? var checks return value from wget. If it's not 0 something bad happened. Send email. Exit.
if ($? != 0) {
  $mail_body = "Wget could not retrieve the webpage correctly.\n\nTry the command below (remove -q) and see if there is a problem.\n\n$wget 
$url_of_filelist\n";
  $mail_subject = "Wget command in script $0 did not exit correctly!";
  send_email ($mail_subject,$mail_body);
  exit();
}

# Update date-time file with the new current date
write_current_date();

# If data exists in the hash then the package page was updated.
# Send an e-mail about it.
if (%package_date_hash) {
    while ( ($key, $value) = each(%package_date_hash) ) {
      $mail_body .= "Date/Time: $value Package: $key\n";
    }
  $mail_subject = "OpenBSD $version package update!";
  send_email ($mail_subject,$mail_body);
}

# Subroutine to update a file with a date/time stamp of the
# last time a update check was run.
sub write_current_date {
  open(LAST_CHECK2,">$lastcheck_date_time_filename") or die("Cannot open file to set date.");
  print LAST_CHECK2 "$Cur_date_time";
  close(LAST_CHECK2);
}

# Send email subroutine. $_[0],$_[1] is accessing the @_ var.
sub send_email {
  open (MAIL,"| $sendmail") or die "Can't access $sendmail for sending the e-mail\n";
  print MAIL "To: $to\n";
  print MAIL "Cc: $cc\n" if $cc;
  print MAIL "Bcc: $bcc\n" if $bcc;
  print MAIL "From: $from\n";
  print MAIL "Subject: $_[0]\n\n";
  print MAIL "$_[1]";
  close MAIL;
}

Del.icio.us! | Digg Me! | Reddit!

Related stories