Return to BSD News archive
Path: euryale.cc.adfa.oz.au!newshost.carno.net.au!harbinger.cc.monash.edu.au!munnari.OZ.AU!news.ecn.uoknor.edu!news.wildstar.net!news.ececs.uc.edu!newsxfer.itd.umich.edu!newsxfer3.itd.umich.edu!su-news-hub1.bbnplanet.com!cpk-news-hub1.bbnplanet.com!news.bbnplanet.com!ais.net!news.idt.net!out2.nntp.cais.net!news2.cais.com!news From: Vivek Khera <khera@kciLink.com> Newsgroups: comp.unix.bsd.bsdi.misc Subject: Re: BSDI3.0 and Skill (superkill) Date: 07 Apr 1997 00:12:16 -0400 Organization: Khera Communications, Inc., Rockville, MD Lines: 385 Message-ID: <x7wwqfii8v.fsf@kci.kciLink.com> References: <3347c498.0@news.nucleus.com> NNTP-Posting-Host: 204.117.82.1 Mime-Version: 1.0 (generated by tm-edit 7.106) Content-Type: text/plain; charset=US-ASCII X-Newsreader: Gnus v5.4.37/XEmacs 19.15 Xref: euryale.cc.adfa.oz.au comp.unix.bsd.bsdi.misc:6605 I use a perl version of skill that has worked fine since BSD/OS 2.1. It seems to work on BSD/OS 3.0 also, since it only relies on the output of the ps program to be the same. #!/bin/sh # This is a shell archive (produced by GNU sharutils 4.1). # To extract the files from this archive, save it to some FILE, remove # everything before the `!/bin/sh' line above, then type `sh FILE'. # # Made on 1997-04-07 00:12 EDT by <khera@kci.kciLink.com>. # Source directory was `/usr/local/bin'. # # Existing files will *not* be overwritten unless `-c' is specified. # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 7808 -rwxr-xr-x skill # touch -am 1231235999 $$.touch >/dev/null 2>&1 if test ! -f 1231235999 && test -f $$.touch; then shar_touch=touch else shar_touch=: echo echo 'WARNING: not restoring timestamps. Consider getting and' echo "installing GNU \`touch', distributed in GNU File Utilities..." echo fi rm -f 1231235999 $$.touch # # ============= skill ============== if test -f 'skill' && test X"$1" != X"-c"; then echo 'x - skipping skill (file already exists)' else echo 'x - extracting skill (text)' sed 's/^X//' << 'SHAR_EOF' > 'skill' && #!/usr/bin/perl # zap -- blow away (or renice) processes # tom christiansen -- tchrist@usenix.org # # currently configured for BSD # # Patterned after an idea from K&P, an old script # of mine, and Jeff Forys's humungous C program, skill. :-) # # # some defaults... look out for the first one! X ($PRIO_MIN, $PRIO_MAX) = (-64, 64); # from sys/resource.h $signal = 'TERM'; $priority = +4; X ############################################################### X setpriority(0, $$, $PRIO_MIN); # faster faster faster $SIG{HUP} = IGNORE; X $| = 1; X &init; &parse_args; &usage unless @cmd || @tty || @pid || @regexp || @user; &dump_values if $flag{'d'}; &start_ps; &kill_procs; exit $status; X ##################################################################### X sub parse_args { X local($numarg, $type, $signals); # include *targets and die X X while ($_ = shift @ARGV) { X if (/^[-+](\d+)$/) { X $numarg = $_; # signal or numeric X } X elsif (s/^-//) { X if (defined $signame{$_}) { X if ($mode eq 'nice') { X warn "$0: can't mix signals with niceties, ignoring -$_\n"; X } else { X $signal = $_; X } X } X elsif (s/^([cputr])(.*)//) { X *targets = $targptr{$type = $abbrev{$1}}; X $_ = $2 || shift @ARGV; X unless (&targets($_)) { X die "$0: $_: invalid $type" unless $type eq 'regexp'; X die "$0: $@\n"; X } X push(@targets, $_); X } X else { # these can be anywhere X $flag{$1}++ while s/^([ildvNna])//; X if (/[cputr]/) { s/^/-/; redo; } # bad hack X if ($_ ne '') { X warn "$0: unknown option -$_\n"; X &usage; X } X if ($flag{'l'}) { X $signals = "\@signum"; X write; # see format at end of file X exit; X } X } X } X else { # time to guess X if ( s!^/dev/!! || &tty($_)) { X *targets = $targptr{'tty'}; X } elsif (&user($_)) { X *targets = $targptr{'user'}; X } elsif (&pid($_)) { X *targets = $targptr{'pid'}; X } elsif (s!^/(.*)/?$!$1!) { X die "$0: $@\n" unless ®exp($_); X *targets = $targptr{'regexp'}; X } else { X *targets = $targptr{'cmd'}; X } X push(@targets,$_); X } X } X X $mode = 'nice' if $flag{'N'}; X X if (defined $numarg) { X if ($mode eq 'kill') { X $numarg =~ s/^[-+]//; X $signal = $numarg ? $signum[$numarg] : 0; # perl hates 'ZERO' X } else { X undef $signal; X $priority = $numarg; X $priority = $PRIO_MIN if $priority < $PRIO_MIN; X $priority = $PRIO_MAX if $priority > $PRIO_MAX; X } X } X } X X ##################################################################### X sub uid2name { X local($uid) = @_; X unless (defined $name{$uid}) { X local($name) = (getpwuid($uid))[0]; X $uid{$name} = $uid; X $name{$uid} = $name; X } X $name{$uid}; } X sub name2uid { X local($name) = @_; X unless (defined $uid{$name}) { X local($uid) = (getpwnam($name))[2]; X $uid{$name} = $uid; X $name{$uid} = $name; X } X $uid{$name}; } X ###################################################################### # magic names here -- touch these and you are apt to be surprised X sub pid { X local($pid) = @_; X $pid =~ /^\d+$/; } X sub tty { X local($tty) = @_; X $tty =~ /^tty/ && -c "/dev/$tty"; } X sub user { X local($who) = @_; X local($ok) = &name2uid($who); X defined $ok; } X sub cmd { X 1; } X sub regexp { X local($pat) = @_; X eval '/$pat/'; X $@ =~ s/at \(eval\).*\n//; X $@ eq ''; } X ###################################################################### X sub init { X # run either as skill or as snice; this tells whether -5 is a # signal or a priority X X $mode = 'kill'; X $mode = 'nice' if $0 =~ /nice/; X # generate signal names ; comment out signames assignment # to run kill -l instead to figure it out X X $signames = <<__EOLIST__; # comment out for dynamic determination X HUP INT QUIT ILL TRAP IOT EMT FPE KILL BUS SEGV SYS PIPE ALRM X TERM URG STOP TSTP CONT CHLD TTIN TTOU IO XCPU XFSZ VTALRM PROF X WINCH INFO USR1 USR2 __EOLIST__ X X local($signal); X $signum[0] = 'ZERO'; X for (split(' ', $signames ? $signames : `kill -l`)) { X $signame{$_} = ++$signal; X $signum[$signal] = $_; X } X # set up pointers and single-char abbrev for our 4 target arrays # if you change one of strings, all idents of this name, including # the subroutines, must change also. be VERY CAREFUL. X X for ('cmd', 'pid', 'user', 'tty', 'regexp') { X $abbrev{(/^(.)/)[0]} = $_; X $targptr{$_} = eval "*$_"; X } X # some defaults X } X ##################################################################### X sub dump_values { X print "signal is $signal -$signame{$signal}\n" if $mode eq 'kill'; X print "will renice targets to $priority\n" if $mode eq 'nice'; X X for (keys %targptr) { X *targ = $targptr{$_}; X next unless defined @targ; X print "$_ targets are ", join(', ', @targ), "\n"; X } X X @flags = keys %flag; X grep(s/^/-/, @flags); X print "option flags are @flags\n"; } X ##################################################################### X sub usage { X die <<EOF; Usage: X skill [-signal] [-Nildvna] {tty user command pid regexp} X snice [(-|+)priority] [-Nildvna] {tty user command pid regexp} X X -i interactive X -v show candidates X -n like -v but do not really do it X -a all procs are candidates X -N nice mode X -d enable debugging X X -l list signals and exit X X Uniquely identify {...} args with leading -t, -u, -c, -p, -r X Or use a leading slash for a regexp. EOF X exit 1; } X ###################################################################### X sub start_ps { X $ps = 'ps xl'; X $ps .= 'w'; X X grep($pid{$_}++, @pid); X grep($user{&name2uid($_)}++, @user); X grep($tty{$_}++, @tty); X grep($cmd{$_}++, @cmd); X $regexp = join('|', @regexp); X X $ps .= 'w' if $regexp; X $ps .= 'a' if $> == 0 || X $flag{'a'} || X @user > 1 || X (@user == 1 && &name2uid($user[0]) != $>); X # if (! $pattern && @cmd && !grep(m!^/!, @cmd)) { $ps .= 'c'; } X X if (@tty == 1) { # faster X $tty[0] =~ /^tty(..)/; X $ps .= "t$1"; X } X X print "ps command is $ps\n" if $flag{'d'}; X X defined($kid_pid = open(PS, "$ps |")) || die "can't run ps: $!"; X if (<PS> !~ /UID/) { X warn "Something's wrong with ps"; X kill 'TERM', $kid_pid; X exit 2; X } X X $dad_pid = getppid(); } X ###################################################################### X sub kill_procs { X while (<PS>) { X # first two fields on BSDi X ($user, $pid) = /^\s*(\d+)\s*(\d+)/i; X X next if $pid == $$; X next if $pid == $kid_pid; X next if $pid == $dad_pid && $mode eq 'kill'; X X next if @user && !$user{$user}; X next if @pid && !$pid{$pid}; X X # time is in dd:dd.dd format on BSDi X ($tty, $cmd) = /\s*(\S*)\s*\d+:\d+\.\d+\s+(.*)$/; X $tty = "tty$tty" unless $tty =~ /\?/; X X next if @tty && !$tty{$tty}; X next if @regexp && $cmd !~ /$regexp/o; X X if (@cmd) { X ($cmdname) = ($cmd =~ /^(\S+)/); X $cmdname =~ s!.*/!!; X next if !$cmd{$cmd} && !$cmd{$cmdname}; X } X X printf "%5d %-8s %-5s %s ", $pid, &uid2name($user), $tty, $cmd X if $flag{'v'} || $flag{'i'} || $flag{'n'}; X X if ($flag{'i'}) { X $_ = <STDIN>; X defined || exit; X /^\s*y/i || next; X } X X $hits++; X X unless ($flag{'n'}) { X $! = 0; X if ($mode eq 'kill') { X kill $signal, $pid; X } else { X setpriority(0, $pid, $priority); X } X if ($!) { X warn (($mode eq 'kill' ? 'kill' : 'setpriority') X . " $pid: $!\n"); X $status = 1; X next; X } X } X X print "\n" if $flag{'v'} || $flag{'n'}; X } X close PS || die "something happened to your $ps"; X warn "$0: no target processes found\n" unless $hits; } X ###################################################################### X format STDOUT = Any of the following signals are valid, or their numeric equivalents: X~~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< X $signals X. SHAR_EOF $shar_touch -am 0204173396 'skill' && chmod 0755 'skill' || echo 'restore of skill failed' shar_count="`wc -c < 'skill'`" test 7808 -eq "$shar_count" || echo "skill: original size 7808, current size $shar_count" fi exit 0