#!/bin/bash
# =============================================================================
# 
# @(#) strload,v openss7-0_9_2_F(0.9.2.9) 2006/09/29 11:51:16
#
# -----------------------------------------------------------------------------
#
# Copyright (c) 2001-2006  OpenSS7 Corporation <http://www.openss7.com>
# Copyright (c) 1997-2000  Brian F. G. Bidulock <bidulock@openss7.org>
#
# All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 675 Mass
# Ave, Cambridge, MA 02139, USA.
#
# -----------------------------------------------------------------------------
#
# U.S. GOVERNMENT RESTRICTED RIGHTS.  If you are licensing this Software on
# behalf of the U.S. Government ("Government"), the following provisions apply
# to you.  If the Software is supplied by the Department of Defense ("DoD"), it
# is classified as "Commercial Computer Software" under paragraph 252.227-7014
# of the DoD Supplement to the Federal Acquisition Regulations ("DFARS") (or any
# successor regulations) and the Government is acquiring only the license rights
# granted herein (the license rights customarily provided to non-Government
# users).  If the Software is supplied to any unit or agency of the Government
# other than DoD, it is classified as "Restricted Computer Software" and the
# Government's rights in the Software are defined in paragraph 52.227-19 of the
# Federal Acquisition Regulations ("FAR") (or any successor regulations) or, in
# the cases of NASA, in paragraph 18.52.227-86 of the NASA Supplement to the FAR
# (or any successor regulations).
#
# -----------------------------------------------------------------------------
#
# Commercial licensing and support of this software is available from OpenSS7
# Corporation at a fee.  See http://www.openss7.com/
#
# -----------------------------------------------------------------------------
#
# Last Modified 2006/09/29 11:51:16 by brian
#
# =============================================================================

ECHO='echo'
SHELL='/bin/bash'
SED='sed'

# Check that we have a woring $ECHO.
if test "X$1" = X--no-reexec ; then
    # Discard the --no-reexec flag, and continue
    shift
elif test "X`(echo '\t') 2>/dev/null`" = 'X\t' ; then
    :
else
    exec $SHELL "$0" --no-reexec ${1+"$@"}
fi

if test "X$1" = X--fallback-echo ; then
    shift
    cat <<EOF
$*
EOF
    exit 0
fi

program=`$ECHO "$0" | $SED -e 's%^.*/%%'`
modename="$program"

ident='strload,v openss7-0_9_2_F(0.9.2.9) 2006/09/29 11:51:16'

# Sed substitution that helps us do robust quoting.  It backslashifies
# metacharacters that are still active within double-quoted strings.
Xsed="$SED"' -e 1s/^X//'
sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
# test EBCDIC or ASCII
case `$ECHO A | od -x` in
    *[Cc]1*) # EBCDIC based system
	SP2NL="tr '\100' '\n'"
	NL2SP="tr '\r\n' '\100\100'"
	;;
    *) # Assume ASCII based system
	SP2NL="tr '\040' '\012'"
	NL2SP="tr '\015\012' '\040\040'"
	;;
esac

# NLS nuisances.
# Only set LANG and LC_ALL to C if already set.
# These must not be set unconditionally because not all systems understand
# e.g. LANG=C (notably SCO).
# We save the old values to restore during execute mode.
if test "${LC_ALL+set}" = set ; then
    save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
fi
if test "${LANG+set}" = set ; then
    save_LANG="$LANG"; LANG=C; export LANG
fi

# Make sure IFS has a sensible default
: ${IFS=" 	"}

strload_letters='abcdefghijklmnopqrstuvwxyz'
strload_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
strload_Letters=$strload_letters$strload_LETTERS
strload_numbers='0123456789'
strload_alphano=$strload_Letters$strload_numbers
strload_uppercase="$SED y%*$strload_letters%P$strload_LETTERS%;s%[^_$strload_alphano]%_%g"
strload_tokenize="$SED s%[^a-zA-Z0-9]%_%g"

# Defaults

default_command="config"
default_filesrch="/etc/strload.conf:/etc/sysconfig/streams/strload.conf:$HOME/strload.conf:./strload.conf"
default_filename="/etc/strload.conf"

command=
filename=
debug=0
verbose=1

function version()
{
    if test ${show:-yes} = no ; then
	return
    fi
    cat <<EOF
$ident
Copyright (c) 2001-2006  OpenSS7 Corporation.  All Rights Reserved.
Distributed under GPL Version 2, included here by reference.
See \`$program --copying' for copying permissions.
EOF
}

function usage()
{
    if test ${show:-yes} = no ; then
	return
    fi
    cat <<EOF
Usage:
    $program [options] [{-l|--load}]
    $program [options] {-u|--unload}
    $program [options] {-q|--query}
    $program {-h|--help}
    $program {-V|--version}
    $program {-C|--copying}
EOF
}

function help()
{
    if test ${show:-yes} = no ; then
	return
    fi
    usage
    cat <<EOF
Options:
    -d, --drivers LIST
        comma separated list of additional drivers
    -m, --modules LIST
        comma separated list of additional modules
    -f, --filename FILENAME
        specify configuration file [default: '$default_filename']
    -q, --query
        report on status of referenced drivers and modules
    -u, --unload
	unload the referenced drivers and modules
    -l, --load
	load the referenced drivers and modules
    -n, --dryrun
        don't perform the actions, just check them
    -Q, --quiet
        suppress normal output
    -D, --debug [LEVEL]
        increase or set debugging verbosity
    -v, --verbose [LEVEL]
        increase or set output verbosity
    -h, --help
        prints this usage information and exits
    -V, --version
        prints the version and exits
    -C, --copying
        prints copying permissions and exits
EOF
}

function copying()
{
    if test ${show:-yes} = no ; then
	return
    fi
    cat <<EOF
--------------------------------------------------------------------------------
$ident
--------------------------------------------------------------------------------
Copyright (c) 2001-2006  OpenSS7 Corporation <http://www.openss7.com>
Copyright (c) 1997-2000  Brian F. G. Bidulock <bidulock@openss7.org>

All Rights Reserved.
--------------------------------------------------------------------------------
This program is free software; you can  redistribute  it and/or modify  it under
the terms  of the GNU General Public License  as  published by the Free Software
Foundation; version 2 of the License.

This program is distributed in the hope that it will  be useful, but WITHOUT ANY
WARRANTY; without even  the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.  See the GNU General Public License for more details.

You should  have received a copy of the GNU  General  Public License  along with
this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.
--------------------------------------------------------------------------------
U.S. GOVERNMENT RESTRICTED RIGHTS.  If you are licensing this Software on behalf
of the U.S. Government ("Government"), the following provisions apply to you. If
the Software is supplied by the  Department of Defense ("DoD"), it is classified
as "Commercial  Computer  Software"  under  paragraph  252.227-7014  of the  DoD
Supplement  to the  Federal Acquisition Regulations  ("DFARS") (or any successor
regulations) and the  Government  is acquiring  only the  license rights granted
herein (the license rights customarily provided to non-Government users). If the
Software is supplied to any unit or agency of the Government  other than DoD, it
is  classified as  "Restricted Computer Software" and the Government's rights in
the Software  are defined  in  paragraph 52.227-19  of the  Federal  Acquisition
Regulations ("FAR")  (or any successor regulations) or, in the cases of NASA, in
paragraph  18.52.227-86 of  the  NASA  Supplement  to the FAR (or any  successor
regulations).
--------------------------------------------------------------------------------
Commercial  licensing  and  support of this  software is  available from OpenSS7
Corporation at a fee.  See http://www.openss7.com/
--------------------------------------------------------------------------------
EOF
}

function syntax_error()
{
    if test ${verbose:-0} -gt 0 ; then
	$ECHO "$program: syntax error -- $1" >&2
	( usage ) >&2
    fi
    exit 2
}

function option_unrec()
{
    opt=`$ECHO -n "X$1" | $Xsed -e 's|=.*||'`
    syntax_error "\`$opt' unrecognized"
}

function option_noarg()
{
    opt=`$ECHO -n "X$1" | $Xsed -e 's|=.*||'`
    syntax_error "\`$opt' does not accept an argument"
}

function option_needarg()
{
    syntax_error "\`$1' requires an argument"
}

function option_after()
{
    syntax_error "\`$1' cannot occur after \`$2'"
}

function option_with()
{
    syntax_error "\`$1' cannot occur with \`$2'"
}

# Parse our command line options once, thoroughly.
while test "$#" -gt 0 -o ":$more" != ":"
do
    if test ":$more" != ":" ; then arg="-$more" ; more= ; else arg="$1" ; shift ; fi
    # check for attached option argument
    case $arg in
	--filename=* | --filenam=* | --filena=* | --filen=* | --file=* | --fil=* | --fi=* | --f=* | \
	--modules=*  | --module=*  | --modul=*  | --modu=*  | --mod=*  | --mo=*  | --m=*  | \
	--drivers=*  | --driver=*  | --drive=*  | --driv=*  | --dri=*  | --dr=*  | --d=*)
	    optarg=`$ECHO "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
	--*=*)
	    option_noarg $arg ;;
	-[qulnQDvhVC])
	    optarg= ;;
	-[qulnQDvhVC]*)
	    optarg=
	    more=`$ECHO "X$arg" | $Xsed -e 's|-[qulnQDvhVC]||'`
	    eval "arg=\`$ECHO \"X$arg\" | $Xsed -e 's|$more||'\`"
	    ;;
	-[fdm])
	    optarg= ;;
	-[fdm]*)
	    optarg=`$ECHO "X$arg" | $Xsed -e 's|-[fdm]||'` ;;
	*)
	    optarg= ;;
    esac
    # check for optional or required option argument
    if test -n "$prev" ; then
	case $arg in
	    -*) # optional arguments not forthcoming
		case $prev in
		    debug | verbose) eval "(($prev++))" ;;
		    # the rest have required arguments
		    filename | modules | drivers)
			option_needarg $prevopt ;;
		esac
		prev= ; prevopt=
		;;
	    *) # if the previous option needs an argument, assign it.
		eval "$prev=\"\$arg\""
		prev= ; prevopt=
		continue
		;;
	esac
    fi
    # Have we seen a non-optional argument yet?
    case $arg in
	--help | --h | --Help | --H | -h | -H | -\? | --\?)
	    show_help=yes
	    if test ":$command" = ":" ; then command=none ; fi
	    ;;
	--version | --versio | --versi | --vers | -V)
	    show_version=yes
	    if test ":$command" = ":" ; then command=none ; fi
	    ;;
	--copying | --copyin | --copyi | --copy | --cop | --co | --c | -C)
	    show_copying=yes
	    if test ":$command" = ":" ; then command=none ; fi
	    ;;
	--verbose | --verbos | --verbo | --verb)
	    prevopt="$arg"
	    prev=verbose
	    ;;
	-v)
	    ((verbose++))
	    ;;
	--verbose=* | --verbos=* | --verbo=* | --verb=*)
	    verbose="$optarg"
	    ;;
	--debug | --debu | --deb)
	    prevopt="$arg"
	    prev=debug
	    ;;
	-D)
	    $ECHO "$program: enabling shell trace mode" 1>&2
	    set -x
	    ;;
	--debug=* | --debu=* | --deb=*)
	    debug="$optarg"
	    ;;
	--dry-run | --dryrun | --n | -n)
	    run=no
	    ;;
	--quiet | --silent | -Q)
	    show=no
	    verbose=0
	    debug=0
	    ;;
	--filename | --filenam | --filena | --filen | --file | --fis | --fi | --f | -f)
	    prevopt="$arg"
	    prev=filename
	    ;;
	--filename=* | --filenam=* | --filena=* | --filen=* | --file=* | --fil=* | --fi=* | --f=* | -f*)
	    filename="$optarg"
	    ;;
	--drivers | --driver | --drive | --driv | --dri | --dr | --d | -d)
	    prevopt="$arg"
	    prev=drivers
	    ;;
	--drivers=* | --driver=* | --drive=* | --driv=* | --dri=* | --dr=* | --d=* | -d*)
	    drivers="$optarg"
	    ;;
	--modules | --module | --modul | --modu | --mod | --mo | --m | -m)
	    prevopt="$arg"
	    prev=modules
	    ;;
	--modules=* | --module=* | --modul=* | --modu=* | --mod=* | --mo=* | --m=* | -m*)
	    modules="$optarg"
	    ;;
	--load | --loa | --lo | --l | -l)
	    if test ":$command" != ":" -a ":$command" != ":load" ; then option_after $arg --$command ; fi
	    command=load
	    ;;
	--unload | --unloa | --unlo | --unl | --un | --u | -u)
	    if test ":$command" != ":" -a ":$command" != ":unload" ; then option_after $arg --$command ; fi
	    command=unload
	    ;;
	--query | --quer | --que | --qu | --q | -q)
	    if test ":$command" != ":" -a ":$command" != ":query" ; then option_after $arg --$command ; fi
	    command=query
	    ;;
	--)
	    # end of options
	    break
	    ;;
	-*)
	    option_unrec $arg
	    ;;
	*)
	    nonopt="${nonopt}${nonopt:+ }'$arg'"
	    ;;
    esac
done

# hit end of list wanting arguments
case $prev in
    # these have optional arguments
    debug | verbose) eval "(($prev++))" ;;
    # the rest have required arguments
    filename | drivers | modules)
	option_needarg $prevopt ;;
esac

if test x"$nonopt${nonopt:+ }${1+$@}" != "x" ; then
    eval "files=($nonopt${nonopt:+ }${1+$@})"
else
    files=
fi

# assign all defaults
if test ":$command" = ":" ; then
    command=load
fi
if test ":$filename$drivers$modules" = ":" ; then
    for file in `$ECHO -n "$default_filesrch" | $SED -e 's|:| |g'` ; do
	if test -f $file ; then
	    default_filename="$file"
	    break
	fi
    done
    filename="$default_filename"
fi

function parse_message()
{
    if test ${verbose:-0} -gt 0 ; then
	$ECHO "$program: $1: \`$filename' at line $lineno: $2" >&2
    fi
}

function parse_error()
{
    parse_message "error" "$1"
}

function parse_warning()
{
    parse_message "warning" "$1"
}

function fatal_error()
{
    if test ${verbose:-0} -gt 0 ; then
	$ECHO "$program: error: $1" >&2
    fi
    exit 1
}

function add_tokens()
{
    tokenlist="${tokenlist}${tokenlist:+ }$token"
    eval "${token}_mdtype=\"$mdtype\""
    eval "${token}_multiple=\"$multiple\""
    eval "${token}_node=\"$node\""
    eval "${token}_module=\"$module\""
    eval "${token}_modfile=\"$modfile\""
    eval "${token}_config=\"$config\""
    eval "${token}_device=\"$device\""
    eval "${token}_minors=\"$minors\""
}

function get_tokens()
{
    eval "mdtype=\"\$${1}_mdtype\""
    eval "multiple=\"\$${1}_multiple\""
    eval "node=\"\$${1}_node\""
    eval "module=\"\$${1}_module\""
    eval "modfile=\"\$${1}_modfile\""
    eval "config=\"\$${1}_config\""
    eval "device=\"\$${1}_device\""
    eval "minors=\"\$${1}_minors\""
}

function parse_file()
{
    lineno=0
    while read -a tokens
    do
	((lineno++))
	line="${tokens[*]}"
	line=`$ECHO "X$line" | $Xsed -e s'|#.*||g'`
	tokens=($line)
	numb=${#tokens[*]}
	if test $numb -eq 0 ; then continue ; fi
	# check for too few tokens
	if test $numb -lt 2 ; then parse_error "too few tokens, $numb instead of 2" ; continue ; fi
	# check for excess tokens
	if test $numb -gt 8 ; then parse_error "too many tokens, $numb instead of 8" ; continue ; fi
	modtyp="${tokens[0]}"
	module="${tokens[1]}"
	config="${tokens[2]}"
	device="${tokens[3]}"
	minors="${tokens[4]}${tokens[5]:+ }${tokens[5]}${tokens[6]:+ }${tokens[6]}${tokens[7]:+ }${tokens[7]}${tokens[8]:+ }${tokens[8]}"
	if test ":$config" = ":-" ; then config= ; fi
	if test ":$device" = ":-" ; then device= ; fi
	if test ":$minors" = ":-" ; then minors= ; fi
	case "$modtyp" in
	    m)		mdtype='module' ; multiple='no'  ; node='clone'    ; ;;
	    m\+)	mdtype='module' ; multiple='yes' ; node='clone'    ; ;;
	    ms)		mdtype='module' ; multiple='no'  ; node='standard' ; ;;
	    ms\+)	mdtype='module' ; multiple='yes' ; node='standard' ; ;;
	    m\+s)	mdtype='module' ; multiple='yes' ; node='standard' ; ;;
	    d)		mdtype='driver' ; multiple='no'  ; node='clone'    ; ;;
	    d\+)	mdtype='driver' ; multiple='yes' ; node='clone'    ; ;;
	    ds)		mdtype='driver' ; multiple='no'  ; node='standard' ; ;;
	    ds\+)	mdtype='driver' ; multiple='yes' ; node='standard' ; ;;
	    d\+s)	mdtype='driver' ; multiple='yes' ; node='standard' ; ;;
	    *)		parse_error "invalid attributes \`$modtyp'" ; continue ; ;;
	esac
	if test ":$mdtype" = ":module" ; then device= ; minors= ; fi
	modfile=`$ECHO "X$module" | $Xsed -r -e 's|^.*[/]||g;s|^streams[-_]||;s|\.[k]?o$||'`
	module=$(find /lib/modules/`uname -r`/ -regex '.*/streams[-_]'$modfile'.[k]?o' | head -1)
	if test -z "$module" ; then
	    parse_warning "file \`streams-$modfile' does not exist"
	    module="streams-$modfile"
	elif test ! -e $module ; then
	    parse_warning "file \`streams-$modfile' does not exist"
	    module="streams-$modfile"
	elif test ! -f $module ; then
	    parse_warning "file \`$module' is not a regular file"
	    module="streams-$modfile"
	elif test ! -r $module ; then
	    parse_warning "file \`$module' cannot be read"
	    module="streams-$modfile"
	fi
	if test -z "$config" ; then config="$modfile" ; fi
	if test -z "$device" ; then device="/dev/$modfile" ; fi
	if test -n "$minors" ; then
	    newminors=
	    for i in $minors ; do
		case $i in
		    0 | 1 | 2 | 3 | 4) newminors="${newminors}${newminors:+ }$i" ;;
		    *) parse_error "illegal minor number \`$i'" ;;
		esac
	    done
	    minors="$newminors"
	    unset newminors
	fi
	token=`$ECHO -n "$modfile$lineno" | $strload_tokenize`
	add_tokens
    done
}

function parse_drivers()
{
    while test -n "$1" ; do
	modfile=`$ECHO "X$1" | $Xsed -r -e 's|^.*[/]||g;s|^streams[-_]||;s|\.[k]?o$||'`
	mdtype='driver'
	multiple='no'
	node='clone'
	module=$(find /lib/modules/`uname -r`/ -regex '.*/streams[-_]'$modfile'.[k]?o' | head -1)
	if test -z "$module" ; then
	    parse_warning "file \`streams-$modfile' does not exist"
	    module="streams-$modfile"
	elif test ! -e $module ; then
	    parse_warning "file \`streams-$modfile' does not exist"
	    module="streams-$modfile"
	elif test ! -f $module ; then
	    parse_warning "file \`$module' is not a regular file"
	    module="streams-$modfile"
	elif test ! -r $module ; then
	    parse_warning "file \`$module' cannot be read"
	    module="streams-$modfile"
	fi
	config="$modfile"
	device="/dev/$modfile"
	minors=
	token=`$ECHO -n "$modfile" | $strload_tokenize`
	add_tokens
	shift
    done
}

function parse_modules()
{
    while test -n "$1" ; do
	modfile=`$ECHO "X$1" | $Xsed -r -e 's|^.*[/]||g;s|^streams[-_]||;s|\.[k]?o$||'`
	mdtype='module'
	multiple='no'
	node='clone'
	module=$(find /lib/modules/`uname -r`/ -regex '.*/streams[-_]'$modfile'.[k]?o' | head -1)
	if test -z "$module" ; then
	    parse_warning "file \`streams-$modfile' does not exist"
	    module="streams-$modfile"
	elif test ! -e $module ; then
	    parse_warning "file \`streams-$modfile' does not exist"
	    module="streams-$modfile"
	elif test ! -f $module ; then
	    parse_warning "file \`$module' is not a regular file"
	    module="streams-$modfile"
	elif test ! -r $module ; then
	    parse_warning "file \`$module' cannot be read"
	    module="streams-$modfile"
	fi
	config="$modfile"
	device=
	minors=
	token=`$ECHO -n "$modfile" | $strload_tokenize`
	add_tokens
	shift
    done
}

function parse_input()
{
    if test -n "$filename" ; then
	if test ${verbose:-0} -gt 1 ; then
	    $ECHO "$1 using configuration file \`$filename'"
	fi
	test_input_file
	parse_file <$filename
    fi
    if test -n "$drivers" ; then
	d=(`$ECHO "X$drivers" | $Xsed -e 's|,| |g'`)
	if test ${verbose:-0} -gt 1 ; then
	    $ECHO "$1 drivers \`${d[*]}'"
	fi
	parse_drivers ${d[*]}
    fi
    if test -n "$modules" ; then
	m=(`$ECHO "X$modules" | $Xsed -e 's|,| |g'`)
	if test ${verbose:-0} -gt 1 ; then
	    $ECHO "$1 modules \`${m[*]}'"
	fi
	parse_modules ${m[*]}
    fi
}

function none_command()
{
    if test -n "$show_version$show_help$show_copying" ; then
	if test ${verbose:-0} -gt 1 ; then
	    $ECHO "Displaying information"
	fi
	if test ":$show_version" != ":" ; then
	    version
	fi
	if test ":$show_help" != ":" ; then
	    help
	fi
	if test ":$show_copying" != ":" ; then
	    copying
	fi
    fi
}

function test_input_file()
{
    if test ! -e $filename ; then fatal_error "file \`$filename' does not exist" ; fi
    if test ! -f $filename ; then fatal_error "file \`$filename' is not a regular file" ; fi
    if test ! -r $filename ; then fatal_error "file \`$filename' cannot be read" ; fi
}

function query_command()
{
    parse_input "Querying"
    if test -n "$tokenlist" ; then
	for token in $tokenlist ; do
	    get_tokens "$token"
	    if grep "^streams[-_]$modfile\>" /proc/modules >/dev/null 2>&1; then
		if test ${verbose:-0} -gt 0 ; then
		    $ECHO "$modfile is loaded."
		fi
	    elif grep "\<$modfile\>" /proc/devices >/dev/null 2>&1; then
		if test ${verbose:-0} -gt 0 ; then
		    $ECHO "$modfile is loaded."
		fi
	    else
		if test ${verbose:-0} -gt 0 ; then
		    $ECHO "$modfile is not loaded."
		fi
	    fi
	    majors=(`grep "\<$modfile\>" /proc/devices 2>/dev/null | $SED -e "s/$modfile//"`)
	    if test -n "${majors[*]}" ; then
		if test ${verbose:-0} -gt 0 ; then
		    $ECHO "$modfile has major device numbers ${majors[*]}"
		fi
	    fi
	done
    fi
}

function load_command()
{
    parse_input "Loading"
}

function unload_command()
{
    parse_input "Unloading"
}

case "$command" in
    none)
	none_command
	;;
    query)
	query_command
	;;
    load)
	load_command
	;;
    unload)
	unload_command
	;;
    *)
	( usage ) >&2
	exit 1
	;;
esac

exit 0

# vim: ft=sh sw=4
