#! /bin/bash
#
# ../scripts/realtime.  Generated from realtime.in by configure. 
# on Tue May  8 22:31:24 MDT 2018
#

export LANG=C

PIDOF=/bin/pidof

CheckKernel() {
    case "" in
    "") ;;
    *)
	if [ `uname -r` != "" ]; then
	    cat 1>&2 << EOF
RTAPI requires the real-time kernel  to run.  Before running
this realtime application, reboot and choose this kernel at the boot menu.
EOF
	    exit 1
	fi
    esac
}

RUN_IN_PLACE=no
if [ $RUN_IN_PLACE = yes ]; then
    # When using RIP make sure PATH includes the directory where rtapi_app
    # resides
    PATH=/usr/bin:$PATH; export PATH
fi

CheckConfig(){
    prefix=/usr
    exec_prefix=${prefix}
    sysconfdir=/etc
    if [ $RUN_IN_PLACE = yes ]; then
        RTAPICONF=
        # check in the LinuxCNC scripts directory
        # $0 is the command to run this script
        # strip the script name to leave the path
        SCRIPT_DIR=${0%/*}
        # the path might be relative
        # convert it to an absolute path
        SCRIPT_DIR=$(cd $SCRIPT_DIR ; pwd -P)
        # now look for rtapi.conf there
        if [ -f $SCRIPT_DIR/rtapi.conf ] ; then
            RTAPICONF=$SCRIPT_DIR/rtapi.conf
        fi
    else
        if [ -f $sysconfdir/linuxcnc/rtapi.conf ]; then
                RTAPICONF=$sysconfdir/linuxcnc/rtapi.conf
        fi
    fi
    if [ -z "$RTAPICONF" ] ; then
	echo "Missing rtapi.conf.  Check your installation." 1>&2
	exit 1
    fi
    INSMOD="/usr/bin/linuxcnc_module_helper insert"
    RMMOD="/usr/bin/linuxcnc_module_helper remove"
    LSMOD="/bin/lsmod"
    FUSER="/bin/fuser"

    # Import the config
    source $RTAPICONF
    if [ ! -e $RTLIB_DIR/.runinfo -a -e $RTLIB_DIR/emc2/.runinfo ]; then
        # installed system: we don't want our modules mixed up with rtai
        RTLIB_DIR=$RTLIB_DIR/emc2
    fi
    # Export the module path specified in the config.
    export MODPATH
    # Generate module lists for loading and unloading
    # lists contain RTOS modules plus RTAPI and HAL
    # unload list is in reverse order
    # any module names that are symlinks are resolved to their real names
    MODULES_LOAD=
    MODULES_UNLOAD=
    case $RTPREFIX in
    uspace) SHM_DEV=/dev/zero;;
    *)
        for  MOD in $MODULES ; do
            eval MOD=\${MODPATH_$MOD}
            if [ -z "$MOD" ]; then continue; fi
            if [ -L $MOD ]; then
                MOD=${MOD%/*}/$(readlink $MOD)
            fi
            MODULES_LOAD="$MODULES_LOAD $MOD"
            MOD="${MOD##*/}"
            MOD="${MOD%$MODULE_EXT}"
            MODULES_UNLOAD="$MOD $MODULES_UNLOAD"
        done
        MODULES_LOAD="$MODULES_LOAD $RTLIB_DIR/rtapi$MODULE_EXT $RTLIB_DIR/hal_lib$MODULE_EXT"
        MODULES_UNLOAD="hal_lib rtapi $MODULES_UNLOAD"
        case "$MODULES" in
        *rtai*)
            SHM_DEV=/dev/rtai_shm
        ;;
        *mbuff*)
            SHM_DEV=/dev/mbuff
        ;;
        esac
    esac
}

CheckStatus(){
    case $RTPREFIX in
    uspace)
        if [ -z "$($PIDOF rtapi_app)" ]; then
            exit 1
        else
            exit 0
        fi ;;
    *)
        # check loaded/unloaded status of modules
        unset NOTLOADED
        for MOD in $MODULES_UNLOAD ; do
            if /bin/lsmod | awk '{print $1}' | grep -x $MOD >/dev/null ; then
                echo "$MOD is loaded"
            else
                echo "$MOD is not loaded"
                NOTLOADED=NOT
            fi
        done
        if [ -z $NOTLOADED ]; then
            exit 0
        else
            exit 1
        fi
    esac
}

CheckMem(){
# check for user space processes using shared memory
    if [ -e /dev/mbuff ] ; then
	# device file exists, check for processes using it
	if $FUSER -s /dev/mbuff 2>/dev/null; then
	    # at least one process is using it
	    echo "ERROR:  Can't remove RTLinux modules, kill the following process(es) first"
	    $FUSER -v /dev/mbuff
	    exit 1
	fi
    elif [ -e /dev/rtai_shm ] ; then
	# device file exists, check for processes using it
	if $FUSER -s /dev/rtai_shm 2>/dev/null; then
	    # at least one process is using it
	    echo "ERROR:  Can't remove RTAI modules, kill the following process(es) first"
	    $FUSER -v /dev/rtai_shm
	    exit 1
	fi
    fi
}

Load(){
    CheckKernel
    case $RTPREFIX in
    uspace)
    ;;
    *)
        for MOD in $MODULES_LOAD ; do
            $INSMOD $MOD || return $?
        done
        if [ "$DEBUG" != "" ] && [ -w /proc/rtapi/debug ] ; then
            echo "$DEBUG" > /proc/rtapi/debug
        fi
    esac
}

CheckLoaded(){
    # this abomination is needed because udev sometimes doesn't
    # have the device ready for us in time.
    n=0
    while [ $n -lt 100 ]; do
        [ -w $SHM_DEV ] && return 0
        echo "." 1>&2
        sleep .1
        n=$(($n+1))
    done
    echo "Can't write to $SHM_DEV - aborting" 1>&2
    exit 1
}

Unload(){
    CheckKernel
    case $RTPREFIX in
    uspace)
        rtapi_app exit 

        # wait 5 seconds for rtapi_app to die and be reaped by its parent
        START=$SECONDS
        while [ 5 -gt $((SECONDS-START)) ]; do
            if ! ps -C rtapi_app > /dev/null 2> /dev/null; then
                break
            fi
            sleep 0.1
        done
        if ps -C rtapi_app > /dev/null 2> /dev/null; then
            echo "ERROR: rtapi_app failed to die" 1>&2
        fi

        ipcrm -M 0x48414c32 2>/dev/null ;# HAL_KEY
        ipcrm -M 0x90280A48 2>/dev/null ;# RTAPI_KEY
        ipcrm -M 0x48484c34 2>/dev/null ;# UUID_KEY
        ;;
    *)
        for module in $MODULES_UNLOAD ; do
            $RMMOD $module
        done
    esac
}

CheckUnloaded(){
# checks to see if all modules were unloaded
    STATUS=
    for module in $MODULES_UNLOAD ; do
	# check to see if the module is installed
	if /bin/lsmod | awk '{print $1}' | grep -x $module >/dev/null ; then
	    echo "ERROR: Could not unload '$module'"
	    STATUS=error
	fi
    done
    if [ -n "$STATUS" ] ; then
	exit 1
    fi
}

CMD=$1

case "$CMD" in
  start|load)
	CheckConfig
	Load || exit $?
	CheckLoaded
	;;
  restart|force-reload)
	CheckConfig
	CheckMem
	Unload
	CheckUnloaded
	Load || exit $?
	CheckLoaded
	;;
  stop|unload)
	CheckConfig
	CheckMem
	Unload || exit $?
	;;
  status)
	CheckConfig
	CheckStatus
	;;
  *)
	echo "Usage: $0 {start|load|stop|unload|restart|force-reload|status}" >&2
	exit 1
	;;
esac

exit 0

