#!/usr/bin/env bash
#
# Author: RainbowMiner <rbm2018@gmail.com>
#
### BEGIN INIT INFO
# Provides:          ocdaemon
# Required-Start:    $local_fs $remote_fs $syslog
# Required-Stop:     $local_fs $remote_fs $syslog
# X-Start-Before:    
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Auto execution of oc scripts
# Description:       Rainbowminer daemon to provide root overclocking
### END INIT INFO

VER="1.0.2"

OCDDATA=/opt/rainbowminer/ocdcmd
OCDBIN=/usr/bin/ocdaemon
OCDPID=/var/run/ocdaemon.pid
OCDLOGFILE=/var/log/ocdaemon.log
OCDERRORLOGFILE=/var/log/ocdaemon_error.log
OCDVERSIONFILE=/opt/rainbowminer/ocdcmd/version.log

test -x "$OCDBIN" || exit 1

# Function to check if the user is root
is_user_root() { [ "${EUID:-$(id -u)}" -eq 0 ]; }
SUDO="${SUDO:-$(is_user_root || echo sudo)}"

do_wrpid() {
  if [ ! -f "$OCDPID" ]; then
    echo -n $$ > "$OCDPID"
    chmod 666 "$OCDPID"
  fi
}

do_rmpid() {
  if [ -f "$OCDPID" ]; then
    rm "$OCDPID"
  fi
}

do_log_start() {
  local now=$(date +"%Y-%m-%d %T")
  echo -n "[$now] $1"
}

do_log_end() {
  echo "$1"
}

do_log() {
  do_log_start "$1"
  do_log_end
}

do_status() {
  if [ -s "$OCDPID" ]; then
    local pid="$(<$OCDPID)"

    if [ -h "/proc/$pid/exe" ]; then
      echo "running"
    else
      do_rmpid
      echo "crashed"
    fi
  else
    echo "stopped"
  fi
}

do_cleanup() {
  # Cleanup
  for entry in "$OCDDATA"/*.run "$OCDDATA"/*.out "$OCDDATA/stop"
  do
    if [ -f "$entry" ]; then
      rm "$entry"
    fi
  done
}

do_stop() {
  echo -n "Stopping RainbowMiner ocdaemon .. "
  if [ "$(do_status)" == "running" ]; then
    date +%s > "$OCDDATA/stop"
    COUNT=0
    while [ $COUNT -le 10 ]; do
      if [ "$(do_status)" != "running" ]; then
        echo "stopped"
        exit
      fi
      (( COUNT++ ))
      sleep 0.5
    done

    local pid="$(<$OCDPID)"
    if [ "$(ps -p $pid -o command=)" ]; then
      kill -9 $pid
    fi
    do_rmpid
    echo "killed"
    exit
  fi

  if [ `id -u` == 0 ]; then
    for i in `ps aux | grep "$OCDBIN run" | grep "run1" | awk '{print $2}' | uniq`; do kill -9 $i; done
  fi

  echo "not running"
}

do_run() {
  if ! is_user_root; then
    do_log "ERROR: Daemon needs to be run as root/sudo" >&2
    exit
  fi
  if [ "$(do_status)" == "running" ]; then
    do_log "ERROR: Another daemon seems to be running!" >&2
    exit
  fi

  do_log "ocdaemon started"

  # Check for data directory
  if [ ! -d "$OCDDATA" ]; then
    mkdir "$OCDDATA"
    chmod 777 "$OCDDATA"
  fi

  do_cleanup

  # Run the loop
  while [ ! -f "$OCDDATA/stop" ]; do
    for entry in "$OCDDATA"/*.sh
    do
      do_wrpid
      if [ -f "$entry" ]; then
        lockfn=`echo ${entry} | sed s/\.sh/.lock/g`
        outfn=`echo ${entry} | sed s/\.sh/.out/g`
        runfn=`echo ${entry} | sed s/\.sh/.run/g`
        now=`date +%s`
        if [ -f "$entry" ] && [ ! -f "$lockfn" ];then
          echo $now > $runfn
          chmod 666 "$runfn"
          chmod 777 "$entry"
          $entry > $outfn
          if [ -f "$outfn" ]; then
            chmod 666 "$outfn"
          fi
          if [ -f "$entry" ]; then
            rm "$entry"
          fi
          if [ -f "$runfn" ]; then
            rm "$runfn"
          fi
          if [ -f "$lockfn" ]; then
            rm "$lockfn"
          fi
        fi
      fi
    done
    sleep 1
  done
  do_log "ocdaemon stopped"
  do_rmpid
}

do_install() {  
  $SUDO echo "" > "$OCDERRORLOGFILE"
  if [ -e "/etc/systemd/system/ocdaemon.service" ]; then
    echo "ocdaemon is already installed. Please use reinstall or uninstall/install."
    exit 1
  else
    if [ -d "/etc/systemd/system" ]; then
      echo "Installing ocdaemon v$VER to systemd"
      $SUDO cp "/opt/rainbowminer/conf/ocdaemon.service" "/etc/systemd/system/ocdaemon.service"
      $SUDO systemctl enable ocdaemon
      $SUDO systemctl start ocdaemon
      echo "Done! ocdaemon is up and running."
      $SUDO echo -n "$VER" > "$OCDVERSIONFILE"
    else
      echo "No systemd found on your system. Please install by hand"
      exit 1
    fi
  fi
}

do_uninstall() {
  if [ -e "/etc/systemd/system/ocdaemon.service" ]; then
    echo "Uninstalling ocdaemon from systemd"
    $SUDO systemctl stop ocdaemon
    $SUDO systemctl disable ocdaemon
    $SUDO rm -f "/etc/systemd/system/ocdaemon.service"
    echo "Done! Success uninstalling ocdaemon"
    $SUDO rm -f "$OCDVERSIONFILE"
  else
    echo "ocdaemon is currently not installed"
  fi
}

do_start() {

  echo -n "Starting RainbowMiner ocdaemon v$VER .. "

  if [ "$(do_status)" == "running" ]; then
    echo "ERROR: Another daemon seems to be running!"
    exit
  fi

  if [ `id -u` != 0 ]; then
    echo -n " $SUDO "
    $SUDO bash -c "$OCDBIN run1"
  else
    "$OCDBIN" run1
  fi

  COUNT=0
  while [ $COUNT -le 10 ]; do
    if [ "$(do_status)" == "running" ]; then
      echo "done"
      exit
    fi
    (( COUNT++ ))
    sleep 0.5
  done

  echo "failed"
}

case "${1}" in
    start)
                do_start
        ;;
    stop)
                do_stop
        ;;
    status)
                do_status
        ;;
    run1)
                tty=$(tty)
                setsid "$OCDBIN" run2 "$tty" "$@" &
        ;;
    run2)
                shift; tty="$1"; shift
                umask 0
                "$OCDBIN" run "$tty" "$@" </dev/null >/dev/null 2>/dev/null &
        ;;
    run)
                exec >"$OCDLOGFILE"
                exec 2>"$OCDERRORLOGFILE"
                exec 0</dev/null
                shift; tty="$1"; shift
                do_run
        ;;
    restart|reload|force-reload)
                do_stop
                do_start
        ;;
    install)
                do_install
        ;;
    uninstall)
                do_uninstall
        ;;
    reinstall)
                if ! [ -s "$OCDVERSIONFILE" ] || [ "$VER" \< "$(<$OCDVERSIONFILE)" ]; then
                  do_uninstall
                  do_install
                else
                  echo "ocdaemon is already uptodate!"
                  exit 1
                fi
        ;;
    *)
        echo "Usage: ${0} {start|stop|status|restart|reload|force-reload|install|uninstall|reinstall}" >&2
                exit 1
        ;;
esac

exit 0
