#!/usr/local/gnubin/bash # 05-Jan-92 Noah Friedman # Last modified 03-Feb-93 # # pidctrl, a shell script for frobnicating processes (probably upon logout) # # There are a few known bugs. For BSDish systems, when the STAT field has # embedded spaces, the printed program name will be wrong. # # Public domain. # function usage () { if [ $# -gt 0 ]; then echo -e "${progname}: $*\n" 1>&2 fi cat 1>&2 < /dev/null)"; echo "${uname:-unknown}" } function parse_command_args () { local orig_number_options=$# # unset option variables to make sure they weren't accidentally # exported unset debug force_kill verbose proglist # If you add new commands be sure to change the wildcards below to make # sure they are unambiguous (i.e. only match one possible long option) # Be sure to show at least one instance of the full long option name to # document what the long option is canonically called. while [ $# -gt 0 ]; do case z$1 in z-D | z--debug | z--d* ) debug=t shift ;; z-k | z--kill | z--k* ) force_kill=t shift ;; z-h* | z--help | z--h* ) usage ;; z-v | z--verbose | z--v* ) verbose=t shift ;; z-- ) shift break ;; z-* ) usage "${bq}${1}${eq} is not a valid option." ;; * ) proglist="${proglist} $1" shift ;; esac done # Return number of shifted arguments so calling function can shift # appropriate amount. return $[ orig_number_options - $# ] } function get_process_list () { local ignore_regexp="$(cons_regexp $$ ${progname} 'ps' 'egrep' 'selection_svc')" local find_regexp="$(cons_regexp ${proglist:-'.*'})" ps ${ps_args} \ | egrep -v "${ignore_regexp}" \ | egrep "${find_regexp}" > "${pretmpfile}" 2>&1 eval $(awk ' NR == 1 { for ( i = 1; i <= NF ; i++ ) { if ( $i == "CMD" || $i == "COMMAND" ) printf("cmd_field=%d ", i); if ($i == "PID" ) printf("pid_field=%d ", i); } } END { printf("num_procs=%i ", NR - 1); }' "${pretmpfile}") # guess, if necessary. (bad, since it's really quite variable) # `5' is the usual cmd field on bsd/sunos/aix, `4' for hpux # FIXME: STAT field output in bsd/sunos ps breaks things. cmd_field=${cmd_field:-"5"} pid_field=${pid_field:-"1"} sed "1d" "${pretmpfile}" > "${tmpfile}" rm -f "${pretmpfile}" } function cons_regexp () { local whitespace_regexp="[ \t]*" local need_closeparen if [ $# -gt 1 ]; then need_closeparen=t echo -n "(" fi while [ $# -ne 0 ]; do echo -ne "${whitespace_regexp}${1}${whitespace_regexp}" test $# -gt 1 && echo -n "|" shift done test "${need_closeparen}" && echo -n ")" echo "" } function frobnicate_processes () { local i=1 get_process_list; while [ ${i} -le ${num_procs} ]; do set -- $(sed -n "${i}p" "${tmpfile}") eval pid="\$${pid_field}" eval cmd="\$${cmd_field}" if [ "${force_kill}" ]; then builtin kill -KILL "${pid}" if [ "${verbose}" ]; then echo "Process ${pid} \"${cmd}\" killed." 1>&2 fi else get_user_command "${pid}" "${cmd}" fi let i="i + 1" done rm -f "${tmpfile}" } function get_user_command () { local help="[ (E)xit (K)ill (S)ignal (R)enice (I)gnore ] " local pid="$1" local cmd="$2" while : ; do echo -ne "Process \"${pid}\t${cmd}\"\t\tOption (h=help): " read ans case "${ans}" in h* | H* ) echo "${help}" continue ;; e* | E* ) exit 0 ;; k* | K* ) builtin kill -KILL ${pid} if [ $? -eq 0 -a "${verbose}" ]; then echo "${progname}: process ${pid} \"${cmd}\" killed." 1>&2 fi return 0 ;; i* | I* ) return 0 ;; s* | S* ) do_signal "${pid}" "${cmd}" ${ans} return $? ;; r* | R* ) do_renice "${pid}" "${cmd}" ${ans} return $? ;; esac done } # Invocation: do_signal [pid] [cmd] s {sig} function do_signal () { local pid="$1" local cmd="$2" local sig shift 2; set -- "$@" if [ $# -eq 1 ]; then while : ; do echo -n "Enter signal to send (h=help): " read sig case ${sig} in e | q ) exit 0 ;; h | H ) kill -l ;; * ) break ;; esac done else sig="$2" fi kill "-${sig}" "${pid}" if [ "${verbose}" ]; then echo "${progname}: sent pid ${bq}${pid}${eq} signal ${bq}-${sig}${eq}" 1>&2 fi } # Invocation: do_signal [pid] [cmd] r {renice_value} function do_renice () { local pid="$1" local cmd="$2" local renice_value shift 2; set -- "$@" if [ $# -eq 1 ]; then echo -n "Enter nice value: " read renice_value else renice_value="$2" fi if [ ! "${renice_value}" ]; then return 1 fi if [ ! "${verbose}" ]; then renice ${renice_value} -p ${pid} > /dev/null 2>&1 else renice ${renice_value} -p ${pid} fi return $? } function exit () { rm -f "${tmpfile}" builtin exit "$@" } main "$@" # # eof #