#!/bin/bash # Wrapper program, mainly for cleaning up after netscape leaves lock and core # files. But it can be used to wrap any program. # Functionality: when this script receives a signal 1, 2, 3 or 15; it will # send that signal and then signals 1, 2, 3, 15 and 9 (except for the signal # sent first) at 3 second intervals to the wrapped program, until it dies. # Then it will clean up a lock file, if required, and a core file, if required # -- see below. # Author: John Latham, Dept. of Computer Science, University of Manchester, UK. # Email jtl@cs.man.ac.uk # Time-stamp: # Usage: place this in a directory anywhere earlier in the PATH than the # program you want it to wrap, and give it the same name. /usr/local/bin is an # obvious place. Any other programs you also want it to wrap can simply each # have a link to this file, of the same name as the wrapped program. This # wrapper should find the real program to wrap from $0 and by manipulating # $PATH to temporarily remove the place where this wrapper is put. The wrapped # program must appear on the PATH, and no other copy of the wrapper may appear # in the PATH (that would lead to recursive calls!) # Set $TraceActions to True if you want this wrapper to report what it is # doing to Standard output (if that is a tty) and also to the file $TraceFile # (if that variable is not empty) # This is set via $DefaultTraceActions, possibly overrriden by the environment # variable $WRAPPER_TRACE #DefaultTraceActions=True DefaultTraceActions=False TraceActions=${WRAPPER_TRACE:-$DefaultTraceActions} # Set $DefaultTraceFile to the default name of the file you want this wrapper # to trace actions to (if $TraceActions is True). This is in addition to traces # being written on standard output (if it is a tty). The value of $TraceFile is # set to $DefaultTraceFile, unless the environment variable $WRAPPER_TRACE_FILE # is set; in which case that value is used. If $TraceFile is empty, then there # will be no tracing to a file. #DefaultTraceFile=`tty` #DefaultTraceFile=/dev/console DefaultTraceFile="" TraceFile=${WRAPPER_TRACE_FILE:-$DefaultTraceFile} # Set $TestForLockFile to be some test for the existence of a file (e.g. a # lock file) which should be removed on exit; iff it was not existing on entry. # This is ignored if it is empty. # Set $RemoveLockFile to be a command which will remove the above file. # Set $TestForCoreFile to be a test for a core file which must be removed on # exit (even if it was there on entry). Ignored if empty. # Set $RemoveCoreFile to be a command that removes the above core file. case $0 in *netscape*) TestForLockFile="test -L $HOME/.netscape/lock" RemoveLockFile="rm -f $HOME/.netscape/lock" TestForCoreFile="strings core 2>&1|grep netscape > /dev/null" RemoveCoreFile="rm -f core" ;; *) TestForLockFile="" TestForCoreFile="" ;; esac function trace_action() { if test "$TraceActions" = True then if test "$TraceFile" != "" then echo `/bin/date`:`hostname`:$USER:$0 $1 >> $TraceFile fi test -t 1 && echo $1 fi } function error_report() { test -t 2 && echo $1 >&2 } function check_lock() { if test "$LockToBeRemoved" = True then # $TestForLockFile && sleep 1 if $TestForLockFile then trace_action "$ChildProgram left the lock file (now removed)" $RemoveLockFile else trace_action "$ChildProgram removed the lock file" fi fi } function check_core() { if test "$TestForCoreFile" != "" then if eval $TestForCoreFile then trace_action "$ChildProgram left a core file (now removed)" $RemoveCoreFile else trace_action "$ChildProgram did not leave a core file" fi fi } function terminate() { trap - $1 trace_action "Received signal $1" trace_action "Sending signal $1 to $ChildProgram($ChildPid)" kill -$1 $ChildPid for Count in 1 2 3 do test "`ps $ChildPid 2>&1 |grep $ChildPid`" != "" && sleep 1 done for Signal in 1 2 3 15 9 do if test $Signal != $1 then test "`ps $ChildPid 2>&1 |grep $ChildPid`" != "" && sleep 1 if test "`ps $ChildPid 2>&1 |grep $ChildPid`" != "" then trace_action "Sending signal $Signal to $ChildProgram($ChildPid)" kill -$Signal $ChildPid fi fi done check_lock check_core exit `expr 128 + $1` } trap "terminate 1" 1 trap "terminate 2" 2 trap "terminate 3" 3 trap "terminate 15" 15 case $TestForLockFile in "") LockToBeRemoved=False ;; *) LockToBeRemoved=True $TestForLockFile && LockToBeRemoved=False ;; esac case $0 in .*|/*) ThisProgramPath=$0 ;; *) ThisProgramPath=`which $0` ;; esac ThisDirectory=`dirname $ThisProgramPath` ThisProgramName=`basename $ThisProgramPath` OldPath=$PATH RemovePattern=`echo $ThisDirectory | sed "s|\.|\\\\\.|g"` export PATH=`echo $PATH | sed "s|:$RemovePattern:|:|g" \ | sed "s|^$RemovePattern:||g" \ | sed "s|:$RemovePattern\$||g"` ChildProgram=`which $ThisProgramName` 2>/dev/null case $ChildProgram in *no" "*" "in*) ChildProgram="" ;; esac export PATH=$OldPath if test "$ChildProgram" = "" then error_report "Cannot find $ThisProgramName from wrapper" else $ChildProgram $* & ChildPid=$! wait $ChildPid NormalExitStatus=$? check_lock check_core exit $NormalExitStatus fi