#!/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 ;
}