# shell-script-helper v1.6
# Copyright (c) 2024 Raphaël Halimi <raphael.halimi@gmail.com>
# Licence: GPL-3+

# Please read the shell-script-helper(3) manpage for documentation

###############################################################################
# Functions - System
###############################################################################

# Allow only root to run the script
# ARGS: none
root_only () {
  if [ "$(id -u)" != "0" ] ; then
    print_error "This script must be run as root, aborting."
    exit 1
  fi
}

# Allow only one instance of the script
# ARGS: none
lock_script () {
  local LOCK_FILE
  LOCK_FILE="/run/lock/$(basename "$0").pid"
  if [ -e "$LOCK_FILE" ] ; then
    ps "$(cat "$LOCK_FILE")" > /dev/null
    if [ $? -ne 0 ] ; then
      printf "Deleting stale lock file %s\n" "$LOCK_FILE"
      rm -f "$LOCK_FILE"
    else
      print_error "Script already running with PID $(cat "$LOCK_FILE"), aborting."
      exit 1
    fi
  fi
  print_debug "Creating lock file $LOCK_FILE with PID $$"
  echo $$ > "$LOCK_FILE"
}

# Remove lock file
# ARGS: none
unlock_script () {
  local LOCK_FILE
  LOCK_FILE="/run/lock/$(basename "$0").pid"
  if [ -e "$LOCK_FILE" ] ; then
    if [ "$(cat "$LOCK_FILE")" -eq $$ ] ; then
      print_debug "Deleting lock file $LOCK_FILE with PID $$"
      rm -f "$LOCK_FILE"
    fi
  fi
}

# Delete one or more files, with some checks and feedback
# ARGS: FILE...
delete_files () {
  local FILE_TO_DELETE
  for FILE_TO_DELETE in "$@" ; do
    print_debug "Deleting file $FILE_TO_DELETE..."
    rm -f "$FILE_TO_DELETE" || print_error "Couldn't delete file $FILE_TO_DELETE"
  done
}

# Exit on fatal error
# ARGS: [STRING]
die () {
  print_error "${1:-"Unknown error"}, aborting."
  exit 1
}

# Automatically executed when the script exits
# ARGS: none
quit () {
  command -v on_exit > /dev/null 2>&1 && on_exit
  unlock_script
}


###############################################################################
# Functions - Output
###############################################################################

# Enable verbose mode
# ARGS: none
enable_verbose () {
  VERBOSE=1
  print_debug "Verbose mode enabled"
}

# Enable debug mode
# ARGS: none
enable_debug () {
  DEBUG=1
  print_debug "Debug mode enabled"
}


# Print strings on STDOUT only if verbose mode is enabled
# ARGS: STRING...
print_verbose () {
  [ $VERBOSE -eq 1 ] && for MESSAGE in "$@" ; do
    printf "%-8s%s\n" "[INFO]" "$MESSAGE"
  done
}


# Print strings on STDOUT only if debug mode is enabled
# ARGS: STRING...
print_debug () {
  [ $DEBUG -eq 1 ] && for MESSAGE in "$@" ; do
    printf "%-8s%s\n" "[DEBUG]" "$MESSAGE"
  done
}


# Print strings on STDERR with the [ERROR] prefix
# ARGS: STRING...
print_error () {
  for MESSAGE in "$@" ; do
    printf "%-8s%s\n" "[ERROR]" "$MESSAGE" 1>&2
  done
}


# Display options in the help message
# ARGS: OPTION OPTION_DESCRIPTION
print_option() {
  printf "  %-20s%s\n" "$1" "$2"
}




###############################################################################
# Traps
###############################################################################

# Handle common signals gracefully
trap 'die "SIGINT caught (interrupt from keyboard)"' 2
trap 'die "SIGPIPE caught (write to pipe with no readers)"' 13
trap 'die "SIGTERM caught (termination signal)"' 15

# Call the quit function when the script exits
trap 'quit' 0


###############################################################################
# Verbosity
###############################################################################

# These variables are meant to be changed with switches
VERBOSE=0
DEBUG=0


###############################################################################
# Examples
###############################################################################

# Print help
#print_help () {
#  printf "Usage: %s [OPTIONS] [ARGS...]\n" "$(basename "$0")"
#  printf "\nOPTIONS:\n"
#  print_option "-v" "Verbose mode"
#  print_option "-d" "Debug mode"
#  print_option "-h" "Print this help message"
#}

# Options processing
#while getopts "vdh" OPTION ; do
#  case $OPTION in
#    v) enable_verbose ;;
#    d) enable_debug ;;
#    h) print_help ; exit 0 ;;
#    *) print_help ; exit 1 ;;
#  esac
#done ; shift $((OPTIND-1))

# vim: ft=sh
