Index: gsdl/trunk/bin/script/schedule.pl
===================================================================
--- gsdl/trunk/bin/script/schedule.pl	(revision 16137)
+++ gsdl/trunk/bin/script/schedule.pl	(revision 16137)
@@ -0,0 +1,578 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# schedule.pl --
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program 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 program 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+package schedule;
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/cpan");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/plugins");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/plugouts");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/classify");
+
+    if (defined $ENV{'GSDLEXTS'}) {
+	my @extensions = split(/:/,$ENV{'GSDLEXTS'});
+	foreach my $e (@extensions) {
+	    my $ext_prefix = "$ENV{'GSDLHOME'}/ext/$e";
+
+	    unshift (@INC, "$ext_prefix/perllib");
+	    unshift (@INC, "$ext_prefix/perllib/cpan");
+	}
+    }
+}
+
+use strict; 
+no strict 'refs'; 
+no strict 'subs'; 
+
+use FileHandle; 
+use Fcntl; 
+use printusage; 
+use parse2; 
+use parse3;
+use gsprintf 'gsprintf';
+
+
+my $frequency_list = 
+    [  { 'name' => "hourly",
+         'desc' =>  "{schedule.frequency.hourly}" }, 
+       { 'name' => "daily",
+         'desc' =>  "{schedule.frequency.daily}" }, 
+       { 'name' => "weekly",
+         'desc' =>  "{schedule.frequency.weekly}" } 
+     ];
+
+my $action_list = 
+    [  { 'name' => "add",
+         'desc' =>  "{schedule.action.add}" }, 
+       { 'name' => "update",
+         'desc' =>  "{schedule.action.update}" }, 
+       { 'name' => "delete",
+         'desc' =>  "{schedule.action.delete}" } 
+     ];
+
+my $arguments = 
+    [
+     { 'name' => "schedule", 
+       'desc' => "{schedule.schedule}",
+       'type' => "flag", 
+       'reqd' => "no", 
+       'modegli' => "3" }, 
+      { 'name' => "frequency", 
+       'desc' => "{schedule.frequency}",
+       'type' => "enum",
+       'list' => $frequency_list, 
+       'deft' => "hourly", 
+       'reqd' => "no", 
+       'modegli' => "4" }, 
+     { 'name' => "action", 
+       'desc' => "{schedule.action}",
+       'type' => "enum", 
+       'list' => $action_list, 
+       'deft' => "add", 
+       'reqd' => "no", 
+       'modegli' => "4" },
+     { 'name' => "import", 
+       'desc' => "{schedule.import}",
+       'type' => "quotestr", 
+       'deft' => "", 
+       'reqd' => "yes", 
+       'hiddengli' => "yes" },
+     { 'name' => "build", 
+       'desc' => "{schedule.build}",
+       'type' => "quotestr", 
+       'deft' => "", 
+       'reqd' => "yes", 
+       'hiddengli' => "yes" }, 
+     { 'name' => "colname", 
+       'desc' => "{schedule.colname}",
+       'type' => "string", 
+       'deft' => "", 
+       'reqd' => "no", 
+       'hiddengli' => "yes" }, 
+     { 'name' => "xml", 
+       'desc' => "{scripts.xml}",
+       'type' => "flag", 
+       'reqd' => "no", 
+       'hiddengli' => "yes" },
+     { 'name' => "language", 
+       'desc' => "{scripts.language}",
+       'type' => "string", 
+       'reqd' => "no", 
+       'hiddengli' => "yes" },
+     { 'name' => "email", 
+       'desc' => "{schedule.email}",
+       'type' => "flag", 
+       'reqd' => "no", 
+       'modegli' => "4" },
+     { 'name' => "toaddr", 
+       'desc' => "{schedule.toaddr}",
+       'type' => "string", 
+       'reqd' => "no", 
+       'deft' => "", 
+       'modegli' => "4" },
+     { 'name' => "fromaddr", 
+       'desc' => "{schedule.fromaddr}",
+       'type' => "string",
+       'deft' => "", 
+       'reqd' => "no",
+       'modegli' => "4" },
+     { 'name' => "smtp", 
+       'desc' => "{schedule.smtp}",
+       'type' => "string",
+       'deft' => "",
+       'reqd' => "no", 
+       'modegli' => "4" },
+     { 'name' => "out",
+        'desc' => "{schedule.out}",
+        'type' => "string",
+        'deft' => "STDERR",
+        'reqd' => "no",
+        'hiddengli' => "yes" },
+     { 'name' => "gli",
+        'desc' => "{schedule.gli}",
+        'type' => "flag",
+        'reqd' => "no",
+        'hiddengli' => "yes" }
+     ];
+
+
+my $options = { 'name' => "schedule.pl",
+		'desc' => "Interaction with Cron",
+		'args' => $arguments };
+
+&main(); 
+
+sub main { 
+
+    #params
+    my ($action, $frequency, $import, $build, $colname, $xml, $language, 
+        $email, $toaddr, $fromaddr, $smtp, $gli, $out);
+
+    #other vars
+    my ($i,$numArgs,$os,$erase,$erase2,$copy,$newpl,$gsdl,$path,$cronf,
+        $nf,$of,$opf, $cronstr, $ecmd,$ecmd2, $record, $cronrec,$ncronf);
+
+    #some defaults
+    $action = "add";   
+    $frequency = "hourly"; 
+    $import = ""; 
+    $build = ""; 
+    $colname = "";
+    $xml = 0; 
+    $email = 0;
+    $gli = 0; 
+    $language = ""; 
+    $out = "STDERR"; 
+
+
+    $gsdl = $ENV{'GSDLHOME'};
+    $os = $ENV{'GSDLOS'};
+    $path = $ENV{'PATH'}; 
+
+    my $service = "schedule"; 
+
+    #For this to work, we need to know if -gli exists
+ 
+    $numArgs=$#ARGV+1; 
+    $i = 0; 
+    while($i < $numArgs)
+    {
+	if($ARGV[$i] =~ /gli/) {
+	    $gli = 1; 
+	}
+	$i++; 
+    } 
+
+    #We are using two different parsers here, because the GLI in linux (and probably darwin) will not take
+    #an entire double-quoted string as an argument, while if schedule.pl is 
+    #executed from the command line, the entire double-quoted string is taken
+    #as an argument. For Windows, it seems that it does. 
+    my $hashParsingResult = {}; 
+    my $intArgLeftAfterParsing; 
+    if($gli && $os eq "linux") {  
+	$intArgLeftAfterParsing = parse3::parse(\@ARGV, $arguments, $hashParsingResult, "allow_extra_options"); 
+    } else {
+	$intArgLeftAfterParsing = parse2::parse(\@ARGV, $arguments, $hashParsingResult, "allow_extra_options"); 
+
+    } 
+
+    #check for extra options
+    if ($intArgLeftAfterParsing == -1 || $intArgLeftAfterParsing > 0 || (@ARGV && $ARGV[0] =~ /^\-+h/))
+    {
+        &PrintUsage::print_txt_usage($options, "{schedule.params}");
+        die "\n";
+    }
+
+    foreach my $strVariable (keys %$hashParsingResult)
+    {
+        eval "\$$strVariable = \$hashParsingResult->{\"\$strVariable\"}";
+    }
+  
+    if ($xml) {
+	    &PrintUsage::print_xml_usage($options); 
+	    print "\n"; 
+	    return; 
+
+    }
+
+    if ($gli) { # the gli wants strings to be in UTF-8
+        &gsprintf::output_strings_in_UTF8; 
+    }
+
+    if($action eq "add" || $action eq "update") { 
+	if($email) {
+	    if($smtp eq "" || $toaddr eq "" || $fromaddr eq "" || $smtp =~ /^-/ || $toaddr =~ /^-/ || $fromaddr =~ /^-/) {
+		&gsprintf($out, "{schedule.error.email} \n"); 
+		die "\n"; 
+	    }
+	
+
+	    if($import eq "" || $build eq "") { 
+		&gsprintf($out, "{schedule.error.importbuild} \n");
+		die "\n"; 
+	    }
+	}
+    } 
+    if($colname eq "") { 
+	 &gsprintf($out, "{schedule.error.colname} \n");
+	 die "\n"; 
+    }
+
+    #not sure if this is always set? 
+    #language may be passed in too
+    if($language eq "" && exists($ENV{'GSDLLANG'}))  {
+        $language = $ENV{'GSDLLANG'}; 
+    }
+    elsif($language eq "")  {
+	$language = "en"; 
+    } 
+
+    $newpl = "cron.pl"; 
+    my $logfile = "cron".time().".txt";  
+
+    if($action eq "delete") {
+
+	print STDERR "<Delete>\n" if $gli; 
+
+	if($os =~ /^linux$/ || $os =~ /^darwin$/) { 
+	        system("\\rm $gsdl/collect/$colname/$newpl 2>/dev/null");
+		system("\\rm $gsdl/collect/$colname/cronjob 2>/dev/null"); 
+	} else {  #in windows
+
+	        system("del $gsdl\\\\collect\\\\$colname\\\\$newpl 2>nul");  #nul is windows equivalent to /dev/null
+
+	} 
+
+
+	&gsprintf($out, "{schedule.deleted}\n");
+    } 
+    else {
+	#For the Scheduling monitor
+	print STDERR "<Schedule>\n" if $gli; 
+
+	if ($os =~ /^linux$/ || $os =~ /^darwin$/) {
+ 
+	    $import = $import." 2>$gsdl/collect/$colname/log/$logfile";
+	    $build = $build." 2>>$gsdl/collect/$colname/log/$logfile"; 
+	    $erase = "\\\\rm -r $gsdl/collect/$colname/index 2>>$gsdl/collect/$colname/log/$logfile";
+	    $erase2 = "mkdir $gsdl/collect/$colname/index 2>>$gsdl/collect/$colname/log/$logfile";  
+	    $copy = "mv $gsdl/collect/$colname/building/* $gsdl/collect/$colname/index/ 2>>$gsdl/collect/$colname/log/$logfile";
+	    if($email) {
+		#first,we need to add backslashes before the 'at' symbol. 
+		$toaddr =~ s/\@/\\\@/g; 
+		$fromaddr =~ s/\@/\\\@/g; 
+
+		$ecmd = "$gsdl/bin/script/sendmail.pl -to $toaddr -from $fromaddr -smtp $smtp -msgfile $gsdl/collect/$colname/log/$logfile -subject \\\"Results of build for collection $colname\\\" 2>>$gsdl/collect/$colname/log/$logfile >>$gsdl/collect/$colname/log/$logfile"; 
+
+		$ecmd2 = "$gsdl/bin/script/sendmail.pl -to $toaddr -from $fromaddr -smtp $smtp -msgfile $gsdl/etc/cronlock.txt -subject \\\"Results of build for collection $colname\\\" 2>>$gsdl/collect/$colname/log/$logfile >>$gsdl/collect/$colname/log/$logfile"; 	       
+	    }
+   
+	} else {   #in windows
+
+	    $gsdl =~ s/\\/\\\\/g; 
+	    $path =~ s/\\/\\\\/g; 
+
+	    $import =~ s/\\/\\\\/g;
+	    $build =~ s/\\/\\\\/g; 
+
+  	    $import =~ s/exe/exe\\\"/g;
+	    $import =~ s/pl/pl\\\"/g; 
+  	    $build =~ s/exe/exe\\\"/g;
+	    $build =~ s/pl/pl\\\"/g;  
+
+
+	    my $prompt = substr($gsdl,0,2); 
+
+	    $import =~ s/$prompt/\\\"$prompt/g; 
+	    $build =~ s/$prompt/\\\"$prompt/g; 
+
+	    #not the best solution - won't work if someone chooses something weird
+	    $import =~ s/\\collect/\\collect\\\"/; 
+            $build =~ s/\\collect/\\collect\\\"/; 
+
+	    $import = "$import 2>\\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\$logfile\\\" "; 
+	    $build = "$build 2>>\\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\$logfile\\\" "; 
+
+
+	    $erase = "rd \\\/S \\\/Q \\\"$gsdl\\\\collect\\\\$colname\\\\index\\\" 2>>\\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\$logfile\\\" "; 
+	    $erase2 = "md \\\"$gsdl\\\\collect\\\\$colname\\\\index\\\" 2>>\\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\$logfile\\\" "; 
+	    $copy = "xcopy \\\/E \\\/Y \\\"$gsdl\\\\collect\\\\$colname\\\\building\\\\*\\\" \\\"$gsdl\\\\collect\\\\$colname\\\\index\\\\\\\" >>\\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\$logfile\\\" ";
+	    if($email) {
+		$toaddr =~ s/\@/\\\@/g; 
+		$fromaddr =~ s/\@/\\\@/g; 
+		$ecmd = "\\\"$gsdl\\\\bin\\\\windows\\\\perl\\\\bin\\\\perl.exe\\\" -S \\\"$gsdl\\\\bin\\\\script\\\\sendmail.pl\\\" -to $toaddr -from $fromaddr -smtp $smtp -msgfile \\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\$logfile\\\" -subject \\\"Results of build for collection $colname\\\" >>\\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\$logfile\\\" "; 
+
+		$ecmd2 = "\\\"$gsdl\\\\bin\\\\windows\\\\perl\\\\bin\\\\perl.exe\\\" -S \\\"$gsdl\\\\bin\\\\script\\\\sendmail.pl\\\" -to $toaddr -from $fromaddr -smtp $smtp -msgfile \\\"$gsdl\\\\etc\\\\cronlock.txt\\\" -subject \\\"Results of build for collection $colname\\\" >>\\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\$logfile\\\" "; 	       
+	    }
+	}
+
+
+	$nf = new FileHandle() ||
+            (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
+
+	open($nf, ">$gsdl/collect/$colname/$newpl") ||
+            (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
+ 
+	
+	print $nf "\#!/usr/bin/perl"; 
+	print $nf "\n\n"; 
+
+
+	#we need to set environment variables for import and build
+	print $nf "\$ENV{'GSDLHOME'}=\"$gsdl\"\;\n"; 
+	print $nf "\$ENV{'GSDLOS'}=\"$os\"\;\n";
+	print $nf "\$ENV{'GSDLLANG'}=\"$language\"\;\n";  
+	print $nf "\$ENV{'PATH'}=\"$path\"\;\n";  
+
+	if($os =~ /^windows$/) {
+		print $nf "if\(-e \\\"$gsdl\\\\collect\\\\$colname\\\\etc\\\\cron.lck\\\" \"\)\{ \n"; 
+	} else { 
+		print $nf "if\(-e \"$gsdl/collect/$colname/etc/cron.lck\"\) \{ \n";
+	}
+	if($email) { 
+	    print $nf "    system(\"$ecmd2\")\;\n"; 
+	}
+	else { 
+	    print $nf "    system(\"more \"$gsdl/etc/cronlock.txt\" >\"$gsdl/collect/$colname/log/$logfile\"\"\)\;\n"; 
+
+	}
+        print $nf "\} else \{\n";
+
+	if($os eq "linux" || $os eq "darwin")  {
+	    $import =~ s/\"//; 
+	    $import =~ s/\"//;
+	    $build =~ s/\"//; 
+	    $build =~ s/\"//; 
+	}
+       
+	if($os =~ /^windows$/) {
+		print $nf "system(\"echo lock \>\\\"$gsdl\\\\collect\\\\$colname\\\\etc\\\\cron.lck\\\"\")\;\n"; 
+	} else { 
+		print $nf "system(\"echo lock >\\\"$gsdl/collect/$colname/etc/cron.lck\\\" \")\;\n"; 
+	}
+
+	print $nf "	system(\"$import\")\;\n";
+	print $nf "	system(\"$build\")\;\n"; 
+
+	print $nf "	system(\"$erase\")\;\n"; 
+	print $nf "	system(\"$erase2\")\;\n"; 
+
+	print $nf "	system(\"$copy\")\;\n";
+	if($email)  {
+	    print $nf "	system(\"$ecmd\")\;\n"; 
+	}
+
+
+	#need to set permissions in linux
+	if($os =~ /^linux$/ || $os =~ /^darwin$/) {
+	    print $nf "system(\"chmod -R 755 $gsdl/collect/$colname/index/*\")\;\n";
+	    print $nf "system(\"\\\\rm $gsdl/collect/$colname/etc/cron.lck\")\;\n"; 
+	} else { 
+            print $nf "system(\"del \\\"$gsdl\\\\collect\\\\$colname\\\\etc\\\\cron.lck\\\" \")\;\n"; 
+	}
+
+
+
+        print $nf "\}\n"; 
+
+	close($nf); 
+	if($os =~ /^linux$/ || $os =~ /^darwin$/) {
+	    system("chmod 755 $gsdl/collect/$colname/cron.pl"); 
+	}
+
+	&gsprintf($out, "{schedule.scheduled}\n");
+    }
+
+    #next, we need to create a crontab file.  For now, a crontab will be set up
+    #to run at midnight either nightly or weekly.  
+    $gsdl =~ s/\\\\/\\/g;
+    if ($os =~ /^linux$/ || $os =~ /^darwin$/)
+    {
+	$cronf="cronjob"; 
+	open($nf, ">$gsdl/collect/$colname/$cronf") ||
+            (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
+
+	#see if there is an existing crontab
+	system("crontab -l >$gsdl/collect/$colname/outfile 2>/dev/null"); 
+
+	$opf = new FileHandle(); 
+	open($opf, "$gsdl/collect/$colname/outfile")   ||
+            (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
+	$record = <$opf>;  
+
+	#if there is an existing crontab file
+	#preserve all records and change existing record for 
+	#current collection
+	if ($record) 
+	{
+	    do
+	    {
+		if($record !~ /$colname/)
+		{
+		    print $nf $record; 
+		} 
+	    } while($record = <$opf>); 
+
+	    close($opf); 
+	}
+
+
+	if($action =~ /^add$/ || $action =~ /^update$/)
+	{
+	    if($frequency eq "hourly") {
+		$cronrec = "50 * * * * $gsdl/collect/$colname/cron.pl";
+	    }
+	    elsif($frequency eq "daily") {
+		$cronrec = "00 0 * * * $gsdl/collect/$colname/cron.pl";
+	    }
+	    elsif($frequency eq "weekly") {
+		$cronrec = "59 11 * * 0 $gsdl/collect/$colname/cron.pl";
+	    }
+
+	    $cronrec = $cronrec." 2>/dev/null\n"; 
+	
+	    print $nf $cronrec; 
+	}
+
+	close($nf); 
+
+	#this makes the cronjob official
+	#still needs to be done for existing records
+	system("crontab $gsdl/collect/$colname/$cronf 2>/dev/null"); 
+
+	#cleanup
+	system("\\rm $gsdl/collect/$colname/outfile"); 
+	system("\\rm $gsdl/collect/$colname/$cronf");
+
+	if($action eq "add" || $action eq "update")  {
+	    &gsprintf($out, "{schedule.cron}\n");
+	}
+
+    } else {  
+
+    #for windows, we will put crontab file in the same place.  some limitations
+    #1) the absolute path to greenstone cannot have spaces if one is going to do this
+    #2) cron.exe needs to be started manually before doing this
+    #3) greenstone may have to be shut down completely to do this or lock problems occur
+
+	$cronf="crontab";  #pycron.exe expects this filename!
+	$ncronf="crontab.new"; 
+	#check to see if crontab file exists
+	if(-e "$gsdl/collect/$cronf")
+	{
+		
+		open($of, "$gsdl/collect/$cronf") ||
+            (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
+
+
+		open($nf, ">$gsdl/collect/$ncronf")  ||
+            (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
+
+		while($record = <$of>)
+		{
+	 		if($record !~ /$colname/)
+			{
+			    print $nf $record; 
+			}
+		} 
+		close($of);
+		close($nf);
+
+		system("del \"$gsdl\\collect\\$cronf\""); 
+		system("move \"$gsdl\\collect\\$ncronf\" \"$gsdl\\collect\\$cronf\""); 
+		
+		
+		if($action =~ /^add$/ || $action =~ /^update$/)
+		{
+		    open($nf, ">>$gsdl/collect/$cronf") ||
+            (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
+
+		    if($frequency eq "hourly") {
+			print $nf "50 * * * * silentstart.exe $gsdl\\collect\\$colname\\cron.pl\n";
+		    }
+		    elsif($frequency eq "daily") {
+			print $nf "00 0 * * * silentstart.exe $gsdl\\collect\\$colname\\cron.pl\n";
+		    }
+		    elsif($frequency eq "weekly") {
+			print $nf "59 11 * * 0 silentstart.exe $gsdl\\collect\\$colname\\cron.pl\n";
+		    }
+		    close($nf);
+		}
+
+	} else {	
+	    if($action =~ /^add$/ || $action =~ /^update$/)
+	    {
+		open($nf, ">$gsdl/collect/$cronf") ||
+            (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
+		if($frequency eq "hourly") {
+	 	   print $nf "50 * * * * silentstart.exe $gsdl\\collect\\$colname\\cron.pl\n";
+		}
+		elsif($frequency eq "daily") {
+		    print $nf "00 0 * * * silentstart.exe $gsdl\\collect\\$colname\\cron.pl\n";
+		}
+		elsif($frequency eq "weekly") {
+		    print $nf "59 11 * * 0 silentstart.exe $gsdl\\collect\\$colname\\cron.pl\n";
+		}
+
+		close($nf); 
+	    }
+	}
+
+	if($action eq "update" || $action eq "add") { 
+	    &gsprintf($out, "{schedule.cron}\n");
+	}
+    }
+
+    #For the scheduling monitor
+    print STDERR "<Done>\n" if $gli; 
+
+ 
+
+} #end sub main
