#!/usr/local/bin/perl
# killer.pl -- return list of pid's 

use locale;
use Text::ParseWords;

sub pusher {};
sub help {};

%OPT=( '--name' => 8, '--ppid' => 2, '--pid' => 1,
  '--tty' => 5, '--uid' => 6, '--user' => 5
);
my $sps="ps -a ";

my $a, $pid, $i, @name=(), $pp2=0, $ykill="n", $par, @apar=(), $all="NO";
@apid1=(); %apid=(); %hpid=();

$pid=shift;
if(!defined $pid) { help(); exit 1; }
my $str="", @a1=(), $sysname=`uname -s`, $nt=1;

while($pid) {
  @a1=quotewords("=",0,$pid);
  if($a1[0] eq "--help") { help(); exit 0; }
  if($a1[0] eq "--auto") { $ykill="y"; }
  if($a1[0] eq "--win") {
    if($sysname !~ /CYGWIN_9/) {
      if ($pp2==$OPT{'--name'}) { $pp2++; } $OPT{'--name'}++;
      $nt=0;
    }
    $sps.="-W ";
  }
  if(defined $OPT{$a1[0]}) {
    $par=$a1[0];
    $pp2=$OPT{$par};
    @apar=quotewords(",",0,$a1[1]);
    if($apar[0] eq "ALL") {$all="ALL";}
  }

  $pid=shift;
}

open(OH,$sps." |") or return "Could't run $sps 4 killer.pl ";
$i=<OH>;
while(<OH>) {
  $_=lc;
  if( ! (/^i\s+\d+/ && /\/perl$/) )  {
    chomp $_;
    $_ =~ s/([A-Za-z])\s([A-Za-z])/$1_$2/g;
    ($pid,$a,$i)=(split(/\s+/,$_))[1,2,$pp2];
    $apid{$a}=() unless $apid{$a} ;
    push(@{$apid{$a}},$pid);
    $i=~ s/\\/\//g;
    push(@name,$i);
    push(@apid1,$pid);
  }
}
close(OH);

foreach $p2 (@apar) { $p2=lc($p2); }

if ($par eq "--user") {
  open(FH,"/etc/passwd");
  $str=join(/\n/,<FH>);
  close(FH);
  @a1=split(/\n/,$str);
}
if ($par eq "--user" && $all eq "ALL") {
  foreach (@a1) { ($pid)=(split(/:/,$_))[2]; push(@apar,$pid); }}
if ($par eq "--user" && $all ne "ALL") {
  foreach $i (@apar) { foreach (@a1) {
    ($a,$pid)=(split(/:/,$_))[0,2];
    if ($a eq $i) { push(@apar,$pid); last; }
  }}
}

if ($par ne "--user" && $all eq "ALL") { @apar=(); push(@apar,@name); }

foreach $p2 (@apar) {
  if($pp2 == $OPT{'--ppid'} || $pp2 == $OPT{'--pid'}) {
    $hpid{$p2}++;
    for($i=0; $i<=$#name; $i++) { if ($name[$i] == $p2) {
      $hpid{$apid1[$i]}++;
      pusher(\%apid, $apid1[$i]);
    } }
  }

  if($pp2 == $OPT{'--name'}) { for($i=0; $i<=$#name; $i++) {
    if ($name[$i] =~ /\/$p2/) {
      $hpid{$apid1[$i]}++; pusher(\%apid, $apid1[$i]); } } }

  if($pp2==$OPT{'--tty'} || $pp2==$OPT{'--uid'} || $pp2==$OPT{'--user'}) {
    for($i=0; $i<=$#name; $i++) {
    if ($name[$i] eq $p2) { $hpid{$apid1[$i]}++; } } }

}

@a=keys(%hpid);
if ($#a<0) { print "Not found pid's"; }
else { if($ykill ne "y") {
    print "Kill this proc [ @a ] [y|n] : ";
    $ykill=<STDIN>;
    $ykill=lc($ykill);
  }
  if ($ykill eq "y") {
    if ($nt) {
      $sps="kill -9";
      foreach $i (@a) { $sps.=" $i"; }
      open(OH,$sps." |") or return "Could't run $sps 4 killer.pl ";
      while(<OH>) { print $_; }
      close(OH);
    } else {  kill 9, @a; }
  }
}

exit;

sub pusher {
  my ($h,$p)=@_;
  my $i,$j;
  foreach $i (@{$h->{$p}}) {
   $hpid{$i}++;
   if($h->{$i}) {pusher($h,$i); }
  }
  return;
}

sub help {
print "\
Killer -- program for kill process with win-process\
sort by pid, ppid, uid, tty , user or procname.\
Usage $0 OPTION=p1,p2,... [--auto]\
Command line parametrs:\
--pid=  -- kill process on pid\
--ppid= -- kill process on ppid & pid==ppid\
--uid=  -- kill process on uid\
--user= -- kill process on user name or ALL\
--tty=  -- kill process on tty\
--name= -- kill process by name\
--win   -- include WINDOWS process\
--auto  -- auto kill\
--help  -- print this text\
\ 
Killer v 1.0\
Copyleft CNU GPL. Bootmaker SoftWARe 1999-2004.\n";

  return;
}

