Hi,

I fixed two bugs in the script and am attaching the fixed version.

Fixed bugs:

 * No longer assume name of parent initscript is 2nd word of
   /proc/$PPID/cmdline.

 * When sending a service the kill signal, issue "sv d servicename" first
   because initscripts assume that the service will be down after a kill.

Andras

-- 
                     Andras Korn <korn at elan.rulez.org>
                      There is no spoon(). Only a fork().
#!/bin/zsh
#
# This script is intended to wrap start-stop-daemon. It will call the
# original start-stop-daemon with the supplied arguments unless the daemon
# to be started appears to exist as a runit service, in which case it will
# map the start-stop-daemon call to an sv(8) call.
#

# If called by non-root user, fall back to original start-stop-daemon
# unconditionally
[[ $UID -gt 0 ]] && exec /sbin/start-stop-daemon.real $@

set -A args $@

SVDIR=${SVDIR:-/etc/service}

unset mode signal exec timeout startas testmode oknodo quiet verbose command 
svstat
oknodo=0
quiet=0

while [[ -n "$1" ]]; do
        case "$1" in
                -S|--start)
                        mode=start
                        ;;
                -K|--stop)
                        mode=stop
                        ;;
                -T|--status)
                        mode=status
                        ;;
                -H|--help|-V|--version)
                        exec /sbin/start-stop-daemon.real $args
                        ;;
                -x|--exec)
                        shift
                        exec="$1"
                        ;;
                -s|--signal)
                        shift
                        signal=$1
                        ;;
                --signal=*)
                        signal="${1/--signal=/}"
                        ;;
                -R|--retry)
                        shift
                        timeout="$1"
                        ;;
                --retry=*)
                        timeout="${1/--retry=/}"
                        ;;
                -a|--startas)
                        shift
                        startas="$1"
                        ;;
                -t|--test)
                        testmode=1
                        ;;
                -o|--oknodo)
                        oknodo=1
                        ;;
                -q|--quiet)
                        quiet=1
                        exec >/dev/null
                        ;;
                -v|--verbose)
                        verbose=1
                        ;;
                
-p|--pidfile|-n|--name|-u|--user|-g|--group|-r|--chroot|-d|--chdir|-N|--nicelevel|-P|--procsched|-I|--iosched|-k|--umask|-m|--make-pidfile)
                        # ignored
                        shift
                        ;;
                
--pidfile=*|-b|--background|--nicelevel=*|--procsched=*|--iosched=*|--umask=*)
                        ;;
                --)
                        # What follows is args to the daemon. Avoid parsing
                        # those accidentally.
                        break
                        ;;
                *)
                        # Assume the previous was the last option; the rest
                        # is the name of the daemon plus args, of which we
                        # only care about the daemon.
                        command=$1
                        break
                        ;;
        esac
        shift
done
# Try to infer runit service name. If our parent is an initscript, use its
# basename
read -A cmdline </proc/$PPID/cmdline
while [[ -n "$cmdline[1]" ]]; do
        if [[ "${cmdline[1]:h}" = /etc/init.d ]]; then
                svname=${cmdline[1]:t}
                break
        fi
        shift cmdline
done
if [[ -z "$svname" ]] && [[ "${$(readlink -f /proc/$PPID/exe):h}" = /etc/init.d 
]]; then
        read svname < /proc/$PPID/comm
fi
# if not, try other heuristics
svnames=($startas $exec $command)
while ! [[ -d $SVDIR/$svname/supervise/. ]] && [[ -n "$svnames[1]" ]]; do
        svname=${svnames[1]:t}
        shift svnames
done
# if runit service doesn't exist, call real start-stop-daemon.
if ! [[ -d $SVDIR/$svname/supervise/. ]] || [[ -z "$svname" ]]; then
        exec /sbin/start-stop-daemon.real $args
fi
# otherwise, do what we've been asked to
[[ "$quiet" = "0" ]] && [[ "$verbose" = "1" ]] && echo 
"start-stop-daemon.runit: will act on $svname service." >&2

function sendsig() {
        case "$signal" in
                HUP|1)
                        sv hup $svname
                        ;;
                INT|2)
                        sv interrupt $svname
                        ;;
                QUIT|3)
                        sv quit $svname
                        ;;
                KILL|9)
                        sv d $svname
                        sv kill $svname
                        ;;
                USR1|10)
                        sv 1 $svname
                        ;;
                USR2|12)
                        sv 2 $svname
                        ;;
                ALRM|14)
                        sv alarm $svname
                        ;;
                TERM|15)
                        sv down $svname
                        ;;
                CONT|18)
                        sv cont $svname
                        ;;
                STOP|19)
                        sv pause $svname
                        ;;
                *)
                        echo "$0: ERROR: don't know how to send $signal signal 
to $svname." >&2
                        exit 3
                        ;;
        esac
}

function wait_until_exited() {
        counter=0
        read svstat < $SVDIR/$svname/supervise/stat
        while ! [[ "$svstat" = down ]]; do
                ((counter++))
                [[ $counter -gt $timeout ]] && return 1
                sleep 1
                read svstat < $SVDIR/$svname/supervise/stat
        done
        return 0
}

function do_stop() {
        if [[ $timeout =~ / ]]; then
# handle complex schedule
                OLDIFS="$IFS"
                IFS=/
                echo $timeout | read -A schedule
                IFS="$OLDIFS"
                while [[ -n "$schedule[1]" ]]; do
                        signal=$schedule[1]
                        sendsig
                        shift schedule
                        timeout=$schedule[1]
                        wait_until_exited && exit 0
                        shift schedule
                done
                exit 2
        else
# simple timeout
                if [[ -z "$signal" ]]; then
                        if [[ $timeout =~ ^[0-9]+$ ]]; then
                                export SVWAIT=$timeout
                        fi
                        if sv stop $svname; then
                                exit 0
                        else
                                exit 1
                        fi
                else
                        sendsig
                        [[ -n "$timeout" ]] && if wait_until_exited; then
                                exit 0
                        else
                                exit 1
                        fi
                fi
        fi
}

read svstat < $SVDIR/$svname/supervise/stat
case "$mode" in
        start)
                [[ "$svstat" = run ]] && [[ "$oknodo" = "0" ]] && exit 1 # 
Emulate start-stop-daemon semantics
                [[ -z "$testmode" ]] && sv start $svname
                exit 0
                ;;
        stop)
                [[ "$svstat" = down ]] && [[ "$oknodo" = "1" ]] && exit 1 # 
Emulate start-stop-daemon semantics
                [[ -z "$testmode" ]] && do_stop # handles --retry and --signal, 
therefore separate function
                ;;
        status)
                case "$svstat" in
# States are complex; we only handle the most basic cases here and bail on
# the rest (e.g. "finish" cannot be correctly reported as "running" or "not
# running")
                        run)
                                exit 0
                                ;;
                        down)
                                exit 3
                                ;;
                        *)
                                exit 4
                                ;;
                esac
                ;;
esac
exit 0

Reply via email to