#!/usr/bin/perl # # Rat's thwap script, rewritten in perl and diffed a lot. # # django@ccs.neu.edu # July 24, 1993 # # 1/19/94 v2.01 - bdowling # Added: Interactive prompting (-i) # Whuggled option handling # -Allows numeric signals # -Allows varied ordering # Changed finding processes slightly # Added sysV support ?? # 1997.08.05 jay # added Solaris support $0 =~ s#.*/##; $| = 1; $fakeit = 0; $iprompt = 0; # gdc - /usr/bin/kill -> /bin/kill, Redhat Linux 4.2 had only /bin/kill @valid_signals = split(/[ \t\n]+/, `/bin/kill -l`); die "$0: error running 'kill' to gather signals!: $!\n" if $?; $signal = "KILL"; while ($ARGV[0] =~ /^-/) { $_ = shift(@ARGV); if (/^-n$/) { $fakeit = 1; $iprompt = 0; } elsif (/^-i$/) { $iprompt = 1; $fakeit = 0; } elsif (/^-(\w+)/) { $signal = $1; $signal =~ tr/[a-z]/[A-Z]/; $signal =~ s/^SIG//; die "$1: $signal is not a valid signal\n" if (! grep(/^$signal$/, (@valid_signals, (1..$#valid_signals+1) ) ) ); } } #warn "> $signal\n"; # we don't need to do this, since Perl can handle named signals just as well # as numberic ones. In fact, this causes us grief because kill -l does not # return the same thing on all systems #if (! ($signal =~ /^[0-9]+$/)) { # We want to work with a numeric signal # for($x=0;$x<=$#valid_signals;$x++) { # do { $numsignal = ++$x; last; } if @valid_signals[$x] eq $signal; # } #} #warn "> $signal\n"; &usage if ($#ARGV < 0); foreach $uname ('/bin/uname', '/usr/bin/uname', '/sbin/uname') { next unless (-x $uname); chop($rev = `$uname -r`); ($OSMAJOR = $rev) =~ s/\..*//; last; } if ($OSMAJOR == 5) { # System V $ps_flags = " -f "; $ps_flags .= " -e " if ($> == 0); $ps_flags .= " -u $>" if ($> != 0); # Do we need this? Could we just do # ps -f above? It gets some root procs # such as rlogin etc. (which is cool!) } else { # Assume BSD system, what others could we check for? $ps_flags = "uxww"; $ps_flags .= "a" if ($> == 0); # Only need this if we're root } # Don't want a leading "-" on the flags, so it works on both Alphas and Suns: $ps_pid = open(PS, "ps $ps_flags |"), "\n"; $header = ; $seen_header = 0; $thwapped = 0; while () { ($foo = $_) =~ s/^\s*//; ($user, $pid, @rest) = split(' ',$foo); next if ($pid == $$ || $pid == $ps_pid); # Don't thwap this process! next if (/thwap/); # Hackish attempt to avoid # thwapping this process # when invoked via rsh testit: foreach $expr (@ARGV) { if ($expr =~ /^[0-9]+$/) { # make numbers only match pids next testit if ($pid != $expr); } if (grep(/$expr/, $_)) { # warn "expr = $expr; user = $user; pid = $pid; rest = @rest\n"; warn $header if (! $seen_header); warn "\n" if ($seen_header && $iprompt); $seen_header = 1; warn $_; if (! $iprompt || &AskYN() ) { # warn "-> kill $signal $pid\n" if (! $fakeit); if (! $fakeit ) { # quotes needed around $signal so Perl will interpret both # numeric and non-numberic signals properly -- dNb $killed = kill("$signal", $pid); warn "kill: $!\n" if ! $killed; $thwapped += $killed; } else { $thwapped++; } } last testit; # Okay it's dead jim, we're done this loop. } } } close(PS); warn "$0: ", ( $fakeit ? "would have " : "" ), "sent SIG${signal} to $thwapped process", ($thwapped == 1 ? "" : "es"), "\n"; sub usage { warn <<"EOT"; Usage: $0 [options] ... Options: -n fake mode - only display processes that would be selected -i interactive mode - prompt on each suspect process - any valid literal or numeric signal (see kill -l) EOT exit(1); } sub AskYN { print STDERR "Send SIG", @valid_signals[$numsignal-1], " to this process? (y/n/a)? "; $ans = ; $iprompt = ! ($ans =~ /^a/i); return( $ans =~ /^[ay]/i ); }