#!/usr/bin/perl

$repertoire_de_base = "/usr/local/etc/g2c";
# une première version les mettait dans /etc/
# mais cela avait l'inconvénient de 'boucler' par 'fileschanged -r /etc'

$param = shift; 	# 1° paramètre à la ligne de commande
$configuration = $param;
$repertoire_config = "$repertoire_de_base/$configuration";
# une première version les mettait dans /etc/
# mais cela avait l'inconvénient de 'boucler' par 'fileschanged -r /etc'
$param2 = shift; 	# 2° paramètre à la ligne de commande

if ($param eq "") {	# message affiché si pas de paramètre donné
	$nom_du_script = $0;
	$nom_du_script =~ s/\.\///;
	print "\n$nom_du_script est un script qui détecte les modifications de fichiers de configuration \n";
	print "induits par l'utilisation d'un outil de configuration GUI.\n";
	print "Le 1° paramètre sera le nom du sous-répertoire produit par la commande\n";
	print "du répertoire $repertoire_de_base qui contiendra les fichiers gérant cette configuration.\n";
	
	print "La liste des fichiers potentiellement modifiés sera établie\n";
	print "lors d'une première modification par l'outil de configuration GUI;\n";
	print "	\n";
	print "Si cette liste existe déjà, le script passe immédiatement aux 2° et 3° phases :\n";
	print "\t2° Enregistrer une copie des fichiers qui sont modifiés par l'outil GUI\n";
	print "\t\tet (après une nouvelle modification par l'outil GUI);\n";
	print "\t3° Enregistrer les modifications effectives opérées par l'outil GUI\n";
	print "\n";
	print "Si la liste existe déjà, mais qu'on veut quand même\n";
	print "refaire la 1° phase\n";
	print "Il faut donner un '-' comme 2° paramètre à la ligne de commande \n";
	print "\n";
	print "De plus, il faut être 'root' (pour pouvoir écrire dans le répertoire /etc)\n";
	print "\t\n";
	print "Les fichiers de configuration du script 'g2c' sont dans le répertoire  \n";
	print "$repertoire_config/1°paramètre : \n";
	print "\tliste.raw\tproduit brut de la commande 'fileschanged -r /etc'\n";
	print "\tliste.sort\tle même, mais trié\n";
	print "\tliste.unic\tet après suppression des doublons\n";
	print "\tliste.diff\tliste des fichiers effectivement différents (dans leur contenu)\n";
	print "\tps\trésultat de '/bin/ps aux' avant la suppression des processus (par les 'kill')\n";
	print "\tpid\tliste des PID des processus supprimés par les 'kill'\n";
	print "\n";
	exit;
}

$id = `whoami`;
chomp $id;
if ($id ne "root") {
	print "Il faut être 'root' (pour pouvoir écrire dans le répertoire /etc)\n";
	exit;
}

if ( ! -d "$repertoire_de_base") {
	print "Création du répertoire de base destiné à contenir les fichiers de configuration de g2c\n";
 	print "\t$repertoire_de_base\n";
   	system("/bin/mkdir $repertoire_de_base"); 
}

if ( ! -d "$repertoire_config") {
	print "Création du répertoire destiné à contenir les fichiers de configuration de g2c\n";
	print "pour la configuration \n";
 	print "\t$repertoire_config\n";
   	system("/bin/mkdir $repertoire_config"); 
}

# définition des noms de fichier
$fcr = "$repertoire_config/liste.raw";
$fcs = "$repertoire_config/liste.sort";
$fcu = "$repertoire_config/liste.unic";
$fcd = "$repertoire_config/liste.diff";
$fcp = "$repertoire_config/pid";
$fcps = "$repertoire_config/ps";

# le fichier '.unic' est le seul qu'il est vraiment nécessaire de consever
# '.raw' et '.sort' sont gardés pour qu'on puisse examiner les étapes intermédiares
# '.diff' permet de ne pas devoir chercher les fichier vraiment modifiés
# '.pid' et '.ps' permettent de voir ce qui se passe au niveau des processus

if ( $param2 eq "-" ) {	
# si on veut recommencer l'opération (phase 1)
   	system("/bin/rm -f $fcu"); 
	# on supprime le fichier $fcu
}
if ( ! -e "$fcu") {	
# si le fichier existe déjà, on ne recommence pas l'opération
	$created = "true";
	# variable auxilliaire permettant un affichage grammatical plus bas
	print "\nDétermination des fichiers modifiés par l'outil de configuration GUI\n";
	print "Tapez 'ENTER' après avoir utilisé l'outil de configuration GUI :";
	if ($pid = fork) {
		chomp $pid;
		# le processus père, celui qui a été créé pour exécuter le script
		# il garde le contrôle de l'entrée standard
		$in = <STDIN>;
    		system("/bin/ps aux > $fcps"); 
		# noter les processus actuels
		open(FCP, ">$fcp");
		# c'est donc ici que l'on peut signaler (par le clavier)
		# qu'on a terminé l'opération GUI
		print FCP "$pid\n";
		# noter le $pid supprimé dans $fcd
    		system("/usr/bin/kill -9 $pid"); 
		# et qu'on peut terminer l'exécution du fils
		# (qui fait le 'fileschanged')
		# car on ne veut que les modifications liées à l'opération GUI
		# MAIS :
		# il faut en fait terminer l'exécution de trois processus :
		# le premier est le fils = un exemplaire de g2c, créé par le 'fork' de la ligne 86 
		# et qui lance (par "system" à la ligne 119 de ce script)
		# le 2° qui est un shell (bash) qui en lance 
		# un 3° : la commande "fileschanged -r /etc > $fcr"
		# il faut donc terminer l'exécution du 'petit-fils' et de
		# l'arrière-petit-fils' aussi
		# (on a simplifié en postulant que les PID's des 'petit-fils' et 'arrière-petit-fils' 
		# sont numériquement suivants
		# ce sera le plus souvent le cas, mais ce n'est pas garanti :
		# si une autre tâche crée des taches 'en même temps' il y risque de panachage des PID's)
		# (Pour être sûr d'être correct, 
		# il faudrait extraire les PID's du fichier $fcps que l'on vient de créer, 
		# au lieu d'incrémenter)
		$pid++;
		# incrémenter $pid
		print FCP "$pid\n";
		# noter le $pid supprimé dans $fcd
    		system("/usr/bin/kill -9 $pid"); 
		# terminer l'exécution du 'petit-fils'
		$pid++;
		# incrémenter $pid
		print FCP "$pid\n";
		# noter le $pid supprimé dans $fcd
    		system("/usr/bin/kill -9 $pid"); 
		# terminer l'exécution de l'arrière-petit-fils'
		close(FCP);
	} else {   
		# le processus fils, celui qui a été créé à la ligne 86 de ce script
    		system("/usr/bin/fileschanged -r /etc > $fcr"); 
		exit; 
		# inutile en fait, car le processus est tué 
		# (par le kill de la ligne 98) avant d'arriver ici.
		# Je mets le 'exit' pour insister sur le fait que le fils ne va pas plus loin
	}	


print "\nExécution de 'fileschanged' terminée\n";

system("/bin/sort $fcr > $fcs");
# le fichier $fcs contient maintenant les noms des fichiers modifiés par le GUI, triés

open(FCS, "<$fcs");
open(FCU, ">$fcu");
while (<FCS>) {
	$ligne = $_;
	print ;
  	if ($ligne_precedante eq $ligne) {	# si la ligne est identique à la précédante 
  		next;
		# on passe au traitement de la ligne suivante
		# (donc sans écrire dans FCU)
	}
	$ligne_precedante = $ligne;
	print FCU;
}	
close FCS;
close FCU;
# le fichier $fcu contient maintenant les noms des fichiers modifiés par le GUI, 
# triés et uniques

print "\nLa liste des fichiers modifiés (potentiellement) par l'outil de configuration GUI\n";
print "est enregistrés dans le fichier $fcu :\n\n";
# affichage à l'écran du stade auquel on est arrivé

system("cat $fcu");
# et le contenu correspondant
print "\n";
# et une ligne vide



}	


open(FCU, "<$fcu");
while (<FCU>) {
	chomp;
	$fichier_de_configuration = $_;
	$nom_du_fichier = $fichier_de_configuration;
	$nom_du_fichier =~ s/.*\/([^\/])/$1/;
	$fichier_de_sauvegarde = "$repertoire_config/$nom_du_fichier";
	
	system("/bin/cp -f $fichier_de_configuration $fichier_de_sauvegarde");
	# on le fait toujours, si le fichier existe déjà, on l'écrase
	# sans demander (-f = 'force')
}	
close FCU;
print "\nEtat actuel des fichiers (potentiellement) modifiés par l'outil de configuration GUI\n";
print "sauvegardés (dans le répertoire $repertoire_config)\n";
# affichage à l'écran du stade auquel on est arrivé


print "\n";
if ( $created eq "true" ) {	
	print "re";
	# détail : pour un affichage grammatical
}
print "faites une modification 'GUI'\n";
print "\npuis faites 'ENTER'\n";
$stdin = <STDIN>;
# entrée au clavier : ne sert qu'à attendre, on n'utilise pas la valeur entrée


open(FCU, "<$fcu");
open(FCD, ">$fcd");
while (<FCU>) {
#	pour chaque fichier pouvant être modifié
	chomp;
	# enlever la fin de ligne
	$fichier_de_configuration = $_;
	$nom_du_fichier = $fichier_de_configuration;
	$nom_du_fichier =~ s/.*\/([^\/])/$1/;
	$fichier_de_sauvegarde = "$repertoire_config/$nom_du_fichier";
	$fichier_diff = "$fichier_de_sauvegarde.diff";

 	$diff = `/usr/bin/diff $fichier_de_sauvegarde $fichier_de_configuration`;
	if ($diff ne "") {	# s'il y a une différence
		print FCD "$fichier_diff\n";
		# mentionner le fichier dans $fcd
		open(OUT, ">$fichier_diff");
		# créer un fichier
			print OUT $diff;
			# contenant la différence
		close OUT;
	}

}	
close FCD;
close FCU;

print "\nLes différences entre l'état actuel des fichiers (effectivement) modifiés\n";
print "par l'outil de configuration GUI\n";
print "et les états sauvegardés sont dans les fichiers avec ajout d'une extension '.diff'\n";
print "La liste de ces fichiers '.diff' se trouve dans $fcd\n";

