#!/bin/bash

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

#set -x
set -o pipefail
set -o errtrace

error_handler_rads() {
   echo "[${red}${bold}ERROR${reset}] \
ret: $? | BASH_COMMAND: $BASH_COMMAND | Please report this bug!"
}

trap "error_handler_rads" ERR

exit_handler_rads() {
   delete_display_manager_startup_block
   #echo "INFO: Switch virtual console ('tty2'). See: ${PROJECT_HOMEPAGE}/wiki/vu"
   return
}

trap "exit_handler_rads" EXIT

sigint_handler_rads() {
   exit 0
}

trap "sigint_handler_rads" SIGINT

colors() {
   if [ "$TERM" = "" ]; then
      return 0
   fi

## Thanks to:
## http://mywiki.wooledge.org/BashFAQ/037
## Variables for terminal requests.
[[ -t 2 ]] && {
    alt=$(      tput smcup  || tput ti      ) # Start alt display
    ealt=$(     tput rmcup  || tput te      ) # End   alt display
    hide=$(     tput civis  || tput vi      ) # Hide cursor
    show=$(     tput cnorm  || tput ve      ) # Show cursor
    save=$(     tput sc                     ) # Save cursor
    load=$(     tput rc                     ) # Load cursor
    bold=$(     tput bold   || tput md      ) # Start bold
    stout=$(    tput smso   || tput so      ) # Start stand-out
    estout=$(   tput rmso   || tput se      ) # End stand-out
    under=$(    tput smul   || tput us      ) # Start underline
    eunder=$(   tput rmul   || tput ue      ) # End   underline
    reset=$(    tput sgr0   || tput me      ) # Reset cursor
    blink=$(    tput blink  || tput mb      ) # Start blinking
    italic=$(   tput sitm   || tput ZH      ) # Start italic
    eitalic=$(  tput ritm   || tput ZR      ) # End   italic
[[ $TERM != *-m ]] && {
    red=$(      tput setaf 1|| tput AF 1    )
    green=$(    tput setaf 2|| tput AF 2    )
    yellow=$(   tput setaf 3|| tput AF 3    )
    blue=$(     tput setaf 4|| tput AF 4    )
    magenta=$(  tput setaf 5|| tput AF 5    )
    cyan=$(     tput setaf 6|| tput AF 6    )
}
    white=$(    tput setaf 7|| tput AF 7    )
    default=$(  tput op                     )
    eed=$(      tput ed     || tput cd      )   # Erase to end of display
    eel=$(      tput el     || tput ce      )   # Erase to end of line
    ebl=$(      tput el1    || tput cb      )   # Erase to beginning of line
    ewl=$eel$ebl                                # Erase whole line
    draw=$(     tput -S <<< '   enacs
                                smacs
                                acsc
                                rmacs' || { \
                tput eA; tput as;
                tput ac; tput ae;         } )   # Drawing characters
    back=$'\b'
} 2>/dev/null ||:
}

delete_display_manager_startup_block() {
   rm --force "/run/rads/rads-block-display-manger-startup.status"
}

create_status_file_no_start_dm() {
   mkdir --parents "/run/rads"
   touch "/run/rads/no_start_dm.status"
   rm --force "/run/rads/start_dm.status"

   #if [ "$rads_no_switch_vt" = "1" ]; then
      #true "INFO: Not switching virtual terminal because rads_no_switch_vt=1."
      #return 0
   #fi

   #echo "INFO: Switching to virtual terminal ('tty${rads_vt}')..."
   ## https://forums.whonix.org/t/no-login-prompt-getty-started-on-tty1-anymore-in-whonix-16-debian-bullseye-based/12475
   #chvt "$rads_vt"
   #echo -n "OK."
}

create_status_file_start_dm() {
   mkdir --parents "/run/rads"
   rm --force "/run/rads/no_start_dm.status"
   touch "/run/rads/start_dm.status"
}

ram-adjusted-desktop-starter() {
   shopt -s nullglob
   local i
   for i in /etc/rads.d/*.conf /usr/local/etc/rads.d/*.conf; do
      bash -n "$i"
      source "$i"
   done

   [ -n "$rads_debug" ] || rads_debug="0"
   if [ "$rads_debug" = "1" ]; then
      set -x
   fi

   [ -n "$x_default_dm_config_file" ] || x_default_dm_config_file="/etc/X11/default-display-manager"

   if [ -z "$rads_display_manager" ]; then
      ## greetd is the only supported Wayland greeter. Look for it, use it if
      ## available.
      if [ -f /usr/lib/systemd/system/greetd.service ]; then
         rads_display_manager='greetd'
      elif [ -f "$x_default_dm_config_file" ]; then
         rads_display_manager="$(basename -- "$(cat -- "$x_default_dm_config_file")")"
         if [ "$rads_display_manager" = "" ]; then
            rads_display_manager="lightdm"
         fi
      else
         rads_no_default_dm="1"
      fi
   fi

   [ -n "$rads_minimum_ram" ] || rads_minimum_ram="710"
   [ -n "$rads_start_display_manager" ] || rads_start_display_manager="1"
   [ -n "$rads_skip_ram_test" ] || rads_skip_ram_test="0"
   [ -n "$rads_wait" ] || rads_wait="1"
   [ -n "$rads_wait_seconds" ] || rads_wait_seconds="10"
   [ -n "$rads_no_switch_vt" ] || rads_no_switch_vt="0"
   [ -n "$rads_vt" ] || rads_vt="2"

   if test -x /usr/libexec/helper-scripts/origins-parser ; then
      ## sets: PROJECT_NAME
      ## sets: PROJECT_HOMEPAGE
      ## sets: derivative_major_release_version
      source /usr/libexec/helper-scripts/origins-parser
   fi

   ## {{ Expand PATH variable. Otherwise for example "/usr/sbin/lightdm" could
   ##    not be detected below using "command -v".
   ##    NOTE: The PATH= here not persistently affect the graphical session.
   ##          rads essentially only executes 'systemctl start display-manager'.
   ##          'systemctl' by design does not pass environment variables.
   PATH_OLD="$PATH"
   PATH="$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
   export PATH
   ## }}

   if ! command -v "$rads_display_manager" >/dev/null ; then
      true "INFO: display manager \
'$rads_display_manager' configured in /etc/rads.d/ \
configuration folder does not exist. Not starting a desktop environment."
      create_status_file_no_start_dm
      exit 0
   fi

   if [ "$rads_no_default_dm" = "1" ]; then
      true "INFO: config file \
$x_default_dm_config_file \
does not exist and greetd is not installed. Probably no desktop environment \
installed. Not starting a desktop environment."
      create_status_file_no_start_dm
      exit 0
   fi

   if systemctl --no-pager status "$rads_display_manager" >/dev/null ; then
      true "INFO: \
Not starting '$rads_display_manager', already running."
      exit 0
   fi

   if ! systemctl --no-pager is-enabled "$rads_display_manager" &>/dev/null ; then
      true "INFO: \
Not starting '$rads_display_manager', since disabled.
( to enable, run: sudo systemctl enable $rads_display_manager )"
      exit 0
   fi

   ## Check how much RAM the system has in total.
   ## Thanks to:
   ## http://stackoverflow.com/a/10277712
   total_ram="$(LC_ALL=C free -m | sed  -n -e '/^Mem:/s/^[^0-9]*\([0-9]*\) .*/\1/p')"

   if [ "$rads_start_display_manager" = "0" ]; then
      true "INFO: \
rads_start_display_manager is set to 0 in /etc/rads.d/ \
configuration folder, not starting a desktop environment."
      create_status_file_no_start_dm
      exit 0
   fi

   if [ ! "$rads_skip_ram_test" = "1" ]; then
      if [ "$total_ram" -lt "$rads_minimum_ram" ]; then
         echo "[${green}INFO${reset}] Not starting display manager \
(graphical desktop environment) ('$rads_display_manager'), \
because there is only $total_ram MB total RAM. (A minimum of \
$rads_minimum_ram MB total RAM is configured in /etc/rads.d/ \
configuration folder.)"
         sleep 5
         create_status_file_no_start_dm
         exit 0
      fi
   fi

   if [ -e "/usr/share/anon-gw-base-files/gateway" ]; then
      ## Whonix specific info message. Feel free to implement your own.
      if [ -f "/usr/share/whonix/marker" ]; then
         echo "[${green}INFO${reset}] If your \
host has little RAM, you are advised to reduce Gateway \
RAM to 256 MB. No graphical desktop environment will be started in that case. \
A Gateway without graphical desktop environment works as good as one with, \
it's just not that convenient. If you want, you can sometimes start a graphical \
desktop environment by toggling how much RAM is available to Gateway. \
Documentation about this feature can be found here: \
https://www.whonix.org/wiki/rads"
      fi
   fi

   ## Fallback.
   read_exit_code="0"
   if [ "$rads_wait" = "0" ]; then
      true "INFO: Waiting feature disabled."
   else
      echo "[${green}INFO${reset}] Starting display manager \
(graphical desktop environment) '$rads_display_manager' in \
$rads_wait_seconds seconds, unless you abort using ctrl + c. \
This can be disabled or configured in /etc/rads.d/ configuration folder."
      read -t "$rads_wait_seconds" read_input || { read_exit_code="$?" ; true; };
      ## read exits,
      ## 0: when enter has been pressed with or without input
      ## 142: on timeout
      ## 130: on ctrl + c
   fi

   if [ "$read_exit_code" = "0" ] || [ "$read_exit_code" = "142" ]; then
      if systemctl --no-pager status "$rads_display_manager" >/dev/null ; then
         echo "[${green}INFO${reset}] '$rads_display_manager' already running, not starting."
      else
         echo "[${green}INFO${reset}] Trying to start display manager \
(graphical desktop environment) '$rads_display_manager'..."

         delete_display_manager_startup_block

         if systemctl --no-pager start "$rads_display_manager" ; then
            true "INFO: Successfully started '$rads_display_manager'."
            create_status_file_start_dm
         else
            echo "[${red}${bold}ERROR${reset}] \
Could not start '$rads_display_manager'. Please report this bug!"
         fi
      fi
   else
      ## We will not boot into a graphical desktop environment.
      ## Make a new line so the ^C stands alone.
      echo ""
      echo "[${green}INFO${reset}] Manually aborted start of display manager \
(graphical desktop environment) '$rads_display_manager'."
      echo "[${green}INFO${reset}] Feel free to manually start a display manager \
(graphical desktop environment) later.
    sudo service $rads_display_manager start"

      create_status_file_no_start_dm
      exit 0
   fi

   true "INFO: End."
   exit 0
}

colors
ram-adjusted-desktop-starter
