#!/bin/bash
###############################################################################
# BRLTTY - A background process providing access to the console screen (when in
#          text mode) for a blind person using a refreshable braille display.
#
# Copyright (C) 1995-2024 by The BRLTTY Developers.
#
# BRLTTY comes with ABSOLUTELY NO WARRANTY.
#
# This is free software, placed under the terms of the
# GNU Lesser General Public License, as published by the Free Software
# Foundation; either version 2.1 of the License, or (at your option) any
# later version. Please see the file LICENSE-LGPL for details.
#
# Web Page: http://brltty.app/
#
# This software is maintained by Dave Mielke <dave@mielke.cc>.
###############################################################################

set -e
. "`dirname "${0}"`/brltty-prologue.sh"

showProgramUsagePurpose() {
cat <<END_OF_PROGRAM_USAGE_PURPOSE
Simplify the job of assigning capabilities to the BRLTTY executable.
END_OF_PROGRAM_USAGE_PURPOSE
}

executeCommand() {
   "${useSudo}" && set -- sudo -- "${@}"

   if "${testMode}"
   then
      echo "${*}"
   else
      "${@}"
   fi
}

setOwner() {
   local type="${1}"
   local root="${2}"
   local command="${3}"

   if "${root}"
   then
      local owner=0
   else
      local owner="$(id -"${type}")"
   fi

   executeCommand "${command}" "${owner}" -- "${executablePath}"
}

setMode() {
   local type="${1}"
   local set="${2}"

   if "${set}"
   then
      local operator="+"
   else
      local operator="-"
   fi

   executeCommand chmod "${type}${operator}s" "${executablePath}"
}

capabilitiesList=()
addCapability() {
   capabilitiesList[${#capabilitiesList[*]}]="${1}"
}

addProgramOption c flag noCreation "don't allow creating missing state directories"
addProgramOption d flag noDevices "don't allow creating needed but missing device files"
addProgramOption g flag noGroups "don't allow switching to the writable group or joining the required groups"
addProgramOption i flag noInput "don't allow injecting input characters"
addProgramOption m flag noModules "don't allow installing kernel modules"
addProgramOption o flag noOwnership "don't allow claiming ownership of the state directories"
addProgramOption p flag noPermissions "don't allow adding group permissions to the state directories"
addProgramOption s flag noSpeaker "don't allow using the built-in PC speaker"
addProgramOption C flag noCapabilities "don't set the capabilities"
addProgramOption G flag rootGroup "set group root execution"
addProgramOption S flag useSudo "use sudo to execute the commands as root"
addProgramOption T flag testMode "test mode - show the commands that would be executed"
addProgramOption U flag rootUser "set user root execution"
addProgramParameter executable executablePath "the path to the executable"
parseProgramArguments "${@}"

verifyExecutableFile "${executablePath}"

"${testMode}" || {
   if "${useSudo}"
   then
      sudo -v
   elif [ "$(id -u)" -ne 0 ]
   then
      semanticError "not executing as root"
   fi
}

setOwner u "${rootUser}" chown
setOwner g "${rootGroup}" chgrp

setMode u "${rootUser}"
setMode g "${rootGroup}"

"${noCapabilities}" || {
   "${noCreation}" || addCapability "cap_dac_override"
   "${noDevices}" || addCapability "cap_mknod"
   "${noGroups}" || addCapability "cap_setgid"
   "${noInput}" || addCapability "cap_sys_admin"
   "${noModules}" || addCapability "cap_sys_module"
   "${noOwnership}" || addCapability "cap_chown"
   "${noPermissions}" || addCapability "cap_fowner"
   "${noSpeaker}" || addCapability "cap_sys_tty_config"

   [ "${#capabilitiesList[*]}" -eq 0 ] || {
      capabilitiesOperand="${capabilitiesList[*]}"
      capabilitiesOperand="${capabilitiesOperand// /,}"
      capabilitiesOperand+="+p"
      executeCommand setcap "${capabilitiesOperand}" "${executablePath}"
   }
}

exit 0
