--- loncom/lond	2011/01/11 10:32:00	1.468
+++ loncom/lond	2012/02/28 15:54:07	1.486
@@ -2,7 +2,7 @@
 # The LearningOnline Network
 # lond "LON Daemon" Server (port "LOND" 5663)
 #
-# $Id: lond,v 1.468 2011/01/11 10:32:00 foxr Exp $
+# $Id: lond,v 1.486 2012/02/28 15:54:07 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -15,6 +15,7 @@
 #
 # LON-CAPA 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.
 #
@@ -52,13 +53,14 @@ use LONCAPA::lonlocal;
 use LONCAPA::lonssl;
 use Fcntl qw(:flock);
 use Apache::lonnet;
+use Mail::Send;
 
 my $DEBUG = 0;		       # Non zero to enable debug log entries.
 
 my $status='';
 my $lastlog='';
 
-my $VERSION='$Revision: 1.468 $'; #' stupid emacs
+my $VERSION='$Revision: 1.486 $'; #' stupid emacs
 my $remoteVERSION;
 my $currenthostid="default";
 my $currentdomainid;
@@ -90,6 +92,8 @@ my %managers;			# Ip -> manager names
 
 my %perlvar;			# Will have the apache conf defined perl vars.
 
+my $dist;
+
 #
 #   The hash below is used for command dispatching, and is therefore keyed on the request keyword.
 #    Each element of the hash contains a reference to an array that contains:
@@ -419,8 +423,11 @@ sub ReadManagerTable {
 
    my $tablename = $perlvar{'lonTabDir'}."/managers.tab";
    if (!open (MANAGERS, $tablename)) {
-      logthis('<font color="red">No manager table.  Nobody can manage!!</font>');
-      return;
+       my $hostname = &Apache::lonnet::hostname($perlvar{'lonHostID'});
+       if (&Apache::lonnet::is_LC_dns($hostname)) {
+           &logthis('<font color="red">No manager table.  Nobody can manage!!</font>');
+       }
+       return;
    }
    while(my $host = <MANAGERS>) {
       chomp($host);
@@ -445,7 +452,7 @@ sub ReadManagerTable {
          }
       } else {
          logthis('<font color="green"> existing host'." $host</font>\n");
-         $managers{&Apache::lonnet::get_host_ip($host)} = $host;  # Use info from cluster tab if clumemeber
+         $managers{&Apache::lonnet::get_host_ip($host)} = $host;  # Use info from cluster tab if cluster memeber
       }
    }
 }
@@ -507,7 +514,8 @@ sub AdjustHostContents {
     my $me        = $perlvar{'lonHostID'};
 
     foreach my $line (split(/\n/,$contents)) {
-	if(!(($line eq "") || ($line =~ /^ *\#/) || ($line =~ /^ *$/))) {
+	if(!(($line eq "") || ($line =~ /^ *\#/) || ($line =~ /^ *$/) ||
+             ($line =~ /^\s*\^/))) {
 	    chomp($line);
 	    my ($id,$domain,$role,$name,$ip,$maxcon,$idleto,$mincon)=split(/:/,$line);
 	    if ($id eq $me) {
@@ -595,11 +603,8 @@ sub InstallFile {
 #
 #   ConfigFileFromSelector: converts a configuration file selector
 #                 into a configuration file pathname.
-#                 It's probably no longer necessary to preserve
-#                 special handling of hosts or domain as those
-#                 files have been superceded by dns_hosts, dns_domain.
-#                 The default action is just to prepend the directory
-#                 and append .tab
+#                 Supports the following file selectors: 
+#                 hosts, domain, dns_hosts, dns_domain  
 #
 #
 #  Parameters:
@@ -612,15 +617,11 @@ sub ConfigFileFromSelector {
     my $tablefile;
 
     my $tabledir = $perlvar{'lonTabDir'}.'/';
-    if ($selector eq "hosts") {
-	$tablefile = $tabledir."hosts.tab";
-    } elsif ($selector eq "domain") {
-	$tablefile = $tabledir."domain.tab";
-    } else {
+    if (($selector eq "hosts") || ($selector eq "domain") || 
+        ($selector eq "dns_hosts") || ($selector eq "dns_domain")) {
 	$tablefile =  $tabledir.$selector.'.tab';
     }
     return $tablefile;
-
 }
 #
 #   PushFile:  Called to do an administrative push of a file.
@@ -646,6 +647,8 @@ sub PushFile {
     #  supported:
     #   hosts.tab  ($filename eq host).
     #   domain.tab ($filename eq domain).
+    #   dns_hosts.tab ($filename eq dns_host).
+    #   dns_domain.tab ($filename eq dns_domain). 
     # Construct the destination filename or reject the request.
     #
     # lonManage is supposed to ensure this, however this session could be
@@ -677,11 +680,31 @@ sub PushFile {
 	return "error:$!";
     } else {
 	&logthis('<font color="green"> Installed new '.$tablefile
-		 ."</font>");
-
+		 ." - transaction by: $clientname ($clientip)</font>");
+        my $adminmail = $perlvar{'lonAdmEMail'};
+        my $admindom = &Apache::lonnet::host_domain($perlvar{'lonHostID'});
+        if ($admindom ne '') {
+            my %domconfig =
+                &Apache::lonnet::get_dom('configuration',['contacts'],$admindom);
+            if (ref($domconfig{'contacts'}) eq 'HASH') {
+                if ($domconfig{'contacts'}{'adminemail'} ne '') {
+                    $adminmail = $domconfig{'contacts'}{'adminemail'};
+                }
+            }
+        }
+        if ($adminmail =~ /^[^\@]+\@[^\@]+$/) {
+            my $msg = new Mail::Send;
+            $msg->to($adminmail);
+            $msg->subject('LON-CAPA DNS update on '.$perlvar{'lonHostID'});
+            $msg->add('Content-type','text/plain; charset=UTF-8');
+            if (my $fh = $msg->open()) {
+                print $fh 'Update to '.$tablefile.' from Cluster Manager '.
+                          "$clientname ($clientip)\n";
+                $fh->close;
+            }
+        }
     }
 
-
     #  Indicate success:
  
     return "ok";
@@ -1620,6 +1643,74 @@ sub ls3_handler {
 }
 &register_handler("ls3", \&ls3_handler, 0, 1, 0);
 
+sub read_lonnet_global {
+    my ($cmd,$tail,$client) = @_;
+    my $userinput = "$cmd:$tail";
+    my $requested = &Apache::lonnet::thaw_unescape($tail);
+    my $result;
+    my %packagevars = (
+                        spareid => \%Apache::lonnet::spareid,
+                        perlvar => \%Apache::lonnet::perlvar,
+                      );
+    my %limit_to = (
+                    perlvar => {
+                                 lonOtherAuthen => 1,
+                                 lonBalancer    => 1,
+                                 lonVersion     => 1,
+                                 lonSysEMail    => 1,
+                                 lonHostID      => 1,
+                                 lonRole        => 1,
+                                 lonDefDomain   => 1,
+                                 lonLoadLim     => 1,
+                                 lonUserLoadLim => 1,
+                               }
+                  );
+    if (ref($requested) eq 'HASH') {
+        foreach my $what (keys(%{$requested})) {
+            my $response;
+            my $items = {};
+            if (exists($packagevars{$what})) {
+                if (ref($limit_to{$what}) eq 'HASH') {
+                    foreach my $varname (keys(%{$packagevars{$what}})) {
+                        if ($limit_to{$what}{$varname}) {
+                            $items->{$varname} = $packagevars{$what}{$varname};
+                        }
+                    }
+                } else {
+                    $items = $packagevars{$what};
+                }
+                if ($what eq 'perlvar') {
+                    if (!exists($packagevars{$what}{'lonBalancer'})) {
+                        if ($dist =~ /^(centos|rhes|fedora|scientific)/) {
+                            my $othervarref=LONCAPA::Configuration::read_conf('httpd.conf');
+                            if (ref($othervarref) eq 'HASH') {
+                                $items->{'lonBalancer'} = $othervarref->{'lonBalancer'};
+                            }
+                        }
+                    }
+                }
+                $response = &Apache::lonnet::freeze_escape($items);
+            }
+            $result .= &escape($what).'='.$response.'&';
+        }
+    }
+    $result =~ s/\&$//;
+    &Reply($client,\$result,$userinput);
+    return 1;
+}
+&register_handler("readlonnetglobal", \&read_lonnet_global, 0, 1, 0);
+
+sub server_devalidatecache_handler {
+    my ($cmd,$tail,$client) = @_;
+    my $userinput = "$cmd:$tail";
+    my ($name,$id) = map { &unescape($_); } split(/:/,$tail);
+    &Apache::lonnet::devalidate_cache_new($name,$id);
+    my $result = 'ok';
+    &Reply($client,\$result,$userinput);
+    return 1;
+}
+&register_handler("devalidatecache", \&server_devalidatecache_handler, 0, 1, 0);
+
 sub server_timezone_handler {
     my ($cmd,$tail,$client) = @_;
     my $userinput = "$cmd:$tail";
@@ -1668,6 +1759,15 @@ sub server_homeID_handler {
 }
 &register_handler("serverhomeID", \&server_homeID_handler, 0, 1, 0);
 
+sub server_distarch_handler {
+    my ($cmd,$tail,$client) = @_;
+    my $userinput = "$cmd:$tail";
+    my $reply = &distro_and_arch();
+    &Reply($client,\$reply,$userinput);
+    return 1;
+}
+&register_handler("serverdistarch", \&server_distarch_handler, 0, 1, 0);
+
 #   Process a reinit request.  Reinit requests that either
 #   lonc or lond be reinitialized so that an updated 
 #   host.tab or domain.tab can be processed.
@@ -1973,7 +2073,7 @@ sub add_user_handler {
 		    ."makeuser";
 	    }
 	    unless ($fperror) {
-		my $result=&make_passwd_file($uname, $umode,$npass, $passfilename);
+		my $result=&make_passwd_file($uname,$udom,$umode,$npass, $passfilename);
 		&Reply($client,\$result, $userinput);     #BUGBUG - could be fail
 	    } else {
 		&Failure($client, \$fperror, $userinput);
@@ -2048,7 +2148,7 @@ sub change_authentication_handler {
 		    &Failure($client, \$result);
 		}
 	    } else {
-		my $result=&make_passwd_file($uname, $umode,$npass,$passfilename);
+		my $result=&make_passwd_file($uname,$udom,$umode,$npass,$passfilename);
 		#
 		#  If the current auth mode is internal, and the old auth mode was
 		#  unix, or krb*,  and the user is an author for this domain,
@@ -2248,7 +2348,10 @@ sub fetch_user_file_handler {
 
 	my $destname=$udir.'/'.$ufile;
 	my $transname=$udir.'/'.$ufile.'.in.transit';
-	my $remoteurl='http://'.$clientip.'/userfiles/'.$fname;
+        my $clientprotocol=$Apache::lonnet::protocol{$clientname};
+        $clientprotocol = 'http' if ($clientprotocol ne 'https');
+	my $clienthost = &Apache::lonnet::hostname($clientname);
+	my $remoteurl=$clientprotocol.'://'.$clienthost.'/userfiles/'.$fname;
 	my $response;
 	Debug("Remote URL : $remoteurl Transfername $transname Destname: $destname");
 	alarm(120);
@@ -3895,7 +3998,7 @@ sub dump_course_id_handler {
         $creationcontext = '.';
     }
     my $unpack = 1;
-    if ($description eq '.' && $instcodefilter eq '.' && $coursefilter eq '.' && 
+    if ($description eq '.' && $instcodefilter eq '.' && $ownerfilter eq '.' && 
         $typefilter eq '.') {
         $unpack = 0;
     }
@@ -5007,10 +5110,11 @@ sub get_sections_handler {
 sub validate_course_owner_handler {
     my ($cmd, $tail, $client)  = @_;
     my $userinput = "$cmd:$tail";
-    my ($inst_course_id, $owner, $cdom) = split(/:/, $tail);
-
+    my ($inst_course_id, $owner, $cdom, $coowners) = split(/:/, $tail);
+    
     $owner = &unescape($owner);
-    my $outcome = &localenroll::new_course($inst_course_id,$owner,$cdom);
+    $coowners = &unescape($coowners);
+    my $outcome = &localenroll::new_course($inst_course_id,$owner,$cdom,$coowners);
     &Reply($client, \$outcome, $userinput);
 
 
@@ -5998,7 +6102,7 @@ if (-e $pidfile) {
 $server = IO::Socket::INET->new(LocalPort => $perlvar{'londPort'},
                                 Type      => SOCK_STREAM,
                                 Proto     => 'tcp',
-                                Reuse     => 1,
+                                ReuseAddr     => 1,
                                 Listen    => 10 )
   or die "making socket: $@\n";
 
@@ -6061,9 +6165,13 @@ sub HUPSMAN {                      # sig
 #  a setuid perl script that can be root for us to do this job.
 #
 sub ReloadApache {
-    my $execdir = $perlvar{'lonDaemons'};
-    my $script  = $execdir."/apachereload";
-    system($script);
+# --------------------------- Handle case of another apachereload process (locking)
+    if (&LONCAPA::try_to_lock('/tmp/lock_apachereload')) {
+        my $execdir = $perlvar{'lonDaemons'};
+        my $script  = $execdir."/apachereload";
+        system($script);
+        unlink('/tmp/lock_apachereload'); #  Remove the lock file.
+    }
 }
 
 #
@@ -6327,7 +6435,14 @@ $SIG{USR2} = \&UpdateHosts;
 &Apache::lonnet::load_hosts_tab();
 my %iphost = &Apache::lonnet::get_iphost(1);
 
-my $dist=`$perlvar{'lonDaemons'}/distprobe`;
+$dist=`$perlvar{'lonDaemons'}/distprobe`;
+
+my $arch = `uname -i`;
+chomp($arch);
+if ($arch eq 'unknown') {
+    $arch = `uname -m`;
+    chomp($arch);
+}
 
 # --------------------------------------------------------------
 #   Accept connections.  When a connection comes in, it is validated
@@ -6616,8 +6731,7 @@ sub is_author {
 }
 #
 #   Checks to see if the input roleput request was to set
-# an author role.  If so, invokes the lchtmldir script to set
-# up a correct public_html 
+# an author role.  If so, creates construction space 
 # Parameters:
 #    request   - The request sent to the rolesput subchunk.
 #                We're looking for  /domain/_au
@@ -6627,16 +6741,15 @@ sub is_author {
 #
 sub manage_permissions {
     my ($request, $domain, $user, $authtype) = @_;
-
-    &Debug("manage_permissions: $request $domain $user $authtype");
-
     # See if the request is of the form /$domain/_au
     if($request =~ /^(\/\Q$domain\E\/_au)$/) { # It's an author rolesput...
-	my $execdir = $perlvar{'lonDaemons'};
-	my $userhome= "/home/$user" ;
-	&logthis("system $execdir/lchtmldir $userhome $user $authtype");
-	&Debug("Setting homedir permissions for $userhome");
-	system("$execdir/lchtmldir $userhome $user $authtype");
+        my $path=$perlvar{'lonDocRoot'}."/priv/$domain";
+        unless (-e $path) {        
+           mkdir($path);
+        }
+        unless (-e $path.'/'.$user) {
+           mkdir($path.'/'.$user);
+        }
     }
 }
 
@@ -7125,7 +7238,9 @@ sub subscribe {
                 # the metadata
 		unless ($fname=~/\.meta$/) { &unsub("$fname.meta",$clientip); }
 		$fname=~s/\/home\/httpd\/html\/res/raw/;
-		$fname="http://".&Apache::lonnet::hostname($perlvar{'lonHostID'})."/".$fname;
+                my $protocol = $Apache::lonnet::protocol{$perlvar{'lonHostID'}};
+                $protocol = 'http' if ($protocol ne 'https');
+		$fname=$protocol.'://'.&Apache::lonnet::hostname($perlvar{'lonHostID'})."/".$fname;
 		$result="$fname\n";
 	    }
 	} else {
@@ -7167,7 +7282,7 @@ sub change_unix_password {
 
 
 sub make_passwd_file {
-    my ($uname, $umode,$npass,$passfilename)=@_;
+    my ($uname,$udom,$umode,$npass,$passfilename)=@_;
     my $result="ok";
     if ($umode eq 'krb4' or $umode eq 'krb5') {
 	{
@@ -7208,7 +7323,7 @@ sub make_passwd_file {
 	    #
 	    my $uid = getpwnam($uname);
 	    if((defined $uid) && ($uid == 0)) {
-		&logthis(">>>Attempted to create privilged account blocked");
+		&logthis(">>>Attempt to create privileged account blocked");
 		return "no_priv_account_error\n";
 	    }
 
@@ -7220,6 +7335,7 @@ sub make_passwd_file {
 		&Debug("user  = ".$uname.", Password =". $npass);
 		my $se = IO::File->new("|$execpath > $perlvar{'lonDaemons'}/logs/lcuseradd.log");
 		print $se "$uname\n";
+                print $se "$udom\n";
 		print $se "$npass\n";
 		print $se "$npass\n";
 		print $se "$lc_error_file\n"; # Status -> unique file.
@@ -7475,6 +7591,10 @@ sub useable_role {
     return 1;
 }
 
+sub distro_and_arch {
+    return $dist.':'.$arch;
+}
+
 # ----------------------------------- POD (plain old documentation, CPAN style)
 
 =head1 NAME