Diff for /loncom/build/system_dependencies/perltest.pl between versions 1.2 and 1.9

version 1.2, 2001/09/30 21:04:49 version 1.9, 2002/11/04 01:57:53
Line 1 Line 1
 #!/usr/bin/perl  #!/usr/bin/perl
   
 # The LearningOnline Network with CAPA  # perltest.pl - script to test the status of perl modules on a LON-CAPA system
 #  #
 # Testing to see if all needed perl components are on  # $Id$
 # a system  #
   ###
   
   =pod
   
   =head1 NAME
   
   B<perltest.pl> - Test status of perl modules installed on a LON-CAPA system.
   
   =cut
   
   # Written to help LON-CAPA (The LearningOnline Network with CAPA)
 #  #
 # YEAR=2001  # YEAR=2001
 # 9/30 Scott Harrison  # 9/30 Scott Harrison
 #  # YEAR 2002 and onwards
 # I wish there were a more straightforward way to do this.  But I can't  # Scott Harrison, sharrison@users.sourceforge.net
 # seem to find the right internals in the perl programming language.  
 # Also, this program is only a "modest" effort to LOOK and see whether  =pod
   
   =head1 SYNOPSIS
   
   perl perltest.pl [MODE]
   
   This script is located inside the LON-CAPA source code tree.
   This script is invoked by test-related targets inside
   F<loncapa/loncom/build/Makefile>.
   
   This script is also used as a CGI script and is installed
   at the file location of F</home/httpd/cgi-bin/perltest.pl>.
   
   MODE, when left blank, the output defaults to 'statusreport' mode.
   Except however, if $ENV{'QUERY_STRING'} exists, in which case
   'html' mode is safely assumed.
   
   Here is a complete list of MODEs.
   
   =over 4
   
   =item html
   
   A web page detailing the status of CPAN distributions on a LON-CAPA server
   (as well as methods for resolution).
   
   =item synopsis
   
   Plain-text output which just summarizes the status of
   expected CPAN distributions on a system.  (This is what a
   user sees when running the ./TEST command.)
   
   =item statusreport
   
   Plain-text output which provides a detailed status report of
   CPAN distributions on a LON-CAPA server (as well as methods
   for resolution).
   
   =back
   
   =head1 DESCRIPTION
   
   This program tests the status of perl modules installed on a LON-CAPA system.
   As with the other LON-CAPA test scripts, when reasonable, I try
   to avoid importing functionality from other LON-CAPA modules so as to
   avoid indirectly testing software dependencies.
   
   =head2 ORGANIZATION OF THIS PERL SCRIPT
   
   The script is organized into the following sections.
   
   =over 4
   
   =item 1.
   
   Process version information of this file.
   
   =item 2.
   
   Determine output mode for the script.
   
   =item 3.
   
   Output header information.
   
   =item 4.
   
   Make sure the perl version is suitably high.
   
   =item 5.
   
   Make sure we have the find command.
   
   =item 6.
   
   Scan for all the perl modules present on the filesystem.
   
   =item 7.
   
   Read in cpan_distributions.txt.
   
   =item 8.
   
   Loop through all of the needed CPAN distributions and probe the system.
   
   =item 9
   
   Output a report (dependent on output mode).
   
   =item 10
   
   Subroutines.
   
   B<vers_cmp> - compare two version numbers and see which is greater.
   
   B<have_vers> - syntax check the version number and call B<vers_cmp>.
   
   =back
   
   =head1 STATUS
   
   Ratings: 1=horrible 2=poor 3=fair 4=good 5=excellent
   
   =over 4
   
   =item Organization
   
   5
   
   =item Functionality
   
   5
   
   =item Has it been tested?
   
   4
   
   =back
   
   =head1 AUTHOR
   
   Scott Harrison, sharrison@users.sourceforge.net, 2001, 2002
   
   This software is distributed under the General Public License,
   version 2, June 1991 (which is the same terms as LON-CAPA).
   
   This is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   
   This software is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this software; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   
   =cut
   
   # =================================== Process version information of this file.
   my $VERSION = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);
   
   # ========================== Determine the mode that this script should run in.
   my $mode;
   $mode=shift(@ARGV) if @ARGV;
   unless ( $mode )
     {
       $mode = 'statusreport';
     }
   if ( defined($ENV{'QUERY_STRING'}) )
     {
       $mode = 'html';
     }
   
   # ================================================== Output header information.
   my $hostname = `hostname`; chomp($hostname);
   my $date = `date`; chomp($date);
   
   # --- html mode blurb
   if ($mode eq "html") {
       print(<<END);
   Content-type: text/html
   
   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   <html>
   <head>
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
   <title>CPAN perl status report; $hostname; $date</title>
   </head>
   <body bgcolor="white">
   <h1>CPAN perl status report</h1>
   <pre>
   END
   }
   
   print('Running perltest.pl, version '.$VERSION.'.'."\n");
   print('(Test status of perl modules installed on a LON-CAPA system).'."\n");
   
   # This program is only a "modest" effort to LOOK and see whether
 # necessary perl system dependencies are present.  I do not yet  # necessary perl system dependencies are present.  I do not yet
 # try to actually run tests against each needed perl module.  # try to actually run tests against each needed perl module.
   # Eventually, all modules will be version-checked, and reasonable
   # testing implemented.
   
 # --------------------------------- Make sure the perl version is suitably high  # ================================ Make sure the perl version is suitably high.
 my $ret=system("find --version 1>/dev/null");  print('Checking version of perl'."\n");
 if ($]<5.005) {  print(`perl --version`);
     die "DEPENDENCY FAILURE: LON-CAPA requires perl version >= 5.005.\n";  unless (eval("require 5.005"))
 }    {
       die('**** ERROR **** DEPENDENCY FAILURE: require perl version >= 5.005.'.
    "\n".'Do you even have perl installed on your system?'."\n");
     }
   else
     {
       print('Perl >= 5.005...okay'."\n");
     }
   
 # ------------------------------------------ Make sure we have the find command  # ========================================= Make sure we have the find command.
 my $ret=system("find --version 1>/dev/null");  my $ret = system("find --version 1>/dev/null");
 if ($ret) {  if ($ret)
     die "DEPENDENCY FAILURE: A test program requires the GNU ".    {
  "'find' utility.\n";      die('**** ERROR **** DEPENDENCY FAILURE: perltest.pl requires the GNU '.
 }   "'find'".' utility.'."\n");
     }
   else
     {
       print('find command exists...okay'."\n");
     }
   
 # ----------------------------------------- Read in all the system perl modules  # ==================== Scan for all the perl modules present on the filesystem.
 print "Scanning for perl modules...\n";  print('Scanning for perl modules...'."\n");
 my $modules;   my $big_module_string; # All the modules glued together in a string.
 foreach my $inc (@INC) {  my $number_of_modules = 0; # The total number of modules available in system.
     my @m=`find $inc -type f -name '*.pm'`;  # --- Build a pattern matching string.
     foreach my $mod (@m) {  foreach my $inc (@INC)
  $modules.=$mod;    {
     }      my @m = `find $inc -maxdepth 2000 -type f -name '*.pm'`;
 }      foreach my $module (@m)
         {
    $big_module_string .= $module;
    $number_of_modules++;
         }
     }
   # --- Notify user of the number of modules.
   print('There are '.$number_of_modules.
         ' perl modules present on your filesystem.'."\n");
   
 # --------------- Seeing if dependencies are in our "full" list of perl modules  my %dist_module_hash; # Relate the distributions to their VersionFrom modules.
 my %dependencies=qw(  my %module_name_on_filesystem; # Relate module name to filesystem syntax.
     GD/Barcode.pm 1  my %dist_dev_version_hash; # Expected development version of CPAN distribution.
     GD/Barcode/COOP2of5.pm 1  my %dist_stable_version_hash; # Expected stable version of CPAN distribution.
     GD/Barcode/Code39.pm 1  my %module_dev_version_hash; # development version of versionfrom_module.
     GD/Barcode/EAN13.pm 1  my %module_stable_version_hash; # stable version of versionfrom_module.
     GD/Barcode/EAN8.pm 1  
     GD/Barcode/IATA2of5.pm 1  
     GD/Barcode/ITF.pm 1  
     GD/Barcode/Industrial2of5.pm 1  
     GD/Barcode/Matrix2of5.pm 1  
     GD/Barcode/NW7.pm 1  
     GD/Barcode/UPCA.pm 1  
     GD/Barcode/UPCE.pm 1  
     IO/Dir.pm 1  
     IO/Poll.pm 1  
     IO/Socket/INET.pm 1  
     IO/Socket/UNIX.pm 1  
     Algorithm/Diff.pm 1  
     Algorithm/DiffOld.pm 1  
     Bundle/LWP.pm 1  
     File/Listing.pm 1  
     HTML/AsSubs.pm 1  
     HTML/Element.pm 1  
     HTML/Element/traverse.pm 1  
     HTML/Form.pm 1  
     HTML/Parse.pm 1  
     HTML/Tagset.pm 1  
     HTML/Tree.pm 1  
     HTML/TreeBuilder.pm 1  
     HTTP/Cookies.pm 1  
     HTTP/Daemon.pm 1  
     HTTP/Date.pm 1  
     HTTP/Headers.pm 1  
     HTTP/Headers/Auth.pm 1  
     HTTP/Headers/ETag.pm 1  
     HTTP/Headers/Util.pm 1  
     HTTP/Message.pm 1  
     HTTP/Negotiate.pm 1  
     HTTP/Request.pm 1  
     HTTP/Request/Common.pm 1  
     HTTP/Response.pm 1  
     HTTP/Status.pm 1  
     LWP.pm 1  
     LWP/Authen/Basic.pm 1  
     LWP/Authen/Digest.pm 1  
     LWP/Debug.pm 1  
     LWP/MediaTypes.pm 1  
     LWP/MemberMixin.pm 1  
     LWP/Protocol.pm 1  
     LWP/Protocol/data.pm 1  
     LWP/Protocol/file.pm 1  
     LWP/Protocol/ftp.pm 1  
     LWP/Protocol/gopher.pm 1  
     LWP/Protocol/http.pm 1  
     LWP/Protocol/https.pm 1  
     LWP/Protocol/mailto.pm 1  
     LWP/Protocol/nntp.pm 1  
     LWP/RobotUA.pm 1  
     LWP/Simple.pm 1  
     LWP/UserAgent.pm 1  
     MIME/Body.pm 1  
     MIME/Decoder.pm 1  
     MIME/Decoder/Base64.pm 1  
     MIME/Decoder/Binary.pm 1  
     MIME/Decoder/Gzip64.pm 1  
     MIME/Decoder/NBit.pm 1  
     MIME/Decoder/QuotedPrint.pm 1  
     MIME/Decoder/UU.pm 1  
     MIME/Entity.pm 1  
     MIME/Field/ConTraEnc.pm 1  
     MIME/Field/ContDisp.pm 1  
     MIME/Field/ContType.pm 1  
     MIME/Field/ParamVal.pm 1  
     MIME/Head.pm 1  
     MIME/Parser.pm 1  
     MIME/Parser/Filer.pm 1  
     MIME/Parser/Reader.pm 1  
     MIME/Parser/Results.pm 1  
     MIME/Tools.pm 1  
     MIME/Words.pm 1  
     Net/Cmd.pm 1  
     Net/Config.pm 1  
     Net/Domain.pm 1  
     Net/DummyInetd.pm 1  
     Net/FTP.pm 1  
     Net/FTP/A.pm 1  
     Net/FTP/E.pm 1  
     Net/FTP/I.pm 1  
     Net/FTP/L.pm 1  
     Net/FTP/dataconn.pm 1  
     Net/NNTP.pm 1  
     Net/Netrc.pm 1  
     Net/PH.pm 1  
     Net/POP3.pm 1  
     Net/SMTP.pm 1  
     Net/SNPP.pm 1  
     Net/Time.pm 1  
     Text/Query.pm 1  
     Text/Query/Advanced.pm 1  
     Text/Query/Build.pm 1  
     Text/Query/BuildAdvancedString.pm 1  
     Text/Query/BuildSimpleString.pm 1  
     Text/Query/Optimize.pm 1  
     Text/Query/Parse.pm 1  
     Text/Query/ParseAdvanced.pm 1  
     Text/Query/ParseSimple.pm 1  
     Text/Query/Simple.pm 1  
     Text/Query/Solve.pm 1  
     Text/Query/SolveAdvancedString.pm 1  
     Text/Query/SolveSimpleString.pm 1  
     URI.pm 1  
     URI/Escape.pm 1  
     URI/Heuristic.pm 1  
     URI/URL.pm 1  
     URI/WithBase.pm 1  
     URI/_foreign.pm 1  
     URI/_generic.pm 1  
     URI/_login.pm 1  
     URI/_query.pm 1  
     URI/_segment.pm 1  
     URI/_server.pm 1  
     URI/_userpass.pm 1  
     URI/data.pm 1  
     URI/file.pm 1  
     URI/file/Base.pm 1  
     URI/file/FAT.pm 1  
     URI/file/Mac.pm 1  
     URI/file/OS2.pm 1  
     URI/file/QNX.pm 1  
     URI/file/Unix.pm 1  
     URI/file/Win32.pm 1  
     URI/ftp.pm 1  
     URI/gopher.pm 1  
     URI/http.pm 1  
     URI/https.pm 1  
     URI/ldap.pm 1  
     URI/mailto.pm 1  
     URI/news.pm 1  
     URI/nntp.pm 1  
     URI/pop.pm 1  
     URI/rlogin.pm 1  
     URI/rsync.pm 1  
     URI/snews.pm 1  
     URI/telnet.pm 1  
     WWW/RobotRules.pm 1  
     WWW/RobotRules/AnyDBM_File.pm 1  
     Authen/Krb4.pm 1  
     Bundle/DBD/mysql.pm 1  
     Bundle/DBI.pm 1  
     Crypt/DES.pm 1  
     Crypt/IDEA.pm 1  
     DBD/ADO.pm 1  
     DBD/ExampleP.pm 1  
     DBD/Multiplex.pm 1  
     DBD/NullP.pm 1  
     DBD/Proxy.pm 1  
     DBD/Sponge.pm 1  
     DBD/mysql.pm 1  
     DBI.pm 1  
     DBI/DBD.pm 1  
     DBI/FAQ.pm 1  
     DBI/Format.pm 1  
     DBI/ProxyServer.pm 1  
     DBI/Shell.pm 1  
     DBI/W32ODBC.pm 1  
     Digest.pm 1  
     Digest/HMAC.pm 1  
     Digest/HMAC_MD5.pm 1  
     Digest/HMAC_SHA1.pm 1  
     Digest/MD2.pm 1  
     Digest/MD5.pm 1  
     Digest/SHA1.pm 1  
     HTML/Entities.pm 1  
     HTML/Filter.pm 1  
     HTML/HeadParser.pm 1  
     HTML/LinkExtor.pm 1  
     HTML/Parser.pm 1  
     HTML/TokeParser.pm 1  
     MIME/Base64.pm 1  
     MIME/QuotedPrint.pm 1  
     Math/Cephes.pm 1  
     Math/Cephes/Complex.pm 1  
     Math/Cephes/Fraction.pm 1  
     Mysql.pm 1  
     Mysql/Statement.pm 1  
     SHA.pm 1  
     Safe/Hole.pm 1  
     Win32/DBIODBC.pm 1  
     Algorithm/Diff.pm 1  
     Apache/Constants.pm 1  
     Apache/File.pm 1  
     capa.pm 1  
     CGI.pm 1  
     CGI/Cookie.pm 1  
     Crypt/DES.pm 1  
     DBI.pm 1  
     Fcntl.pm 1  
     File/Copy.pm 1  
     FileHandle.pm 1  
     GDBM_File.pm 1  
     HTML/TokeParser.pm 1  
     HTML/TreeBuilder.pm 1  
     HTTP/Headers.pm 1  
     IO/Socket.pm 1  
     LWP/UserAgent.pm 1  
     Math/Cephes.pm 1  
     Math/Random.pm 1  
     Opcode.pm 1  
     POSIX.pm 1  
     Safe.pm 1  
     Safe/Hole.pm 1  
     Socket.pm 1  
     strict.pm 1  
     Text/Query.pm 1  
     tth.pm 1  
     vars.pm 1  
     );  
   
 my $errorflag=0;  
 foreach my $dep (keys %dependencies) {  
     unless ($modules=~/$dep/) {  
  print "MISSING $dep\n";  
  $errorflag++;  
     }  
 }  
   
 unless ($errorflag) {  # ============================================= Read in cpan_distributions.txt.
     print "All perl modules needed by LON-CAPA appear to be present.\n";  
 }  # A brief description of CPAN (Comprehensive Perl Archive Network):
   # CPAN software is not released as separate perl modules.
   # CPAN software is released as "distributions" (also called "dists").
   # Each distribution consists of multiple perl modules.
   # For instance, the dist HTML-Tree (http://search.cpan.org/dist/HTML-Tree/)
   # consists of the modules HTML::AsSubs, HTML::Element, HTML::Element::traverse,
   # HTML::Parse, HTML::TreeBuilder, and HTML::Tree.
   # Most (but not all) distributions have versions which are defined
   # by one of their modules.  For the syntax of cpan_distributions.txt,
   # please read the comments inside cpan_distributions.txt.
   
   # Open cpan_distributions.txt.
   open(IN,'<cpan_distributions.txt') or
       die('**** ERROR **** Cannot find cpan_distributions.txt'."\n");
   
   while(<IN>) # Loop through the lines.
     {
       next if /^\#/; # Ignore commented lines.
       next unless /\S/; # Ignore blank lines.
   
       chomp; # Get rid of the newline at the end of the line.
   
       # Parse the line.
       my ($dist_name,$dist_dev_version,$dist_stable_version,$versionfrom_info) =
    split(/\s+/); # Parse apart the line fields.
       $versionfrom_info =~ /^(.*)\((.*)\)$/; # Parse apart the versionfrom info.
       my ($version_module,$version_match) = ($1,$2); # Parse vals into variables.
   
       # Calculate DevVersion and StableVersion for the VersionFrom module.
       my $module_dev_version;
       my $module_stable_version;
       if ($version_match eq "*") # There is a dist=module version relationship.
         {
    $module_dev_version = $dist_dev_version; # module=dist.
    $module_stable_version = $dist_stable_version; # module=dist.
         }
       else # There is not a dist=module version relationship.
         {
    ($module_dev_version,$module_stable_version) = 
       split(/\,/,$version_match); # module set to customized settings.
         }
   
       $dist_module_hash{$dist_name} = $version_module; # The big dist index.
   
       # What the module "looks like" on the filesystem.
       my $version_modulefs = $version_module;
       $version_modulefs =~ s!::!/!g; $version_modulefs.='.pm';
       $modulefs_hash{$version_module} = $version_modulefs;
   
       # Indexing the expected versions.
       $module_dev_version_hash{$version_module} = $module_dev_version;
       $module_stable_version_hash{$version_module} = $module_stable_version;
       $dist_dev_version_hash{$dist_name} = $dist_dev_version;
       $dist_stable_version_hash{$dist_name} = $dist_stable_version;
     }
   close(IN);
   
   # "MISSING"  means that no module is present inside the include path.
   # "OUTDATED" means that a module is present inside the include path but is
   #            an earlier version than expected.
   # "VERYOKAY" means that the module version is an exact match for the expected
   #            version.
   # "OKAY"     means that the module version is more recent than the expected
   #            version, so things are "probably" okay....  It is still possible
   #            that LON-CAPA is incompatible with the newer distribution version
   #            (corresponding to the module version).
   my @dev_missing;
   my @dev_outdated;
   my @dev_okay;
   my @dev_veryokay;
   my @stable_missing;
   my @stable_outdated;
   my @stable_okay;
   my @stable_veryokay;
   
   # ===== Loop through all of the needed CPAN distributions and probe the system.
   foreach my $dist (keys %dist_module_hash)
     {
       my $module = $dist_module_hash{$dist};
       my $fs = $modulefs_hash{$module};
       my $fsflag = 0;
       if ($big_module_string =~ /$fs/)
         {
           $fsflag = 1;
         }
       my ($vok,$vstr);
       ($vok,$vstr) = have_vers($module,$module_dev_version_hash{$module});
       # print "fsflag: $fsflag, vok: $vok, vstr: $vstr, fs: $fs\n";
       if ($fsflag and !$vok and $vstr=~/not found/)
         {
    push(@dev_missing,'MISSING  '.$dist.' (want distribution version '.
        $dist_dev_version_hash{$dist}.') ?'."\n");
    # The question mark indicates there was a pattern match in the
    # big_module_string which would be unexpected.
    # There is no usual reason to tell the normal LON-CAPA user about this
    # question mark.  This is just source code magic.
         }
       elsif (!$fsflag and !$vok and $vstr=~/not found/)
         {
    push(@dev_missing,'MISSING  '.$dist.' (want distribution version '.
        $dist_dev_version_hash{$dist}.')'."\n");
         }
       elsif ($fsflag and !$vok and $vstr!~/not found/)
         {
    push(@dev_outdated,'OUTDATED '.$dist.' wanted module: v'.
        $module_dev_version_hash{$module}.'; '.$vstr.' (VERSION_FROM is '.
        $fs.') want dist version '.$dist_dev_version_hash{$dist}.'.'.
        "\n");
         }
       elsif ($fsflag)
         {
    $vstr=~/found v(.*)/;
    my $vc=$1;
    if ($vc eq $module_dev_version_hash{$module})
             {
       push(@dev_veryokay,'VERYOKAY '.$dist.' wanted: v'.
    $module_dev_version_hash{$module}.'; '.$vstr.
    ' (VERSION_FROM is '.$fs.') want dist version '.
    $dist_dev_version_hash{$dist}."\n");
     }
    else
             {
       push(@dev_okay,'OKAY     '.$dist.' wanted: v'.
     $module_dev_version_hash{$module}.'; '.$vstr.
     ' (VERSION_FROM is '.$fs.').'."\n");
     }
         }
       ($vok,$vstr) = have_vers($module,$module_stable_version_hash{$module});
       if ($fsflag and !$vok and $vstr=~/not found/)
         {
    push(@stable_missing,'MISSING  '.$dist.' (want distribution version '.
        $dist_stable_version_hash{$dist}.') ?'."\n");
    # The question mark indicates there was a pattern match in the
    # big_module_string which would be unexpected.
    # There is no usual reason to tell the normal LON-CAPA user about this
    # question mark.  This is just source code magic.
         }
       elsif (!$fsflag and !$vok and $vstr=~/not found/)
         {
    push(@stable_missing,'MISSING  '.$dist.' (want distribution version '.
        $dist_stable_version_hash{$dist}.')'."\n");
         }
       elsif ($fsflag and !$vok and $vstr!~/not found/)
         {
    push(@stable_outdated,'OUTDATED '.$dist.' wanted module: v'.
        $module_stable_version_hash{$module}.'; '.$vstr.
        ' (VERSION_FROM is '.$fs.') want dist version '.
        $dist_stable_version_hash{$dist}.'.'."\n");
         }
       elsif ($fsflag)
         {
    $vstr=~/found v(.*)/;
    my $vc=$1;
    if ($vc eq $module_stable_version_hash{$module})
             {
       push(@stable_veryokay,'VERYOKAY '.$dist.' wanted: v'.
    $module_stable_version_hash{$module}.'; '.$vstr.
    ' (VERSION_FROM is '.$fs.') want dist version '.
    $dist_stable_version_hash{$dist}."\n");
     }
    else
             {
       push(@stable_okay,'OKAY     '.$dist.' wanted: v'.
     $module_stable_version_hash{$module}.'; '.$vstr.
     ' (VERSION_FROM is '.$fs.').'."\n");
     }
         }
     }
   
   print("\n".'SYNOPSIS'."\n");
   
   # ========================================================== The stable report.
   print('**** STABLE REPORT (what a production server should worry about)'."\n");
   if (@stable_missing)
     {
       print('There are '.scalar(@stable_missing).' CPAN distributions missing '.
     'from this LON-CAPA system.'."\n");
     }
   else
     {
       print('All perl modules needed by LON-CAPA appear to be present.'."\n");
     }
   if (@stable_outdated)
     {
       print(scalar(@stable_outdated).' CPAN distributions are out-dated '.
     'on this LON-CAPA system.'."\n");
     }
   if (@stable_veryokay)
     {
       print(scalar(@stable_veryokay).' CPAN distributions are an exact match '.
     '(based on version number).'."\n");
   #    print @stable_veryokay;
     }
   if (@stable_okay)
     {
       print(scalar(@stable_okay).' CPAN dists have a version number '.
     'higher than expected'.
     ' (probably okay).'. "\n");
     }
   print("\n");
   
   # ===================================================== The development report.
   print('**** DEVELOPMENT REPORT (do not worry about this unless you are a'.
         ' coder)'."\n");
   if (@dev_missing)
     {
       print('There are '.scalar(@dev_missing).' CPAN distributions missing '.
     'from this LON-CAPA system.'."\n");
     }
   else
     {
       print('All perl modules needed by LON-CAPA appear to be present.'."\n");
     }
   if (@dev_outdated)
     {
       print(scalar(@dev_outdated).' CPAN distributions are out-dated '.
     'on this LON-CAPA system.'."\n");
     }
   if (@dev_veryokay)
     {
       print(scalar(@dev_veryokay).' CPAN distributions are an exact match '.
     '(based on version number).'."\n");
   #    print @dev_veryokay;
     }
   if (@dev_okay)
     {
       print(scalar(@stable_okay).' CPAN dists have a version number '.
     'higher than expected'.
     ' (probably okay).'. "\n");
     }
   
   my $detailstream;
   if ($mode eq 'synopsis')
     {
       print("\n".'**** NOTE ****'."\n".
     'After everything completes, please view the CPAN_STATUS_REPORT'.
     ' file for more '."\n".'information on resolving your perl modules.'.
     "\n");
   
       print('* HIT RETURN WHEN READY TO CONTINUE *'."\n");
       my $returnkey=<>;
       open(OUT,'>CPAN_STATUS_REPORT');
       $detailstream=\*OUT;
     }
   else
     {
       $detailstream=\*STDOUT;
     }
   print($detailstream 
         "\n".'DETAILED STATUS REPORT'."\n"); # Header of status report.
   
   # Print advisory notices.
   print($detailstream
         "\n".'(Consult loncapa/doc/otherfiles/perl_modules.txt for '.
         'information on'."\n".
         ' manual build instructions.)'."\n");
   print($detailstream
         "\n".'(**** IMPORTANT NOTICE **** HTML-Parser needs to be patched '.
         "\n".' as described in loncapa/doc/otherfiles/perl_modules.txt)'.
         "\n");
   
   print($detailstream
         "\n".'For manual installation of CPAN distributions, visit'."\n".
         'http://search.cpan.org/dist/DistName'."\n".
         'where DistName is something like "HTML-Parser" or "libwww-perl".'.
         "\n");
   
   print($detailstream
         "\n".'For automatic installation of CPAN distributions, visit'."\n".
         'http://install.lon-capa.org/resources/cpanauto/DistName.bin'."\n".
         'where DistName.bin is something like "HTML-Parser.bin" or '.
         '"libwww-perl.bin".'."\n");
   
   # Print detailed report of stable.
   print($detailstream
         "\n".'STABLE (DETAILED REPORT)'."\n");
   print $detailstream @stable_missing;
   print $detailstream @stable_outdated;
   print $detailstream @stable_veryokay;
   print $detailstream @stable_okay;
   print($detailstream "\n".'DEVELOPMENT (DETAILED REPORT)'."\n");
   print $detailstream @dev_missing;
   print $detailstream @dev_outdated;
   print $detailstream @dev_veryokay;
   print $detailstream @dev_okay;
   
   if ($mode eq "html")
     {
       print(<<END);
   </pre>
   </body>
   </html>
   END
     }
   
   # ================================================================ Subroutines.
   # Note that "vers_cmp" and "have_vers" are adapted from a bugzilla version 2.16
   # "checksetup.pl" script.
   
   # ------------ vers_cmp : compare two version numbers and see which is greater.
   # vers_cmp is adapted from Sort::Versions 1.3 1996/07/11 13:37:00 kjahds,
   # which is not included with Perl by default, hence the need to copy it here.
   # Seems silly to require it when this is the only place we need it...
   sub vers_cmp
     {
       if (@_ < 2) { die "not enough parameters for vers_cmp" }
       if (@_ > 2) { die "too many parameters for vers_cmp" }
       my ($a, $b) = @_;
       my (@A) = ($a =~ /(\.|\d+|[^\.\d]+)/g);
       my (@B) = ($b =~ /(\.|\d+|[^\.\d]+)/g);
       my ($A,$B);
       while (@A and @B)
         {
           $A = shift @A;
           $B = shift @B;
           if ($A eq "." and $B eq ".")
             {
               next;
             }
           elsif ( $A eq "." )
             {
               return -1;
             }
           elsif ( $B eq "." )
             {
               return 1;
             }
           elsif ($A =~ /^\d+$/ and $B =~ /^\d+$/)
             {
               return $A <=> $B if $A <=> $B;
             }
           else
             {
               $A = uc $A;
               $B = uc $B;
               return $A cmp $B if $A cmp $B;
             }
         }
       @A <=> @B;
     }
   
   # --------------- have_vers: syntax check the version number and call vers_cmp.
   # This was originally clipped from the libnet Makefile.PL, adapted here to
   # use the above vers_cmp routine for accurate version checking.
   sub have_vers
     {
       my ($pkg, $wanted) = @_;
       my ($msg, $vnum, $vstr);
       no strict 'refs';
       # printf("Checking for %15s %-9s ", $pkg, !$wanted?'(any)':"(v$wanted)");
   
       eval { my $p; ($p = $pkg . ".pm") =~ s!::!/!g; require $p; };
   
       $vnum = ${"${pkg}::VERSION"} || ${"${pkg}::Version"} || 0;
       $vnum = -1 if $@;
   
       if ($vnum eq "-1") # string compare just in case it's non-numeric
         {
           $vstr = "not found";
         }
       elsif (vers_cmp($vnum,"0") > -1)
         {
           $vstr = "found v$vnum";
         }
       else
         {
           $vstr = "found unknown version";
         }
   
 exit $errorflag;      my $vok = (vers_cmp($vnum,$wanted) > -1);
       # print ((($vok) ? "ok: " : " "), "$vstr\n");
       return ($vok,$vstr);
     }

Removed from v.1.2  
changed lines
  Added in v.1.9


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>