#!/bin/bash
#
# linuxmuster-reset-rooms
# resets the internet, intranet, webfilter, lession state of rooms/hosts
#
# thomas@linuxmuster.net
# 04.03.2016
# GPL V3
#


# check for linuxmuster-reset-rooms lockfile
locker=/tmp/.linuxmuster-reset-rooms
if [ -e "$locker" ]; then
	echo "Caution! Lockfile $locker detected!"
	echo "Probably there is another linuxmuster-reset-rooms process running!"
	echo "If this is not the case you can safely remove the lockfile $locker"
        echo "and give linuxmuster-reset-rooms another try."
	exit 1
fi
touch $locker
chmod 400 $locker


exit_script() {
 local RC=1
 [ -n "$1" ] && RC="$1"
 echo | tee -a $LOGFILE
 echo "Terminating linuxmuster-reset session at `date`" | tee -a $LOGFILE
 echo "#####################################################################" | tee -a $LOGFILE
 rm -f $locker $HOSTLIST $ROOMLIST
 exit "$RC"
}

# source linuxmuster defaults
. /usr/share/linuxmuster/config/dist.conf || exit_script

# source helperfunctions
. $HELPERFUNCTIONS || exit_script

# logfile
LOGFILE="$LOGDIR/linuxmuster-reset.log"

# parsing parameters
getopt $*

usage() {
  echo
  echo "Usage: linuxmuster-reset --room=<roomname> [--kill]"
  echo "                         --host=<hostname>"
  echo "                         --all [--kill]"
  echo
  echo "--room : reset all hosts of this room."
  echo "--host : reset only this specific host."
  echo "--all  : reset all rooms and hosts defined in $(basename $ROOMDEFAULTS)"
  echo "         and $(basename $CLASSROOMS)."
  echo "--kill : kill the room's active lession, if there is one (optional)."
  echo "         Use this with care!"
  echo
  echo "Note: --room and --host are using default values if room/host is not"
  echo "      defined in $ROOMDEFAULTS."
  exit_script
}

# test parameters
[[ -z "$room" && -z "$host" && -z "$all" ]] && usage
[[ -n "$room" && -n "$all" ]] && usage
[[ -n "$room" && -n "$host" ]] && usage
[[ -n "$host" && -n "$all" ]] && usage
[[ -n "$host" && -n "$kill" ]] && usage


# check if $ROOMDEFAULTS exists
if [ ! -e "$ROOMDEFAULTS" ]; then
	echo "Fatal: File $ROOMDEFAULTS not found!"
	exit_script
fi

# check for firewall availability
if ! test_pwless_fw 2>> $LOGFILE 1>> $LOGFILE; then
 echo "Passwordless connection to firewall is not available!" | tee -a $LOGFILE
 exit_script
fi

# start
echo | tee -a $LOGFILE
echo "#####################################################################" | tee -a $LOGFILE
echo "Starting linuxmuster-reset session at `date`" | tee -a $LOGFILE


# get default values from room_defaults or set it to on if not defined
defaults="$(grep -iw ^default $ROOMDEFAULTS | tr A-Z a-z)"
internet_default="$(echo $defaults | awk '{ print $2 }')"
[ -z "$internet_default" ] && internet_default=on
intranet_default="$(echo $defaults | awk '{ print $3 }')"
[ -z "$intranet_default" ] && intranet_default=on
webfilter_default="$(echo $defaults | awk '{ print $4 }')"
[ -z "$webfilter_default" ] && webfilter_default=on


# create empty list files
HOSTLIST="/var/tmp/hosts_to_reset.$$"
ROOMLIST="/var/tmp/rooms_to_reset.$$"
for i in "$HOSTLIST" "$ROOMLIST"; do
 rm -f "$i"
 touch "$i"
done

# all is given on cl
if [ -n "$all" ]; then

 # process all entries in room_defaults and create first a roomlist and a hostlist
 grep ^[A-Za-z0-9] $ROOMDEFAULTS | tr A-Z a-z | while read line; do
  item="$(echo $line | awk '{ print $1 }')"
  # room
  if grep -qi ^$item\; $WIMPORTDATA; then
   echo "$line" >> "$ROOMLIST"
  # host
  elif grep ^[A-Za-z] $WIMPORTDATA | awk -F\; '{ print "X"$2"X" }' | grep -qiw X${item}X; then
   echo "$line" >> "$HOSTLIST"
  else
   continue
  fi
 done
 
 # process roomlists, look for already defined hosts, add hosts not defined with defaults
 for i in $(cat $ROOMLIST $CLASSROOMS | grep ^[A-Za-z0-9] | awk '{ print $1 }' | tr A-Z a-z | sort -u); do
  # read defaults for room
  defaults="$(grep -iw ^$i $ROOMDEFAULTS | tr A-Z a-z)"
  internet_room="$(echo $defaults | awk '{ print $2 }')"
  [ -z "$internet_room" ] && internet_room="$internet_default"
  intranet_room="$(echo $defaults | awk '{ print $3 }')"
  [ -z "$intranet_room" ] && intranet_room="$intranet_default"
  webfilter_room="$(echo $defaults | awk '{ print $4 }')"
  [ -z "$webfilter_room" ] && webfilter_room="$webfilter_default"
  # get hosts for room from workstations file
  for h in $(grep -i ^$i\; $WIMPORTDATA | awk -F\; '{ print $2 }' | tr A-Z a-z | sort -u); do
   # write hosts to hostlist if not yet there
   grep -qi ^$h "$HOSTLIST" || echo "$h $internet_room $intranet_room $webfilter_room" >> "$HOSTLIST"
  done
 done

# a single host is given on cl
elif [ -n "$host" ]; then

 # test if host is defined in workstations file
 if ! grep ^[0-9A-Za-z] $WIMPORTDATA | awk -F\; '{ print "X"$2"X" }' | grep -qiw X${host}X; then
  echo "Host $host is not known to the system." | tee -a $LOGFILE
  exit_script
 fi
 # read defaults for host
 defaults="$(grep -iw ^$host $ROOMDEFAULTS | tr A-Z a-z)"
 internet_host="$(echo $defaults | awk '{ print $2 }')"
 [ -z "$internet_host" ] && internet_host="$internet_default"
 intranet_host="$(echo $defaults | awk '{ print $3 }')"
 [ -z "$intranet_host" ] && intranet_host="$intranet_default"
 webfilter_host="$(echo $defaults | awk '{ print $4 }')"
 [ -z "$webfilter_host" ] && webfilter_host="$webfilter_default"
 # write hostlist
 echo "$host $internet_host $intranet_host $webfilter_host" > "$HOSTLIST"

# a specific room is given on cl
elif [ -n "$room" ]; then

 # read defaults for room
 defaults="$(grep -iw ^$room $ROOMDEFAULTS | tr A-Z a-z)"
 internet_room="$(echo $defaults | awk '{ print $2 }')"
 [ -z "$internet_room" ] && internet_room="$internet_default"
 intranet_room="$(echo $defaults | awk '{ print $3 }')"
 [ -z "$intranet_room" ] && intranet_room="$intranet_default"
 webfilter_room="$(echo $defaults | awk '{ print $4 }')"
 [ -z "$webfilter_room" ] && webfilter_room="$webfilter_default"
 # write room list
 echo "$room $internet_room $intranet_room $webfilter_room" > "$ROOMLIST"
 # get hosts for room from workstations file
 for h in $(grep -i ^$room\; $WIMPORTDATA | awk -F\; '{ print $2 }' | tr A-Z a-z | sort -u); do
  # write hosts to hostlist if not yet there
  line="$(grep -wi ^$h $ROOMDEFAULTS | tr A-Z a-z)"
  if [ -n "$line" ]; then
   echo "$line" >> "$HOSTLIST"
  else
   echo "$h $internet_room $intranet_room $webfilter_room" >> "$HOSTLIST"
  fi
 done

fi


# exit if hostlist is empty
if [ ! -s "$HOSTLIST" ]; then
 echo | tee -a $LOGFILE
 echo "No items to process." | tee -a $LOGFILE
 exit_script 0
fi


# read variable for internal firewall
. /etc/default/linuxmuster-base || exit_script


# check if urlfilter is active
$SCRIPTSDIR/check_urlfilter.sh &> /dev/null && uf_active=yes


# call internet/intranet/urlfilter on_off script
call_script() {
 local target="$1"
 local trigger="$2"
 local hostlist="$(echo $3 | sed -e 's| |,|g')"
 local script="$SCRIPTSDIR/$(echo $target | tr A-Z a-z)_on_off.sh"
 local RCTMP="0"
 echo | tee -a $LOGFILE
 echo " * $target $(echo $trigger | tr a-z A-Z)" | tee -a $LOGFILE
 echo "   -> $(echo $hostlist | sed -e 's|,|\n   -> |g')" | tee -a $LOGFILE
 $script --trigger=$trigger --hostlist=$hostlist 2>> $LOGFILE 1>> $LOGFILE ; RCTMP="$?"
 if [ "$RCTMP" = "0" ]; then
  echo "   OK!"
 else
  echo "   FAILED!"
  RC="1"
 fi
 return "$RCTMP"
}


RC="0"

# do internet reset
# hosts to trigger on
internet_on="$(grep ^[A-Za-z0-9] $HOSTLIST | awk '{ print $1 " " $2 }' | grep -i " on" | awk '{ print $1 }')"
[ -n "$internet_on" ] && call_script Internet on "$internet_on"

# hosts to trigger off
internet_off="$(grep ^[A-Za-z0-9] $HOSTLIST | awk '{ print $1 " " $2 }' | grep -i " off" | awk '{ print $1 }')"
[ -n "$internet_off" ] && call_script Internet off "$internet_off"


# do intranet reset, only if internal firewall is active
if [ "$START_LINUXMUSTER" = "yes" ]; then

 # hosts to trigger on
 intranet_on="$(grep ^[A-Za-z0-9] $HOSTLIST | awk '{ print $1 " " $3 }' | grep -i " on" | awk '{ print $1 }')"
 [ -n "$intranet_on" ] && call_script Intranet on "$intranet_on"

 # hosts to trigger off
 intranet_off="$(grep ^[A-Za-z0-9] $HOSTLIST | awk '{ print $1 " " $3 }' | grep -i " off" | awk '{ print $1 }')"
 [ -n "$intranet_off" ] && call_script Intranet off "$intranet_off"

else

 echo | tee -a $LOGFILE
 echo " * Skipping intranet reset." | tee -a $LOGFILE

fi


# do urlfilter reset, only if urlfilter is active
if [ -n "$uf_active" ]; then

 # hosts to trigger on
 urlfilter_on="$(grep ^[A-Za-z0-9] $HOSTLIST | awk '{ print $1 " " $4 }' | grep -i " on" | awk '{ print $1 }')"
 [ -n "$urlfilter_on" ] && call_script Urlfilter on "$urlfilter_on"

 # hosts to trigger off
 urlfilter_off="$(grep ^[A-Za-z0-9] $HOSTLIST | awk '{ print $1 " " $4 }' | grep -i " off" | awk '{ print $1 }')"
 [ -n "$urlfilter_off" ] && call_script Urlfilter off "$urlfilter_off"

else

 echo | tee -a $LOGFILE
 echo " * Skipping urlfilter reset." | tee -a $LOGFILE

fi


# kill active lessions
if [ -s "$ROOMLIST" -a -n "$kill" ]; then

 # set session file prefix
 roomfile_prefix="/var/lib/schulkonsole/room_"

 # process rooms from roomlist
 for r in $(grep -i ^[A-Za-z0-9] $ROOMLIST | awk '{ print $1 }'); do
 
  roomfile=${roomfile_prefix}$(echo -n $r | md5sum | awk '{ print $1 }')
  if [ -e "$roomfile" ]; then
   # check if exam is active
   if grep -q test_step $roomfile; then
    OIFS="$IFS"
    IFS=","
    for i in `cat $roomfile`; do
     if stringinstring user_id "$i"; then
      user_id="$(echo "$i" | awk -F\' '{ print $4 }')"
      break
     fi
    done
    IFS="$OIFS"
    get_login_by_id $user_id
    teacher=$RET
    if check_teacher $teacher; then
     echo " * WARNING: Terminating ongoing exam of teacher $teacher in room $r!" | tee -a $LOGFILE
     if sophomorix-teacher --teacher $teacher --room $r --exam --collect 2>> $LOGFILE 1>> $LOGFILE; then
      echo "   For detailed output of sophomorix-teacher see $LOGFILE!"
     else
      echo "   sophomorix-teacher failed! See $LOGFILE for details."
      RC="1"
     fi
    fi
   fi
   echo " * WARNING: I'm killing an active lession in room $r!" | tee -a $LOGFILE
   rm -f $roomfile
  fi
 
 done

fi


# start nscd if not running
if ! ps ax | grep nscd | grep -v grep &> /dev/null; then
 echo | tee -a $LOGFILE
 service nscd start | tee -a $LOGFILE
fi


if [ "$RC" != "0" ]; then
 echo | tee -a $LOGFILE
 echo "Terminated with error(s)!" | tee -a $LOGFILE
fi
exit_script "$RC"
