#!/bin/bash
#run given shell command on the attached ESP
#Install this script in /usr/bin on an MBARI LRAUV
: ${iface:=ppp0}
: ${user:=esp}
: ${console:=/dev/ttyA6}
: ${constty:=115200 raw -echo}
: ${conout=/mnt/mmc/esp-console.out}
: ${bootLimit:=120}
export bootlimit
PATH=${PATH%:/LRAUV/Tools}:/LRAUV/Tools
self=`basename $0`
power=

while [ "$1" ]; do
  case $1 in
    --offAfter|--offNow|--stayOn)
      [ "$power" ] && {
        echo "$self: $1 conflicts with previous $power option" >&2
      exit 2
    }
    power=$1
    shift
    continue
  ;;
    -*) echo "\
Run given command as $user@ESP interfaced via $iface -- 4/17/21 brent@mbari.org
Powers up the ESP if the $iface link to it is down

Usage:
  $self {--offAfter|--offNow|--stayOn} {command}
Options:
 By default, switches off ESP after command done only if ESP was off beforehand
  --stayOn      leave ESP powered after command completes
  --offAfter    always switch off ESP after command completes
  --offNow      switch off the ESP and cancel other running $self commands
  --help        prints this
Examples:
  $self espclient myName                    #start an espclient
  $self --offAfter espclient --wait myName  #switch off ESP after client exits
  $self --offNow    #switch off ESP, aborting other $self commands in progress
  $self upsync      #copy $user user's logs to espshore
  $self             #start interactive Linux $user user shell
  user=root $self --stayOn   #start a root shell (leave ESP on after it exits)
Environment Variables:
 \$user = ESP user name  ($user)
 \$sshOpt = ssh options  ($sshOpt)
 \$bootLimit = seconds allowed for ESP to boot  ($bootLimit)
 \$console = console serial port ($console)
 \$constty = serial port parameters ($constty)
 \$conout  = console output file ($conout)
Notes:
  This utility assumes the ESP is powered iff the $iface link is up.
  PPP links take a few seconds to tear down.
  Use ssh -t option when running an interactive esp command remotely.
  Example:  $ ssh -t makai espclient myName" >&2
    exit 2
  esac
  break
done

netIfPtp() {
  #output the IP address of the PtP peer for specified PPP interface
  #if there's a valid peer, any additional args are also output
  ifconfig $1 2>/dev/null | tr : " " | {
    local ignore inet addr ip ptp peer ignore
    read -r ignore
    read -r inet addr ip ptp peer ignore
    shift
    [ "$ptp" = "P-t-P" ] && echo $peer $*
  }
}

cleanup() {
  [ "$consolePID" ] && kill $consolePID 2>/dev/null
}

ESPwasDown=
result=
consolePID=
trap "cleanup" EXIT QUIT TERM INT HUP PIPE

if [ "$power" = --offNow ]; then
  [ "$1" ] && {
    echo "$self:  The $power option can't be used with commands" >&2
    exit 2
  }
else
  [ -t 0 -a -z "$sshOpt" ] && sshOpt=-t
  net=/sys/class/net
  ifstate=$net/$iface/carrier #was operstate
  up=1  #was UP

  await() {
   #poll file $1 once per second until it reads $2
   #return error if more that bootLimit seconds elapse
   try=0
   while [[ "try=$try+1" -le $bootLimit ]]; do
     state=`cat $1 2>/dev/null` && [ "$state" = "$2" ] && return
     sleep 1
   done
   echo "The ESP is not coming up" >&2
   return 5
  }

  [ -d $net/$iface ] || {  #Power on the ESP if net interface not already active
    ESPwasDown=yes
    [ "$console" ] && {
      fuser -s $console || {
        stty -F$console $constty
        cat $console >$conout &
        consolePID=$!
      }
    }
    esp-ppp-mivegas.sh >/dev/null  #brings up the esp
    echo -n "Waiting for ESP to boot... " >&2
    await $ifstate $up || exit $?
    echo "Connected." >&2
    sleep 15  #wait for boot to complete
  }
  ipAddr=`netIfPtp $iface`
  [ "$ipAddr" ] || {
    echo "Link to ESP still down.  Consider retrying after $self --offNow" >&2
    return 7
  }
  ssh="ssh $sshOpt $user@$ipAddr"
  echo "`date` -- $ssh $@" >&2
  sync=
  [ "$power" != "--stayOn" -a \( "$power" -o "$ESPwasDown" \) ] && {
    [ -t 0 ] && echo ">>> ESP will power off when above command exits <<<" >&2
    sync="trap sync EXIT;"
    [ "$1" ] || sync="${sync}sh"
  }
  $ssh "$sync$@"
  result=$?
fi

case $power in
  --stayOn)
    exit $result
;;
  '')
    [ "$ESPwasDown" ] || exit $result
esac

[ -t 0 -a -d $net/$iface ] && {  #wait only if interactive and link is up
  trap "echo; echo 'Aborted ESP shutdown!'; exit $result" INT QUIT TERM HUP PIPE
  echo -n "`date` -- Shutting down ESP in 20 seconds ... " >&2
  sleep 20 &&
  trap "cleanup" INT QUIT TERM HUP PIPE
}
others=`pidof -xo $$ $self`
[ "$others" ] && {
  echo
  echo "Killing other $self commands ($others) ... "
  for other in $others; do
    kill -- -$other  #kill $self shell and its subprocesses
  done
}
echo shutting ESP off >&2
esp-mivegas-off.sh >&2  #turn off the esp
exit $result
