### Written for the LFS community by DJ Lucas <dj@linuxfromscratch.org>
### 20071012

#!/bin/bash
# Begin /lib/lsb/install_initd

. /lib/lsb/initd_functions

# This script is grossly over commented, but is somewhat complex.
# It is exactly to spec and meets the LSB requirements, and LFS's 
# requirements as I have defined them.  It takes advantage of the 
# GNU make utility to handle dependency tracking, so that note
# might help explain the numerous comments pointing to these
# magical makefiles.

# First, the program should take exactly one argument, the full path of the
# script only! Check to make sure only one argument is passed, if not exit 2
# This is not defined by LSB, but is consistent with the exit code for
# invalid or excess arguments in init scripts.
if test ! -n "${1}" -o -n "${2}"
then
    echo ""
    echo "Invalid or excess arguments!"
    echo "Usage: ${0} /etc/init.d/<scriptname>"
    echo ""
    exit 2
fi

case "${1}" in
    -*)
        echo ""
        echo "Usage: ${0} /etc/init.d/<scriptname>"
        echo ""
        exit 0
    ;;
esac

# Next check to make sure that the script really exists
# If it does not, exit 5. Again this is not defined by the LSB, however, is
# consistent with the exit values for init scripts when the program is not 
# installed.

if test ! -f "${1}"
then
    echo ""
    echo "Script does not exist!"
    echo "Usage: ${0} /etc/init.d/<scriptname>"
    echo ""
    exit 5
fi

# Go ahead and get all the information that is needed from disk in one shot
get_headers

# Now get the array index number for the specified script.
# Also note that the 'filename' variable is set (basename of script), and
# the script is verified that it is LSB compliant.
get_index "${1}"
# filename and index will be overwritten if we have to cycle through deps, so
# assign those values to alternate variables
install_filename="${filename}"
install_index="${index}"

# Check to see if script is already enabled
grep "${filename}" /lib/lsb/scriptlist 2>&1 >/dev/null
if test ${?} -eq 0; then
    echo "Script is already enabled!"
    echo "Check /lib/lsb/scriptlist if you believe this is in error."
    exit 0
else
    checkfind=`find /etc/rc*.d -name ???${filename}`
    if test ! -z ${checkfind}; then
        echo "Script is manually enabled!"
        echo "You will need to remove manually created symlinks prior to running this"
        echo "script.  Unable to continue...Exiting!"
        exit 2
    fi
    unset checkfind
fi

# Give the user something other than dead time
echo -n "Resolving dependencies (this may take a bit)..."

# Cleanup any previous leftovers and create all of our temporary files
rm -rf /tmp/lsbinitd
mkdir /tmp/lsbinitd
touch /tmp/lsbinitd/sysinitstart
for runlevel in 0 1 2 3 4 5 6
do
    touch /tmp/lsbinitd/${runlevel}{start,stop}
done
cp /lib/lsb/scriptlist /tmp/lsbinitd/scriptlist
echo "${1}" | sed 's@/etc/init.d/@@' >> /tmp/lsbinitd/scriptlist

# Fingure out which runlevels will be modified and only regenerate the link
# order on those runlevels.
get_default_start
get_default_stop

# Figure out the starting runlevels first
## for each runlevel in $default_start find the provides for the newly
## installed script and use the temp files created above to track deps
## (if necessary)

# First, find the provides for the newly installed script and cycle through
# the should_{start,stop} values in the array to see if we've provided a new
# optional dependency for another script, if we have, see if that script is
# started in any of the runlevels
# then we now have a 
# ceiling/floor value for the numeric link that we'll have to take into 
# account a little later on.


## Figure out starting first
## Simply take the Required-Start and Should-Start items and grep
## through the array's provides section to find them.

## When a Required-Start item  is found, find that it's in sysinit, or find
## the start link in runlevel 5, record it, and continue on to the next
## Required-Start item.  If a Required-Start item is not found, then exit
## immediately with an exit status of 1.
get provides
get_required_start "${filename}"
get_should_start "${filename}"

for runlevel in `echo "${default_start}"`
do
    ## This is where the provides should be used to determine $maxval on
    ## a pure runlevel basis.  For now, set $maxval to 99 for testing.
    maxval=99
    count=1
    while test ! "${count}" -gt "${scriptcount}"
    do
        for facility in $(echo "${requiredstart}")
        do
            echo "${fullheaders[${count}]}" \
                | grep "^# Provides" \
                | grep "${facility}" > /dev/null
            if test "${?}" -eq "0"
            then
                reqlist="${reqlist} ${scriptlist[${count}]}"
            fi
        done
        count=$(( ${count} + 1 ))
    done

    if test -z "${reqlist}"
    then
        echo ""
        echo "Required-Start facility ${facility} was not found!"
        echo ""
        exit 1
    fi
    startlink="0"
    for required in $(echo "${reqlist}")
    do
        if test -f /etc/rcsysinit.d/S??"${required}"
        then
            continue
        elif test -f /etc/rc${runlevel}.d/S??"${required}"
        then
            # Get the start link number
            link=$( ls /etc/rc${runlevel}.d/S??"${required}" |
                        sed "s@/etc/rc${runlevel}.d/@@" | sed 's@^S@@' | \
                        sed "s@${required}@@" )
            if test "${link}" -gt "${startlink}"
            then
                startlink="${link}"
            fi
        else
            echo ""
            echo "Required-Start facility ${facility} is not started!"
            echo ""
            exit 1
        fi
    done
    unset reqlist link count

    ## When a Should-Start item is found, find that it's in sysinit, or find the
    ## start link in runlevel, record it, and continue on to the next
    ## Should-Start item.  If a Should-Start item is not found, then simply
    ## continue on to the next item or create the link based on the recorded 
    ## value plus half of the difference of the next higher numbered script.

    if test ! -z "${shouldstart}"
    then
        count=1
        while test ! "${count}" -gt "${scriptcount}"
        do
            for facility in $(echo "${shouldstart}")
            do
                echo "${fullheaders[${count}]}" \
                    | grep "^# Provides" \
                    | grep "${facility}" > /dev/null
                if test "${?}" -eq "0"
                then
                    reqlist="${reqlist} ${scriptlist[${count}]}"
                fi
            done
            count=$(( ${count} + 1 ))
        done

        for optional in $(echo "${reqlist}")
        do
            if test -f /etc/rcsysinit.d/S??"${optional}"
            then
                continue
            elif test -f /etc/rc${runlevel}.d/S??"${optional}"
            then
                # Get the start link number
                link=$( ls /etc/rc5.d/S??"${optional}" |
                            sed "s@/etc/rc${runlevel}.d/@@" | sed 's@^S@@' | \
                            sed "s@${optional}@@" )
                if test "${link}" -gt "${startlink}"
                then
                    startlink="${link}"
                fi
            fi
        done
    fi
    unset reqlist link count

    # Now, find the next highest start link
    nextscript=$( ls /etc/rc${runlevel}.d/ | grep -A 1 "S${startlink}" \
                    | sed -e "/S${startlink}/d" \
                          -e "s@^S@@" )
    nextscriptname=$( echo "${nextscript}" | sed 's@..@@' )
    nextlink=$( echo "${nextscript}" | sed "s@${nextscriptname}@@" )
    # A little bash math to get a working value 
    diff=$(( ${nextlink} - ${startlink} ))
    add=$(( ${diff} / 2 ))
    if test -z ${add}; then
        # We need to reorder
        /lib/lsb/organize_links -a "${install_filename}"
        # always exit immediately and on exitval of organize_links if
        # control is returned to this script.
        exit ${?}
    fi
    startlink=$(( ${startlink} + ${add} ))
    unset add diff nextlink nextscriptname nextscript

    if test ${startlink} -lt ${maxval}; then
        echo "ln -s ../init.d/${filename} /etc/rc${runlevel}.d/S${startlink}${filename}"
    else
        # We need to reorder
        /lib/lsb/organize_links -a "${install_filename}"
        exit ${?}
    fi
done

#### Now do the stop links!
## for runlevel in `echo "${default_stop}"`
## do
##     ## DO SOMETHING HERE LIKE ABOVE
## done



# Okay script is valid so it's okay to add it to the list
## Commented out for now
# cp /tmp/lsbinitd/scriptlist /lib/lsb/scriptlist
# chown root:root /lib/lsb/scriptlist > /dev/null
# chmod 644 /lib/lsb/scriptlist > /dev/null

# Clean up our mess
## Commented out for now
# rm -rf /tmp/lsbinitd

