#!/usr/bin/perl -w
# 14 mars 2004
#
# PARTIE DAEMON
# 3 partie:
#     + Ecriture du pid fork dans /var/run/atscript.pid
#     + Ouverture d un pipe en lecture/ecriture
#     + sleep indefini pour ne pas quitter et garder un oeil sur le pipe.
# les fichiers se nomment en fonction du temps en seconde a la quelle ils vont etre lances.
# 
##############################################################################

# INITIALISATION
use Fcntl;
require POSIX;
use strict;
use Proc::Daemon;
Proc::Daemon::Init;

my ($forkpid,$logfile,$oldpid,$sleep,$current_time,$sec,$min,$hour,$mday,$mon,$year,$c_sec,$c_min,$c_hour,$c_mday,$c_mon,$c_year,$file
,$pid,$pipe,@users,$user,@times);


$|= 1;

$logfile = "/var/log/atscript";
$SIG{'CHLD'} = \&zombies;
#############################################################################
# Reaction commandes de lancement
# die si on est pas root !
# $ARGV[0] eq '--stop' , on coupte
# $ARGV[0] eq '--start' , on commence, si pid non reactif, etc
# $ARGV[0] eq '--restart' , on tue le pid, et on relance?
open(LOG,">>".$logfile);
if ($ENV{'USER'} ne 'root') { print LOG "Pas root, dsl\n";  close LOG; die; }
if ($ARGV[0])
{
    if ($ARGV[0] eq '--stop') { 
	print LOG "OK";
	open(PID,"/var/run/atscriptd.pid") or do {
			    print LOG "NON LANCE!\n"; 
			    die();
			    };
	$pid = <PID>;
	close PID;
	kill 'KILL',$pid;
	print LOG "done.\n"; die("Done\n");
	}
    elsif ($ARGV[0] eq '--start') { 
	if (open(PID,"/var/run/atscriptd.pid"))
        {
    	    $pid = <PID>;
    	    close PID;
        }
	if ($pid and kill 0,$pid) { print LOG "Core deja lance!\n"; die; }
	print LOG "done.\n";1
    }
    elsif ($ARGV[0] eq '--restart') { 
	open(PID,"/var/run/atscriptd.pid") or do {
			    print LOG "NON LANCE!\n"; 
			    die();
			    };
	$pid = <PID>;
	print LOG "PID: $pid\n";
	close PID;
	if (kill 0,$pid) { kill 'KILL',$pid; }
	if (open(PID,"/var/run/atscript.pid")) 
	    { 
		$pid = <PID>;
		if (kill 0,$pid) { kill 'KILL',$pid; }
		close PID;
	    }
	unlink("/var/run/atscriptd.pid");
	print LOG "restarting...\n";
	}
}
else { print LOG "Pas d arg"; }
close LOG;



sub log_send($)
{
    $_ = shift;
    open(LOG,">>$logfile") or die "log impossible";
    select LOG;
    print $_;
    close LOG;
}




#############################################################################
# Mise a jour du pid atd !
# die si le pid est reactif.
# Nouveau pid si pas de pid, ou non reactif
undef($pid);
if (open(PID,"/var/run/atscriptd.pid"))
{    $pid = <PID>;    close PID; }

if ($pid and kill 0,$pid) { 
    open(LOG,">>".$logfile);
    print LOG "\nPid reactif\n";
    close LOG; 
    print STDOUT "Deja lance!\n"; die("not");
    }
else 
{
open(PID,">/var/run/atscriptd.pid");
print PID $$;
close PID;
}

#############################################################################

log_send "\n\n".gmtime(time)."\n********************************************\nRuning $0\n";
&mise_a_jour;
log_send  "Fin mise a  jour";
close LOG;

$pipe = "/var/run/atscript";
if (-e $pipe) {    unlink $pipe;    }
POSIX::mkfifo($pipe,0666) or die "mknod failed $!\n";
chmod 0666, $pipe or die $!;
sysopen(FIFO,$pipe,O_RDWR) or die "LEcture failed\n";

while(1)
{ while (<FIFO>)
    {
        if (/Update/) {   log_send "RECU: update !\n";    &mise_a_jour;log_send "!!!!\n\nFin mise a jour (recu update)!!!!!!!!!!\n\n";  }
        elsif (/Show/) {   log_send "RECU: show !\n"; print FIFO "Recu !n\n\nRECU !!\n";}
	else { log_send  "Message inconnu recu !\n"; }
        next;
    }
}


        



#Lancement de la mise a jour au debut du script puis a chaque signal recu.





sub pid_send($)
{
    $_ = shift;
    open(SPID,">/var/run/atscript.pid") or die("ERROR");
    select SPID;
    print $_;
    close SPID;
}






sub mise_a_jour
{
    undef($forkpid);
    if ($forkpid = fork)  
	{
	    if (open(PID,"/var/run/atscript.pid")) { $oldpid = <PID>;} else { $oldpid = 0; }
	    close PID;
	    pid_send("$forkpid");	    
	    log_send ("oldpid = \" $oldpid\"\n");
	    log_send ("OLDPID: $oldpid !!!!!!!!!!!!!!!!!!!!\n");
	    if ($oldpid > 0) { 	log_send ("TUer le pid: $oldpid\n");   kill 'KILL',$oldpid;}
	    log_send "En attente...\n\n";
	}
    elsif (defined($forkpid))
    {
	$|=1;
	log_send("Dans le fork: ($$)\n");

	log_send("APRES LE SEND !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!n");
        $current_time = &make_time;    
        ($c_year,$c_mon,$c_mday,$c_hour,$c_min,$c_sec) = $current_time =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/;
        print "Time: $c_year $c_mon $c_mday $c_hour $c_min $c_sec\n";
        @users = &config() or die $!;
	print "USERS: "; print @users; print "\n";
	undef @times;	
        foreach $user(@users){
	    print "Lecture de $user\n";
	    if ($user ne 'root') {  opendir(DIR,"/home/$user/.atscript/") or next; }
	    else {  opendir(DIR,"/$user/.atscript/") or next; }
	    push (@times,"$_ $user")  foreach ( grep(! /^\./, readdir(DIR))); 
            close DIR;
        }	
	print scalar @times." fichiers dans le .atscript\n";
        @times = sort @times;

	print "Sleeping !\n";	
        foreach (@times) { 
	select(undef,undef,undef,3000000);
	}
	}
	}
#	    print "Etude de $_\n";
#	    ($file,$user) = split / /,$_; # user $min , #stop at $sec secondes.
#	    if ($user ne'root') 
#	    {
#		if ($file < $current_time) 
#		    { 
#		        unlink("/home/$user/.atscript/$file"); 
#		        log_send "/home/$user/.atscript/$file fichier obsolete: supprime\n";
#		    }
#	    }
#	    else {  
#		if ($file < $current_time) 
#	    { 
#	    unlink("/root/.atscript/$file"); 
#	    log_send "/root/.atscript/$file fichier obsolete: supprime\n";
#	    }
#    }
#           ($year,$mon,$mday,$hour,$min,$sec) = $file =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/;
#           log_send "Execution: $year $mon $mday $hour $min $sec\n";	
#   	    $sleep =(($year-$c_year)*60*60*24*365 + ($mday-$c_mday)*60*60*24 + ($hour-$c_hour)*60*60 + ($min-$c_min)*60  +($sec-$c_sec));
#           log_send "\t+ Sleep de $current_time a $file: soit une attente de $sleep secondes\n"; 
#    if ($sleep > 0 ) {
#                select(undef,undef,undef,$sleep) or log_send "Error: $!\n";
#		log_send "Apres le sleep?\n";
#       		open(JOB,"/home/$user/.atscript/$file") or open(JOB,"/root/.atscript/$file")
#       		    or log_send ("Erreur de lecture du fichier /home/$user|/root|/.atscript/$file\n");
#       		foreach(<JOB>)    	{ s/\"//;  chomp; log_send "su $user -c \"$_\"\n"; system("su $user -c \"$_\" &");}
#       		close JOB;	    
#   }
#   log_send "Suprression du fichier\n";
#   if ($user ne 'root'){unlink("/home/$user/.atscript/$file")	}		
#   else {    unlink("/root/.atscript/$file"); }
#   log_send "Nouveaux temp: $c_year,$c_mon,$c_mday,$c_hour,$c_min,$c_sec\n";
#           $current_time = &make_time;    
#    ($c_year,$c_mon,$c_mday,$c_hour,$c_min,$c_sec) = $current_time =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/;
#    }
#    close LOG;
#    kill 'KILL',$$;	    
#    }
#}    



#########################################################################
sub make_time
{
    ($sec,$min,$hour,$mday,$mon,$year) = localtime(time);
    if ($sec==0){ $sec="00";} elsif ($sec<10) { $sec = "0".$sec; }
    if ($min==0){ $min="00";} elsif ($min<10) { $min = "0".$min; }    
    if ($hour==0){ $hour="00";} elsif ($hour<10) { $hour = "0".$hour; }    
    if ($mday==0){ $mday="00";} elsif ($mday<10) { $mday = "0".$mday; }    
    if ($mon==0){ $mon="00";} elsif ($mon<10) { $mon = "0".$mon; }    
    $year = $year+1900;
    return $year.$mon.$mday.$hour.$min.$sec;
}

sub config {
    open(CONF,"/etc/atscript.conf") or die "Fatal: no config found /etc/atscript.conf\n";
    while(<CONF>)   {
        if (/^users:(.*)/) { @users = split / /,$1;  }
    }
    close CONF;
    if (!@users) { die "Fatal: no config users set in /etc/atscript.conf\n"; }
    return @users;
}



sub zombies { 1 until (waitpid(-1 , 'WNOHANG') == -1); }



print STDOUT "Fin du lancement.\n";    
close LOG;

while(1)
{
select(undef,undef,undef,1);
}







