#!/bin/bash # # This file is part of TALER # Copyright (C) 2023, 2024 Taler Systems SA # # TALER 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; either version 3, or # (at your option) any later version. # # TALER 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 TALER; see the file COPYING. If not, see # # # Author: Christian Grothoff # # Script to test for network connectivity, and if # successful launch some "main" application. If # the network goes down, stop the "main" application # and show an error message. # set -eu EXIT_STATUS=0 CHILD_PID=-1 ERROR_PID=-1 # Exit, with error message (hard failure) function exit_fail() { echo " FAILURE:" "$@" >&2 EXIT_STATUS=1 exit "$EXIT_STATUS" } CONF="$HOME/.config/taler.conf" # Parse command-line options while getopts ':c:f:h' OPTION; do case "$OPTION" in c) CONF="$OPTARG" ;; f) FAIL_PROG="$OPTARG" ;; h) echo 'Supported options:' # shellcheck disable=SC2016 echo ' -c $CONF -- set configuration' # shellcheck disable=SC2016 echo ' -f $CMD -- command to run to display failures' ;; ?) exit_fail "Unrecognized command line option" ;; esac done shift $((OPTIND - 1)) WORKER="$@" dig -h > /dev/null || exit_fail "'dig' is required" if [[ ${FAIL_PROG:-} = "" ]] then FAIL_PROG=$(taler-config -c "$CONF" -s taler-mdb -o "FAIL_HELPER") fi # Cleanup to run whenever we exit function cleanup() { echo "network-check terminating!" >&2 if [ "$ERROR_PID" != "-1" ] then kill -TERM "$ERROR_PID" wait "$ERROR_PID" ERROR_PID="-1" fi if [ "$CHILD_PID" != "-1" ] then kill -TERM "$CHILD_PID" wait "$CHILD_PID" CHILD_PID="-1" fi for n in $(jobs -p) do kill "$n" 2> /dev/null || true done wait exit "$EXIT_STATUS" } # Function called with the short-hand of a detected # Failure. Stop our child (if any) and show it. function show_failure() { echo "Showing failure $1" if [ "$ERROR_PID" != "-1" ] then kill -TERM "$ERROR_PID" wait ERROR_PID="-1" fi if [ "$CHILD_PID" != "-1" ] then kill -TERM "$CHILD_PID" wait CHILD_PID="-1" fi ${FAIL_PROG} "$1" >&2 & ERROR_PID=$! } # Install cleanup handler (except for kill -9) trap cleanup EXIT # shellcheck disable=SC2120 function check_network() { DEF_BACKEND=$(taler-config -c "$CONF" -s "taler-mdb" -o "BACKEND_BASE_URL") BACKEND_HOSTNAME=$(echo "$DEF_BACKEND" | awk -F/ '{print $3}') BACKEND_AUTH=$(taler-config -c "$CONF" -s "taler-mdb" -o "BACKEND_AUTHORIZATION") DNS_HOST=$(grep nameserver /etc/resolv.conf | grep -v '^#' | head -n1 | awk '{print $2}') if ! ping -c1 "$DNS_HOST" &> /dev/null then show_failure no-ip return fi if ! dig "$BACKEND_HOSTNAME" &> /dev/null then show_failure backend-dns-resolution-failure return fi if ! ping -c1 "$BACKEND_HOSTNAME" &> /dev/null then show_failure backend-unreachable return fi if echo "$DEF_BACKEND" | grep "https://" > /dev/null then if ! wget --no-check-certificate "${DEF_BACKEND}config" -O /dev/null &> /dev/null then show_failure backend-no-webserver return fi fi if ! wget "${DEF_BACKEND}config" -O /dev/null &> /dev/null then show_failure backend-x509-cert-bad return fi HAVE_PRODUCT=0 for PS in $(taler-config -c "$CONF" -S | grep "product-" | head -n1) do URL=$(taler-config -c "$CONF" -s "$PS" -o "INSTANCE" 2> /dev/null || echo "$DEF_BACKEND") AUTH=$(taler-config -c "$CONF" -s "$PS" -o "BACKEND_AUTHORIZATION" 2> /dev/null || echo "$BACKEND_AUTH") if ! wget --header "Authorization: $AUTH" "${URL}private/orders" -O /dev/null &> /dev/null then echo "Failed to access backend for product '$PS'" >&2 else HAVE_PRODUCT=1 fi done if [ "$HAVE_PRODUCT" = 0 ] then show_failure backend-auth-failure return fi echo "Network OK" if [ "$ERROR_PID" != "-1" ] then kill -TERM "$ERROR_PID" wait ERROR_PID="-1" fi if [ "$CHILD_PID" = "-1" ] then echo "Starting child using $WORKER" # shellcheck disable=SC2068 $WORKER & CHILD_PID=$! fi } # Check network status while true do echo "Checking network status" check_network sleep 30 if ! ps "$ERROR_PID" &> /dev/null then wait "${ERROR_PID}" ERROR_PID="-1" fi if ! ps "$CHILD_PID" &> /dev/null then wait "${CHILD_PID}" CHILD_PID="-1" fi done