#!/bin/bash

## Copyright (C) 2012 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See the file COPYING for copying conditions.

## {{ maybe_kill_apt_get_update
##
## apt-get-update runs as root (using a /etc/sudoers.d/ exception) while
## systemcheck runs as user. Therefore we can't kill apt-get-update using
## process_killer_helper. (Can't kill processes owned by other users.)
## In case apt-get-update is still running, we need to start
## apt-get-update-kill-helper as root (again using a /etc/sudoers.d/
## exception). This might look like a lot effort for little gain, but when
## the user terminated systemcheck, apt-get is still running and the user wants
## to manually use apt-get, it would show an error because the apt-get lockfile
## would still exist.
maybe_kill_apt_get_update() {
   if [ "$apt_get_update_pid" = "" ]; then
      ## Pid never set. Either the check_operating_system check has been disabled,
      ## or signal received earlier or this isn't systemcheck. Either way.
      ## Nothing to do.
      return 0
   fi

   ## Check if apt-get-update has already terminated.
   local ps_p_exit_code
   ps_p_exit_code="0"
   ps -p "$apt_get_update_pid" >/dev/null 2>/dev/null || { ps_p_exit_code="$?" ; true; };

   if [ ! "$ps_p_exit_code" = "0" ]; then
      ## apt-get-update already terminated, nothing to do.
      return 0
   fi
   ## apt-get-update still running.

   ## There is an exception in /etc/sudoers.d/.
   ## "|| true", to avoid an error when systemcheck receives a sigterm signal
   ## while running this command (such as when systemcheckd gets stopped).
   leaprun apt-get-update-kill-helper || true
}
## }}

cleanup_files() {
   if [ "$DEL_TMP" = "false" ]; then
      echo "$SCRIPTNAME: Not deleting TEMP_DIR: $TEMP_DIR"
   else
      if [ -d "$TEMP_DIR" ]; then
         safe-rm --recursive -- "$TEMP_DIR"
      fi
   fi
}

## {{ ex_funct

## This function gets called by trap_sigterm (ex: yad cancel button),
## trap_sigint (ex: ctrl + c) and error_handler.

ex_funct() {
   ## In case parse_cmd failed.
   [ -n "$output_cli" ] || output_cli="true"
   [ -n "$output_x" ] || output_x="true"
   [ -n "$output_general" ] || output_general="true"

   if [ ! "$SIGNAL_TYPE" = "NONE" ]; then
      echo "$SCRIPTNAME: signal $SIGNAL_TYPE received. Cleaning up... Exiting..."
   fi

   ## Deactivate traps, so when pressing ctrl + c several times this won't
   ## create an endless loop.
   trap - SIGTERM
   trap - SIGINT
   trap - SIGUSR2

   maybe_kill_apt_get_update

   if command -v "process_killer_helper" >/dev/null ; then
      ## kill $lastpid (if running)
      process_killer_helper

      lastpid="$tail_pid"
      ## kill $lastpid (if running)
      process_killer_helper
   fi

   cleanup_files

   ## Check if $output command has been already defined. This is not the case,
   ## when the script is terminated very early.
   local command_v_output_exit_code
   command_v_output_exit_code="0"
   command -v "output_func" >/dev/null || { command_v_output_exit_code="$?" ; true; };
   if [ "$command_v_output_exit_code" = "0" ]; then
      local output_status_exit_code
      output_status_exit_code="0"
      $output_general ${output_opts[@]} --identifier "$IDENTIFIER" --status --messagecli || { output_status_exit_code="$?" ; true; };

      if [ ! "$progressbaridx" = "" ]; then
         local progress_bar_open
         progress_bar_open="0"
         $output_general ${output_opts[@]} --identifier "$IDENTIFIER" --status --progressbaridx "$progressbaridx" --progressbarxprogresstxtexisting || { progress_bar_open="$?" ; true; };
      fi

      if [ "$SIGNAL_TYPE" = "SIGUSR2" ]; then
         true "User most likely pressed cancel button. No need to send progress 100 to close progress bar."
      else
         if [ "$progress_bar_open" = "0" ]; then
            $output_x ${output_opts[@]} --progressbaridx "$progressbaridx" --progressx "100"
         else
            true "No progress bar open. No need to send progress 100 to close progress bar."
         fi
      fi

      if [ "$TITLE_X" = "" ]; then
         TITLE="No TITLE defined yet."
      fi
      if [ "$TITLE_CLI" = "" ]; then
         TITLE="No TITLE defined yet."
      fi
      $output_x ${output_opts[@]} --titlex "$TITLE_X"
      $output_cli ${output_opts[@]} --titlecli "$TITLE_CLI"

      if [ ! "$SIGNAL_TYPE" = "NONE" ]; then
         local MSG="<p><b>$SCRIPTNAME aborted!</b> (SIGNAL_TYPE: $SIGNAL_TYPE)</p>"
         ## Not adding aborted message to gui output. Caused too much confusion.
         #$output_x ${output_opts[@]} --messagex --typex "info" --message "$MSG"
         $output_cli ${output_opts[@]} --messagecli --typecli "info" --message "$MSG"
      fi

      $output_x ${output_opts[@]} --messagex --done
      $output_cli ${output_opts[@]} --messagecli --done
   else
      if [ ! "$SIGNAL_TYPE" = "NONE" ]; then
         local MSG="$SCRIPTNAME aborted! (SIGNAL_TYPE: $SIGNAL_TYPE)"
         echo "$MSG"
      fi
   fi

   if [ -z "$EXIT_CODE" ] || [ "$EXIT_CODE" = '0' ]; then
      ## 'exit_code' inherited from error_handler
      if [ -n "$exit_code" ]; then
         EXIT_CODE="$exit_code"
      else
         EXIT_CODE="0"
      fi
   fi

   exit "$EXIT_CODE"
}

## }}

trap_sigterm() {
   SIGNAL_TYPE="SIGTERM"
   EXIT_CODE="143"
   ex_funct
}

trap "trap_sigterm" SIGTERM

trap_sigint() {
   SIGNAL_TYPE="SIGINT"
   EXIT_CODE="130"
   ex_funct
}

trap "trap_sigint" SIGINT ## ctrl + c

trap_sigusr2() {
   SIGNAL_TYPE="SIGUSR2"
   EXIT_CODE="0"
   ex_funct
}

trap "trap_sigusr2" SIGUSR2 ## msgcollector, yad cancel button

cleanup() {
   true "$FUNCNAME..."

   sync

   SIGNAL_TYPE="NONE"

   ex_funct
}
