#!/bin/bash
#(c) Copyright Barry Kauler, 31 January 2017. License: GPL V3 (/usr/share/doc/legal)
#Easy Linux script for Easy Containers, to stop a running container.
#passed in parameter is name of executable.
#170523 replaced 'EC_LAYER' with 'EASY_LAYER'
#170523 sfs may have a glob wildcard. 170527 fix.
#170804 moved umount container/dev/* here from ec-chroot

[ ! $1 ] && exit 1
EXE="$1"

. /etc/DISTRO_SPECS #170527
. /etc/rc.d/PUPSTATE #has BOOT_DEV, BOOT_FS, BOOT_DIR, WKG_DEV, WKG_FS, WKG_DIR, QSFS_PATH

[ ! -d /mnt/${WKG_DEV}/${WKG_DIR}containers/${EXE} ] && exit 1

#At first it tries nicely with SIGTERM
#After a timeout, it uses SIGKILL
#ref: http://askubuntu.com/questions/162319/how-do-i-stop-all-processes-in-a-chroot
kill_pid_func() {
 PROC_TO_KILL=$1
 #Make sure we have an arg to work with
 if [[ "$PROC_TO_KILL" == "" ]]
 then
  echo "KILL_PID: \$1 cannot be empty"
  return 1
 fi
 #Try to kill it nicely
 kill -0 $PROC_TO_KILL &>/dev/null && kill -15 $PROC_TO_KILL
 #Check every second for 5 seconds to see if $PROC_TO_KILL is dead
 WAIT_TIME=5
 #Do a quick check to see if it's still running
 #It usually takes a second, so this often doesn't help
 kill -0 $PROC_TO_KILL &>/dev/null &&
 for SEC in $(seq 1 $WAIT_TIME)
 do
  sleep 1
  if [[ "$SEC" != $WAIT_TIME ]]
  then
   #If it's dead, exit
   kill -0 $PROC_TO_KILL &>/dev/null || break
  else
   #If time's up, kill it
   kill -0 $PROC_TO_KILL &>/dev/null && kill -9 $PROC_TO_KILL
  fi
 done
}

cd /mnt/${WKG_DEV}/${WKG_DIR}containers/${EXE}
. ./configuration

#kill all processes, and everything mounted, in the container.
#ref: http://askubuntu.com/questions/162319/how-do-i-stop-all-processes-in-a-chroot
CONTAINER="/mnt/${WKG_DEV}/${WKG_DIR}containers/${EXE}/container"
#Find processes who's root folder is actually the chroot...
for ROOT in $(find /proc/*/root)
do
 #Check where the symlink is pointing to
 LINK=$(readlink -f $ROOT)
 #If it's pointing to the $CONTAINER, kill the process
 if echo $LINK | grep -q ${CONTAINER%/}
 then
  PID=$(basename $(dirname "$ROOT"))
  kill_pid_func $PID
 fi
done
#Get a list of PIDs that are using $CONTAINER for anything
#original code requires full 'lsof', hopefully get it to work with busybox lsof...
#PID_LIST=$(lsof +D $CONTAINER 2>/dev/null | tail -n+2 | tr -s ' ' | cut -d ' ' -f 2 | sort -nu)
PID_LIST="$(busybox lsof | grep "$CONTAINER" | tail -n+2 | cut -d ' ' -f 1 | sort -nu | tr '\n' ' ')"
#Kill all PIDs holding up unmounting $CONTAINER
for PID in $PID_LIST
do
 kill_pid_func $PID
done

#170804 need this...
if [ "$EC_NS_UNSHARE_MOUNT" == "false" ];then
 busybox umount ${CONTAINER}/dev/shm
 busybox umount ${CONTAINER}/dev/pts
 busybox umount ${CONTAINER}/tmp
 busybox umount ${CONTAINER}/dev
 busybox umount ${CONTAINER}/sys
 busybox umount ${CONTAINER}/proc
fi

sync
busybox umount /mnt/${WKG_DEV}/${WKG_DIR}containers/${EXE}/container #unmount overlay.
busybox umount /mnt/${WKG_DEV}/${WKG_DIR}containers/${EXE}/.ro0 #unmount ro layer.
#unmount any extra sfs files...
for NUM in 4 3 2 1
do
 eval "ROsfs=\$EASY_LAYER_RO${NUM}" #implements indirection. EASY_LAYER_RO1='devx.sfs' in configuration file, will assign 'devx.sfs' to ROsfs
 if [ "$ROsfs" ];then
  #170523 may have a glob wildcard...
  FNDSFSS="$(ls -1 /mnt/${WKG_DEV}/${WKG_DIR}repository/easy-${DISTRO_VERSION}/${ROsfs} | tr '\n' ' ')"
  for FNDSFS in $FNDSFSS
  do
   ANAME="$(basename $FNDSFS .sfs)"
   busybox umount .${ANAME}
  done
 fi
done

echo "Container ${EXE} stopped"
exit 0
