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

# /lib/lsb/initd_functions contains the functions used by 
# /lib/lsb/install_initd and /lib/lsb/remove_initd as well as additional helper
# functions for use in programs that would provide functionality similar to
# the RedHat chkconfig utility.  These functions are complicated, but I want
# them to be useable, and understandable.  I've been very generous with the
# comments so that they meet both of those requirements, maybe even a little
# too generous.  Better that than a complete mess that nobody can 
# understand, right?  Happy hacking!

# Define rcbase and distro here for now
## (this will go away when a config file is defined)
rcbase=/etc/init.d
distro=LFS

## Define all arrays at script start to avoid scope issues
# a list of valid scripts used as an index
declare -a scriptlist
# a complete set of valid LSB headers is stored here for each indexed script
declare -a fullheaders
# The distro extension headers are stored here for a single script.
# For this implementation, I have defined X-<distro>-Default-Start[1],
# and X-<distro>-Default-Stop[2].  X-<distro>-Provided-By[3] is also defined
# but probably not used durring installation.
declare -a distroheaders

###############################################################################
# get_headers() - Obtains a valid list of scripts contained in ${rcbase} and  #
#                 inserts the name of the script into the scriptlist[] array  #
#                 for use by all other functions.  Additionally, it inserts   #
#                 the entire LSB header information from each script into a   #
#                 second array, fullheaders[], so that diskreads need only be #
#                 done once                                                   #
###############################################################################
get_headers()
{
    echo -n "Retrieving script information from disk..."
    count=1
    for file in $(find -P /etc/init.d -xdev -perm -u=x | sed -n 2~1p \
                      | sed "s@/etc/init.d/rc@@")
    do
        # determine if script is an LSB compliant script
        grep "### BEGIN INIT INFO" $file > /dev/null
        if test $? -gt "0"
        then
            # this is not a valid script and is ignored
            # skip the rest of the loop
            continue
        fi
        # determine basename using only bash (is basename a builtin?)
        filename=$(echo "${file}" | sed "s@${rcbase}/@@")
        # assign it to an array possition
        scriptlist["${count}"]="${filename}"
        # find the begining of the init info for the script
        begin=$(grep -n "### BEGIN INIT INFO" "${file}" | cut -d: -f1)
        # find the end of the init info for the script
        end=$(grep -n "### END INIT INFO" "${file}" | cut -d: -f1)
        # we'll use the difference between the values in the tail command
        diff=$(( ${end} - ${begin} ))
        # assign the entire LSB header information as a single string to the
        # fullheaders[] array
        fullheaders["${count}"]=$(head -n "${end}" "${file}" \
                                    | tail -n "${diff}")
        count=$(( ${count} + 1 ))
        unset begin
        unset end
        unset diff
        unset filename
    done
    # a number or array elements would be a nice regular variable assignment
    scriptcount="${#scriptlist[@]}"
    unset count
    echo -e "Completed!"
}

###############################################################################
# print_headers() - Presents a formatted list of all LSB compliant script     #
#                   headers to stdout preceeded by script name for use in     #
#                   other scripts                                             #
###############################################################################
print_headers()
{
    get_headers
    count=1
    while test "${count}" -lt "${scriptcount}"
    do
        echo "${scriptlist[$count]}"
        echo "============================================================="
        echo "${fullheaders[$count]}"
        echo ""
        echo ""
        count="$(( ${count} + 1 ))"
    done
}

###############################################################################
# get_index() - Determines the array index of the specified script            #
###############################################################################
get_index()
{
    filename=$(echo "${1}" | sed "s@${rcbase}/@@")
    count=1
    while test "${count}" -lt "${scriptcount}"
    do
        echo "${scriptlist[${count}]}" | grep "${filename}" > /dev/null
        if test "${?}" -ne "0"
        then
            count=$(( ${count} + 1 ))
            continue
        else
            break
        fi
    done
    if test "${filename}" == "${scriptlist[${count}]}"
    then
        index="${count}"
    else
        echo "${1} is not a valid LSB init script."
        exit 1
    fi
    unset count
}

###############################################################################
# get_distro_headers() - Gets and loads an array for only the extension       #
#                        headers of a specified script                        #
###############################################################################
get_distro_headers()
{
    echo "${fullheaders[${index}]}" \
        | grep "X-${distro}-Enabled" > /dev/null
    if test "${?}" -eq "0"
    then
        distroheaders[3]=$( echo "${fullheaders[${index}]}" \
                                | grep "X-${distro}-Provided-By" \
                                | awk '{print $3}' )
        distroheaders[4]=$( echo "${fullheaders[${index}]}" \
                                | grep "X-${distro}-Enabled" \
                                | awk '{print $3}' )
        return 0
    else
        return 1
    fi
}

###############################################################################
# get_default_start() - Obtains the Default-Start runlevels (limit 8)         #
###############################################################################
get_default_start()
{
    defaultstart=$( echo "${fullheaders[${index}]}" \
                        | grep "^# Default-Start" \
                        | awk '{print $3" "$4" "$5" "$6" "$7" "$8" "$9" "$10}' )

}

###############################################################################
# get_default_stop() - Obtains the Default-Start runlevels (limit 8)          #
###############################################################################
get_default_stop()
{
    defaultstop=$( echo "${fullheaders[${index}]}" \
                       | grep "^# Default-Stop" \
                       | awk '{print $3" "$4" "$5" "$6" "$7" "$8" "$9" "$10}' )

}

###############################################################################
# get_provides() - Obtains the Provides header for an indexed item            #
###############################################################################
get_provides()
{
    provides=$( echo "${fullheaders[${index}]}" \
                    | grep "^# Provides" \
                    | awk '{print $3}' )

}

###############################################################################
# get_required_start() - Obtains the Required-Start header for an indexed     #
#                        item                                                 #
###############################################################################
get_required_start()
{
    requiredstart=$( echo "${fullheaders[${index}]}" \
                        | grep "^# Required-Start" \
                        | awk '{print $3" "$4" "$5" "$6" "$7" "$8" "$9" "$10}' )

}

###############################################################################
# get_should_start() - Obtains the Should-Start header for an indexed item    #
###############################################################################
get_should_start()
{
    shouldstart=$( echo "${fullheaders[${index}]}" \
                       | grep "^# Should-Start" \
                       | awk '{print $3" "$4" "$5" "$6" "$7" "$8" "$9" "$10}' )

}

###############################################################################
# get_required_stop() - Obtains the Required-Stop header for an indexed item  #
###############################################################################
get_required_stop()
{
    requiredstop=$( echo "${fullheaders[${index}]}" \
                        | grep "^# Required-Stop" \
                        | awk '{print $3" "$4" "$5" "$6" "$7" "$8" "$9" "$10}' )

}

###############################################################################
# get_should_stop() - Obtains the Should-Stop header for an indexed item      #
###############################################################################
get_should_stop()
{
    shouldstop=$( echo "${fullheaders[${index}]}" \
                      | grep "^# Should-Stop" \
                      | awk '{print $3" "$4" "$5" "$6" "$7" "$8" "$9" "$10}' )

}

###############################################################################
# convert_lsb_required() - Converts LSB defined facilities (facility names    #
#                          begining with a '$' character) into script names   #
#                          for required start/stop                            #
###############################################################################
convert_lsb_required()
{
    unset reqprovideslist
    for reqfacility in $@
    do
        # find the requires and it's index and then find the script name 
        # from the index.  Since this is required, exit if it is not found
        ## If reqfacility is already in script name format, nothing needs to
        ## be done, just echo it back out.  I can't think of an easy way to
        ## do this right now, the scriptname will be the same as the provides
        ## anyway, so just let it fly for now...it'll be correct, it just 
        ## takes an extra couple of commands to get the same result.
        ## Besides, this will do some extra sanity checking in case somebody
        ## writes a script that isn't named the same as provides, though this
        ## isn't LSB compliant.  Maybe we can add that into the test framework
        ## later.  Additionally, these same comments apply to the 
        ## convert_lsb_should() fucntion below.
        count=0
        while test ${count} -lt ${scriptcount}
        do
            count=$(( $count + 1 ))
            index=${count}
            get_provides 
            if test "${provides}" = "${reqfacility}"
            then
                 reqprovideslist="${reqprovideslist} ${scriptlist[$count]}"
                 break
            fi
            if test ${count} -eq ${scriptcount}; then
                # If we've never broken out of the while loop, then this is an
                # unrecoverable error since it is a required item.  Exit now!
                echo "Error: unable to locate required facility ${reqfacility}!"
                exit 5
            fi
        done
    done
}

###############################################################################
# convert_lsb_should() - Converts LSB defined facilities (facility names      #
#                        begining with a '$' character) into script names for #
#                        should start/stop                                    #
###############################################################################

convert_lsb_should()
{
    unset optprovideslist
    for optfacility in $@
    do
        # find the should and it's index and then find the script name 
        # from the index.  Since this is not an error, simply warn if it
        # is not found.
        count=0
        while test ${count} -lt ${scriptcount}
        do
            count=$(( $count + 1 ))
            index=${count}
            get_provides
            if test "${provides}" = "${optfacility}"
            then
                 optprovideslist="${optprovideslist} ${scriptlist[$count]}"
                 break
            fi
            # No need to error or warn on should items, and it's messy if so!
        done
    done
}


