#! /bin/sh
#
# Name: spxtest
# Author: SpinetiX
# Copyright: 2015 SpinetiX
# License: 2015 (c) SpinetiX. This file is licensed
#          under the terms of the GNU General Public License version 2.
#          This program is licensed "as is" without any warranty of any
#          kind, whether express or implied.
#
# Copyright 1999-2003 MontaVista Software, Inc.
# Copyright 2002, 2003, 2004 Sony Corporation
# Copyright 2002, 2003, 2004 Matsushita Electric Industrial Co., Ltd.
#
### BEGIN INIT INFO
# Required-Start:
# Required-Stop:
# Should-Start:
# Should-Stop:
# Default-Start: 2 3 4 5
# Default-Stop:
# Short-Description: automatic test
# Description: automatic test which only runs on first boot
### END INIT INFO

# Init script information
NAME=spxtest
DESC="SpinetiX test"

# Defaults
STATUSFILE=/etc/spxtest/status
STATUS=done
WAIT=10
TYPE=local
MOUNTPOINT=/media/usb1
TESTSCRIPT=spxtest.sh

# Load init script configuration
[ -f /etc/default/$NAME ] && . /etc/default/$NAME

# Source the init script functions
. /etc/init.d/functions

parse_args() {
    TYPE="${1%%:*}"
    TYPEARGS="${1#*:}"
}

do_local() {
    local ret

    if [ -f "$MOUNTPOINT/$TESTSCRIPT" ]; then
	echo -n "starting... "

	tmpdir="$(mktemp -q -d /tmp/spxtest.XXXXXX)"
	if [ $? -ne 0 ]; then
	    echo -n "cannot create temp dir "
	    return 1
	fi

	(cd "$tmpdir" && bash "$MOUNTPOINT/$TESTSCRIPT")
	ret=$?
	# Be sure the mountpoing stays ro
	mount -o ro,remount "$MOUNTPOINT"
    else
	echo -n "no test script found, "
	ret=0
    fi
    return $ret
}

led_fail() {
    if [ -d /sys/class/leds ]; then
	# new style LEDs
	local l
	for l in /sys/class/leds/system\:*\:status /sys/class/leds/*\:*\:status[0-9]; do
	    [ -f "$l"/trigger ] && echo none > "$l"/trigger
	done
	for l in /sys/class/leds/system\:red\:status /sys/class/leds/*\:red\:status[0-9]; do
	    [ -f "$l"/max_brightness -a -f "$l"/brightness ] && \
	        cat "$l"/max_brightness > "$l"/brightness
	done
    else
	# old style LEDs
	local ledfile=/sys/devices/system/leds/leds0/event
	if [ -f "$ledfile" ]; then
	    echo red on > "$ledfile"
	fi
    fi
}

do_net() {
    local ret url scheme tmpdir file

    url="$1"
    if [ -z "$url" ]; then
	echo -n "no URL provided "
	return 1
    fi

    scheme="${url%%://*}"
    tmpdir="$(mktemp -q -d /tmp/spxtest.XXXXXX)"
    if [ $? -ne 0 ]; then
	echo -n "cannot create temp dir "
	return 1
    fi
    file="$tmpdir/spxtest"

    echo -n "downloading... "
    case "$scheme" in
	http|ftp)
	    curl -g -s -S -f -L --retry 3 -o "$file" --max-time 10 "$url"
	    ret=$?
	    ;;
	tftp)
	    local host path url_path
	    url_path="${url#${scheme}://}"
	    host="${url_path%%/*}"
	    path="/${url_path#*/}"
	    if [ -z "$host" -o -z "$path" ]; then
		echo -n "missing TFTP host or path in URL "
		ret=1
	    else
		tftp -m binary "$host" -c get "$path" "$file" < /dev/null
		ret=$?
		# TFTP does not always return non-zero exit code on failure
		if [ "$ret" -eq 0 -a ! -s "$file" ]; then
		    ret=1
		fi
	    fi
	    ;;
	*)
	    echo -n "unrecognized '$scheme' scheme "
	    ret=1
	    ;;
    esac

    if [ $ret -ne 0 ]; then
	echo -n "failed downloading test "
	rm -rf "$tmpdir"
	return $ret
    fi

    echo -n "starting... "
    chmod +x "$file"
    (cd "$tmpdir" && "$file")
    ret=$?
    rm -rf "$tmpdir"

    return $ret
}

start() {
    local RET ERROR=

    KARGS="$(sed -e 's/.*\bspxtest=\([^[:space:]]\+\).*/\1/p;d' \
            < /proc/cmdline)"

    if [ -z "$KARGS" ]; then
	STATUS=done
	if [ -f "$STATUSFILE" ]; then
	    . "$STATUSFILE"
	fi
    else
	parse_args "$KARGS"
	WAIT=
	STATUS=start
    fi

    if [ "$STATUS" != "start" ]; then
	return 0
    fi
	
    echo -n "Starting $DESC: "

    echo -n "marking as done, "

    # write via a temporary file + rename to ensure proper commit to
    # fs (in particular with fs using delayed allocation, e.g., ext4).
    echo -e "# The status variable indicates if we should 'start' or we are 'done'\nSTATUS=done" > \
	"$STATUSFILE".tmp
    fsync "$STATUSFILE".tmp 2>/dev/null || sync
    mv "$STATUSFILE".tmp "$STATUSFILE"

    if [ -n "$WAIT" ]; then
	echo -n "waiting $WAIT secs... "
	sleep "$WAIT"
    fi

    case "$TYPE" in
	local)
            do_local "$TYPEARGS"
	    RET=$?
	    ;;
	net)
	    do_net "$TYPEARGS"
	    RET=$?
	    if [ $RET -ne 0 ]; then
		led_fail
	    fi
	    ;;
	*)
	    echo -n "Unrecognized test type '$TYPE'"
	    RET=$?
	esac

	if [ $RET -eq 0 ]; then
	    echo -n "done. "
	    success; echo
	else
	    echo -n " failed. "
	    failure; echo
	    return 1
	fi
	
	return 0
}

parse() {
    case "$1" in
	start)
	    start
	    return $?
	    ;;
	stop)
	    return 0
	    ;;
	*)
	    echo "Usage: $NAME {start|stop}" >&2
	    ;;
    esac
	
    return 1
}

parse $@
