head	1.5;
access;
symbols
	ansi-20040405-merged:1.4
	postmerge-20040405-ansi:1.4
	premerge-20040404-ansi:1.4
	postmerge-autoconf:1.4
	autoconf-freeze:1.4
	premerge-autoconf:1.4
	postmerge-20040315-windows:1.4
	premerge-20040315-windows:1.4
	windows-20040315-freeze:1.4
	autoconf-20031203:1.4
	autoconf-20031202:1.4
	autoconf-branch:1.4.0.12
	phong-branch:1.4.0.10
	photonmap-branch:1.4.0.8
	rel-6-1-DP:1.4
	windows-branch:1.4.0.6
	rel-6-0-2:1.4
	ansi-branch:1.4.0.4
	rel-6-0-1-branch:1.4.0.2
	hartley-6-0-post:1.4
	hartley-6-0-pre:1.4
	rel-6-0-1:1.4
	rel-6-0:1.4;
locks; strict;
comment	@# @;


1.5
date	2004.05.19.19.16.08;	author morrison;	state dead;
branches;
next	1.4;

1.4
date	2001.10.23.16.15.48;	author morrison;	state Exp;
branches;
next	1.3;

1.3
date	2001.10.17.07.44.58;	author morrison;	state Exp;
branches;
next	1.2;

1.2
date	2001.10.12.23.11.20;	author morrison;	state Exp;
branches;
next	1.1;

1.1
date	2001.10.04.18.26.17;	author morrison;	state Exp;
branches;
next	;


desc
@@


1.5
log
@The old regression test scripts are being replaced by something else.  Likely it'll be Corredor with some unit test framework.  The old scripts are so far out of sync and so inadequate that it's simply not worth it any more.
@
text
@#!/bin/sh
#
# l i b r a r y
#
###
#   this is a general purpose sh utility library providing a set of environment
#   variables and function calls.  the primary intended usage is to aid the
#   brlcad regression testing suite.
#
#   do not copy the routines found here.  instead, include this library into
#   scripts as such:
#
#     . `dirname $0`/library
#
#   dirname is used so that the including scripts may be called from any path
#   and the library script will be found and included regardless of the script
#   or shell behavior.
#
#   listed below are the functions and variables that are provided by sourcing
#   this script.  see the respective function for more details on what 
#   arguments it takes and how the function behaves.
#
###
#
# FUNCTIONS
#
#   log
#       writes output to a given log file
#   plog
#       writes "pretty" output to a given log file in column format
#   bomb
#       writes an error message to the log
#   warn
#       writes a warning message to the log, optionally bombing
#
#   initializeVariable
#       initializes a given variable to a defaultValue if it is not already set
#   setHostName
#       sets a var to the HOSTNAME from a variety of potential methods
#   hostIsAlive
#       returns a boolean whether the given host/ip is alive (answers ping)
#   loadSourceFile
#       loads the requested file and evaluates the contents as script source
#
#   acquireLock
#       creates a cooperative lock file ("blocks" when one already exists)
#   releaseLock
#       releases and/or removes a cooperative lock file (rm's the lock)
#   releaseAllLocks
#       releases all locally acquired locks (via internal _ACQUIRED_LOCKS)
#
#   acquireSemaphore
#       gets a cooperative file semaphore ("blocks" when one does not exist)
#   releaseSemaphore
#       releases and/or creates a cooperative file semaphore (touch's the 
#       semaphore)
#   releaseAllSemaphores
#       releases all locally acquired semaphores (via internal 
#       _ACQUIRED_SEMAPHORES)
#
#   mail
#       mail a file with optional attachments to a user
#   cvsExport
#       perform a cvs export for given source tag
#   unpackArchive
#       unpack an archive in a variety of formats (tar files, tgz, zip, etc)
#
###
#
# GLOBALS
# 
#   LOG
#       output is sent to $LOG, and is /dev/tty by default
#   DEBUG  
#       when non-null defined, extra call details will be sent to $LOG.
#       that means define DEBUG if you're modifying scripts for extra info
#   SILENT
#       when non-null defined, logging output is suppressed (except log debug
#       messages).
#   HOSTNAME
#       the host name derifed from 1) hostname command, 2) HOST env var,
#       3) HOSTNAME env var, 4) default "unknown" value
#   ARCH
#       the complete architecture definition of this client as given by uname
#   LPWD
#       current working directory path where library is included
#
#   LIBRARY_VERSION
#       version of this library file being used (majorRelease.minorRelease)
#
#
# INTERNAL  (do not use)
#
#   _ACQUIRED_LOCKS
#   _ACQUIRED_SEMAPHORES
#   _TEMP_DEBUG_OFF
#
###
#
# REGRESSION TEST FUNCTIONS
#
#   logSuccess
#       outputs a success message with ansi or text, depending on the style
#   logFailure
#       outputs a failure message with ansi or text, depending on the style
#   logPassed
#       outputs a passed message with ansi or text, depending on the style
#
#   initializeTest
#       initializes an environment and some variables
#   uninitializeTest
#       returns an environment to a previously initialized state
#
#   regress
#       main regression testing function for regression scripts to call
#
# REGRESSION TEST VARIABLES
#
#   STYLE
#       set to color to take advantage of a terminal that supports
#       color output (though ansi escape sequences)
#   SETCOLOR_SUCCESS
#       set output color for a success statement
#   SETCOLOR_FAILURE
#       set output color for a failure statement
#   SETCOLOR_WARNING
#       set output color for a warning statement
#   SETCOLOR_NORMAL
#       set output color for a normal statement
#
###############################################################################

# version of this library script file
LIBRARY_VERSION=1.0 ; export LIBRARY_VERSION

# have to init LOG here so functions will output properly
# common log defaults include /dev/tty, stdout, or stderr
if [ x$LOG = x ] ; then 
    LOG="stdout" ; export LOG
fi
#
# log [-n] [messageToWrite] [fileToWriteTo]
#
# log writes a given message out to a file name.
# when given the -n option, it does not output the trailing newline (assumes -n support in echo).
# log should *never* call the inherited warn() or bomb() calls
#
# set SILENT variable to non-empty string to avoid output of actual message
#
log ( ) {
    __NEWLINE="" 
    __ENDARGS=""
    while [ "x$__ENDARGS" = "x" ] ; do
        case "$1" in
            -n | -e | -ne | -en )
                __NEWLINE="$__NEWLINE $1"
                __MESSAGE="\$2"
                if [ "x$3" = "x" ] ; then __FILE="$LOG" ; else __FILE="$3" ; fi
                shift
                ;;
            * )
                __MESSAGE="\$1"
                __ENDARGS="yes"
                if [ "x$2" = "x" ] ; then __FILE="$LOG" ; else __FILE="$2" ; fi
                ;;
        esac
    done
    unset __ENDARGS

    # convert stdout and stderr to the proper redirect
    if [ "x$__FILE" = "xstdout" ] ; then 
	__FILE=""
    elif [ "x$__FILE" = "xstderr" ] ; then 
	__FILE="1>&2"
    else
	__FILE=">> $__FILE"
    fi

    # this is the only call that sends debug after initialization since we want
    # to properly handle a "std???" set LOG var
    if [ x$_TEMP_DEBUG_OFF = x ] ; then
	# for gratuitous logging...
	if [ ! "x$DEBUG" = x ] ; then echo "log( \$1=[$1] \$2=[$2] \$3=[$3])" $__FILE ; fi
    fi


    # check for explicit escape option support
    # try to find a decent echo with -e support
    __LOGTEST=`echo -e "\t\ntest"`
    if [ `echo $__LOGTEST | awk '{print $1}'` = "test" ] ; then
	__ECHO="echo -e"
    # no -e support
    else
	# need to do some extra checking since the sun5 /bin/echo sucks
	# see if default echo supports special chars
	__LOGTEST=`echo "\t\ntest"`
	if [ "x`echo $__LOGTEST | awk '{print $1}'`" = "xtest" ] ; then 
	    __ECHO="echo"
	else
	    # for sun5 (built-in echo is poor)
	    __LOGTEST=`/usr/bin/echo "\t\ntest"`
	    if [ "x`echo $__LOGTEST | awk '{print $1}'`" = "xtest" ] ; then
		__ECHO="/usr/bin/echo"
	    else
		echo "WARNING: cannot find decent echo"
		__ECHO="echo"
	    fi
	fi
    fi

# for gratuitous logging...
#    if [ ! x$DEBUG = x ] ; then echo "log: __ECHO=[${__ECHO}] __MESSAGE=[${__MESSAGE}] __FILE=[${__FILE}]" >> $LOG ; fi

    # output the message unless we are in "silent" mode
    if [ "x$SILENT" = "x" ] ; then
        eval "$__ECHO $__NEWLINE \"$__MESSAGE\" $__FILE"
    fi
}
# log the LOG var
if [ ! "x$DEBUG" = "x" ]  ; then log "LOG=$LOG" ; fi

#
# plog [messageToWrite] [fileToWriteTo] [columnWidth] [leadingEdge]
#
# plog "pretty writes" a given message out to a file name
# the columnWidth is the maximum length of a given column, while the
# leading edge is what kind of padding (if any) needs to go on the left
# of each line.
# plog, like log, should *never* call the inherited warn() or bomb() calls
#
plog ( ) {
    if [ "x$2" = "x" ] ; then __FILE="$LOG" ; else __FILE="$2" ; fi
    if [ "x$3" = "x" ] ; then __COLUMN="32000" ; else __COLUMN="$3" ; fi
    __LEAD="$4"

    # this is the only call that sends debug after initialization since we want
    # to properly handle a "std???" set LOG var
    if [ x$_TEMP_DEBUG_OFF = x ] ; then
	# for gratuitous logging...
	if [ ! "x$DEBUG" = x ] ; then echo "plog( \$1=[$1] \$2=[$2] \$3=[$3] \$4=[$4] )" $__FILE ; fi
    fi

    # turn off log debugging
    if [ ! "x$DEBUG" = x ] ; then export _TEMP_DEBUG_OFF=1 ; fi

    __LINE=""
    __POS=0
# !!! some shells will have already expanded $1 -- need better method for handling newlines and the sort
    for __WORD in $1 ; do

# !!! see if all our systems support the -c option to wc since obviating awk will speed this up a little 
# (faster)        __SIZE="`echo $__WORD | wc -c`"

        __NEWLINE=`echo $__WORD | grep '\\\n'`
        if [ ! "x$__NEWLINE" = "x" ] ; then
            __SIZE=`expr -$__POS + -$__COLUMN`
        else
            __SIZE="`echo $__WORD | wc | awk '{print $3}'`"
            # add extra padding for a tab (!!! should convert to spaces)
            if [ ! "x`echo $__WORD | grep '\\\t'`" = "x" ] ; then
                __SIZE=`expr $__SIZE + 7`
            # add an extra space at the end of a sentance
            elif [ ! "x`echo $__WORD | grep '\\.$'`" = "x" ] ; then
                __SIZE=`expr $__SIZE + 1`
                __WORD="$__WORD "
            fi
        fi

        __NEWSIZE=`expr $__POS + $__SIZE + 1`

        if [ $__NEWSIZE -gt $__COLUMN ] ; then
            log "${__LEAD}${__LINE}" "$__FILE"
            __LINE="$__WORD"
            __POS="$__SIZE"
        elif [ $__NEWSIZE -lt 0 ] ; then
            log "${__LEAD}${__LINE} $__WORD" "$__FILE"
            __LINE=""
            __POS=0
        else
            __POS=$__NEWSIZE
            if [ "x$__LINE" = "x" ] ; then
                __LINE="$__WORD"
            else
                __LINE="${__LINE} $__WORD"
            fi
        fi
    done
    log "${__LEAD}${__LINE}" "$__FILE"

    # turn log debugging back on if it was
    if [ ! "x$DEBUG" = x ] ; then unset _TEMP_DEBUG_OFF ; fi

}


#
# bomb [messageToWrite] [fileToWriteTo] [returnCode]
#
# writes a message out via the log facility and then exits returning a given 
# value. if the global _ACQUIRED_LOCKS or _ACQUIRED_SEMAPHORES variables are
# set (done by acquireLock() and acquireSemaphore()), then they are released
# prior to exiting.
#
# by default we write bomb output to stderr instead of stdout
# 
bomb ( ) {
    if [ x$_TEMP_DEBUG_OFF = x ] ; then
        if [ ! "x$DEBUG" = x ] ; then log "bomb( \$1=[$1] \$2=[$2] \$3=[$3] )" ; fi
    fi

    if [ "x$2" = "x" ] ; then __BOMBLOG="$2" ; else __BOMBLOG="$2" ; fi

    # need a check if dollar three is a number...
    if [ "x$3" = "x" ] ; then __CODE=1 ; else __CODE="$3" ; fi

    # release any locks or semaphores quietly
    releaseAllLocks > /dev/null 2>&1
    releaseAllSemaphores > /dev/null 2>&1

    # turn off log debugging
    if [ ! "x$DEBUG" = x ] ; then export _TEMP_DEBUG_OFF=1 ; fi

    log "ERROR: $1" "$__BOMBLOG"
    # explicitly display the error message to terminal if logging elsewhere
    # !!! may consider switching default behaviour to be stdout instead of terminal
    if [ ! "x$__BOMBLOG" = "x/dev/tty" ] ; then 
	if [ "x$__BOMBLOG" = "x" ] ; then
	    if [ ! "x$LOG" = "x/def/tty" ] ; then
		if [ -w /dev/tty ] ; then
		    log "ERROR: $1" "/dev/tty"
		fi
	    fi
	fi
    fi

    # exit as requested
    exit $__CODE
}


#
# warn [messageToWrite] [fileToWriteTo] [noWarnings]
#
# writes a message out via the log facility and optionally will bomb instead of
# simply warn if NO_WARNINGS is set or specified, noWarnings arg overrides 
# (any non-zero value is true)
# 
# by default we write warn output to stderr instead of stdout
#
warn ( ) {
    if [ x$_TEMP_DEBUG_OFF = x ] ; then
        if [ ! "x$DEBUG" = x ] ; then log "warn( \$1=[$1] \$2=[$2] \$3=[$3] )" ; fi
    fi

    if [ "x$2" = "x" ] ; then __WARNLOG="$2" ; else __WARNLOG="$2" ; fi

    # should check if dollar three is a number...
    __BOMB=0
    if [ ! x$NO_WARNINGS = x ] ; then __BOMB=$NO_WARNINGS ; fi
    if [ ! "x$3" = "x" ] ; then __BOMB=1 ; fi

    # turn off log debugging
    if [ ! "x$DEBUG" = x ] ; then export _TEMP_DEBUG_OFF=1 ; fi

    log "WARNING: $1" "$__WARNLOG"
    if [ ! "x$__BOMB" = "x0" ] ; then
	bomb "fail on warnings is set so exiting now"
    fi

    # turn log debugging back on if it was
    if [ ! "x$DEBUG" = x ] ; then unset _TEMP_DEBUG_OFF ; fi
}


#
# initializeVariable variableName [defaultValue]
#
# initializes a variable to a given value unless that variable
# is already defined (e.g. already initialized).  this allows
# script variables to also be overridden by environment variables
#
initializeVariable ( ) {
    if [ ! "x$DEBUG" = "x" ] ; then log "initializeVariable( \$1=[$1] \$2=[$2] )" ; fi

    if [ "x$1" = "x" ] ; then 
	bomb "initializeVariable() arg1 mismatch"
    else 
	__VAR="$1"
    fi
    # do not need to check since may be empty anyways
    __DEF="$2"

    # stupid name to variable translation is a bitch..especially on sun5

    # make sure a value is not already set for the variable being initialized
    __PVAR="echo \$$__VAR"
    if [ x`eval $__PVAR` = x ] ; then
	__CMD="$__VAR=\"$__DEF\""
	eval $__CMD
	export $__VAR
    fi

    if [ ! x$DEBUG = x ] ; then log "initializeVariable: $__VAR=[`eval $__PVAR`]" ; fi
}


#
# setHostName [variable] [defaultValue]
#
# attempts to derive the host name of the running machine.
# precedence is given to the HOSTNAME and HOST environment
# variables, then we try uname.  by default we set to
# the HOSTNAME environment variable
#
setHostName ( ) {
    if [ ! "x$DEBUG" = x ] ; then log "setHostName( \$1=[${1}] \$2=[${2}] )" ; fi

    if [ "x$1" = x ] ; then 
	__VAR="HOSTNAME"
    else 
	__VAR="$1"
	# do not forget to check system
	initializeVariable $__VAR "$HOST"
	if [ x$__VAR = x ] ; then $__VAR=$HOSTNAME ; export $__VAR ; fi
    fi
    if [ "x$2" = x ] ; then __DEFVAL="unknown" ; else __DEFVAL=$2 ; fi

    __VARVAL="echo \$$__VAR"
    if [ ! "x$DEBUG" = x ] ; then log "setHostName: ${__VAR}=[`eval $__VARVAL`]" ; fi

    # multiple inits work (without the ifthen mess) since the set should
    # not clobber a variable that already has a non-empty value set
    if [ x`eval $__VARVAL` = x ] ; then initializeVariable $__VAR `hostname` ; fi
    if [ x`eval $__VARVAL` = x ] ; then initializeVariable $__VAR $HOST ; fi
    if [ x`eval $__VARVAL` = x ] ; then initializeVariable $__VAR `uname -n` ; fi
    if [ x`eval $__VARVAL` = x ] ; then initializeVariable $__VAR $__DEFVAL ; fi
}

#
# hostIsAlive hostOrIP
#
# returns a boolean whether the given host or ip address is "valid" or not.
# a host is considered valid if it is responding to ping requests
#
hostIsAlive ( )  {
    if [ ! "x$DEBUG" = x ] ; then log "hostIsAlive( \$1=[${1} ) " ; fi

    if [ ! "x$1" = "x" ] ; then
        __HOST="$1"
    else 
        bomb "hostIsAlive() arg1 mismatch -- no host was given"
    fi

    if ping -c 2 $__HOST > /dev/null 2>&1 ; then
        return 0
    # handle cads odd location of ping
    elif /usr/etc/ping -c 2 $__HOST > /dev/null 2>&1 ; then
        return 0
    elif `which ping` -c 2 $__HOST > /dev/null 2>&1 ; then
        return 0
    fi

    # fail if we couldn't get a successful ping (after two tries)
    return 1
}


#
# loadResourceFile fileName
#
loadResourceFile ( ) {
    if [ ! "x$DEBUG" = x ] ; then log "loadResourceFile( \$1=[${1} ) " ; fi

    if [ ! "x$1" = "x" ] ; then
        __FILE="$1"
    else 
        bomb "loadResourceFile() arg1 mismatch -- no file was given"
    fi

    if [ ! -f "$__FILE" ] ; then
        warn "Resource file [$__FILE] does not exist"
        return 1
    elif [ ! -r "$__FILE" ] ; then
        warn "Unable to read resource file [$__FILE]"
        return 1
    fi
    
    __RCSRC="`cat $__FILE`"
    eval $__RCSRC

    if [ $? != 0 ] ; then
        warn "Unable to properly load resource file"
        return 1
    fi

    return 0
}


#
# acquireLock [lockName] [retryCount] [waitLength] [location]
#
# will create a file that will block subsequent calls to acquireLock until the 
# file lock is released.  a ".lock" extension is appended automatically to 
# distinguish between file locks and file semaphores.
# locks acquired are listed in the ACQUIRED_LOCKS global var
#
# if file exists then wait/fail
# else create lock file and log
#
acquireLock ( ) {
    if [ ! "x$DEBUG" = x ] ; then log "acquireLock( \$1=[$1] \$2=[$2] \$3=[$3] \$4=[$4] )" ; fi

    if [ "x$1" = x ] ; then __NAME="local" ; else __NAME="${1}" ; fi
    if [ "x$2" = x ] ; then __RETRY=1 ; else __RETRY=$2 ; fi
    if [ "x$3" = x ] ; then __WAIT=0 ; else __WAIT=$3 ; fi
    if [ "x$4" = x ] ; then 
	# if we start with a slash, prefix is nothing (rooted name), otherwise use a relative path
	__SWS=`echo $__NAME | sed 's/^\/.*/___ROOTED_NAME___/'`
	if [ "x$__SWS" = "x___ROOTED_NAME___" ] ; then __PREFIX="" ; else __PREFIX="./" ; fi
    else 
	# if we end with a slash, no worries, otherwise, append one
	__SWS=`echo $__NAME | sed 's/.*\/$/___END_SLASH___/'`
	if [ "x$__SWS" = "x___END_SLASH___" ] ; then __PREFIX="$4" ; else __PREFIX="${4}/" ; fi
    fi
    __LOCK="${__NAME}.lock"

    while [ -f ${__PREFIX}$__LOCK ] ; do
	__RETRY=`expr $__RETRY - 1`
	if [ $__RETRY -lt 1 ] ; then
	    warn "Unable to obtain $__LOCK in $__PREFIX"
            
            if [ ! "x$USER" = "x" ] ; then __USER="$USER" ; unset USER ; fi
            if [ ! "x$PID" = "x" ] ; then __PID="$USER" ; unset PID ; fi
            if [ ! "x$DATE" = "x" ] ; then __DATE="$USER" ; unset DATE ; fi
            loadResourceFile "${__PREFIX}$__LOCK"
            if [ ! "x$USER" = "x" ] ; then
                log "Timed out waiting for ${USER}'s lock held since ${DATE} (pid: $PID)"
            fi
            if [ ! "x$__USER" = "x" ] ; then USER="$__USER" ; unset __USER ; fi
            if [ ! "x$__PID" = "x" ] ; then PID="$__USER" ; unset __PID ; fi
            if [ ! "x$__DATE" = "x" ] ; then DATE="$__USER" ; unset __DATE ; fi
            
	    return 1
	fi
	log "Waiting for $__LOCK ($__WAIT seconds)... $__RETRY attempts remain"
	sleep $__WAIT
    done
    touch ${__PREFIX}$__LOCK
    if [ ! -w ${__PREFIX}$__LOCK ] ; then
        warn "Unable to write to lock file $__LOCK in ${__PREFIX}?"
    fi
    # save details about the acquiring process to the lock file
    if [ ! "x$USER" = "x" ] ; then log "USER=\"$USER\"" "${__PREFIX}$__LOCK" ; else log "USER=\"unknown\"" "${__PREFIX}$__LOCK" ; fi
    log "PID=\"$$\"" "${__PREFIX}$__LOCK"
    log "DATE=\"`date`\"" "${__PREFIX}$__LOCK"
    # keep a list of the acquired locks up to date
    _ACQUIRED_LOCKS="$_ACQUIRED_LOCKS ${__PREFIX}$__NAME" ; export _ACQUIRED_LOCKS
    log "Acquired $__LOCK"

    return 0
}


#
# releaseLock [lockName] [location]
#
# if file exists then remove and try unlog
# else warn and try unlog
#
releaseLock ( ) {
    if [ ! "x$DEBUG" = x ] ; then log "releaseLock( \$1=[$1] \$2=[$2] )" ; fi

    if [ "x$1" = x ] ; then __NAME="local" ; else __NAME="${1}" ; fi
    if [ "x$2" = x ] ; then 
	# if we contain a slash, prefix is nothing (rooted or relative-path name), otherwise use a current dir
	__SWS=`echo $__NAME | sed 's/.*\/.*/___ROOTED_NAME___/'`
	if [ ! "x$DEBUG" = x ] ; then log "releaseLock: __SWS=[$__SWS]" ; fi
	if [ "x$__SWS" = "x___ROOTED_NAME___" ] ; then __PREFIX="" ; else __PREFIX="./" ; fi
    else 
	# if we end with a slash, no worries, otherwise, append one
	__SWS=`echo $__NAME | sed 's/.*\/$/___END_SLASH___/'`
	if [ "x$__SWS" = "x___END_SLASH___" ] ; then __PREFIX="$2" ; else __PREFIX="${2}/" ; fi
    fi
    __LOCK="${__NAME}.lock"

    if [ ! "x$DEBUG" = x ] ; then log "releaseLock: __PREFIX=[$__PREFIX] __LOCK=[$__LOCK]" ; fi

    if [ ! -f "${__PREFIX}$__LOCK" ] ; then
	warn "Lock [$__LOCK] is already released"
	# make sure the lock is not registered 
	if [ ! "x$_ACQUIRED_LOCKS" = "x" ] ; then
	    __NEW_AL=""
	    for __CL in $_ACQUIRED_LOCKS ; do
		if [ ! "x$__CL" = "x${__PREFIX}$__NAME" ] ; then
		    __NEW_AL="$__NEW_AL $__CL"
		fi
	    done
	    _ACQUIRED_LOCKS="$__NEW_AL" ; export _ACQUIRED_LOCKS
	fi
	return 1
    fi
    rm -f ${__PREFIX}$__LOCK
    # unregister the lock with the _ACQUIRED_LOCKS var
    if [ ! "x$_ACQUIRED_LOCKS" = "x" ] ; then
	__NEW_AL=""
	__FOUND_LOCK=0
	for __CL in $_ACQUIRED_LOCKS ; do
	    if [ "x$__CL" = "x${__PREFIX}$__NAME" ] ; then
		__FOUND_LOCK=1
	    else
		__NEW_AL="$__NEW_AL $__CL"
	    fi
	done
	if [ ! "x$__FOUND_LOCK" = "x1" ] ; then
	    warn "bad bookkeeping -- _ACQUIRED_LOCKS is missing entry $__NAME [LOCK=${__PREFIX}${__NAME}] [_A_L=$_ACQUIRED_LOCKS]"
	fi
	_ACQUIRED_LOCKS="$__NEW_AL" ; export _ACQUIRED_LOCKS
    else
	warn "bad bookkeeping -- _ACQUIRED_LOCKS is empty prior to a release of $__NAME"
    fi
    log "Released $__LOCK"
    return 0
}

#
# releaseAllLocks
#
releaseAllLocks ( ) {
    if [ ! "x$DEBUG" = x ] ; then log "releaseAllLocks() _ACQUIRED_LOCKS=[$_ACQUIRED_LOCKS]" ; fi

    if [ ! "x$_ACQUIRED_LOCKS" = x ] ; then
	for __LOCK in $_ACQUIRED_LOCKS ; do
	    releaseLock $__LOCK
	done
    fi
}

#
# acquireSemaphore [semaphoreName] [retryCount] [waitLength] [location]
#
# if file exists then remove file and log
# else wait/fail
#
acquireSemaphore ( ) {
    if [ ! "x$DEBUG" = x ] ; then log "acquireSemaphore( \$1=[$1] \$2=[$2] \$3=[$3] \$4=[$4] )" ; fi

    if [ "x$1" = x ] ; then __NAME="local" ; else __NAME="${1}" ; fi
    if [ "x$2" = x ] ; then __RETRY=1 ; else __RETRY=$2 ; fi
    if [ "x$3" = x ] ; then __WAIT=0 ; else __WAIT=$3 ; fi
    if [ "x$4" = x ] ; then 
	# if we start with a slash, prefix is nothing (rooted name), otherwise use a relative path
	__SWS=`echo $__NAME | sed 's/^\/.*/___ROOTED_NAME___/'`
	if [ "x$__SWS" = "x___ROOTED_NAME___" ] ; then __PREFIX="" ; else __PREFIX="./" ; fi
    else 
	# if we end with a slash, no worries, otherwise, append one
	__SWS=`echo $__NAME | sed 's/.*\/$/___END_SLASH___/'`
	if [ "x$__SWS" = "x___END_SLASH___" ] ; then __PREFIX="$4" ; else __PREFIX="${4}/" ; fi
    fi
    __SEMAPHORE="${__NAME}.semaphore"

    while [ ! -f ${__PREFIX}$__SEMAPHORE ] ; do
	__RETRY=`expr $__RETRY - 1`
	if [ $__RETRY -lt 1 ] ; then
	    warn "Unable to obtain $__SEMAPHORE in $__PREFIX"
	    return 1
	fi
	log "Waiting for $__SEMAPHORE ($__WAIT seconds)... $__RETRY attempts remain"
	sleep $__WAIT
    done
    # we move instead of delete so that we can tell who has acquired the semaphore
    mv -f "${__PREFIX}${__SEMAPHORE}" "${__PREFIX}${__SEMAPHORE}.acquired"
    if [ ! -w "${__PREFIX}${__SEMAPHORE}.acquired" ] ; then
        warn "Unable to write to acquired semaphore file ${__SEMAPHORE}.acquired in ${__PREFIX}"
    fi    
    # sanity check - make sure file is gone
    if [ -f "${__PREFIX}${__SEMAPHORE}" ] ; then
	warn "Unable to properly remove/acquire semaphore file ${__SEMAPHORE} in ${__PREFIX}"
	return 1
    fi

    if [ ! "x$USER" = "x" ] ; then log "USER=$USER" "${__PREFIX}${__SEMAPHORE}.acquired" ; else log "USER=unknown" "${__PREFIX}${__SEMAPHORE}.acquired" ; fi
    log "PID=$$" "${__PREFIX}${__SEMAPHORE}.acquired"
    log "DATE=`date`" "${__PREFIX}${__SEMAPHORE}.acquired"

    _ACQUIRED_SEMAPHORES="$_ACQUIRED_SEMAPHORES ${__PREFIX}$__NAME" ; export _ACQUIRED_SEMAPHORES
    log "Acquired $__SEMAPHORE"

    return 0
}


#
# releaseSemaphore [semaphoreName]
#
# if file exists then warn and try unlog
# else create file and try unlog
#
releaseSemaphore ( ) {
    if [ ! "x$DEBUG" = x ] ; then log "releaseSemaphore( \$1=[$1] \$2=[$2] )" ; fi

    if [ "x$1" = x ] ; then __NAME="local" ; else __NAME="${1}" ; fi
    if [ "x$2" = x ] ; then 
	# if we start with a slash, prefix is nothing (rooted name), otherwise use a relative path
	__SWS=`echo $__NAME | sed 's/^\/.*/___ROOTED_NAME___/'`
	if [ "x$__SWS" = "x___ROOTED_NAME___" ] ; then __PREFIX="" ; else __PREFIX="./" ; fi
    else 
	# if we end with a slash, no worries, otherwise, append one
	__SWS=`echo $__NAME | sed 's/.*\/$/___END_SLASH___/'`
	if [ "x$__SWS" = "x___END_SLASH___" ] ; then __PREFIX="$2" ; else __PREFIX="${2}/" ; fi
    fi
    __SEMAPHORE="${__NAME}.semaphore"

    if [ -f ${__PREFIX}$__SEMAPHORE ] ; then
	warn "Semaphore [$__SEMAPHORE] is already released"
    fi

    # recreate the semaphore
    touch ${__PREFIX}$__SEMAPHORE

    # get rid of the stale semaphore acquired file.
    # if the file was properly registered, it should have a backup copy
    if [ -f ${__PREFIX}${__SEMAPHORE}.acquired ] ; then
	rm -f ${__PREFIX}${__SEMAPHORE}.acquired
    else
	warn "Acquired semaphore ${__SEMAPHORE}'s backup copy disappeared in $__PREFIX"
    fi

    if [ ! -w ${__PREFIX}$__SEMAPHORE ] ; then
        warn "Unable to write to semaphore file $__SEMAPHORE in ${__PREFIX}?"
    fi
    # save the PID of the process that last released this semaphore
    if [ ! "x$USER" = "x" ] ; then log "USER=$USER" "${__PREFIX}${__SEMAPHORE}" ; else log "USER=unknown" "${__PREFIX}${__SEMAPHORE}" ; fi
    log "PID=$$" "${__PREFIX}${__SEMAPHORE}"
    log "DATE=`date`" "${__PREFIX}${__SEMAPHORE}"

    # unregister the semaphore with the _ACQUIRED_SEMAPHORES var
    if [ ! "x$_ACQUIRED_SEMAPHORES" = "x" ] ; then
	__NEW_AS=""
	__FOUND_SEM=0
	for __SEM in $_ACQUIRED_SEMAPHORES ; do
	    if [ "x$__SEM" = "x${__PREFIX}$__NAME" ] ; then
		__FOUND_SEM=1
	    else
		__NEW_AS="$__NEW_AS $__SEM"
	    fi
	done
	_ACQUIRED_SEMAPHORES="$__NEW_AS" ; export _ACQUIRED_SEMAPHORES

	if [ x$__FOUND_SEM = x0 ] ; then
	    warn "bad bookkeeping -- _ACQUIRED_SEMAPHORES is missing entry $__NAME"
	    log "Created ${__SEMAPHORE}??"
        else
	    log "Released $__SEMAPHORE"
	fi
    else
	log "Created $__SEMAPHORE"
    fi
    return 0
}

#
# releaseAllSemaphores
#
releaseAllSemaphores ( ) {
    if [ ! "x$DEBUG" = x ] ; then log "releaseAllSemaphores() _ACQUIRED_SEMAPHORES=[$_ACQUIRED_SEMAPHORES]" ; fi

    if [ ! "x$_ACQUIRED_SEMAPHORES" = x ] ; then
	for __SEM in $_ACQUIRED_SEMAPHORES ; do
	    releaseSemaphore $__SEM
	done
    fi
}


#
# mail {addressList} [subject] [body] [{attachmentTupleList}]
#
# mailer sends out a mail message with a given subject and given body to an address list
# addressList is required only if USER is not set
# attachmentTupleList is a 2-tuple pair of 'filename' and 'label' that will be attached
#   as a mime text attachment, single quote wrapping and label are both required
#   e.g. $4="'file1' 'label1' 'file2' 'label2' 'file3' 'label3' "
#
mail ( ) {
    if [ ! "x$DEBUG" = "x" ] ; then log "mail( \$1=[$1] \$2=[$2] \$3=[$3] \$4=[$4])" ; fi

    if [ "x$1" = x ] ; then 
	if [ ! "x$USER" = x ] ; then
	    __ADDRESS="$USER"
	else
	    bomb "mail() arg1 mismatch -- no e-mail address given, no USER set"
	fi
    else
	__ADDRESS="$1"
    fi
    if [ "x$2" = x ] ; then __SUBJECT="" ; else __SUBJECT="$2" ; fi
    if [ "x$3" = x ] ; then __BODY="" ; else __BODY="$3" ; fi
    if [ ! "x$4" = x ] ; then __MULTI="yes"; __FILES="$4" ; else __MULTI="no"; __FILES="" ; fi
    BOUNDARY="xxxxqwertyxxxx.${HOSTNAME}.$$"


    # need sendmail to properly give mime types
    for __MAILER in /bin/sendmail /usr/lib/sendmail /usr/bin/sendmail /usr/sbin/sendmail ; do
	if [ -f "$__MAILER" ] && [ -x "$__MAILER" ] ; then
	    break
	fi
    done
    if [ ! -x "${__MAILER}" ] ; then
	warn "Unable to find sendmail -- hoping it is in path"
	__MAILER="sendmail"
    fi

    # find a decent echo (!!! may want to consolidate later with log)
    __LOGTEST=`echo -e "\t\ntest"`
    if [ `echo $__LOGTEST | awk '{print $1}'` = "test" ] ; then
	__ECHO="echo -e"
    # no -e support
    else
	# need to do some extra checking since the sun5 /bin/echo sucks
	# see if default echo supports special chars
	__LOGTEST=`echo "\t\ntest"`
	if [ "x`echo $__LOGTEST | awk '{print $1}'`" = "xtest" ] ; then 
	    __ECHO="echo"
	else
	    # for sun5 (built-in echo is poor)
	    __LOGTEST=`/usr/bin/echo "\t\ntest"`
	    if [ "x`echo $__LOGTEST | awk '{print $1}'`" = "xtest" ] ; then
		__ECHO="/usr/bin/echo"
	    else
		echo "WARNING: cannot find decent echo"
		__ECHO="echo"
	    fi
	fi
    fi
    __BODY=`$__ECHO $__BODY`

    # weed off files that are not readable
    __NEWFILES=""
    __FILEORLABEL="file"
    # set the field separator to a single quote
    __PIFS="$IFS"
    IFS="'"
    for __FILELABEL in $__FILES ; do
	IFS="$__PIFS"  # restore briefly so sed/awk do not screw up
	if [ "x`echo $__FILELABEL | awk '{print $1}'`" = "x" ] ; then continue ; fi

        if [ "x$__FILEORLABEL" = "xfile" ] ; then 
	    __FILE="$__FILELABEL"
	    __FILEORLABEL="label"
	else 
	    __LABEL=$__FILELABEL
	    if [ ! -f "$__FILE" ] ; then
		warn "Unable to read attachment file [$__FILE]"
	    else
		__NEWFILES="$__NEWFILES '$__FILE' '$__LABEL'"
	    fi
	    __FILEORLABEL="file"
	fi
	IFS="'"
    done
    IFS="$__PIFS"  # restore so sed/awk do not screw up
    if [ ! "x$__FILEORLABEL" = "xfile" ] ; then
	warn "Missing attachment file label, using null"
	__NEWFILES="$__NEWFILES ''"
    fi
    __FILES="$__NEWFILES"
    
    # !!! should test validity of mail program existance
    if [ ! "x$DEBUG" = "x" ] ; then log "mail: __MAILER=[$__MAILER] __ADDRESS=[$__ADDRESS] __SUBJECT=[$__SUBJECT] __ATTACHMENTS=[$__MUTLI]\nmail: __FILES=[$__FILES]" ; fi

    # if we weeded off all attachments, then turn off multi
    if [ "x$__FILES" = "x" ] ; then __MULTI="no" ; fi
    # if we have attachments, we need to loop over them and add them properly
    if [ "x$__MULTI" = "xyes" ] ; then
	__ATTACH=""

	__FILEORLABEL="file"
	# set the field separator to a single quote
	__PIFS="$IFS"
	IFS="'"
	for __FILELABEL in $__FILES ; do
	    IFS="$__PIFS"  # restore briefly so sed/awk do not screw up
	    if [ "x`echo $__FILELABEL | awk '{print $1}'`" = "x" ] ; then continue ; fi
	    
	    if [ "x$__FILEORLABEL" = "xfile" ] ; then 
		__FILE="$__FILELABEL"
		__FILEORLABEL="label"
	    else 
		__LABEL=$__FILELABEL
		__FILEORLABEL="file"
		
		# process the file/label pair now
		if [ ! "x$DEBUG" = "x" ] ; then log "Processing attachment: [${__FILE}]" ; fi
		__FILEBASE=`basename "$__FILE"`
		__ATTACH="${__ATTACH}
--${BOUNDARY}
Content-Type: text/plain; charset=US-ASCII; name=\"$__FILEBASE\"
Content-Description: ${__LABEL}
Content-Disposition: attachment; filename=\"$__FILEBASE\"
Content-Transfer-Encoding: 7bit

`cat \"$__FILE\"`
"

	    fi
	    IFS="'"
	done
	IFS="$__PIFS"  # restore field separator (awk chokes otherwise)

	# loop over outgoing address list
	for __ADDR in $__ADDRESS ; do
	    $__MAILER $__ADDR <<EOF
Subject: ${__SUBJECT}
MIME-Version: 1.0
Content-type: multipart/mixed; boundary="${BOUNDARY}"
Content-Transfer-Encoding: 7bit

This message is in MIME format.  The first part should be readable text,
while the remaining parts are likely unreadable without MIME-aware tools.
Send mail to lamas@@arl.army.mil for more info.

--${BOUNDARY}
Content-Type: text/plain; charset=US-ASCII; name="e-mail.body"
Content-Description: ${__SUBJECT}
Content-Disposition: inline; filename="e-mail.body"
Content-Transfer-Encoding: 7bit
${__BODY}


${__ATTACH}

--${BOUNDARY}--
EOF
        done

    # otherwise we are not sending attachments
    else
	# loop over outgoing address list
	for __ADDR in $__ADDRESS ; do
	    $__MAILER $__ADDR <<EOF
Subject: ${__SUBJECT}
MIME-Version: 1.0
Content-Type: text/plain; charset=US-ASCII; name="e-mail.body"
Content-Disposition: inline; filename="e-mail.body"
Content-Transfer-Encoding: 7bit

${__BODY}

EOF
	done
    fi

    # check for failure and log if so
    if [ $? != 0 ] ; then
	log "ERROR: mail failed"
	return 1
    fi
    return 0
}


#
# cvsExport cvsTag cvsRoot [exportDir] [cvsBinary] [cvsLogfile]
#
cvsExport ( ) {
    if [ ! "x$DEBUG" = "x" ] ; then log "cvsExport( \$1=[$1] \$2=[$2] \$3=[$3] \$4=[$4])" ; fi

    if [ "x$1" = x ] ; then 
	if [ ! "x$CVS_TAG" = "x" ] ; then
	    __TAG="$CVS_TAG"
	else
	    bomb "cvsExport() arg1 mismatch -- no cvs tag given, no CVS_TAG set"
	fi
    else
	__TAG="$1"
    fi
    if [ "x$2" = x ] ; then 
	if [ ! "x$CVS_ROOT" = "x" ] ; then
	    __ROOT="$CVS_ROOT"
	else
	    bomb "cvsExport() arg2 mismatch -- no cvs root given, no CVS_ROOT set"
	fi
    else
	__ROOT="$2"
    fi
    if [ "x$3" = "x" ] ; then __DIR="." ; else __DIR="$3" ; fi
    if [ "x$4" = "x" ] ; then __BIN="cvs" ; else __BIN="$4" ; fi
    if [ "x$5" = "x" ] ; then __LOG="/dev/null" ; else __LOG="$5" ; fi

    if [ ! -d "$__DIR" ] ; then 
        warn "cvs export directory [$__DIR] does not exist" "$__LOG"
        log "Creating directory [$__DIR]" "$__LOG"
        mkdir -p "$__DIR"
    fi
    if [ ! -w "${__DIR}/." ] ; then
        log "ERROR: Unable to write to cvs export directory [$__DIR]" "$__LOG"
        return 1
    fi

    $__BIN -v > /dev/null 2>&1
    if [ $? != 0 ] ; then
	log "ERROR: cvs export failed (unable to run cvs [$__CVS])" "$__LOG"
	return 1
    fi

    log "Starting cvs export..." "$__LOG"
    log "Running [$__BIN -q -d $__ROOT export -D today -d $__DIR -N $__TAG >> ${__LOG} 2>&1]" "$__LOG"
    $CVS -q -d $__ROOT export -D today -d $__DIR -N $__TAG >> "$__LOG" 2>&1
    # make sure cvs export exited nicely
    if [ $? != 0 ] ; then 
        log "ERROR: cvs export failed" "${__LOG}"
        return 1
    fi

    log "OK: cvs export completed" "${__LOG}"
    return 0
}


#
# unpackArchive archive [extractDir]
#
# as it is, this function merely bombs on error, but it should return a
# truthvalue as to whether the unpacking succeeded or not and let the
# application handle the result.
unpackArchive ( ) {
    if [ ! "x$DEBUG" = "x" ] ; then log "cvsExport( \$1=[$1] \$2=[$2] )" ; fi

    if [ "x$1" = x ] ; then 
        bomb "unpackArchive() arg1 mismatch -- no archive given"
    else
        __ARCHIVE="$1"
    fi
    if [ "x$2" = "x" ] ; then 
        __SWS=`echo $__ARCHIVE | sed 's/^\/.*/___ROOTED_NAME___/'`
        if [ "x$__SWS" = "x___ROOTED_NAME___" ] ; then __DIR=`dirname $__ARCHIVE` ; else __DIR="./"; fi
    else 
        __DIR="$2"
    fi

    if [ ! -f "$__ARCHIVE" ] ; then
        bomb "Unable to find archive [$__ARCHIVE] for unpacking"
    elif [ ! -r "$__ARCHIVE" ] ; then
        bomb "Unable to read archive [$__ARCHIVE] for unpacking"
    fi

    # !!! this is minimal checking and support for right now
    #  we assume that the uncompressor is available and options are supported
    case "$__ARCHIVE" in
        *.tar )
            tar -C "$__DIR" -xf "$__ARCHIVE" ;;
        *.zip )
            unzip "$__ARCHIVE" ;;
        *.tar.Z )
            uncompress -c "$__ARCHIVE" | tar -C "$__DIR" -x ;;
        *.tar.gz | *.tgz )
            gzip -c -d "$__ARCHIVE" | tar -x -C "$__DIR" ;;
        *.tar.bz2 )
            bunzip2 -c "$__ARCHIVE" | tar -C "$__DIR" -x ;;
        * )
            bomb "Unsupported archive format" ;;
    esac

    if [ $? != 0 ] ; then 
        bomb "Archive unpacking failed"
    fi
}


# INTERNAL STUFF
###
# vars used to manage locks and semaphores
initializeVariable _ACQUIRED_LOCKS 
initializeVariable _ACQUIRED_SEMAPHORES

# GLOBAL STUFF
# set a hostname and pwd to play with -- exports HOSTNAME and LPWD accordingly
setHostName

initializeVariable ARCH "`uname -s`"

case $0 in
    # hard path to sourcing script
    /* )
        initializeVariable LPWD "`dirname $0`" ;;
    # relative path to sourcing script
    */* )
        initializeVariable PWD "`pwd`" # this is to avoid the freebsd /bin/sh pwd problem
        initializeVariable LPWD "$PWD/`dirname $0`" ;;
    # sourcing script is in the path
    * )
        initializeVariable PWD "`pwd`" # this is to avoid the freebsd /bin/sh pwd problem
        initializeVariable LPWD "$PWD" ;;
esac
if [ ! -f "$LPWD/library" ] ; then
    warn "Unable to properly initialize path to library source varaible [LPWD=$LPWD]"
fi


#
#  REGRESSION TEST SPECIFIC
###


# set STYLE value to 'color' to invoke color logging output, set to anything
# else to get plain text output
initializeVariable STYLE "color"

# how far over should the test status messages be displayed
[ ! "x$COLUMNS" = "x" ] && COLUMN_TO_MOVE_TO=`expr $COLUMNS - 20` || COLUMN_TO_MOVE_TO=60
# terminal sequence to move to a certain column
MOVE_TO_COLUMN="log -n \\033[${COLUMN_TO_MOVE_TO}G"
# terminal sequence to set color to a 'success' color (currently: green)
SETCOLOR_SUCCESS="log -n \\033[1;32m"
# terminal sequence to set color to a 'failure' color (currently: red)
SETCOLOR_FAILURE="log -n \\033[1;31m"
# terminal sequence to reset to the default color.
SETCOLOR_NORMAL="log -n \\033[0;39m"

TEST_WITH_PATH="$0"
initializeVariable TEST "`echo $0 | sed 's/^.*\/\(.*\)$/\1/'`"
initializeVariable TEST "$0"
initializeVariable TEST "test"
initializeVariable NAME "$TEST"


logSuccess ( ) {
    [ "$STYLE" = "color" ] && $MOVE_TO_COLUMN || log -n "\n\t" $1
    log -n "[   " $1
    [ "$STYLE" = "color" ] && $SETCOLOR_SUCCESS
    log -n "OK" $1
    [ "$STYLE" = "color" ] && $SETCOLOR_NORMAL
    log "   ]" $1
    return 0
}

logFailure ( ) {
    [ "$STYLE" = "color" ] && $MOVE_TO_COLUMN || log -n "\n\t" $1
    log -n "[ " $1
    [ "$STYLE" = "color" ] && $SETCOLOR_FAILURE
    log -n $"FAILED" $1
    [ "$STYLE" = "color" ] && $SETCOLOR_NORMAL
    log " ]" $1
    return 1
}


# Non package-specific settings
initializeTest ( ) { 
    # save the working directory so that we may return to it after a test is run
    __STARTPWD="`pwd`"

    # if we *still* do not have a package name set (i.e. none set in a config
    # test script or from the master regressor), then use dot
    initializeVariable PACKAGE_NAME .
    if [ "x$REGRESS_DIR" = "x" ] ; then
        # if regress_dir was not set, default to the package that this script is included with
        initializeVariable REGRESS_DIR "$PACKAGE_NAME"
    fi

    return 0
}

uninitializeTest ( ) {
    if [ "x$__STARTPWD" = "x" ] ; then
        return 1
    else
        cd "$__STARTPWD"
        return $?
    fi
}


#
# Default start function must be overridden in order for any of these
# scripts to work.  It's the only required function, since the rest is
# handled by bookkeeping behind the scenes.
#
start ( ) { 
    bomb "start function must be implemented for $TEST"
}

#
# These curious little oddities are neccessary only because a few
# misbehaving shells include built-in aliases named "stop" (irix).
# And since the behaviour of the built-in "." source command on that 
# same platform reads in and preprocesses the file beforehand, it's 
# not possible to unalias the alias in order to define a stub function.
#
# We still do the unalias and unsetting here for other shells that may
# behave properly and "do the right thing".
# 
unalias start > /dev/null 2>&1
unalias stop > /dev/null 2>&1
unalias restart > /dev/null 2>&1
unalias status > /dev/null 2>&1
unalias clean > /dev/null 2>&1
unalias regress > /dev/null 2>&1
unset start
unset stop
unset restart
unset status
unset clean
unset regress


#
# regress
#
# This is the primary regression test control function that user scripts 
# get to call for convenience to assure consistent behaviour.  User
# functions may override any of the control functions (start, stop, etc)
# and even not use this function if alternate behaviour is desired.
# Doing so may impact the master regresssion script.
#
regress ( ) {

    __SCRIPT="${TEST}.${1}.${HOSTNAME}.log"
    __ret=1
    case "$1" in
        start )
            initializeTest
            log -n "Running ${TEST} test"
            if acquireLock "$__SCRIPT" 0 0 > /dev/null 2>&1 ; then
                # capture kill events so we may exit gracefully
                trap "log \"\" ; warn \"${TEST} was stopped\" ; logFailure ; rm -f \"$__SCRIPT\" ; bomb "" /dev/null" HUP

                # save the running pid for stop requests
                cat "${__SCRIPT}.lock" >> "${__SCRIPT}"
                __OUTPUT="${TEST}.${HOSTNAME}.log"
                if [ -f "${__OUTPUT}" ] ; then
                    STATUS=RUNNING
                    . "${__OUTPUT}" > /dev/null 2>&1
                    case "$STATUS" in
                        RUNNING )
                            log ""
                            warn "There is presently a [${TEST}] test in progress"
                            warn "TEST STARTED HERE" "$__OUTPUT"
                            ;;
                        * )
                            log ""
                            warn "Saving previous run log as [${__OUTPUT}.bak]"
                            mv "${__OUTPUT}" "${__OUTPUT}.bak"
                            ;;
                    esac
                fi

                log "TEST=\"${TEST}\"" "$__SCRIPT"
                # send the message to the log file now that we are running
                trap "warn \"${TEST} was stopped\" \"$__OUTPUT\" ; rm -f \"$__SCRIPT\" ; logFailure /dev/tty ; bomb \"\" /dev/null" HUP
                $1 >> "$__OUTPUT" 2>&1
                __ret=$?
                releaseLock "$__SCRIPT" > /dev/null 2>&1 
            else
                log ""
                bomb "Unable to acquire test lock [${__SCRIPT}.lock]"
            fi
            uninitializeTest
            if [ $__ret = 0 ] ; then 
                logSuccess 
                log "Test [$TEST] completed successfully" "$__OUTPUT"
            else
                logFailure
                log "TEST [$TEST] failed" "$__OUTPUT"
            fi
            ;;

        stop )
            initializeTest
            log -n "Stopping ${TEST}"
            if acquireLock "$__SCRIPT" 0 0 > /dev/null 2>&1 ; then
                $1 > "$__SCRIPT" 2>&1
                if [ ! "x`cat $__SCRIPT | tail -n 1 | sed 's/\(.*command not found\)/__CNF__/'`" = "x__CNF__" ] ; then
                    __ret=$?
                else
                    __ret=0
                fi


                if [ -f "${TEST}.start.${HOSTNAME}.log" ] ; then
                    PID=1
                    . "${TEST}.start.${HOSTNAME}.log" > /dev/null 2>&1
                    if [ "x$PID" = "x1" ] ; then
                        log ""
                        warn "Unable to determine running PID"
                    else
                        kill -HUP "$PID" > /dev/null 2>&1
                        if [ $? = 0 ] ; then
                            log "\nKilled off process [$PID]"
                        else
                            # only need to blather output if the logs are not stale from a stop
                            if [ ! "x`cat ${TEST}.${HOSTNAME}.log | tail -n 1 | sed 's/\(.*was stopped\)/__STP__/'`" = "x__STP__" ] ; then
                                log ""
                                warn "Stale log file exists, run clean command"
                                
                            fi
                        fi
                        __ret=`expr $__ret + $?`
                    fi
                fi

                releaseLock "$__SCRIPT" > /dev/null 2>&1 
            else
                bomb "Unable to acquire test lock [${__SCRIPT}.lock]"
            fi

            uninitializeTest
            [ $__ret = 0 ] && logSuccess || logFailure
            ;;

        restart )
            # see if client defined a restart
            initializeTest
            if acquireLock "$__SCRIPT" 0 0 > /dev/null 2>&1 ; then
                $1 > "$__SCRIPT" 2>&1
                if [ ! "x`cat $__SCRIPT | tail -n 1 | sed 's/\(.*command not found\)/__CNF__/'`" = "x__CNF__" ] ; then
                    __ret=$?
                    log -n "Restarting ${TEST}"
                    uninitializeTest
                    [ $__ret = 0 ] && logSuccess || logFailure
                fi
                releaseLock "$__SCRIPT" > /dev/null 2>&1 
            else
                bomb "Unable to acquire test lock [${__SCRIPT}.lock]"
            fi

            regress stop
            uninitializeTest
            initializeTest
            regress start
            uninitializeTest
            ;;

        status )
            initializeTest
            if acquireLock "$__SCRIPT" 0 0  > /dev/null 2>&1 ; then
                $1 > "$__SCRIPT" 2>&1
                if [ ! "x`cat $__SCRIPT | tail -n 1 | sed 's/\(.*command not found\)/__CNF__/'`" = "x__CNF__" ] ; then
                    log "`cat $__SCRIPT`"
                fi

                # first we check and see if there is a running log file
                if [ -f "${TEST}.start.${HOSTNAME}.log" ] ; then
                    log "Test [${TEST}] is currently running"
                # otherwise we may have completed, so we show the last line of the log
                elif [ -f "${TEST}.${HOSTNAME}.log" ] ; then
                    log "`tail -n 1 \"${TEST}.${HOSTNAME}.log\"`"
                else
                    log "Test [${TEST}] does not appear to have run"
                fi

                releaseLock "$__SCRIPT" > /dev/null 2>&1 
            else
                bomb "Unable to acquire test lock [${__SCRIPT}.lock]"
            fi
            uninitializeTest

            ;;

        clean )
            initializeTest
            log -n "Cleaning up ${TEST}"
            if acquireLock "$__SCRIPT" 0 0 > /dev/null 2>&1 ; then
                $1 > "$__SCRIPT" 2>&1
                if [ ! "x`cat $__SCRIPT | tail -n 1 | sed 's/\(.*command not found\)/__CNF__/'`" = "x__CNF__" ] ; then
                    __ret=$?
                else
                    __ret=0
                fi

                # remove start log
                if [ -f "${TEST}.${HOSTNAME}.log" ] ; then
                    rm -f "${TEST}.${HOSTNAME}.log"
                    __ret=`expr $__ret + $?`
                fi

                # remove start log backup
                if [ -f "${TEST}.${HOSTNAME}.log.bak" ] ; then
                    rm -f "${TEST}.${HOSTNAME}.log.bak"
                    __ret=`expr $__ret + $?`
                fi

                # remove command log files (stale?) and test for running commands in general
                for cmd in start stop restart status ; do
                    # individual command log files should never exist, unless a command is in progress
                    if acquireLock "${TEST}.${cmd}.${HOSTNAME}.log" 1 10 > /dev/null 2>&1 ; then
                        [ -f "${TEST}.${cmd}.${HOSTNAME}.log" ] && rm -f "${TEST}.${cmd}.${HOSTNAME}.log" && __ret=`expr $__ret + $?`
                        releaseLock "${TEST}.${cmd}.${HOSTNAME}.log" > /dev/null 2>&1
                    else
                        log ""
                        warn "Command [$cmd] is currently running"
                        log "Interrupt and remove lock [${TEST}.${cmd}.${HOSTNAME}.log.lock] manually"
                        __ret=`expr $__ret + 1`
                    fi
                done

                releaseLock "$__SCRIPT" > /dev/null 2>&1 
            else
                bomb "Unable to acquire test lock [${__SCRIPT}.lock]"
            fi
            uninitializeTest
            [ $__ret = 0 ] && logSuccess || logFailure
            ;;
        * )
            log "Usage: $TEST_WITH_PATH {start|stop|restart|status|clean}"
            return 1
    esac
    # remove our temp log file for cleanliness (unless we were start)
    [ -f "$__SCRIPT" ] && rm -f "$__SCRIPT"


    return $?
}

@


1.4
log
@finally completed default regress behaviour
@
text
@@


1.3
log
@added boundary variable to hopefully not get pine confused with a messy inbox
@
text
@d13 5
a17 1
#     . ./library
d77 3
d88 31
a130 10
#   LIBRARY_VERSION
#       version of this library file being used (majorRelease.minorRelease)
#   
#
# INTERNAL  (do not use)
#
#   _ACQUIRED_LOCKS
#   _ACQUIRED_SEMAPHORES
#   _TEMP_DEBUG_OFF
#
d142 1
a142 1
# log [messageToWrite] [fileToWriteTo]
d144 2
a145 1
# log writes a given message out to a file name
d148 2
d151 18
a168 2
    __MESSAGE="\$1"
    if [ "x$2" = "x" ] ; then __FILE="$LOG" ; else __FILE="$2" ; fi
d183 1
a183 1
	if [ ! "x$DEBUG" = x ] ; then echo "log( \$1=[$1] \$2=[$2] )" $__FILE ; fi
d214 4
a217 1
    eval "$__ECHO \"$__MESSAGE\" $__FILE"
d316 4
d336 1
a336 6
    # turn log debugging back on if it was
    if [ ! "x$DEBUG" = x ] ; then unset _TEMP_DEBUG_OFF ; fi

    releaseAllLocks
    releaseAllSemaphores
    
d365 1
a365 1
    log "WARNING: $1" "$__WARN"
d576 2
a577 2
	# if we start with a slash, prefix is nothing (rooted name), otherwise use a relative path
	__SWS=`echo $__NAME | sed 's/^\/.*/___ROOTED_NAME___/'`
d603 1
a603 1
    rm ${__PREFIX}$__LOCK
d615 2
a616 2
	if [ x$__FOUND_LOCK = x0 ] ; then
	    warn "bad bookkeeping -- _ACQUIRED_LOCKS is missing entry $__NAME"
d1100 6
d1110 4
a1113 3
# terminal sequence to move to that column. You could change this
# to something like "tput hpa ${RES_COL}" if your terminal supports it
MOVE_TO_COLUMN="echo -en \\033[60G"
d1115 1
a1115 1
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
d1117 1
a1117 3
SETCOLOR_FAILURE="echo -en \\033[1;31m"
# terminal sequence to set color to a 'warning' color (currently: yellow)
SETCOLOR_WARNING="echo -en \\033[1;33m"
d1119 1
a1119 6
SETCOLOR_NORMAL="echo -en \\033[0;39m"



# REGRESSION TEST SPECIFIC
###
d1128 22
d1151 2
d1154 2
a1155 1
    # if regress_dir was not set, default to the package that this script is included with
d1158 2
a1159 11
        if [ -d "$LPWD/../../../$PACKAGE_NAME" ] ; then
            initializeVariable REGRESS_DIR "$LPWD/../../.."
        elif [ -d "$LPWD/../../$PACKAGE_NAME" ] ; then
            initializeVariable REGRESS_DIR "$LPWD/../.."
        elif [ -d "$LPWD/../$PACKAGE_NAME" ] ; then
            initializeVariable REGRESS_DIR "$LPWD/.."
        elif [ -d "$LPWD/$PACKAGE_NAME" ] ; then
            initializeVariable REGRESS_DIR "$LPWD"
        else
            warn "Unable to locate $PACKAGE_NAME"
        fi
d1161 1
a1161 1
    
d1165 9
d1185 8
a1192 5
# This curious little oddity is neccessary only because a few misbehaving
# shells include built-in aliases named "stop" (irix).  And since the 
# behaviour of the built-in "." source command on that same platform 
# reads in and preprocesses the file beforehand, it's not possible to
# unalias the alias in order to define a stub function. 
d1194 6
a1199 23
# Hence the solution in use here is to use alternate stub functions and
# then test at runtime whether the user defined the appropriate function.
# If they did, we use it, if not, we use the "default" behaviour defined
# here.
#
_stop ( ) {
    log "Stopping $TEST"
    return 0
}
_status ( ) {
    log "Checking $TEST status"
    return 0
}
_clean ( ) {
    log "Cleaning $TEST"
    return 0
}

unalias start
unalias stop
unalias restart
unalias status
unalias clean
d1205 1
d1219 2
d1224 43
a1266 1
            eval start
d1268 1
d1271 39
a1309 2
            eval _stop
            exec stop > /tmp/${TEST}.stop 2>&1
d1311 1
d1313 1
d1315 18
a1332 2
            eval _stop
            eval start
d1334 1
d1337 22
a1358 1
            eval _status
d1360 1
d1363 41
a1403 1
            eval _clean
d1409 3
@


1.2
log
@*** empty log message ***
@
text
@d751 3
d848 1
a848 1
--xxxxqwertyxxxx
d867 1
a867 1
Content-type: multipart/mixed; boundary="xxxxqwertyxxxx"
d874 1
a874 1
--xxxxqwertyxxxx
d884 1
a884 1
--xxxxqwertyxxxx--
@


1.1
log
@added new test scripts
@
text
@d735 1
a735 1
###
d1037 2
a1038 1
        initializeVariable LPWD "`pwd`/`dirname $0`" ;;
d1041 2
a1042 1
        initializeVariable LPWD "`pwd`" ;;
d1045 1
a1045 1
    warn "Unable to properly initialize path to library source varaible [LPWD]"
d1063 123
@

