#!/bin/sh

# Set up ofono to run with the phone simulator. This uses an unshared tmpfs
# mount over /etc/ofono/ to avoid having to modify the file system.  The script
# can either be invoked without arguments and run until Control-C, or run a
# program (with arguments), in which case everything will be restored when the
# program ends.
#
# Author: Martin Pitt <martin.pitt@ubuntu.com>

set -e

# kill previous instances
pkill --signal KILL -x ofono-phonesim || true
pkill --signal KILL -f '/etc/ofono/phonesim-dbus.conf' || true

# run program under an unshared /etc/ofono/, to be able to run ofono
# with a custom configuration without having to touch the fs
if [ -z "$WITH_OFONO_PHONESIM_UNSHARED" ]; then
    export WITH_OFONO_PHONESIM_UNSHARED=1
    exec unshare -m -- "$0" "$@"
fi

PHONESIM_CONF=/etc/ofono/phonesim.conf
SCRIPTS_DIR=/usr/share/ofono/scripts

# enable to get ofono debugging log on failure
#DEBUG_OFONO=-d

if [ "$1" = "--help" ]; then
    echo "Usage: $0 [<program to run> [args..] ]" >&2
    exit 0
fi

# check our dependencies
[ -e $PHONESIM_CONF ] || { 
    echo "You need to install ofono-phonesim for this" >&2
    exit 1
}
if ! type xvfb-run >/dev/null 2>&1; then
    echo "You need to install xvfb for this" >&2
    exit 1
fi
if ! type $SCRIPTS_DIR/online-modem >/dev/null 2>&1; then
    echo "You need to install ofono-scripts for this" >&2
    exit 1
fi

# read ofono config and uncomment phonesim stanza
MYCONF=$(sed '/\[phonesim/,$ s/^#//' $PHONESIM_CONF)

# write our own config into tmpfs overlay
mount --make-rprivate / 2> /dev/null || : # reset / to private mounts (systemd changes this to shared)
mount -n -t tmpfs tmpfs /etc/ofono
echo "$MYCONF" > $PHONESIM_CONF

ofonod -P ril,rildev,stktest $DEBUG_OFONO -n >/etc/ofono/ofono.log 2>&1 &
OFONO_PID=$!
echo "$0: started ofono (pid $OFONO_PID)"

# session D-BUS config for phomesim where everyone can send messages to
cat <<EOF > /etc/ofono/phonesim-dbus.conf
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
  <type>session</type>
  <listen>unix:tmpdir=/tmp</listen>
  <pidfile>/run/lock/ofono-phonesim-dbus.pid</pidfile>
  <!-- <auth>EXTERNAL</auth> -->

  <policy context="default">
    <allow user="*"/>
    <allow send_destination="*" eavesdrop="true"/>
    <allow eavesdrop="true"/>
    <allow own="*"/>
  </policy>
</busconfig>
EOF

# clean up phonesim, dbus, and restart original ofono at the end
cleanup() {
    set +e
    echo "$0: cleaning up..."
    pkill -x ofono-phonesim
    # kill the dbus session daemon
    pkill -f '/etc/ofono/phonesim-dbus.conf'
    kill $OFONO_PID 2>/dev/null
    wait
    if [ -e /run/lock/ofono-phonesim-dbus.pid ]; then
        cat /run/lock/ofono-phonesim-dbus.pid | xargs kill
        rm /run/lock/ofono-phonesim-dbus.address
    fi
    pkill telepathy-ofono
    echo "$0: finished"
}

trap cleanup 0 TERM INT QUIT HUP PIPE

# start phonesim on a publicly accessible D-BUS daemon as user nobody
su -s /bin/sh nobody > /etc/ofono/phonesim.log <<EOF 2>&1 &
  eval \`dbus-launch --config-file=/etc/ofono/phonesim-dbus.conf\`
  echo \$DBUS_SESSION_BUS_ADDRESS > /run/lock/ofono-phonesim-dbus.address
  export DBUS_SESSION_BUS_ADDRESS
  # fails with configured proxy, so ignore it
  unset http_proxy
  xvfb-run -a ofono-phonesim -p 12345 -gui /usr/share/phonesim/default.xml
EOF

echo "$0: waiting for simulated modem to appear ..."
timeout=10
while [ $timeout -gt 0 ]; do
    sleep 1 
    timeout=$((timeout-1))
    $SCRIPTS_DIR/enable-modem && break
done
[ $timeout -ge 0 ] || {
    echo "timed out waiting for phonesim modem to appear" >&2
    exit 1
}
echo "$0: started phonesim"

# force restart of telepathy-ofono against new ofonod
pkill telepathy-ofono || true

# no arguments: interactive, kill with Control-C
if [ -z "$1" ]; then
    echo "$0: run your application now, and Control-C or kill this process to stop this simulator"
    tail -f /etc/ofono/ofono.log
    echo "$0: shutting down"
    exit 0
fi

# with "quiet": don't tail logs, script can be killed
if [ "$1" = "quiet" ]; then
    echo "$0: run your application now, and kill this process ($$) to stop the simulator"
    # need to sleep within the shell to be able to catch signals, so use the builtin read
    mkfifo /etc/ofono/silent
    read x < /etc/ofono/silent || true
    exit 0
fi

# otherwise: run specified program
echo "$0: running command line specified program/test..."
$@ || {
    RC=$?
    echo "program/test failed with exit status $RC" >&2
    echo "------ ofono log -------------" >&2
    cat /etc/ofono/ofono.log >&2
    echo "------ end ofofono log -------------" >&2
    exit $RC
}
