#!/usr/local/bin/perl
#####################################################################
# TITRE:	TivVcnxTMR
#--------------------------------------------------------------------
# CREE LE:	15/11/1999			Par: V.BRION S.GISLAIN
#--------------------------------------------------------------------
#    
# OBJET DU PRESENT TEMPLATE: 
# - Recherche le nombre de process Autosys "interface graphique"
#   consommant plus de $SeuilCpu% de cpu (=> pb si > 0).
# - Envoi de 1 a l'opcmon si process trouve(s).
# - Si reception de 1, l'opcmon re-appelle alors le template avec "" en parametre.
# - Le template renvoie alors le nom des process en cause dans les annotations ITO, 
#   plus le nom du responsable a contacter et l'adresse IP d'ou a ete generee le process.
#			
#====================================================================
# Modifie le:	JJ/MM/AA		Par: 
#	Motif: motif ayant justifie la modification et points
#	modifies si besoin
#
#####################################################################
# REMARQUES: Les entetes des fonctions ont ete allegees pour plus
#            de lisibilite (fonction de petite taille et presque
#            identiques
#
#####################################################################
# CONVENTION DES CODES DE RETOUR (autres que 0 (Ok) et 1 (erreur))
#
#====================================================================
# ACCES ET DROITS D'APPEL
#	Mode: 0777	Owner: 			Group:
#====================================================================
# PRE-REQUIS EN ENTREE
# Environnement materiel:
#	Machine: 			Constructeur: HP,SUN,IBM,SGI
# Environnement logiciel:
#	OS: hp-ux			Version: 9.05
#	    hp-ux				 10.20
#	    Solaris				 5.3
#	    Solaris				 5.5
#	    SunOs 				 4.1.3
#	    AIX					 3.x
#	    AIX					 4.2
#	    IRIX				 5.3
# Initialisation des variables globales (environnement, reseau...):
#	VARIABLE1	=	
#	VARIABLE2	=
#####################################################################

### Fonctions:
####################
# IdentificationAutosys(<process>):	Verifie si le process contient les chaines de caractere
#					identifiant un process Autosys 'interface graphique'.
# Continuer:				Traitement effectue lors du second appel du template.
# ChercheParPtree(<process>):		Lance /usr/proc/bin/ptree sur un process.
# ChercheParPs(<process>):		Output par ps d'un process recupere auparavant par ptree.
# AnnotationIto:			Affichage des process fautifs dans les annotations ITO.
# ChercheProprio(<process>):		Recherche le proprietaire d'un process selon son champ 'user'.
#					Les proprietaires sont codes en dur dans le template.
# ChercheTerminal(<process>):		Recherche du terminal ayant lance un process, par equivalence
#					entre le champ TTY du process et le DISPLAY correspondant      
# 					retourne par who. Seules les adresses IP sont retenues.

### parametrie
####################
$Chaines = "<defunct> autosc autoc cape";	# Chaines identifiant les process cherches:
						# <defunct>, autosc, autocons, autocal, hostcape, jobscape.
@IdentifieChaine = split(/ /,$Chaines);		# Tableau des chaines precedentes pour traitement en boucle.
$Defunct = "<defunct>";		# <defunct> est recuperee par ps -aef, pas par ps -aef -o ...
$Proprio = "KO";		# Passe a OK si le user est identifiable (liste en dur dans ce fichier)	
$Terminal = "KO";		# passe a OK si le terminal est identifiable (adresse IP => PC)
$SeuilCpu = 15;			# Seuil de % de cpu consomme a partir duquel declencher une alerte. 
$Nbr = 0;			# 0 ou 1, renvoye comme argument. Autre utilisation dans &Continuer.
$TotalCpu = 0;			# Compteur de process fautifs trouves.
$Cpt = 0;			# Compteur de process fautifs pour l'affichage sous ITO.
$Host = `/usr/bin/hostname`; 
chop $Host;
$Date = `/usr/bin/date`; 
chop $Date;

$NomTemplate = "";
$NomTemplate = $ARGV[0] if(scalar(@ARGV) > 0);

# Recuperation de tous les process dans TabPs_aef (TabPsC_aef = id, avec ligne d'en-tete).
#######################################################
@TabPsC_aef = `/usr/bin/ps -aef -o s,user,pid,ppid,tty,stime,pcpu,pmem,comm`;
foreach $TabPsC_aef(@TabPsC_aef)
{
        chop $TabPsC_aef;
        if($TabPsC_aef !~ /PPID/)
        {
                push (@TabPs_aef,$TabPsC_aef);
        }
}

# Sur ces process, recuperation des seuls process Autosys 'interface graphique' consommant plus de $SeuilCpu% de cpu.
#######################################################
foreach $TabPs_aef(@TabPs_aef)
{
        ($S,$User,$Pid,$Ppid,$Tty,$Stime,$Pcpu,$Mem,$Com) = split(/\s+/,$TabPs_aef);
	$TabPs_aef = $TabPs_aef . $Defunct if($Com eq "");
        if(($Pcpu >= $SeuilCpu) && (&IdentifieAutosys($Com) == 1))
        {
               	push (@TabCpuKo,$TabPs_aef);
        }
	$TotalCpuKo = scalar(@TabCpuKo);	
}

# Fonction d'identification des process Autosys 'interface graphique'.
#######################################################
sub IdentifieAutosys 
{
	local ($Com) = @_;
	foreach $IdentifieChaine(@IdentifieChaine)
	{
		if($Com =~ /$IdentifieChaine/)
		{
			return 1;
			last;
		}
	}
	return 0;
}

# Premier appel: envoi de 0 ou 1 a l'opcmon. Second appel: on continue.
#######################################################
if($NomTemplate eq "")
{
	&Continuer;
}
else
{
	$Nbr = 1 if(scalar(@TabCpuKo) > 0) ;
	$Commande = "/logiciel/OpC/opcmon $NomTemplate=$Nbr";
#	$Commande = "/logiciel/autosys/outils/cmd/ps-ito $Nbr";
	system( $Commande );
}

	

# Second appel
#######################################################
sub Continuer
{
	&AnnotationIto;
	foreach $TabCpuKo(@TabCpuKo)
        {
		$Cpt++;
		if($TotalCpuKo > 1)
		{
			print "Process fautif numero $Cpt:\n";
		}	
		&ChercheParPtree($TabCpuKo);
		print "\nLe ou les process a killer sont:\n\n";
        	print "@TabPsC_aef[0]\n";
		foreach $PidPtree(@PidPtree)
		{
			&ChercheParPs($PidPtree);
		}
                foreach $TabFin(@TabFin)
                {
                        &ChercheProprio($TabFin) if($Proprio ne "OK");
                        &ChercheTerminal($TabFin) if($Terminal ne "OK");
                }
                print "$b\n";
                print "\n" if($Nbr != 0);
		print "Demander a la ou les personnes suivantes l'autorisation de killer ce(s) process:\n";
                print "$Chaine\n";
                $TerminalUser = "inconnu" if($Terminal ne "OK");
                print "Terminal ayant lance le process fautif: $TerminalUser.\n";
                print "----------------------------------------------------------------------------\n";
                $Proprio = "KO";
                $Terminal = "KO";
                print "\n";
        }
}

# Second appel: arborescence d'un process par /usr/proc/bin/ptree. 
#######################################################
sub ChercheParPtree
{
        local($TabCpuKo) = @_;
                @TabFin = ();
		@PidPtree = ();
        	($S,$User,$Pid,$Ppid,$Tty,$Stime,$Pcpu,$Mem,$Com) = split(/\s+/,$TabCpuKo);
		@Ptree = `/usr/proc/bin/ptree $Pid`;
		$NbrPtree = scalar(@Ptree);
		print "\nArborescence du process:\n\n" if($NbrPtree > 1);
		foreach $Ptree(@Ptree)
		{
			print "$Ptree" if($NbrPtree > 1);
			($PidPtree,$Reste1,$Reste2) = split(/\s+/,$Ptree);
			$PidPtree = $Reste1 if($PidPtree eq "");
			push(@PidPtree,$PidPtree);
		}
}

# Second appel: affichage litteral d'un process par ps (Autosys seul). 
#######################################################
sub ChercheParPs
{
        local($PidPtree) = @_;
        		foreach $TabPs_aef(@TabPs_aef)
        		{
				($S,$User,$Pid,$Ppid,$Tty,$Stime,$Pcpu,$Mem,$Com) = split(/\s+/,$TabPs_aef);
				if(($Pid == $PidPtree) && (&IdentifieAutosys($Com) == 1))
				{
					if(($Com eq "") && ($S eq "Z"))
					{
						$NewCom = $Defunct;
						$TabPs_aef = $TabPs_aef . $NewCom;
					}
					push (@TabFin,$TabPs_aef);
					print "$TabPs_aef\n";
					last;
				}
			}
}

# Second appel: affichage dans les annotations ITO.
#######################################################
sub AnnotationIto
{
        print "##############################################################################\n";
        print "$Date     $Host\n";
	print "Liste des process Autosys 'interface graphique' consommant plus de $SeuilCpu% de cpu:\n";	
        print "##############################################################################\n";
}

# Second appel: recherche du user ayant lance le process.
#######################################################
sub ChercheProprio
{
        local($TabFin) = @_;
        ($S,$User,$Pid,$Ppid,$Tty,$Stime,$Pcpu,$Mem,$Com) = split(/\s+/,$TabFin);
        if($User =~ /adminalc/)
        {
                $Chaine = "user ". $User . " => Robert Wamba, tel:49338.";
                $Proprio = "OK";
        }
        elsif($User =~ /polalc/)
        {
		$Chaine1 = "user ". $User . " => Nicolas Bachellereau, tel:42672,\n";
		$Chaine2 = "            ou Bernard Becheny,      tel:49302,\n";
		$Chaine3 = "            ou Stephane Laruelle,    tel:49342.";
		$Chaine = $Chaine1 . $Chaine2 . $Chaine3;
                $Proprio = "OK";
        }
        elsif($User =~ /adminphf/)
        {
                $Chaine = "user ". $User . " => Dominique Soyer, tel:42551.";
                $Proprio = "OK";
        }
        elsif($User =~ /adminbpu/)
        {
                $Chaine = "user ". $User . " => Robert Wamba, tel:49338.";
                $Proprio = "OK";
        }
        else
        {
                $Chaine = "user ". $User . " inconnu";
        }
}

# Second appel: recherche de l'adresse IP du terminal ayant lance le process.
#######################################################
sub ChercheTerminal
{
        local($TabFin) = @_;
        ($S,$User,$Pid,$Ppid,$Tty,$Stime,$Pcpu,$Mem,$Com) = split(/\s+/,$TabFin);
        if($Tty =~ /pts/)
        {
                $Term = `/usr/bin/who | grep "$Tty"`;
		chop $Term;
                ($a1,$a2,$a3,$a4,$a5,$TerminalUser) = split(/\s+/,$Term);
#		Seules les adresses IP son retenues comme adresses interessantes.
#		Le process du pts/xx peut avoir disparu au moment ou est lance &ChercheTerminal, d'ou:
                $Terminal = "OK" if(($TerminalUser ne "") && ($TerminalUser =~ /\./));
        }
}
