#!/bin/sh

#
# This runit service emulates the normal Docker ENTRYPOINT/CMD handling,
# insofar as possible.
#
# Docker's semantics for ENTRYPOINT/CMD vary depending on if those
# values are specified as arrays of string, or simple as single strings
# (which must be interpreted by /bin/sh -c).
#
# Handling all the quoting possibilities in the shell is a major pain.
# So, this script handles the basic stuff (in particular, sourcing env
# vars, because we want the shell to interpret them!) -- then execs our
# perl companion script (run.pl) to deal with the entrypoint/command
# files that libvnode_docker::emulabizeImage and
# libvnode_docker::vnodeCreate populated.
#
# libvnode_docker creates these single-line files in /etc/emulab/docker
# as either string:hexstr(<entrypoint-or-cmd-string>), or
# array:hexstr(a[0]),hexstr(a[1])... .  This allows us to preserve the
# original type of the image's entrypoint/cmd as well as the runtime
# entrypoint/cmd, and to preserve the exact bytes for the eventual final
# call to exec.
#
# The static files builtin to an emulabized image are
# /etc/emulab/docker/{entrypoint.image,cmd.image}, and those created
# dynamically at runtime if user changes the entrypoint or cmd are
# bind-mounted to /etc/emulab/docker{entrypoint.runtime,cmd.runtime}.
#
# Given the presence (or absence!) of those files, this script
# implements the emulation, based upon the content in those files:
#
# if entrypoint.runtime.type == string:
#   Run exactly the command in entrypoint.runtime
# elif entrypoint.image.type == string:
#   Run exactly the command in entrypoint.image
# else:
#   cmd = ""
#   if entrypoint.runtime != "":
#     cmd = `cat entrypoint.runtime`
#   elif entrypoint.image != "":
#     cmd = `cat entrypoint.image`
#   if type(cmd.runtime) == string:
#     strings = `cat cmd.runtime`
#     cmd = "$cmd /bin/sh -c $strings"
#   elif cmd.image.type == string:
#     strings = `cat cmd.image`
#     cmd = "$cmd /bin/sh -c $strings"
#   elif -n cmd.runtime:
#     strings = `cat cmd.runtime`
#     cmd = "$cmd $strings"
#   elif -n cmd.image:
#     strings = `cat cmd.image`
#     cmd = "$cmd $strings"
#
# If we still have nothing to run, we down the service and exit.
#
# Before executing "$cmd", we include the dockerenv.image file, then
# include the dockerenv.runtime file, if either exists.  Finally, we check
# to see if a USER was specified for the image; and if so, exec "$cmd"
# as that USER via chpst.
#
# When we run chpst, we also close stdin, and we redirect $cmd's outputs
# to /var/log/entrypoint.log.  Initially, we redirect our own outputs to
# /var/log/entrypoint-debug.log .
#

mkdir -p /var/log
exec >> /var/log/entrypoint-debug.log
exec 2>&1

EXECTARGET=`pwd`/run.pl
CHPST=/usr/bin/chpst
PREFIX=/etc/emulab/docker
ENVFILE_G=$PREFIX/dockerenv.generated
ENVFILE_I=$PREFIX/dockerenv.image
ENVFILE_R=$PREFIX/dockerenv.runtime

USER=""
if [ -e $PREFIX/user ]; then
    USER=`cat $PREFIX/user`
fi
WORKINGDIR=""
if [ -e $PREFIX/workingdir ]; then
    WORKINGDIR=`cat $PREFIX/workingdir`
fi
if [ -z "$WORKINGDIR" ]; then
    WORKINGDIR="/"
fi

echo `date`: setting environment...

if [ -e $ENVFILE_G ]; then
    . $ENVFILE_G
fi
if [ -e $ENVFILE_I ]; then
    . $ENVFILE_I
fi
if [ -e $ENVFILE_R ]; then
    . $ENVFILE_R
fi
env

echo `date`: changing to $WORKINGDIR
cd $WORKINGDIR

HELPER="$CHPST -0"
if [ -n "$USER" ]; then
    HELPER="$HELPER -U $USER -u $USER"
fi

echo `date`: executing $EXECTARGET $HELPER

exec $EXECTARGET $HELPER || {
    echo "exec failed!"
    exit 999
}
