#!/bin/sh

# /etc/rc.d/rc.updated
# 2015-10-30
# by Gernot WALZL

# Update Daemon for Slackware Linux
# It uses slackpkg to receive patches.

# http://software.jaos.org/
# http://www.sbopkg.org/

# /etc/rc.d/rc.local
# /etc/rc.d/rc.updated start

. /etc/rc.d/rc.updated.conf
REMOVE_MULT_VERS_SAME_PKG=${REMOVE_MULT_VERS_SAME_PKG:-on}
AUTO_UPGRADE_SLACKPKG=${AUTO_UPGRADE_SLACKPKG:-on}
AUTO_UPGRADE_SLAPTGET=${AUTO_UPGRADE_SLAPTGET:-on}
CLEAN_CACHE_AFTER_UPGRADE_SLACKPKG=${CLEAN_CACHE_AFTER_UPGRADE_SLACKPKG:-on}
CLEAN_CACHE_AFTER_UPGRADE_SLAPTGET=${CLEAN_CACHE_AFTER_UPGRADE_SLAPTGET:-on}
SLACKPKG_TEMP=${SLACKPKG_TEMP:-/var/cache/packages}
DAEMON_SLEEP=${DAEMON_SLEEP:-24h}

PKGDBDIR="/var/log/packages"
LOGGER="/usr/bin/logger"
REMOVEPKG="/sbin/removepkg"
SLACKPKG="/usr/sbin/slackpkg"
SLAPTGET="/usr/sbin/slapt-get"
SBOPKG="/usr/sbin/sbopkg"

export HOME=/root   # gpg looks for keys in $HOME/.gnupg

print_usage () {
  echo "Usage:"
  echo "  $0 {slackpkg,slapt-get,sbopkg,daemon,start,stop,status}"
}

repair_pkg_db () {
  local PRGNAM
  local PKG
  for PRGNAM in $(ls -v "$PKGDBDIR" \
      | sed -n 's/^\(.\+\)-[^-]\+-[^-]\+-[^-]\+$/\1/p' \
      | uniq -d); do
    PKG=$(cd "$PKGDBDIR"; ls -v ${PRGNAM}-* \
      | grep -e "^${PRGNAM}-[^-]\+-[^-]\+-[^-]\+\$" -m 1)
    if [ "$PKG" != "" ]; then
      $LOGGER "UPDATED: Multiple versions of $PRGNAM detected. Removing $PKG"
      $REMOVEPKG $PKG
      if [ "$AUTO_UPGRADE_SLACKPKG" = "on" ]; then
        $SLACKPKG -dialog=off -batch=on -default_answer=yes reinstall $PRGNAM || true
      fi
      if [ "$AUTO_UPGRADE_SLAPTGET" = "on" ]; then
        $SLAPTGET -i $PRGNAM --reinstall --no-prompt || true
      fi
    fi
  done
}

remove_old_patches () {
  local PKGDIR="$SLACKPKG_TEMP/patches/packages"
  if [ ! -d "$PKGDIR" ]; then
    return 1
  fi
  local PRGNAM
  local PKG
  local TOREMOVE
  for PRGNAM in $(cd "$PKGDIR"; ls -v *.t?z 2> /dev/null \
      | sed -n 's/^\(.\+\)-[^-]\+-[^-]\+-[^-]\+\.t[gx]z$/\1/p' \
      | uniq -d); do
    PKG=$(cd "$PKGDIR"; ls -v ${PRGNAM}-*.t?z \
      | grep -e "^${PRGNAM}-[^-]\+-[^-]\+-[^-]\+\.t[gx]z\$" -m 1)
    if [ "$PKG" != "" ]; then
      TOREMOVE=$(echo "$PKG" | rev | cut -d . -f 2- | rev)
      rm -f "$PKGDIR/$TOREMOVE".*
    fi
  done
}

slackpkg_upgrade_all () {
  $SLACKPKG -dialog=off -batch=on -default_answer=no update || return 1
  $SLACKPKG -dialog=off -batch=on -default_answer=yes upgrade-all || return 1
  if [ "$CLEAN_CACHE_AFTER_UPGRADE_SLACKPKG" = "on" ]; then
    remove_old_patches
  fi
}

slaptget_upgrade () {
  local OUTPUT=$(LANG=C $SLAPTGET --update) || return 1
  echo "$OUTPUT"
  local NUM_REPOS=$(echo "$OUTPUT" \
    | grep "^Retrieving package data" | wc -l)
  local NUM_VERIFIED=$(echo "$OUTPUT" \
    | grep "^Verifying checksum signature \[.*\]\.\.\.Verified$" | wc -l)
  if [ "$NUM_REPOS" -eq "$NUM_VERIFIED" ]; then
    $SLAPTGET --upgrade --no-prompt || return 1
    if [ "$CLEAN_CACHE_AFTER_UPGRADE_SLAPTGET" = "on" ]; then
      $SLAPTGET --autoclean --no-prompt
    fi
  else
    return 1
  fi
}

sbopkg_updates () {
  # $SBOPKG -u || return 1
  $SBOPKG -r || return 1
  $SBOPKG -c || return 1
}

wait_for_inet () {
  while ! ping -c 1 -W 5 8.8.8.8 > /dev/null 2>&1 ; do
    sleep 5m
  done
}

daemon () {
  wait_for_inet
  if [ "$REMOVE_MULT_VERS_SAME_PKG" = "on" ]; then
    repair_pkg_db
  fi
  while :; do
    if [ "$AUTO_UPGRADE_SLACKPKG" = "on" ]; then
      slackpkg_upgrade_all > /dev/null 2>&1
    fi
    if [ "$AUTO_UPGRADE_SLAPTGET" = "on" ]; then
      slaptget_upgrade > /dev/null 2>&1
    fi
    sleep "$DAEMON_SLEEP"
  done
}

start () {
  local PID
  if [ -r /var/run/updated.pid ]; then
    PID=$(cat /var/run/updated.pid)
    if ps -p $PID; then
      echo "Already running."
    else
      daemon &
      PID=$!
      echo $PID > /var/run/updated.pid
    fi
  else
    daemon &
    PID=$!
    echo $PID > /var/run/updated.pid
  fi
}

stop () {
  local PID
  if [ -r /var/run/updated.pid ]; then
    PID=$(cat /var/run/updated.pid)
    kill $PID
    rm /var/run/updated.pid
  fi
}

status () {
  local PID
  if [ -r /var/run/updated.pid ]; then
    PID=$(cat /var/run/updated.pid)
    if ps -p $PID; then
      echo "Running."
    else
      echo "Not running."
    fi
  else
    echo "Not running."
  fi
}

case "$1" in
'slackpkg')
  slackpkg_upgrade_all
  ;;
'slapt-get')
  slaptget_upgrade
  ;;
'sbopkg')
  sbopkg_updates
  ;;
'daemon')
  daemon
  ;;
'start')
  start
  ;;
'stop')
  stop
  ;;
'status')
  status
  ;;
*)
  print_usage
esac
