#!/system/bin/sh

# Copyright (C) 2014 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Run tasks periodically.
# Usage: $0 <delay_seconds> <timeout_seconds> <task_name> <task_binary>
#
# Executes task <task_name> by running <task_binary> every <delay_seconds>.

set -e -u

SCRIPT_NAME="$(basename "$0")"
CHECK_DELAY=300  # Check every 5 minutes.
KILL_DELAY=10    # How long to let the job clean up after a timeout.
# Let the unittests override.
: ${SPOOL_DIR:=/data/misc/crash_reporter/spool/cron-lite}

loginfo() {
  log -p i -t "${SCRIPT_NAME}" "$@"
}

trap "loginfo 'exiting'" EXIT

check_and_fix_spool_paths() {
  # Avoid weird spool paths if possible.
  rm -f "$(dirname "${SPOOL_DIR}")" "${SPOOL_DIR}" 2>/dev/null || :
  mkdir -p "${SPOOL_DIR}"
  if [ ! -O "${SPOOL_DIR}" -o ! -d "${SPOOL_DIR}" ]; then
    loginfo "Spool directory is damaged. Aborting!"
    exit 1
  fi
}

main() {
  local delay="$1"
  local timeout="$2"
  local name="$3"
  local spool_file="${SPOOL_DIR}/${name}"
  shift 3

  [ -z "${delay}" ] && exit 1
  [ -z "${timeout}" ] && exit 1
  [ -z "${name}" ] && exit 1
  [ $# -eq 0 ] && exit 1
  check_and_fix_spool_paths

  while true; do
    # Allow the sleep to be killed manually without terminating the handler.
    # Send stderr to /dev/null to suppress the shell's "Terminated" message.
    sleep $(( CHECK_DELAY + KILL_DELAY )) 2>/dev/null || true

    [ ! -e "${spool_file}" ] && touch "${spool_file}"

    local last_rotation="$(stat -c "%Y" "${spool_file}" 2>/dev/null || echo 0)"
    local now="$(date +%s)"
    local time_diff=$((now - last_rotation))

    if [ ${time_diff} -gt ${delay} ]; then
      rm "${spool_file}" || true
      touch "${spool_file}"
      loginfo "${name}: running $*"
      timeout -k ${KILL_DELAY} ${timeout} "$@" || true
      loginfo "${name}: job completed"
    fi
  done
}

main "$@"
