#!/usr/local/bin/perl
#
# /usr/local/bin/killu - kill users by login name
#
# Author: Jim Wildman, 3X HealthCare Solutions Group
# Date: 12/27/1999
# Updated: many times, whenever I get the urge
use Getopt::Std;
# This is the list of logins/users that we can't kill with this script
@notkillable = ("root","daemon","bin","sys","adm","uucp",
"lp","nuucp","hpdb","www","tftp");
# make sure these are 0
$loginstokill = $kill_mis = $kill_pack = $kill_ship = 0 ;
@kterm = ("killed","exterminated","slaughtered","extinguished","slayed",
"finished off", "eliminated","obliterated",
"administered the coup de gras to","capped","murdered","terminated",
"euthanized");
$kterm_count = $#kterm + 1 ;
getopts('hsu:') || die "Usage: killu [-h] | [-s] -u <Userstringto_kill>\n";
if(($opt_u eq "") || ($opt_h)) {
printf("Usage: killu [-h] | [-s] [-u stringtokill] \n");
printf(" Kill logins by userid\n");
printf(" -h display this help message\n");
printf(" -s simulate, don't kill anyone\n");
printf(" -u actually kill the logins\n");
printf(" Userstringto_kill will be matched against user ids\n");
printf(" beginning at the start of the id. \n");
printf(" -u is required. Will not match root or uids < 100\n");
printf(" brcpk*, brcshp*, and mis* logins will only be\n");
printf(" killed if those prefixes are used.\n");
exit;
}
# set our kill string to match on
$kill_string = $opt_u;
# slurp up the passwd file to get user names.
# sure would be nice to have complete info in here!!
@pwlist = `cat /etc/passwd` ;
foreach $item (@pwlist) {
chomp $item ;
($logname,$f1,$userid,$f3,$username) = split(/\:/,$item) ;
# all we are after is the login id and user id
$uname{$logname} = $userid ;
}
# This depends on all of the 'system' ids being in the notkillable array
foreach $i (@notkillable) {
if($kill_string =~ $notkillable[$i]) {
print( "NO! You are not allowed to kill system processes\n");
print("System processes have to be killed from a root login\n\n");
exit();
}
}
# Get our list of users
# This is where the big delay in the program is. 'who -u' takes a
# couple of seconds
@users = `who -u`;
# unprotect the brcshp (shipping) ids
if($kill_string =~ "brcshp") {
$kill_ship = 1 ;
}
# unprotect the brcpk (packing) ids
if($kill_string =~ "brcpk") {
$kill_pack = 1 ;
}
# unprotect the mis (IS) ids
if($kill_string =~ "mis") {
$kill_mis = 1 ;
}
# For each user analyze the lines.
foreach $item (@users) {
chomp $item;
# split the who output. We really just need user and pid.
($user,$ltty,$lmon,$lday,$time,$idletime,$lpid,$host) = split(/\s+/,$item) ;
if($user =~ "^$kill_string") {
if( ($user =~ "^brcshp") && ($kill_ship == 0) ) {
next ;
}
if( ($user =~ "^brcpk") && ($kill_pack == 0) ) {
next ;
}
if( ($user =~ "^mis") && ($kill_mis == 0) ) {
next ;
}
if( $uname{$user} < 100 ) {
print "$lpid for $user is a system process and will live\n";
next;
}
# associate the user names with their pids
$kuser_list{$lpid} = $user ;
$loginstokill++ ;
if($opt_s ne "") {
printf("%8.8s-%5.0d,", $user, $lpid) ;
if(($loginstokill % 5)==0) { print "\n" ; }
}
}
$tot_users++;
}
print "\n\nLast chance. If you haven't sudo'ed in a while, you will be" ;
print "\nprompted for your password. Otherwise, when you hit 'y<return>'" ;
print "\n******They're gone!!******" ;
print "\nLocked, loaded and ready to kill $loginstokill matching $kill_string out of $tot_users (y/n): ";
$confirm = <STDIN>;
chomp $confirm;
print "\n";
if ($confirm eq "y" || $confirm eq "Y") {
foreach $i (sort by_user (keys %kuser_list)) {
$kindex = $kcount % $kterm_count ;
$kphrase = $kterm[$kindex] ;
$kcount++ ;
if($opt_s) {
print "PID $i for $kuser_list{$i} would have been $kphrase.\n" ;
}
else {
system("sudo kill -9 $i") ;
print "PID $i for $kuser_list{$i} has been $kphrase. \n" ;
}
}
print "I hope you are happy now!\n\n" ;
}
# Define our own sort routine to sort by the user name
sub by_user {
return $kuser_list{$a} cmp $kuser_list{$b} ;
# return $a <=> $b ;
}