Diff for /loncom/loncron between versions 1.108 and 1.127

version 1.108, 2018/08/08 11:49:48 version 1.127, 2021/02/02 20:53:05
Line 34  use lib '/home/httpd/lib/perl/'; Line 34  use lib '/home/httpd/lib/perl/';
 use LONCAPA::Configuration;  use LONCAPA::Configuration;
 use LONCAPA::Checksumming;  use LONCAPA::Checksumming;
 use LONCAPA;  use LONCAPA;
   use LONCAPA::LWPReq;
 use Apache::lonnet;  use Apache::lonnet;
 use Apache::loncommon;  use Apache::loncommon;
   
Line 43  use HTML::Entities; Line 44  use HTML::Entities;
 use Getopt::Long;  use Getopt::Long;
 use GDBM_File;  use GDBM_File;
 use Storable qw(thaw);  use Storable qw(thaw);
   use File::ReadBackwards;
   use File::Copy;
   use GDBM_File qw(GDBM_READER);
   use Storable qw(thaw nfreeze);
   use Sys::Hostname::FQDN();
   
 #globals  #globals
 use vars qw (%perlvar %simplestatus $errors $warnings $notices $totalcount);  use vars qw (%perlvar %simplestatus $errors $warnings $notices $totalcount);
   
Line 75  sub rotate_logfile { Line 82  sub rotate_logfile {
  rename("$file.2","$file.3");   rename("$file.2","$file.3");
  rename("$file.1","$file.2");   rename("$file.1","$file.2");
  rename("$file","$file.1");   rename("$file","$file.1");
     }       }
 }  }
   
 sub start_daemon {  sub start_daemon {
     my ($fh,$daemon,$pidfile,$args) = @_;      my ($fh,$daemon,$pidfile,$args) = @_;
     my $progname=$daemon;      my $progname=$daemon;
     if ($daemon eq 'lonc') {      if ($daemon eq 'lonc') {
  $progname='loncnew';    $progname='loncnew';
     }      }
     my $error_fname="$perlvar{'lonDaemons'}/logs/${daemon}_errors";      my $error_fname="$perlvar{'lonDaemons'}/logs/${daemon}_errors";
     &rotate_logfile($error_fname,$fh,'error logs');      &rotate_logfile($error_fname,$fh,'error logs');
Line 113  sub checkon_daemon { Line 120  sub checkon_daemon {
     my $result;      my $result;
     &log($fh,'<hr /><a name="'.$daemon.'" /><h2>'.$daemon.'</h2><h3>Log</h3><p style="white-space: pre;"><tt>');      &log($fh,'<hr /><a name="'.$daemon.'" /><h2>'.$daemon.'</h2><h3>Log</h3><p style="white-space: pre;"><tt>');
     printf("%-15s ",$daemon);      printf("%-15s ",$daemon);
     if (-e "$perlvar{'lonDaemons'}/logs/$daemon.log"){      if ($fh) {
  open (DFH,"tail -n25 $perlvar{'lonDaemons'}/logs/$daemon.log|");          if (-e "$perlvar{'lonDaemons'}/logs/$daemon.log"){
  while (my $line=<DFH>) {       if (open(DFH,"tail -n25 $perlvar{'lonDaemons'}/logs/$daemon.log|")) {
     &log($fh,"$line");          while (my $line=<DFH>) {
     if ($line=~/INFO/) { $notices++; }              &log($fh,"$line");
     if ($line=~/WARNING/) { $notices++; }              if ($line=~/INFO/) { $notices++; }
     if ($line=~/CRITICAL/) { $warnings++; }              if ($line=~/WARNING/) { $notices++; }
  };              if ($line=~/CRITICAL/) { $warnings++; }
  close (DFH);          }
           close (DFH);
               }
           }
           &log($fh,"</tt></p>");
     }      }
     &log($fh,"</tt></p>");  
       
     my $pidfile="$perlvar{'lonDaemons'}/logs/$daemon.pid";      my $pidfile="$perlvar{'lonDaemons'}/logs/$daemon.pid";
        
     my $restartflag=1;      my $restartflag=1;
     my $daemonpid;      my $daemonpid;
     if (-e $pidfile) {      if (-e $pidfile) {
Line 169  sub checkon_daemon { Line 179  sub checkon_daemon {
             &clean_lonc_childpids();              &clean_lonc_childpids();
         }          }
  &log($fh,"<h3>$daemon not running, trying to start</h3>");   &log($fh,"<h3>$daemon not running, trying to start</h3>");
   
  if (&start_daemon($fh,$daemon,$pidfile,$args)) {   if (&start_daemon($fh,$daemon,$pidfile,$args)) {
     &log($fh,"<h3>$daemon at pid $daemonpid responding</h3>");      &log($fh,"<h3>$daemon at pid $daemonpid responding</h3>");
     $simplestatus{$daemon}='restarted';      $simplestatus{$daemon}='restarted';
Line 194  sub checkon_daemon { Line 204  sub checkon_daemon {
  &log($fh,"<p>Unable to start $daemon</p>");   &log($fh,"<p>Unable to start $daemon</p>");
     }      }
  }   }
           if ($fh) {
  if (-e "$perlvar{'lonDaemons'}/logs/$daemon.log"){      if (-e "$perlvar{'lonDaemons'}/logs/$daemon.log"){
     &log($fh,"<p><pre>");          &log($fh,"<p><pre>");
     open (DFH,"tail -n100 $perlvar{'lonDaemons'}/logs/$daemon.log|");          if (open(DFH,"tail -n100 $perlvar{'lonDaemons'}/logs/$daemon.log|")) {
     while (my $line=<DFH>) {               while (my $line=<DFH>) { 
  &log($fh,"$line");          &log($fh,"$line");
  if ($line=~/WARNING/) { $notices++; }          if ($line=~/WARNING/) { $notices++; }
  if ($line=~/CRITICAL/) { $notices++; }          if ($line=~/CRITICAL/) { $notices++; }
     };              }
     close (DFH);              close (DFH);
     &log($fh,"</pre></p>");                  }
           &log($fh,"</pre></p>");
               }
  }   }
     }      }
       
     my $fname="$perlvar{'lonDaemons'}/logs/$daemon.log";      my $fname="$perlvar{'lonDaemons'}/logs/$daemon.log";
     &rotate_logfile($fname,$fh,'logs');      &rotate_logfile($fname,$fh,'logs');
   
Line 220  sub log_machine_info { Line 232  sub log_machine_info {
     my ($fh)=@_;      my ($fh)=@_;
     &log($fh,'<hr /><a name="machine" /><h2>Machine Information</h2>');      &log($fh,'<hr /><a name="machine" /><h2>Machine Information</h2>');
     &log($fh,"<h3>loadavg</h3>");      &log($fh,"<h3>loadavg</h3>");
   
       my $cpucount;
       if (open(PIPE,"lscpu |grep '^CPU(s)' 2>&1 |")) {
           my $info = <PIPE>;
           chomp($info);
           ($cpucount) = ($info =~ /^\QCPU(s):\E\s+(\d+)$/);
           close(PIPE);
       }
       if (!$cpucount) {
           $cpucount = 1;
       }
       my %loadtarget = (
                           error => 4.0*$cpucount,
                           warn  => 2.0*$cpucount,
                           note  => 1.0*$cpucount,
                        );
     open (LOADAVGH,"/proc/loadavg");      open (LOADAVGH,"/proc/loadavg");
     my $loadavg=<LOADAVGH>;      my $loadavg=<LOADAVGH>;
     close (LOADAVGH);      close (LOADAVGH);
        
     &log($fh,"<tt>$loadavg</tt>");      &log($fh,"<tt>$loadavg</tt>");
       
     my @parts=split(/\s+/,$loadavg);      my @parts=split(/\s+/,$loadavg);
     if ($parts[1]>4.0) {      if ($parts[1]>$loadtarget{'error'}) {
  $errors++;   $errors++;
     } elsif ($parts[1]>2.0) {      } elsif ($parts[1]>$loadtarget{'warn'}) {
  $warnings++;   $warnings++;
     } elsif ($parts[1]>1.0) {      } elsif ($parts[1]>$loadtarget{'note'}) {
  $notices++;   $notices++;
     }      }
   
Line 240  sub log_machine_info { Line 267  sub log_machine_info {
     &log($fh,"<pre>");      &log($fh,"<pre>");
   
     open (DFH,"df|");      open (DFH,"df|");
     while (my $line=<DFH>) {       while (my $line=<DFH>) {
  &log($fh,&encode_entities($line,'<>&"'));    &log($fh,&encode_entities($line,'<>&"'));
  @parts=split(/\s+/,$line);   @parts=split(/\s+/,$line);
  my $usage=$parts[4];   my $usage=$parts[4];
  $usage=~s/\W//g;   $usage=~s/\W//g;
  if ($usage>90) {    if ($usage>90) {
     $warnings++;      $warnings++;
     $notices++;       $notices++;
  } elsif ($usage>80) {   } elsif ($usage>80) {
     $warnings++;      $warnings++;
  } elsif ($usage>60) {   } elsif ($usage>60) {
Line 264  sub log_machine_info { Line 291  sub log_machine_info {
     my $psproc=0;      my $psproc=0;
   
     open (PSH,"ps aux --cols 140 |");      open (PSH,"ps aux --cols 140 |");
     while (my $line=<PSH>) {       while (my $line=<PSH>) {
  &log($fh,&encode_entities($line,'<>&"'));    &log($fh,&encode_entities($line,'<>&"'));
  $psproc++;   $psproc++;
     }      }
     close (PSH);      close (PSH);
Line 287  sub start_logging { Line 314  sub start_logging {
     my %simplestatus=();      my %simplestatus=();
     my $now=time;      my $now=time;
     my $date=localtime($now);      my $date=localtime($now);
        
   
     &log($fh,(<<ENDHEADERS));      &log($fh,(<<ENDHEADERS));
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
Line 403  sub recursive_clean_tmp { Line 430  sub recursive_clean_tmp {
                 ($cleaned,$old,$removed) =                   ($cleaned,$old,$removed) = 
                      &recursive_clean_tmp($innerdir,$cleaned,$old,$removed,$errors);                       &recursive_clean_tmp($innerdir,$cleaned,$old,$removed,$errors);
                 my @doms = &Apache::lonnet::current_machine_domains();                  my @doms = &Apache::lonnet::current_machine_domains();
                   
                 if (open(my $dirhandle,$fname)) {                  if (open(my $dirhandle,$fname)) {
                     unless (($innerdir eq 'helprequests') ||                      unless (($innerdir eq 'helprequests') ||
                             (($innerdir =~ /^addcourse/) && ($innerdir !~ m{/\d+$}))) {                              (($innerdir =~ /^addcourse/) && ($innerdir !~ m{/\d+$}))) {
                         my @contents = grep {!/^\.\.?$/} readdir($dirhandle);                          my @contents = grep {!/^\.\.?$/} readdir($dirhandle);
                                       join('&&',@contents)."\n";                                            join('&&',@contents)."\n";
                         if (scalar(grep {!/^\.\.?$/} readdir($dirhandle)) == 0) {                          if (scalar(grep {!/^\.\.?$/} readdir($dirhandle)) == 0) {
                             closedir($dirhandle);                              closedir($dirhandle);
                             if ($fname =~ m{^\Q$perlvar{'lonDaemons'}\E/tmp/}) {                              if ($fname =~ m{^\Q$perlvar{'lonDaemons'}\E/tmp/}) {
Line 461  sub recursive_clean_tmp { Line 488  sub recursive_clean_tmp {
                                 }                                  }
                             }                              }
                         } elsif (ref($errors->{failopen}) eq 'ARRAY') {                          } elsif (ref($errors->{failopen}) eq 'ARRAY') {
                             push(@{$errors->{failopen}},$fname);                               push(@{$errors->{failopen}},$fname);
                         }                          }
                     } else {                      } else {
                         if (unlink($fname)) {                          if (unlink($fname)) {
Line 487  sub clean_lonIDs { Line 514  sub clean_lonIDs {
     my $cleaned=0;      my $cleaned=0;
     my $active=0;      my $active=0;
     while (my $fname=<$perlvar{'lonIDsDir'}/*>) {      while (my $fname=<$perlvar{'lonIDsDir'}/*>) {
  my ($dev,$ino,$mode,$nlink,          my $now=time;
     $uid,$gid,$rdev,$size,          if (-l $fname) {
     $atime,$mtime,$ctime,              my $linkfname = readlink($fname);
     $blksize,$blocks)=stat($fname);              if (-f $linkfname) {
  my $now=time;                  if ($linkfname =~ m{^$perlvar{'lonIDsDir'}/[^/]+\.id$}) {
  my $since=$now-$mtime;                      my @data = stat($linkfname);
  if ($since>$perlvar{'lonExpire'}) {                      my $mtime = $data[9];
     $cleaned++;                      my $since=$now-$mtime;
     &log($fh,"Unlinking $fname<br />");                      if ($since>$perlvar{'lonExpire'}) {
     unlink("$fname");                          if (unlink($linkfname)) {
  } else {                              $cleaned++;
     $active++;                              &log($fh,"Unlinking $linkfname<br />");
  }                              unlink($fname);
                           }
                       }
                   }
               } else {
                  unlink($fname);
               }
           } elsif (-f $fname) {
               my @data = stat($fname);
               my $mtime = $data[9];
               my $since=$now-$mtime;
               if ($since>$perlvar{'lonExpire'}) {
                   if (unlink($fname)) {
                       $cleaned++;
                       &log($fh,"Unlinking $fname<br />");
                   }
               } else {
                   $active++;
               }
           }
     }      }
     &log($fh,"<p>Cleaned up ".$cleaned." stale session token(s).</p>");      &log($fh,"<p>Cleaned up ".$cleaned." stale session token(s).</p>");
     &log($fh,"<h3>$active open session(s)</h3>");      &log($fh,"<h3>$active open session(s)</h3>");
 }  }
   
   # -------------------------------------------------------- clean out balanceIDs
   
   sub clean_balanceIDs {
       my ($fh)=@_;
       &log($fh,'<hr /><a name="balcookies" /><h2>Session Tokens</h2>');
       my $cleaned=0;
       my $active=0;
       if (-d $perlvar{'lonBalanceDir'}) {
           while (my $fname=<$perlvar{'lonBalanceDir'}/*.id>) {
               my ($dev,$ino,$mode,$nlink,
                   $uid,$gid,$rdev,$size,
                   $atime,$mtime,$ctime,
                   $blksize,$blocks)=stat($fname);
               my $now=time;
               my $since=$now-$mtime;
               if ($since>$perlvar{'lonExpire'}) {
                   $cleaned++;
                   &log($fh,"Unlinking $fname<br />");
                   unlink("$fname");
               } else {
                   $active++;
               }
           }
       }
       &log($fh,"<p>Cleaned up ".$cleaned." stale balancer files</p>");
       &log($fh,"<h3>$active unexpired balancer files</h3>");
   }
   
 # ------------------------------------------------ clean out webDAV Session IDs  # ------------------------------------------------ clean out webDAV Session IDs
 sub clean_webDAV_sessionIDs {  sub clean_webDAV_sessionIDs {
     my ($fh)=@_;      my ($fh)=@_;
Line 531  sub clean_webDAV_sessionIDs { Line 605  sub clean_webDAV_sessionIDs {
     }      }
 }  }
   
   # ------------------------------------------------------------ clean out ltiIDs
   
   sub clean_ltiIDs {
       my ($fh)=@_;
       &log($fh,'<hr /><a name="ltisessions" /><h2>LTI Session Pointers</h2>');
       my $cleaned=0;
       my $active=0;
       if (-d $perlvar{'ltiIDsDir'}) {
           while (my $fname=<$perlvar{'ltiIDsDir'}/*>) {
               my ($dev,$ino,$mode,$nlink,
                   $uid,$gid,$rdev,$size,
                   $atime,$mtime,$ctime,
                   $blksize,$blocks)=stat($fname);
               my $now=time;
               my $since=$now-$mtime;
               if ($since>$perlvar{'lonExpire'}) {
                   $cleaned++;
                   &log($fh,"Unlinking $fname<br />");
                   unlink("$fname");
               } else {
                   $active++;
               }
           }
       }
       &log($fh,"<p>Cleaned up ".$cleaned." old LTI session pointers.</p>");
       &log($fh,"<h3>$active unexpired LTI session pointers</h3>");
   }
   
 # ----------------------------------------------------------- clean out sockets  # ----------------------------------------------------------- clean out sockets
 sub clean_sockets {  sub clean_sockets {
     my ($fh)=@_;      my ($fh)=@_;
Line 568  sub rotate_lonnet_logs { Line 670  sub rotate_lonnet_logs {
     print "Checking logs.\n";      print "Checking logs.\n";
     if (-e "$perlvar{'lonDaemons'}/logs/lonnet.log"){      if (-e "$perlvar{'lonDaemons'}/logs/lonnet.log"){
  open (DFH,"tail -n50 $perlvar{'lonDaemons'}/logs/lonnet.log|");   open (DFH,"tail -n50 $perlvar{'lonDaemons'}/logs/lonnet.log|");
  while (my $line=<DFH>) {    while (my $line=<DFH>) {
     &log($fh,&encode_entities($line,'<>&"'));      &log($fh,&encode_entities($line,'<>&"'));
  }   }
  close (DFH);   close (DFH);
     }      }
     &log($fh,"</pre><h3>Perm Log</h3><pre>");      &log($fh,"</pre><h3>Perm Log</h3><pre>");
       
     if (-e "$perlvar{'lonDaemons'}/logs/lonnet.perm.log") {      if (-e "$perlvar{'lonDaemons'}/logs/lonnet.perm.log") {
  open(DFH,"tail -n10 $perlvar{'lonDaemons'}/logs/lonnet.perm.log|");   open(DFH,"tail -n10 $perlvar{'lonDaemons'}/logs/lonnet.perm.log|");
  while (my $line=<DFH>) {    while (my $line=<DFH>) {
     &log($fh,&encode_entities($line,'<>&"'));      &log($fh,&encode_entities($line,'<>&"'));
  }   }
  close (DFH);   close (DFH);
Line 641  sub test_connections { Line 743  sub test_connections {
   
 # ------------------------------------------------------------ Delayed messages  # ------------------------------------------------------------ Delayed messages
 sub check_delayed_msg {  sub check_delayed_msg {
     my ($fh)=@_;      my ($fh,$weightsref,$exclusionsref)=@_;
     &log($fh,'<hr /><a name="delayed" /><h2>Delayed Messages</h2>');      &log($fh,'<hr /><a name="delayed" /><h2>Delayed Messages</h2>');
     print "Checking buffers.\n";      print "Checking buffers.\n";
           
     &log($fh,'<h3>Scanning Permanent Log</h3>');      &log($fh,'<h3>Scanning Permanent Log</h3>');
   
     my $unsend=0;      my $unsend=0;
       my $ignored=0;
   
     my %hostname = &Apache::lonnet::all_hostnames();      my %hostname = &Apache::lonnet::all_hostnames();
     my $numhosts = scalar(keys(%hostname));      my $numhosts = scalar(keys(%hostname));
       my $checkbackwards = 0;
     my $dfh=IO::File->new("$perlvar{'lonDaemons'}/logs/lonnet.perm.log");      my $checkfrom = 0;
     while (my $line=<$dfh>) {      my $checkexcluded = 0;
  my ($time,$sdf,$dserv,$dcmd)=split(/:/,$line);      my (%bymachine,%weights,%exclusions,%serverhomes);
         if ($numhosts) {      if (ref($weightsref) eq 'HASH') {
             next unless ($hostname{$dserv});          %weights = %{$weightsref};
         }      }
  if ($sdf eq 'F') {       if (ref($exclusionsref) eq 'HASH') {
     my $local=localtime($time);          %exclusions = %{$exclusionsref};
     &log($fh,"<b>Failed: $time, $dserv, $dcmd</b><br />");          if (keys(%exclusions)) {
     $warnings++;              $checkexcluded = 1;
  }              %serverhomes = &read_serverhomeIDs();
  if ($sdf eq 'S') { $unsend--; }          }
  if ($sdf eq 'D') { $unsend++; }  
     }      }
   
     &log($fh,"<p>Total unsend messages: <b>$unsend</b></p>\n");  #
     if ($unsend > 0) {  # For LON-CAPA 1.2.0 to 2.1.3 (release dates: 8/31/2004 and 3/31/2006) any
         $warnings=$warnings+5*$unsend;  # entry logged in lonnet.perm.log for completion of a delayed (critical)
   # transaction lacked the hostID for the remote node to which the command
   # to be completed was sent.
   #
   # Because of this, exclusion of items in lonnet.perm.log for nodes which are
   # no longer part of the cluster from adding to the overall "unsend" count
   # needs additional effort besides the changes made in loncron rev. 1.105.
   #
   # For "S" (completion) events logging in LON-CAPA 1.2.0 through 2.1.3 included
   # "LondTransaction=HASH(hexadecimal)->getClient() :$cmd, where the hexadecimal
   # is a memory location, and $cmd is the command sent to the remote node.
   #
   # Starting with 2.2.0 (released 8/21/2006) logging for "S" (completion) events
   # had sethost:$host_id:$cmd after LondTransaction=HASH(hexadecimal)->getClient()
   #
   # Starting with 2.4.1 (released 6/13/2007) logging for "S" replaced echoing the
   # getClient() call with the result of the Transaction->getClient() call itself
   # undef for completion of delivery of a delayed message.
   #
   # The net effect of these changes is that lonnet.perm.log is now accessed three
   # times: (a) oldest record is checked, if earlier than release date for 2.5.0
   # then (b) file is read backwards, with timestamp recorded for most recent
   # instance of logged "S" event for "update" command without "sethost:$host_id:"
   # then (c) file is read forward with records ignored which predate the timestamp
   # recorded in (b), if one was found.
   #
   # In (c), when calculating the unsend total, i.e., the difference between delayed
   # transactions ("D") and sent transactions ("S"), transactions are ignored if the
   # target node is no longer in the cluster, and also (for "update" commands), if
   # the target node is in the list of nodes excluded from the count, in the domain
   # configuration for this machine's default domain.  The idea here is to remove
   # delayed "update" commands for nodes for which inbound access to port 5663,
   # is blocked, but are still part of the LON-CAPA network, (i.e., they can still
   # replicate content from other nodes).
   #
   
       my $dfh=IO::File->new("$perlvar{'lonDaemons'}/logs/lonnet.perm.log","r");
       if (defined($dfh)) {
           while (my $line=<$dfh>) {
               my ($time,$sdf,$rest)=split(/:/,$line,3);
               if ($time < 1541185772) {
                   $checkbackwards = 1;
               }
               last;
           }
           undef $dfh;
       } 
   
       if ($checkbackwards) {
           if (tie *BW, 'File::ReadBackwards', "$perlvar{'lonDaemons'}/logs/lonnet.perm.log") {
               while(my $line=<BW>) {
                   if ($line =~ /\QLondTransaction=HASH\E[^:]+:update:/) {
                       ($checkfrom) = split(/:/,$line,2);
                       last;
                   }
               }
               close(BW);
           }
       }
       $dfh=IO::File->new("$perlvar{'lonDaemons'}/logs/lonnet.perm.log","r");
       if (defined($dfh)) {
           while (my $line=<$dfh>) {
               my ($time,$sdf,$rest)=split(/:/,$line,3);
               next unless (($sdf eq 'F') || ($sdf eq 'S') || ($sdf eq 'D'));
               next if (($checkfrom) && ($time <= $checkfrom));
               my ($dserv,$dcmd);
               if ($sdf eq 'S') {
                   my ($serva,$cmda,$servb,$cmdb) = split(/:/,$rest);
                   if ($cmda eq 'sethost') {
                       chomp($cmdb);
                       $dcmd = $cmdb;
                   } else {
                       $dcmd = $cmda;
                   }
                   if (($serva =~ /^LondTransaction/) || ($serva eq '')) {
                       unless (($servb eq '') || ($servb =~ m{^/})) {
                           $dserv = $servb;
                       }
                   } else {
                       $dserv = $serva;
                   }
               } else {
                   ($dserv,$dcmd) = split(/:/,$rest);
               }
               if ($sdf eq 'F') {
                   my $local=localtime($time);
                   &log($fh,"<b>Failed: $time, $dserv, $dcmd</b><br />");
                   $warnings++;
               }
               next if ((($dserv eq '') || ($dcmd eq '')) && ($sdf ne 'F'));
               if ($sdf eq 'S') {
                   if ($dcmd eq 'update') {
                       if ($hostname{$dserv}) {
                           if ($exclusions{$serverhomes{$hostname{$dserv}}}) {
                               $ignored --;
                           } else {
                               $unsend --;
                           }
                       }
                       if (exists($bymachine{$dserv})) {
                           $bymachine{$dserv} --;
                       } else {
                           $bymachine{$dserv} = -1;
                       }
                   } else {
                       if ($hostname{$dserv}) {
                           $unsend --;
                       }
                   }
               } elsif ($sdf eq 'D') {
                   if ($dcmd eq 'update') {
                       if ($hostname{$dserv}) {
                           if ($exclusions{$serverhomes{$hostname{$dserv}}}) {
                               $ignored ++;
                           } else {
                               $unsend ++;
                           }
                       }
                       if (exists($bymachine{$dserv})) {
                           $bymachine{$dserv} ++;
                       } else {
                           $bymachine{$dserv} = 1;
                       }
                   } else {
                       if ($hostname{$dserv}) {
                           $unsend ++;
                       }
                   }
               }
           }
           undef $dfh;
           my $nodest = 0;
           my $retired = 0;
           my %active;
           if (keys(%bymachine)) {
               unless ($checkexcluded) {
                   %serverhomes = &read_serverhomeIDs();
               }
               foreach my $key (keys(%bymachine)) {
                   if ($bymachine{$key} > 0) {
                       if ($hostname{$key}) {
                           $active{$serverhomes{$hostname{$key}}} += $bymachine{$key};
                       } else {
                           $retired ++;
                           $nodest += $bymachine{$key};
                       }
                   }
               }
           }
           if (keys(%active)) {
               &log($fh,"<p>Unsend messages by node, active (undegraded) nodes in cluster</p>\n");
               foreach my $key (sort(keys(%active))) {
                   &log($fh,&encode_entities("$key => $active{$key}",'<>&"')."\n");
               }
           }
           &log($fh,"<p>Total unsend messages: <b>$unsend</b> for ".scalar(keys(%active))." active (undegraded) nodes in cluster.</p>\n");
           if (keys(%exclusions) > 0) {
               &log($fh,"<p>Total incomplete updates <b>$ignored</b> for ".scalar(keys(%exclusions))." degraded nodes in cluster.</p>\n");
           }
           if ($retired) {
               &log($fh,"<p>Total unsent <b>$nodest</b> for $retired nodes no longer in cluster.</p>\n");
           }
           if ($unsend > 0) {
               $warnings=$warnings+$weights{'U'}*$unsend;
           }
     }      }
   
     if ($unsend) { $simplestatus{'unsend'}=$unsend; }      if ($unsend) { $simplestatus{'unsend'}=$unsend; }
Line 708  sub check_delayed_msg { Line 974  sub check_delayed_msg {
 }  }
   
 sub finish_logging {  sub finish_logging {
     my ($fh)=@_;      my ($fh,$weightsref)=@_;
       my %weights;
       if (ref($weightsref) eq 'HASH') {
           %weights = %{$weightsref};
       }
     &log($fh,"<a name='errcount' />\n");      &log($fh,"<a name='errcount' />\n");
     $totalcount=$notices+4*$warnings+100*$errors;      $totalcount=($weights{'N'}*$notices)+($weights{'W'}*$warnings)+($weights{'E'}*$errors);
     &errout($fh);      &errout($fh);
     &log($fh,"<h1>Total Error Count: $totalcount</h1>");      &log($fh,"<h1>Total Error Count: $totalcount</h1>");
     my $now=time;      my $now=time;
Line 779  sub write_serverhomeIDs { Line 1049  sub write_serverhomeIDs {
                 eval {                  eval {
                     local $SIG{ ALRM } = sub { die "TIMEOUT" };                      local $SIG{ ALRM } = sub { die "TIMEOUT" };
                     alarm(10);                      alarm(10);
                     $serverhomeID =                       $serverhomeID =
                         &Apache::lonnet::get_server_homeID($name,1,'loncron');                          &Apache::lonnet::get_server_homeID($name,1,'loncron');
                     alarm(0);                      alarm(0);
                 };                  };
Line 824  sub write_checksums { Line 1094  sub write_checksums {
     return;      return;
 }  }
   
   sub write_hostips {
       my $lontabdir = $perlvar{'lonTabDir'};
       my $defdom = $perlvar{'lonDefDomain'};
       my $lonhost = $perlvar{'lonHostID'};
       my $newfile = "$lontabdir/currhostips.tab";
       my $oldfile = "$lontabdir/prevhostips.tab";
       my (%prevhosts,%currhosts,%ipchange);
       if ((-e $newfile) && (-s $newfile)) {
           move($newfile,$oldfile);
           chmod(0644,$oldfile);
           if (open(my $fh,'<',$oldfile)) {
               while (my $line=<$fh>) {
                   chomp($line);
                   if ($line =~ /^([^:]+):([\d.]+)$/) {
                       $prevhosts{$1} = $2;
                   }
               }
               close($fh);
           }
       }
       my ($ip_info,$cached) =
           &Apache::lonnet::is_cached_new('iphost','iphost');
       if (!$cached) {
           &Apache::lonnet::get_iphost();
           ($ip_info,$cached) =
           &Apache::lonnet::is_cached_new('iphost','iphost');
       }
       if (ref($ip_info) eq 'ARRAY') {
           %currhosts = %{$ip_info->[1]};
           if (open(my $fh,'>',$newfile)) {
               foreach my $key (keys(%currhosts)) {
                   print $fh "$key:$currhosts{$key}\n";
               }
               close($fh);
               chmod(0644,$newfile);
           }
       }
       if (keys(%prevhosts) && keys(%currhosts)) {
           foreach my $key (keys(%prevhosts)) {
               unless ($currhosts{$key} eq $prevhosts{$key}) {
                   $ipchange{$key} = $prevhosts{$key}.' | '.$currhosts{$key};
               }
           }
           foreach my $key (keys(%currhosts)) {
               unless ($currhosts{$key} eq $prevhosts{$key}) {
                   $ipchange{$key} = $prevhosts{$key}.' | '.$currhosts{$key};
               }
           }
       }
       if (&Apache::lonnet::domain($defdom,'primary') eq $lonhost) {
           if (keys(%ipchange)) {
               if (open(my $fh,'>>',$perlvar{'lonDaemons'}.'/logs/hostip.log')) {
                  print $fh "********************\n".localtime(time).' Changes --'."\n".
                            "| Hostname | Previous IP | New IP |\n".
                            " --------------------------------- \n";
                  foreach my $hostname (sort(keys(%ipchange))) {
                       print $fh "| $hostname | $ipchange{$hostname} |\n";
                   }
                   print $fh "\n*******************\n\n";
                   close($fh);
               }
               my $emailto = &Apache::loncommon::build_recipient_list(undef,
                                      'hostipmail',$defdom);
               if ($emailto) {
                   my $subject = "LON-CAPA Hostname to IP change ($perlvar{'lonHostID'})";
                   my $chgmail = "To: $emailto\n".
                                 "Subject: $subject\n".
                                 "Content-type: text/plain\; charset=UTF-8\n".
                                 "MIME-Version: 1.0\n\n".
                                 "Host/IP changes\n".
                                 " \n".
                                 "| Hostname | Previous IP | New IP |\n".
                                 " --------------------------------- \n";
                   foreach my $hostname (sort(keys(%ipchange))) {
                       $chgmail .= "| $hostname | $ipchange{$hostname} |\n";
                   }
                   $chgmail .= "\n\n";
                   if (open(my $mailh, "|/usr/lib/sendmail -oi -t -odb")) {
                       print $mailh $chgmail;
                       close($mailh);
                       print "Sending mail notification of hostname/IP changes.\n";
                   }
               }
           }
       }
       return;
   }
   
 sub clean_nosslverify {  sub clean_nosslverify {
     my ($fh) = @_;      my ($fh) = @_;
     my %unlinked;       my %unlinked;
     if (-d "$perlvar{'lonSockDir'}/nosslverify") {      if (-d "$perlvar{'lonSockDir'}/nosslverify") {
         if (opendir(my $dh,"$perlvar{'lonSockDir'}/nosslverify")) {          if (opendir(my $dh,"$perlvar{'lonSockDir'}/nosslverify")) {
             while (my $fname=readdir($dh)) {              while (my $fname=readdir($dh)) {
Line 856  sub clean_lonc_childpids { Line 1214  sub clean_lonc_childpids {
 }  }
   
 sub write_connection_config {  sub write_connection_config {
     my ($isprimary,$domconf,$url,%connectssl,%changes);      my ($domconf,%connectssl,%changes);
     my $primaryLibServer = &Apache::lonnet::domain($perlvar{'lonDefDomain'},'primary');      $domconf = &get_domain_config();
     if ($primaryLibServer eq $perlvar{'lonHostID'}) {  
         $isprimary = 1;  
     } elsif ($primaryLibServer ne '') {  
         my $protocol = $Apache::lonnet::protocol{$primaryLibServer};  
         my $hostname = &Apache::lonnet::hostname($primaryLibServer);  
         unless ($protocol eq 'https') {  
             $protocol = 'http';  
         }  
         $url = $protocol.'://'.$hostname.'/cgi-bin/listdomconfig.pl';  
     }  
     my $domconf = &get_domain_config($perlvar{'lonDefDomain'},$primaryLibServer,$isprimary,  
                                      $url);  
     if (ref($domconf) eq 'HASH') {      if (ref($domconf) eq 'HASH') {
         if (ref($domconf->{'ssl'}) eq 'HASH') {          if (ref($domconf->{'ssl'}) eq 'HASH') {
             foreach my $connect ('connto','connfrom') {              foreach my $connect ('connto','connfrom') {
Line 922  sub write_connection_config { Line 1268  sub write_connection_config {
 }  }
   
 sub get_domain_config {  sub get_domain_config {
     my ($dom,$primlibserv,$isprimary,$url) = @_;      my ($dom,$primlibserv,$isprimary,$url,%confhash);
     my %confhash;      $dom = $perlvar{'lonDefDomain'};
       $primlibserv = &Apache::lonnet::domain($dom,'primary');
       if ($primlibserv eq $perlvar{'lonHostID'}) {
           $isprimary = 1;
       } elsif ($primlibserv ne '') {
           my $protocol = $Apache::lonnet::protocol{$primlibserv};
           my $hostname = &Apache::lonnet::hostname($primlibserv);
           unless ($protocol eq 'https') {
               $protocol = 'http';
           }
           $url = $protocol.'://'.$hostname.'/cgi-bin/listdomconfig.pl?primary='.$primlibserv.'&format=raw';
       }
     if ($isprimary) {      if ($isprimary) {
         my $lonusersdir = $perlvar{'lonUsersDir'};          my $lonusersdir = $perlvar{'lonUsersDir'};
         my $fname = $lonusersdir.'/'.$dom.'/configuration.db';          my $fname = $lonusersdir.'/'.$dom.'/configuration.db';
Line 943  sub get_domain_config { Line 1300  sub get_domain_config {
             }              }
         }          }
     } else {      } else {
         if (open(PIPE,"wget --no-check-certificate '$url?primary=$primlibserv&format=raw' |")) {          my $request=new HTTP::Request('GET',$url);
             my $config = '';          my $response=&LONCAPA::LWPReq::makerequest($primlibserv,$request,'',\%perlvar,5);
             while (<PIPE>) {          unless ($response->is_error()) {
                 $config .= $_;              my $content = $response->content;
             }              if ($content) {
             close(PIPE);                  my @pairs=split(/\&/,$content);
             if ($config) {  
                 my @pairs=split(/\&/,$config);  
                 foreach my $item (@pairs) {                  foreach my $item (@pairs) {
                     my ($key,$value)=split(/=/,$item,2);                      my ($key,$value)=split(/=/,$item,2);
                     my $what = &LONCAPA::unescape($key);                      my $what = &LONCAPA::unescape($key);
Line 991  sub write_hosttypes { Line 1346  sub write_hosttypes {
                 foreach my $lonid (sort(keys(%hostdom))) {                  foreach my $lonid (sort(keys(%hostdom))) {
                     my $type = 'other';                      my $type = 'other';
                     if ($hostdom{$lonid} eq $dom) {                      if ($hostdom{$lonid} eq $dom) {
                         $type = 'dom';                           $type = 'dom';
                     } elsif ($intdom{$lonid} eq $internetdom) {                      } elsif ($intdom{$lonid} eq $internetdom) {
                         $type = 'intdom';                          $type = 'intdom';
                     }                      }
Line 1057  sub reset_nosslverify_pids { Line 1412  sub reset_nosslverify_pids {
                             if ($sslrem{$host}) {                              if ($sslrem{$host}) {
                                 if (ref($pids_by_host{$host}) eq 'HASH') {                                  if (ref($pids_by_host{$host}) eq 'HASH') {
                                     if (ref($pids_by_host{$host}{'insecure'}) eq 'HASH') {                                      if (ref($pids_by_host{$host}{'insecure'}) eq 'HASH') {
                                         if (keys($pids_by_host{$host}{'insecure'})) {                                          if (keys(%{$pids_by_host{$host}{'insecure'}})) {
                                             foreach my $pid (keys($pids_by_host{$host}{'insecure'})) {                                              foreach my $pid (keys(%{$pids_by_host{$host}{'insecure'}})) {
                                                 if (open(PIPE,"ps -o ppid= -p $pid |")) {                                                  if (open(PIPE,"ps -o ppid= -p $pid |")) {
                                                     my $ppid = <PIPE>;                                                      my $ppid = <PIPE>;
                                                     chomp($ppid);                                                      chomp($ppid);
Line 1082  sub reset_nosslverify_pids { Line 1437  sub reset_nosslverify_pids {
     return;      return;
 }  }
   
   sub get_permcount_settings {
       my ($domconf) = @_;
       my ($defaults,$names) = &Apache::loncommon::lon_status_items();
       my (%weights,$threshold,$sysmail,$reportstatus,%exclusions);
       foreach my $type ('E','W','N','U') {
           $weights{$type} = $defaults->{$type};
       }
       $threshold = $defaults->{'threshold'};
       $sysmail = $defaults->{'sysmail'};
       $reportstatus = 1;
       if (ref($domconf) eq 'HASH') {
           if (ref($domconf->{'contacts'}) eq 'HASH') {
               if ($domconf->{'contacts'}{'reportstatus'} == 0) {
                   $reportstatus = 0;
               }
               if (ref($domconf->{'contacts'}{'lonstatus'}) eq 'HASH') {
                   if (ref($domconf->{'contacts'}{'lonstatus'}{weights}) eq 'HASH') {
                       foreach my $type ('E','W','N','U') {
                           if (exists($domconf->{'contacts'}{'lonstatus'}{weights}{$type})) {
                               $weights{$type} = $domconf->{'contacts'}{'lonstatus'}{weights}{$type};
                           }
                       }
                   }
                   if (ref($domconf->{'contacts'}{'lonstatus'}{'excluded'}) eq 'ARRAY') {
                       my @excluded = @{$domconf->{'contacts'}{'lonstatus'}{'excluded'}};
                       if (@excluded) {
                           map { $exclusions{$_} = 1; } @excluded;
                       }
                   }
                   if (exists($domconf->{'contacts'}{'lonstatus'}{'threshold'})) {
                       $threshold = $domconf->{'contacts'}{'lonstatus'}{'threshold'};
                   }
                   if (exists($domconf->{'contacts'}{'lonstatus'}{'sysmail'})) {
                       $sysmail = $domconf->{'contacts'}{'lonstatus'}{'sysmail'};
                   }
               }
           }
       }
       return ($threshold,$sysmail,$reportstatus,\%weights,\%exclusions);
   }
   
   sub read_serverhomeIDs {
       my %server;
       if (-e "$perlvar{'lonTabDir'}/serverhomeIDs.tab") {
           if (open(my $fh,'<',"$perlvar{'lonTabDir'}/serverhomeIDs.tab")) {
               while (<$fh>) {
                   my($host,$id) = split(/:/);
                   chomp($id);
                   $server{$host} = $id;
               }
               close($fh);
           }
       }
       return %server;
   }
   
 sub send_mail {  sub send_mail {
       my ($sysmail,$reportstatus) = @_;
     my $defdom = $perlvar{'lonDefDomain'};      my $defdom = $perlvar{'lonDefDomain'};
     my $origmail = $perlvar{'lonAdmEMail'};      my $origmail = $perlvar{'lonAdmEMail'};
     my $emailto = &Apache::loncommon::build_recipient_list(undef,      my $emailto = &Apache::loncommon::build_recipient_list(undef,
                                    'lonstatusmail',$defdom,$origmail);                                     'lonstatusmail',$defdom,$origmail);
     if ($totalcount>2500) {      if (($totalcount>$sysmail) && ($reportstatus)) {
  $emailto.=",$perlvar{'lonSysEMail'}";   $emailto.=",$perlvar{'lonSysEMail'}";
     }      }
     my $from;      my $from;
Line 1140  Options: Line 1552  Options:
  do not send emails do not   do not send emails do not
                                 check if the daemons are running, do not                                  check if the daemons are running, do not
                                 generate lon-status                                  generate lon-status
                                 --justiptables          Only update the dynamic iptables rules for the
                                   lond port; do not send emails, do not
                                   check if the daemons are running, do not
                                   generate lon-status
 USAGE  USAGE
 }  }
   
 # ================================================================ Main Program  # ================================================================ Main Program
 sub main () {  sub main () {
     my ($help,$justcheckdaemons,$noemail,$justcheckconnections,      my ($help,$justcheckdaemons,$noemail,$justcheckconnections,
  $justreload);   $justreload,$justiptables);
     &GetOptions("help"                 => \$help,      &GetOptions("help"                 => \$help,
  "justcheckdaemons"     => \$justcheckdaemons,   "justcheckdaemons"     => \$justcheckdaemons,
  "noemail"              => \$noemail,   "noemail"              => \$noemail,
  "justcheckconnections" => \$justcheckconnections,   "justcheckconnections" => \$justcheckconnections,
  "justreload"           => \$justreload   "justreload"           => \$justreload,
                   "justiptables"         => \$justiptables
  );   );
     if ($help) { &usage(); return; }      if ($help) { &usage(); return; }
 # --------------------------------- Read loncapa_apache.conf and loncapa.conf  # --------------------------------- Read loncapa_apache.conf and loncapa.conf
Line 1167  sub main () { Line 1583  sub main () {
     if ('{[[[[lonHostID]]]]}' eq $perlvar{'lonHostID'}) {      if ('{[[[[lonHostID]]]]}' eq $perlvar{'lonHostID'}) {
  print("Unconfigured machine.\n");   print("Unconfigured machine.\n");
  my $emailto=$perlvar{'lonSysEMail'};   my $emailto=$perlvar{'lonSysEMail'};
  my $hostname=`/bin/hostname`;   my $hostname = Sys::Hostname::FQDN::fqdn();
  chop $hostname;   $hostname=~s/\.+/./g;
  $hostname=~s/[^\w\.]//g; # make sure is safe to pass through shell   $hostname=~s/\-+/-/g;
    $hostname=~s/[^\w\.-]//g; # make sure is safe to pass through shell
  my $subj="LON: Unconfigured machine $hostname";   my $subj="LON: Unconfigured machine $hostname";
  system("echo 'Unconfigured machine $hostname.' |\   system("echo 'Unconfigured machine $hostname.' |".
  mailto $emailto -s '$subj' > /dev/null");                 " mail -s '$subj' $emailto > /dev/null");
  exit 1;   exit 1;
     }      }
   
Line 1182  sub main () { Line 1599  sub main () {
  print("User ID mismatch. This program must be run as user 'www'.\n");   print("User ID mismatch. This program must be run as user 'www'.\n");
  my $emailto="$perlvar{'lonAdmEMail'},$perlvar{'lonSysEMail'}";   my $emailto="$perlvar{'lonAdmEMail'},$perlvar{'lonSysEMail'}";
  my $subj="LON: $perlvar{'lonHostID'} User ID mismatch";   my $subj="LON: $perlvar{'lonHostID'} User ID mismatch";
  system("echo 'User ID mismatch. loncron must be run as user www.' |\   system("echo 'User ID mismatch. loncron must be run as user www.' |".
  mailto $emailto -s '$subj' > /dev/null");                 " mail -s '$subj' $emailto > /dev/null");
  exit 1;   exit 1;
     }      }
   
Line 1202  sub main () { Line 1619  sub main () {
             }              }
         }          }
     }      }
     &Apache::lonnet::load_hosts_tab(1,$nomemcache);      if (!$justiptables) {
     &Apache::lonnet::load_domain_tab(1,$nomemcache);          &Apache::lonnet::load_hosts_tab(1,$nomemcache);
     &Apache::lonnet::get_iphost(1,$nomemcache);          &Apache::lonnet::load_domain_tab(1,$nomemcache);
           &Apache::lonnet::get_iphost(1,$nomemcache);
       }
   
 # ----------------------------------------- Force firewall update for lond port    # ----------------------------------------- Force firewall update for lond port
   
     if ((!$justcheckdaemons) && (!$justreload)) {      if ((!$justcheckdaemons) && (!$justreload)) {
         my $now = time;          my $now = time;
Line 1221  sub main () { Line 1640  sub main () {
             if (&LONCAPA::try_to_lock('/tmp/lock_lciptables')) {              if (&LONCAPA::try_to_lock('/tmp/lock_lciptables')) {
                 my $execpath = $perlvar{'lonDaemons'}.'/lciptables';                  my $execpath = $perlvar{'lonDaemons'}.'/lciptables';
                 system("$execpath $tmpfile");                  system("$execpath $tmpfile");
                 unlink('/tmp/lock_lciptables');  # Remove the lock file.                   unlink('/tmp/lock_lciptables');  # Remove the lock file.
             }              }
             unlink($tmpfile);              unlink($tmpfile);
         }          }
Line 1233  sub main () { Line 1652  sub main () {
     $warnings=0;      $warnings=0;
     $notices=0;      $notices=0;
   
   
     my $fh;      my $fh;
     if (!$justcheckdaemons && !$justcheckconnections && !$justreload) {      if (!$justcheckdaemons && !$justcheckconnections && !$justreload && !$justiptables) {
  $fh=&start_logging();   $fh=&start_logging();
   
  &log_machine_info($fh);   &log_machine_info($fh);
  &clean_tmp($fh);   &clean_tmp($fh);
  &clean_lonIDs($fh);   &clean_lonIDs($fh);
           &clean_balanceIDs($fh);
         &clean_webDAV_sessionIDs($fh);          &clean_webDAV_sessionIDs($fh);
           &clean_ltiIDs($fh);
  &check_httpd_logs($fh);   &check_httpd_logs($fh);
  &rotate_lonnet_logs($fh);   &rotate_lonnet_logs($fh);
  &rotate_other_logs($fh);   &rotate_other_logs($fh);
     }      }
     if (!$justcheckconnections && !$justreload) {      if (!$justcheckconnections && !$justreload && !$justiptables) {
  &checkon_daemon($fh,'lonmemcached',40000);   &checkon_daemon($fh,'lonmemcached',40000);
  &checkon_daemon($fh,'lonsql',200000);   &checkon_daemon($fh,'lonsql',200000);
  if ( &checkon_daemon($fh,'lond',40000,'USR1') eq 'running') {   if ( &checkon_daemon($fh,'lond',40000,'USR1') eq 'running') {
Line 1267  sub main () { Line 1688  sub main () {
     if ($justcheckconnections) {      if ($justcheckconnections) {
  &test_connections($fh);   &test_connections($fh);
     }      }
     if (!$justcheckdaemons && !$justcheckconnections && !$justreload) {      if (!$justcheckdaemons && !$justcheckconnections && !$justreload && !$justiptables) {
  &check_delayed_msg($fh);          my $domconf = &get_domain_config();
  &log_simplestatus();          my ($threshold,$sysmail,$reportstatus,$weightsref,$exclusionsref) =
               &get_permcount_settings($domconf);
    &check_delayed_msg($fh,$weightsref,$exclusionsref);
         &write_loncaparevs();          &write_loncaparevs();
         &write_serverhomeIDs();          &write_serverhomeIDs();
  &write_checksums();   &write_checksums();
           &write_hostips();
         my %sslrem = &clean_nosslverify($fh);          my %sslrem = &clean_nosslverify($fh);
         my %conchgs = &write_connection_config();          my %conchgs = &write_connection_config();
         my %hosttypechgs = &write_hosttypes();          my %hosttypechgs = &write_hosttypes();
Line 1282  sub main () { Line 1706  sub main () {
             &checkon_daemon($fh,'lond',40000,'USR2');              &checkon_daemon($fh,'lond',40000,'USR2');
             &reset_nosslverify_pids($fh,%sslrem);              &reset_nosslverify_pids($fh,%sslrem);
         }          }
         &finish_logging($fh);          &finish_logging($fh,$weightsref);
  if ($totalcount>200 && !$noemail) { &send_mail(); }          &log_simplestatus();
           if ($totalcount>$threshold && !$noemail) { &send_mail($sysmail,$reportstatus); }
     }      }
 }  }
   

Removed from v.1.108  
changed lines
  Added in v.1.127


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.