#!/bin/bash
#
# /sbin/hwup
#
# Configuring hardware (Preliminary version)
# $Id: hwup,v 1.15 2004/04/29 15:08:54 hare Exp $
#

usage () {
	echo $@
	echo "Usage: hw{up,down,status} [<config>] <hwdesc> [-o <options>]"
#	echo "       (see man hwup for details)"
	echo
	echo "Options are:"
	echo "    auto     : we were called from an automated process (e.g. hotplug)"
	exit $R_USAGE
}

# Debugging
# . ./functions

R_INTERNAL=1      # internal error, e.g. no config or missing scripts
cd /etc/sysconfig/hardware || exit $R_INTERNAL
test -f scripts/functions && . scripts/functions || exit $R_INTERNAL
test -f config && . config

######################################################################
# Commandline parsing
#
# hw{up,down,status} [<config>] <hwdesc> [-o <options>]
SCRIPTNAME=${0##*/}
debug $*
HWDESC=$1
case "$HWDESC" in ""|-h|*help*) usage; esac
shift
if [ -n "$1" -a "$1" != "-o" ] ; then
	CONFIG=$HWDESC
	HWDESC=$1
fi
shift
test "$1" = "-o" && shift
OPTIONS=$@
MODE=manual
while [ $# -gt 0 ]; do
	case $1 in
		auto)    MODE=auto ;;
		hotplug) MODE=auto
		         HOTPLUG=yes ;;
		*)       debug "unknown option $1 ignored" ;;
	esac
	shift
done


######################################################################
# Get a configuration name and additional information
#
# Maybe we already got an configuration name at the command line, but call
# getcfg in any case, because it provides more information.
eval `/sbin/getcfg -d . -f hwcfg- -- $HWDESC 2>/dev/null`
# Try to get a config via getcfg several times if called by hotplug. Sometimes 
# sysfs entries need some time to establish.
for n in 1 2 3 4 5; do
	test "$SCRIPTNAME" = hwdown && break
	test -n "$HWD_CONFIG_0" -o "$HOTPLUG" != yes && break
	sleep 1
	debug "looking again for a configuration ($n)"
	eval `/sbin/getcfg -d . -f hwcfg- -- $HWDESC 2>/dev/null`
done
if [ -z "$CONFIG" -a -n "$HWD_CONFIG_0" ] ; then
	CONFIG=$HWD_CONFIG_0
fi
# Normally we are interested only in the last bus. (It is not of interest that
# below a scsi bus is a pci bus. Otherwise use HWD_BUSNAME_<n>, HWD_BUSID_<n>.)
eval export HWD_BUSNAME=\$HWD_BUSNAME_$((HWD_BUS_N-1))
eval export HWD_BUSID=\$HWD_BUSID_$((HWD_BUS_N-1))

if [ -z "$CONFIG" ] ; then
	case ${HWDESC%%-*} in
		static|boot) CONFIG=$HWDESC;;
	esac
fi

debug "HWDESC = $HWDESC      CONFIG = $CONFIG"

######################################################################
# Now source the configuration file
#
# First remove all variables starting with MODULE because there are variables
# starting with MODULE and unknown suffix in the config file. Otherwise
# environment variables would irritate the code that looks for all MODULE*
# variables.
unset ${!MODULE*}
if [ -n "$CONFIG" -a -r hwcfg-$CONFIG ] ; then
	. hwcfg-$CONFIG
fi

######################################################################
# What shell we do if there is no configuration data?
# - fail
# - get it automatically
# - ask the user
if [ -z "$CONFIG" -o ! -r hwcfg-$CONFIG -o -n "$NODATA" ] ; then
	case $FAILURE_ACTION in
		off)
			test "$HOTPLUG" != yes && \
				logerror "No configuration found for $HWDESC"
			exit $R_NOCONFIG
			;;
		auto-off|auto-manual|manual)
			# to be implemented, see doc/Specification
			logerror "No configuration found for $HWDESC and autoconfig still not
implemented"
			exit $R_NOCONFIG
			;;
		*)
			logerror "No configuration found for $HWDESC"
			exit $R_NOCONFIG
			;;
	esac
fi


######################################################################
# Check if we are supposed to initialize the device
#
# empty $STARTMODE means 'auto'
case "$STARTMODE" in
	off)
		message "$SCRIPTNAME: used configuration has STARTMODE=$STARTMODE."
		exit 0;
		;;
	manual)
		if [ "$MODE" != manual ] ; then
			message "$SCRIPTNAME: used configuration has STARTMODE=$STARTMODE," \
			     "but we are called '$MODE'."
			exit 0;
		fi
		;;
esac

######################################################################
# execute individual prestart or predown scripts if available
#
if [ "$SCRIPTNAME" = hwup ] ; then
# NOTE: 'eval echo' in the next line is necessary to expand settings
# like PRE_UP_SCRIPT="~root/bin/foo"
	for PUS in `eval echo $PRE_UP_SCRIPT scripts/$PRE_UP_SCRIPT`; do
		if [ -x "$PUS" -a ! -d "$PUS" ] ; then
			debug "executing additional start script $PUS"
			$PUS $CONFIG $HWDESC ${OPTIONS:+-o $OPTIONS}
		fi
	done
fi
if [ "$SCRIPTNAME" = hwdown ] ; then
# NOTE: 'eval echo' in the next line is necessary to expand settings
# like PRE_DOWN_SCRIPT="~root/bin/foo"
	for PDS in `eval echo $PRE_DOWN_SCRIPT scripts/$PRE_DOWN_SCRIPT`; do
		if [ -x "$PDS" -a ! -d "$PDS" ] ; then
			debug "executing additional stop script $PDS"
			$PDS $CONFIG $HWDESC ${OPTIONS:+-o $OPTIONS}
		fi
	done
fi

######################################################################
# Call a specialized down script, depending on the event
#
# have a look at 'Call a specialized down script' above
if [ "$SCRIPTNAME" = hwdown ]; then
    # Call an event-specific script if one exists
    if [ "$HWD_DEVTYPE" ]; then
	SCRIPT_DOWN=`eval echo \\$SCRIPTDOWN_$HWD_DEVTYPE`
    fi
    # Call a generic script if no event-specific exists
    if [ -z "$SCRIPT_DOWN" ]; then
	SCRIPT_DOWN=`eval echo \\$SCRIPTDOWN`
    fi
    if test -n "$SCRIPT_DOWN" && test -x "./scripts/$SCRIPT_DOWN" ; then
	debug "Calling scripts/$SCRIPT_DOWN $CONFIG"
	./scripts/$SCRIPT_DOWN $CONFIG $HWDESC ${OPTIONS:+-o $OPTIONS}
    fi
fi

######################################################################
# Load all modules
#
for MODVAR in ${!MODULE*}; do
	: MODVAR=$MODVAR
	# There is a silly design bug: $MODULE_OPTIONS and $MODULE_UNLOAD
	# must not be interpreted as additional MODULE*
	case "$MODVAR" in
		MODULE_OPTIONS*|MODULE_UNLOAD*) continue ;;
	esac
	INDEX=${MODVAR#MODULE}
	if [ -n "$INDEX" ] ; then
		eval MODULE=\$MODULE$INDEX
		eval MODULE_OPTIONS=\$MODULE_OPTIONS$INDEX
		eval MODULE_UNLOAD=\$MODULE_UNLOAD$INDEX
	fi
	test -z "$MODULE" && continue
	if [ "$SCRIPTNAME" = hwup ] ; then
		message "hwup: Loading module '$MODULE'" \
		        "${MODULE_OPTIONS:+with options '$MODULE_OPTIONS' }" \
		        "for device '$HWDESC'"
		/sbin/modprobe $MODULE $MODULE_OPTIONS
	fi
	if [ "$SCRIPTNAME" = hwdown ] ; then
		: # to be implemented
	fi
	if [ "$SCRIPTNAME" = hwstatus ] ; then
		: # to be implemented
	fi
done

######################################################################
# Call a specialized up script, depending on the event
#
# have a look at 'Call a specialized down script' above
if [ "$SCRIPTNAME" = hwup ]; then
    # Call an event-specific script if one exists
    if [ "$HWD_DEVTYPE" ]; then
	SCRIPT_UP=`eval echo \\$SCRIPTUP_$HWD_DEVTYPE`
    fi
    # Call a generic script if no event-specific exists
    if [ -z "$SCRIPT_UP" ]; then
	SCRIPT_UP=`eval echo \\$SCRIPTUP`
    fi
    if test -n "$SCRIPT_UP" && test -x "./scripts/$SCRIPT_UP" ; then
	debug "Calling scripts/$SCRIPT_UP $CONFIG"
	./scripts/$SCRIPT_UP $CONFIG $HWDESC ${OPTIONS:+-o $OPTIONS}
    fi
fi

######################################################################
# execute individual poststart or postdown scripts if available
#
if [ "$SCRIPTNAME" = hwup ] ; then
# NOTE: 'eval echo' in the next line is necessary to expand settings
# like POST_UP_SCRIPT="~root/bin/foo"
	for PUS in `eval echo $POST_UP_SCRIPT scripts/$POST_UP_SCRIPT`; do
		if [ -x "$PUS" -a ! -d "$PUS" ] ; then
			debug "executing additional start script $PUS"
			$PUS $CONFIG $HWDESC ${OPTIONS:+-o $OPTIONS}
		fi
	done
fi
if [ "$SCRIPTNAME" = hwdown ] ; then
# NOTE: 'eval echo' in the next line is necessary to expand settings
# like POST_DOWN_SCRIPT="~root/bin/foo"
	for PDS in `eval echo $POST_DOWN_SCRIPT scripts/$POST_DOWN_SCRIPT`; do
		if [ -x "$PDS" -a ! -d "$PDS" ] ; then
			debug "executing additional stop script $PDS"
			$PDS $CONFIG $HWDESC ${OPTIONS:+-o $OPTIONS}
		fi
	done
fi

