#!/bin/bash
#
# Guralp Configuration System
#   Copyright (c) 2009 Guralp Systems Ltd. All rights reserved.
#
#   GSTM server config



# Handle the navbar query without loading anything
if [ "X$1" == "X--navbar" ]
then
    echo "servicestop    Services"
    echo "servicessub/gstm-server    gstm-server"
    echo "gstm-server/$3    $3"
    exit 0
fi



# Load support functions
script_dir=$(dirname $0)
. $script_dir/functions.sh
. $script_dir/svc_funcs.sh

name="$2"
sel="$3"

CFGFILE="${CONFIGDIR}/${name}/${sel}.local"
CTLFILE="${CONFIGDIR}/${name}/${sel}.ctl.local"
SRVBASE="${SERVDIR}/${name}"
KEYFILE="${CONFIGDIR}/${name}/${sel}.keys.local"



# do_read_var()
#  Reads a variable from the configuration file.
#  $1 -> name
#  $2 -> default
do_read_var() {
    local var_name="$1"
    local default_value="$2"
    local orig_value

    gcs_var "d_${var_name}" "${default_value}"
    [ -e "${CFGFILE}" ] || return 0
    orig_value="$(gcs_get_varcf2 "${var_name}" "${CFGFILE}" "")"
    [ -n "${orig_value}" ] && gcs_var "o_${var_name}" "${orig_value}"
    return 0
}



do_read() {
    # Standard control info
    gcs_svc_read || return 1

    # Process the client keys file
    if [ -r "${KEYFILE}" ]
    then
        n=0
        while read entry
        do
            gcs_var "o_client_name${n}" "${entry/:*/}"
            eval client_name[${n}]="${entry/:*/}"
            gcs_var "o_client_psk${n}"  "${entry/*:/}"
            ((n++))
        done < "${KEYFILE}"
        client_num="${n}"
    fi

    # Read the config file
    do_read_var "bind_host"             ""
    do_read_var "bind_service"          "gstm"
    do_read_var "watchdog_interval"     "30"

    if [ ! -r "${CFGFILE}" ]
    then
        return 0
    fi

    forward_num=0

    # Read clients
    for section in $(gcs_list_varcf2_sections "${CFGFILE}")
    do
        # scan for client_ sections
        case "${section}" in
        client_*)
            c_name="${section/client_/}"
            ;;
        *)
            continue
            ;;
        esac

        # add a client to our list if it doesn't already exist
        # after this, 'n' is set to the index of the client
        n=0
        while [ "${n}" -lt "${client_num}" ]
        do
            eval test_name="\${client_name[${n}]}"
            [ "${test_name}" = "${c_name}" ] && break
            ((n++))
        done
        if [ "${n}" -eq "${client_num}" ]
        then
            eval client_name[${n}]="${c_name}"
            gcs_var "o_client_name${n}" "${c_name}"
            ((client_num++))
        fi

        # grab per-client settings
        gcs_var "o_client_start_command${n}" \
            "$(gcs_get_varcf2 "start_command" "${CFGFILE}" "${section}")"

        # port forwards
        for svar in $(gcs_list_varcf2 "${CFGFILE}" "${section}")
        do
            # scan for port forward (forward_) sections
            case "${svar}" in
            forward_*)
                f_target="${svar/forward_/}"
                ;;
            *)
                continue
                ;;
            esac

            # add to our port forward list
            f_lhost="$(gcs_get_varcf2 "${svar}" "${CFGFILE}" "${section}")"
            f_lservice="${f_lhost/*,/}"
            f_lhost="${f_lhost/,*/}"

            gcs_var "o_forward_host${forward_num}" "${f_lhost}"
            gcs_var "o_forward_service${forward_num}" "${f_lservice}"
            gcs_var "o_forward_cname${forward_num}" "${c_name}"
            gcs_var "o_forward_remote${forward_num}" "${f_target}"
            ((forward_num++))
        done
    done
}



do_check() {
    gcs_read_vars

    # Standard service control/info vars
    gcs_svc_check

    # Service dependent variables

    # TODO: test that there is a PSK for each client
    # TODO: test that there is a port forward for each client
}



do_write() {
    local -i n

    do_check
    if (( gcs_errors > 0 ))
    then
        return
    fi

    if gcs_truefalse "${new_delete:-false}"
    then
        gcs_svc_delete "$name" "$sel"
    fi

    # Standard service controls
    gcs_ensure_cfgfile_exists $CTLFILE
    gcs_set_varf DESC $CTLFILE "$desc"

    NEWCFGFILE="$(mktemp /tmp/gstm-server-conf.XXXXXX)"
    NEWKEYFILE="$(mktemp /tmp/gstm-server-conf.XXXXXX)"

    # Server settings
    [ -n "${new_bind_host}" ] && gcs_set_varcf2 "bind_host" "${NEWCFGFILE}" "${new_bind_host}" ""
    gcs_set_varcf2 "bind_service"       "${NEWCFGFILE}" "${new_bind_service}" ""
    gcs_set_varcf2 "client_keyfile"     "${NEWCFGFILE}" "${KEYFILE}" ""
    gcs_set_varcf2 "watchdog_interval"  "${NEWCFGFILE}" "${new_watchdog_interval}" ""

    # Keys and startup commands
    for (( n = 0 ; n < $new_client_rows ; n++ ))
    do
        eval c_name="\${new_client_name${n}}"
        [ -z "${c_name}" ] && continue
        eval c_psk="\${new_client_psk${n}}"
        eval c_startcmd="\${new_client_start_command${n}}"

        echo "${c_name}:${c_psk}" >> "${NEWKEYFILE}"
        if [ -n "${c_startcmd}" ]
        then
            gcs_set_varcf2 "start_command" "${NEWCFGFILE}" "${c_startcmd}" "client_${c_name}"
        fi
    done

    # Port forwards
    for (( n = 0 ; n < $new_forwards_rows ; n++ ))
    do
        eval f_target="\${new_forward_remote${n}}"
        [ -z "${f_target}" ] && continue
        eval f_lhost="\${new_forward_host${n}}"
        eval f_lservice="\${new_forward_service${n}}"
        eval f_lcname="\${new_forward_cname${n}}"

        f_lbind="${f_lhost}"
        [ -n "${f_lservice}" ] && f_lbind="${f_lbind},${f_lservice}"
        gcs_set_varcf2 "forward_${f_target}" "${NEWCFGFILE}" "${f_lbind}" "client_${f_lcname}"
    done

    # Move new files into place
    group_move_file "${NEWKEYFILE}" "${KEYFILE}"
    group_move_file "${NEWCFGFILE}" "${CFGFILE}"

    # Update the service script
    gcs_update_svc "$name" "$sel" "$enable" "$desc" "$CFGFILE" "$CTLFILE" \
            "$SRVBASE"
    
    gcs_svc_reload "$name" "$sel"
}



case "X$1" in
X--check) do_check    ;;
X--write) do_write    ;;
X--read)  do_read     ;;
*)        exit 1      ;;
esac

gcs_cleanup
exit 0


# vim: ts=4:sw=4:expandtab
