#!/usr/bin/perl

################################################################################
#                                                                              #
#  ext|scripts (C) 2000-2004 Pavel Novikov (pavel@ext.by)                      #
#                                                                              #
################################################################################

################################################################################
#
#  Shutdowns a running jail and all its processes.
#
#  Usage: ./jkill.pl [lj|long_jails] <jail name>
#


#:-)
use strict;

#no buffer
$|=1;

#constants
my $PS_BIN="/bin/ps";
my $PS_OPTIONS;
my $DIR_PROC="/proc";
my $FILE_STATUS="status";

#data
my $pid_position=-1;

#other defaults
my $O_CUT_JAILS=1;

#not jailed
my $NOT_JAILED="-";
my $JAIL="";

#strip shit
sub strip
{

	#come on
	my $line=shift;

	#leading spacing ones
	$line=~s{^\s\s*(.*)$}{$1}gs;

	#trailing spacing ones
	$line=~s{^(.*)\s\s*$}{$1}gs;

	#add eol
	return($line);

}

#read options
while(my $option=shift)
{
	if(($O_CUT_JAILS)&&(($option eq 'lj')||($option eq 'long_jails')))
	{
		$O_CUT_JAILS=0;
	}
	else
	{
		$JAIL=$option;
	}
}
if(!$PS_OPTIONS){$PS_OPTIONS=" -axuf";}

#check
if(!$JAIL){print "ERROR: No jail name specified.\n";exit(1);}

#killed
my $has_processes=1;

#try unless have some processes
while($has_processes)
{

	#flush
	$has_processes=0;

	#open a pipe
	if(open(P,$PS_BIN.$PS_OPTIONS." |"))
	{

		#fetch data
		my $c=0;
		while(<P>)
		{

			#fix & save
			chomp($_);
			my $line=$_;

			#split data
			my @line=split(/\s\s*/,&strip($line));

			#header
			if($c==0)
			{
				my $i=0;
				foreach my $field (@line)
				{
					if($field eq 'PID')
					{
						$pid_position=$i;
						last;
					}
					++$i;
				}
			}

			#line
			else
			{
				if($pid_position>=0)
				{
					my $pid=@line[$pid_position];
					if(open(F,"<".$DIR_PROC."/".$pid."/".$FILE_STATUS))
					{
						while(<F>)
						{
							chomp($_);
							my @data=split(/\s\s*/,$_);
							my $jail=$data[$#data];
							if(($jail)&&($jail ne $NOT_JAILED))
							{
								if($O_CUT_JAILS)
								{
									$jail=~s/^([^\.]*)\..*$/$1/gsmi;
								}
								if($jail eq $JAIL)
								{
									$has_processes=1;
									print "Killing PID #".$pid." ...\n";
									kill(9,$pid);
								}
							}
						}
						close(F);
					}
				}
			}

			#next
			++$c;

		}

		#close the pipe
		close(P);

	}

}

syntax highlighted by Code2HTML, v. 0.9.1