--- loncom/lond 2005/01/03 16:08:07 1.273
+++ loncom/lond 2005/06/03 18:23:19 1.284
@@ -2,7 +2,7 @@
# The LearningOnline Network
# lond "LON Daemon" Server (port "LOND" 5663)
#
-# $Id: lond,v 1.273 2005/01/03 16:08:07 albertel Exp $
+# $Id: lond,v 1.284 2005/06/03 18:23:19 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -58,14 +58,13 @@ my $DEBUG = 0; # Non zero to ena
my $status='';
my $lastlog='';
-my $VERSION='$Revision: 1.273 $'; #' stupid emacs
+my $VERSION='$Revision: 1.284 $'; #' stupid emacs
my $remoteVERSION;
my $currenthostid="default";
my $currentdomainid;
my $client;
my $clientip; # IP address of client.
-my $clientdns; # DNS name of client.
my $clientname; # LonCAPA name of client.
my $server;
@@ -178,7 +177,6 @@ sub ResetStatistics {
# $initcmd - The full text of the init command.
#
# Implicit inputs:
-# $clientdns - The DNS name of the remote client.
# $thisserver - Our DNS name.
#
# Returns:
@@ -187,10 +185,10 @@ sub ResetStatistics {
#
sub LocalConnection {
my ($Socket, $initcmd) = @_;
- Debug("Attempting local connection: $initcmd client: $clientdns me: $thisserver");
- if($clientdns ne $thisserver) {
+ Debug("Attempting local connection: $initcmd client: $clientip me: $thisserver");
+ if($clientip ne "127.0.0.1") {
&logthis(' LocalConnection rejecting non local: '
- ."$clientdns ne $thisserver ");
+ ."$clientip ne $thisserver ");
close $Socket;
return undef;
} else {
@@ -474,39 +472,11 @@ sub CopyFile {
my ($oldfile, $newfile) = @_;
- # The file must exist:
-
- if(-e $oldfile) {
-
- # Read the old file.
-
- my $oldfh = IO::File->new("< $oldfile");
- if(!$oldfh) {
- return 0;
- }
- my @contents = <$oldfh>; # Suck in the entire file.
-
- # write the backup file:
-
- my $newfh = IO::File->new("> $newfile");
- if(!(defined $newfh)){
- return 0;
- }
- my $lines = scalar @contents;
- for (my $i =0; $i < $lines; $i++) {
- print $newfh ($contents[$i]);
- }
-
- $oldfh->close;
- $newfh->close;
-
- chmod(0660, $newfile);
-
- return 1;
-
- } else {
- return 0;
+ if (! copy($oldfile,$newfile)) {
+ return 0;
}
+ chmod(0660, $newfile);
+ return 1;
}
#
# Host files are passed out with externally visible host IPs.
@@ -1411,6 +1381,9 @@ sub du_handler {
®ister_handler("du", \&du_handler, 0, 1, 0);
#
+# The ls_handler routine should be considered obosolete and is retained
+# for communication with legacy servers. Please see the ls2_handler.
+#
# ls - list the contents of a directory. For each file in the
# selected directory the filename followed by the full output of
# the stat function is returned. The returned info for each
@@ -1427,6 +1400,7 @@ sub du_handler {
# The reply is written to $client.
#
sub ls_handler {
+ # obsoleted by ls2_handler
my ($cmd, $ulsdir, $client) = @_;
my $userinput = "$cmd:$ulsdir";
@@ -1473,6 +1447,72 @@ sub ls_handler {
}
®ister_handler("ls", \&ls_handler, 0, 1, 0);
+#
+# Please also see the ls_handler, which this routine obosolets.
+# ls2_handler differs from ls_handler in that it escapes its return
+# values before concatenating them together with ':'s.
+#
+# ls2 - list the contents of a directory. For each file in the
+# selected directory the filename followed by the full output of
+# the stat function is returned. The returned info for each
+# file are separated by ':'. The stat fields are separated by &'s.
+# Parameters:
+# $cmd - The command that dispatched us (ls).
+# $ulsdir - The directory path to list... I'm not sure what this
+# is relative as things like ls:. return e.g.
+# no_such_dir.
+# $client - Socket open on the client.
+# Returns:
+# 1 - indicating that the daemon should not disconnect.
+# Side Effects:
+# The reply is written to $client.
+#
+sub ls2_handler {
+ my ($cmd, $ulsdir, $client) = @_;
+
+ my $userinput = "$cmd:$ulsdir";
+
+ my $obs;
+ my $rights;
+ my $ulsout='';
+ my $ulsfn;
+ if (-e $ulsdir) {
+ if(-d $ulsdir) {
+ if (opendir(LSDIR,$ulsdir)) {
+ while ($ulsfn=readdir(LSDIR)) {
+ undef $obs, $rights;
+ my @ulsstats=stat($ulsdir.'/'.$ulsfn);
+ #We do some obsolete checking here
+ if(-e $ulsdir.'/'.$ulsfn.".meta") {
+ open(FILE, $ulsdir.'/'.$ulsfn.".meta");
+ my @obsolete=;
+ foreach my $obsolete (@obsolete) {
+ if($obsolete =~ m|()(on)|) { $obs = 1; }
+ if($obsolete =~ m|()(default)|) {
+ $rights = 1;
+ }
+ }
+ }
+ my $tmp = $ulsfn.'&'.join('&',@ulsstats);
+ if ($obs eq '1') { $tmp.="&1"; } else { $tmp.="&0"; }
+ if ($rights eq '1') { $tmp.="&1"; } else { $tmp.="&0"; }
+ $ulsout.= &escape($tmp).':';
+ }
+ closedir(LSDIR);
+ }
+ } else {
+ my @ulsstats=stat($ulsdir);
+ $ulsout.=$ulsfn.'&'.join('&',@ulsstats).':';
+ }
+ } else {
+ $ulsout='no_such_dir';
+ }
+ if ($ulsout eq '') { $ulsout='empty'; }
+ &Reply($client, "$ulsout\n", $userinput); # This supports debug logging.
+ return 1;
+}
+®ister_handler("ls2", \&ls2_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.
@@ -1799,10 +1839,11 @@ sub change_authentication_handler {
# to take ownership of the construction space back to www:www
#
- if( ($oldauth =~ /^unix/) && ($umode eq "internal")) { # unix -> internal
+ if( (($oldauth =~ /^unix/) && ($umode eq "internal")) ||
+ (($oldauth =~ /^internal/) && ($umode eq "unix")) ) {
if(&is_author($udom, $uname)) {
&Debug(" Need to manage author permissions...");
- &manage_permissions("/$udom/_au", $udom, $uname, "internal:");
+ &manage_permissions("/$udom/_au", $udom, $uname, "$umode:");
}
}
@@ -2319,6 +2360,61 @@ sub put_user_profile_entry {
}
®ister_handler("put", \&put_user_profile_entry, 0, 1, 0);
+# Put a piece of new data in hash, returns error if entry already exists
+# Parameters:
+# $cmd - The command that got us here.
+# $tail - Tail of the command (remaining parameters).
+# $client - File descriptor connected to client.
+# Returns
+# 0 - Requested to exit, caller should shut down.
+# 1 - Continue processing.
+#
+sub newput_user_profile_entry {
+ my ($cmd, $tail, $client) = @_;
+
+ my $userinput = "$cmd:$tail";
+
+ my ($udom,$uname,$namespace,$what) =split(/:/,$tail,4);
+ if ($namespace eq 'roles') {
+ &Failure( $client, "refused\n", $userinput);
+ return 1;
+ }
+
+ chomp($what);
+
+ my $hashref = &tie_user_hash($udom, $uname, $namespace,
+ &GDBM_WRCREAT(),"N",$what);
+ if(!$hashref) {
+ &Failure( $client, "error: ".($!)." tie(GDBM) Failed ".
+ "while attempting put\n", $userinput);
+ return 1;
+ }
+
+ my @pairs=split(/\&/,$what);
+ foreach my $pair (@pairs) {
+ my ($key,$value)=split(/=/,$pair);
+ if (exists($hashref->{$key})) {
+ &Failure($client, "key_exists: ".$key."\n",$userinput);
+ return 1;
+ }
+ }
+
+ foreach my $pair (@pairs) {
+ my ($key,$value)=split(/=/,$pair);
+ $hashref->{$key}=$value;
+ }
+
+ if (untie(%$hashref)) {
+ &Reply( $client, "ok\n", $userinput);
+ } else {
+ &Failure($client, "error: ".($!+0)." untie(GDBM) failed ".
+ "while attempting put\n",
+ $userinput);
+ }
+ return 1;
+}
+®ister_handler("newput", \&newput_user_profile_entry, 0, 1, 0);
+
#
# Increment a profile entry in the user history file.
# The history contains keyword value pairs. In this case,
@@ -2349,11 +2445,17 @@ sub increment_user_value_handler {
my @pairs=split(/\&/,$what);
foreach my $pair (@pairs) {
my ($key,$value)=split(/=/,$pair);
+ $value = &unescape($value);
# We could check that we have a number...
if (! defined($value) || $value eq '') {
$value = 1;
}
$hashref->{$key}+=$value;
+ if ($namespace eq 'nohist_resourcetracker') {
+ if ($hashref->{$key} < 0) {
+ $hashref->{$key} = 0;
+ }
+ }
}
if (untie(%$hashref)) {
&Reply( $client, "ok\n", $userinput);
@@ -3198,8 +3300,9 @@ sub put_course_id_handler {
# owner - optional supplied username of owner to filter
# the dump. Only courses for which the course
# owner matches the supplied username will be
-# returned. Implicit assumption that owner is a user
-# in the domain in which the course database is defined.
+# returned. Implicit assumption that owner
+# is a user in the domain in which the
+# course database is defined.
# $client - The socket open on the client.
# Returns:
# 1 - Continue processing.
@@ -3210,7 +3313,7 @@ sub dump_course_id_handler {
my $userinput = "$cmd:$tail";
- my ($udom,$since,$description,$instcodefilter,$ownerfilter) =split(/:/,$tail);
+ my ($udom,$since,$description,$instcodefilter,$ownerfilter,$coursefilter) =split(/:/,$tail);
if (defined($description)) {
$description=&unescape($description);
} else {
@@ -3226,6 +3329,11 @@ sub dump_course_id_handler {
} else {
$ownerfilter='.';
}
+ if (defined($coursefilter)) {
+ $coursefilter=&unescape($coursefilter);
+ } else {
+ $coursefilter='.';
+ }
unless (defined($since)) { $since=0; }
my $qresult='';
@@ -3233,15 +3341,9 @@ sub dump_course_id_handler {
if ($hashref) {
while (my ($key,$value) = each(%$hashref)) {
my ($descr,$lasttime,$inst_code,$owner);
- my @courseitems = split/:/,$value;
- $descr = shift @courseitems;
- $lasttime = pop @courseitems;
- if (@courseitems > 0) {
- $inst_code = shift @courseitems;
- }
- if (@courseitems > 0) {
- $owner = shift @courseitems;
- }
+ my @courseitems = split(/:/,$value);
+ $lasttime = pop(@courseitems);
+ ($descr,$inst_code,$owner)=@courseitems;
if ($lasttime<$since) { next; }
my $match = 1;
unless ($description eq '.') {
@@ -3262,6 +3364,12 @@ sub dump_course_id_handler {
$match = 0;
}
}
+ unless ($coursefilter eq '.' || !defined($coursefilter)) {
+ my $unescapeCourse = &unescape($key);
+ unless (eval('$unescapeCourse=~/^$udom(_)\Q$coursefilter\E$/')) {
+ $match = 0;
+ }
+ }
if ($match == 1) {
$qresult.=$key.'='.$descr.':'.$inst_code.':'.$owner.'&';
}
@@ -4285,12 +4393,18 @@ sub ReadHostTable {
my $myloncapaname = $perlvar{'lonHostID'};
Debug("My loncapa name is : $myloncapaname");
while (my $configline=) {
- if (!($configline =~ /^\s*\#/)) {
- my ($id,$domain,$role,$name,$ip)=split(/:/,$configline);
- chomp($ip); $ip=~s/\D+$//;
+ if ($configline !~ /^\s*\#/ && $configline !~ /^\s*$/ ) {
+ my ($id,$domain,$role,$name)=split(/:/,$configline);
+ $name=~s/\s//g;
+ my $ip = gethostbyname($name);
+ if (length($ip) ne 4) {
+ &logthis("Skipping host $id name $name no IP $ip found\n");
+ next;
+ }
+ $ip=inet_ntoa($ip);
$hostid{$ip}=$id; # LonCAPA name of host by IP.
$hostdom{$id}=$domain; # LonCAPA domain name of host.
- $hostip{$id}=$ip; # IP address of host.
+ $hostip{$id}=$ip; # IP address of host.
$hostdns{$name} = $id; # LonCAPA name of host by DNS.
if ($id eq $perlvar{'lonHostID'}) {
@@ -4427,8 +4541,6 @@ sub Reply {
Debug("Request was $request Reply was $reply");
$Transactions++;
-
-
}
@@ -4471,7 +4583,7 @@ sub logstatus {
flock(LOG,LOCK_EX);
print LOG $$."\t".$clientname."\t".$currenthostid."\t"
.$status."\t".$lastlog."\t $keymode\n";
- flock(DB,LOCK_UN);
+ flock(LOG,LOCK_UN);
close(LOG);
}
&status("Finished logging");
@@ -4702,8 +4814,6 @@ sub make_new_child {
if (defined($iaddr)) {
$clientip = inet_ntoa($iaddr);
Debug("Connected with $clientip");
- $clientdns = gethostbyaddr($iaddr, AF_INET);
- Debug("Connected with $clientdns by name");
} else {
&logthis("Unable to determine clientip");
$clientip='Unavailable';
@@ -4743,18 +4853,23 @@ sub make_new_child {
ReadManagerTable; # May also be a manager!!
- my $clientrec=($hostid{$clientip} ne undef);
- my $ismanager=($managers{$clientip} ne undef);
+ my $outsideip=$clientip;
+ if ($clientip eq '127.0.0.1') {
+ $outsideip=$hostip{$perlvar{'lonHostID'}};
+ }
+
+ my $clientrec=($hostid{$outsideip} ne undef);
+ my $ismanager=($managers{$outsideip} ne undef);
$clientname = "[unknonwn]";
if($clientrec) { # Establish client type.
$ConnectionType = "client";
- $clientname = $hostid{$clientip};
+ $clientname = $hostid{$outsideip};
if($ismanager) {
$ConnectionType = "both";
}
} else {
$ConnectionType = "manager";
- $clientname = $managers{$clientip};
+ $clientname = $managers{$outsideip};
}
my $clientok;