#!/bin/bash # SPDX-FileCopyrightText: 2023 Deminder # SPDX-License-Identifier: GPL-3.0-or-later # # Adapted from cpupower extension by: # Martin Koppehel , Fin Christensen # installer.sh - This script installs a policykit rule for the Shutdown Timer gnome-shell extension. # # This file is part of the gnome-shell extension ShutdownTimer@Deminder. set -e ################################ # EXTENSION SPECIFIC OPTIONS: # ################################ EXTENSION_NAME="Shutdown Timer" ACTION_BASE="dem.shutdowntimer" RULE_BASE="$ACTION_BASE.settimers" CFC_BASE="shutdowntimerctl" POLKIT_DIR="polkit" VERSION=1 EXIT_SUCCESS=0 EXIT_INVALID_ARG=1 EXIT_FAILED=2 EXIT_NEEDS_UPDATE=3 EXIT_NEEDS_SECURITY_UPDATE=4 EXIT_NOT_INSTALLED=5 EXIT_MUST_BE_ROOT=6 DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #stackoverflow 59895 export TEXTDOMAINDIR="$DIR/../locale" export TEXTDOMAIN="ShutdownTimer" function gtxt() { gettext "$1" } function polkit_version_greater_than() { printf -v versions '%s\n%s' "$(pkaction --version | cut -d' ' -f3)" "$1" [[ $versions != "$(sort -V <<< "$versions")" ]] } function polkit_action_lookup_program_gets_realpath() { polkit_version_greater_than "126" } function polkit_supports_standalonerule() { polkit_version_greater_than "0.106" } function check_support() { local polkit_info=", stand-alone polkit rules" if polkit_supports_standalonerule; then polkit_info+=" available" if polkit_action_lookup_program_gets_realpath; then polkit_info+=", with realpath program lookup" fi else polkit_info+=" not avaliable" fi if which rtcwake >/dev/null 2>&1 then echo "rtcwake supported${polkit_info}" exit ${EXIT_SUCCESS} else echo "rtcwake unsupported${polkit_info}" exit ${EXIT_FAILED} fi } function require_root() { if [ "${EUID}" -ne 0 ]; then echo "This action must be run as root!" exit ${EXIT_MUST_BE_ROOT} fi } function fail() { echo "$(gtxt "Failed")${1}" >&2 && exit ${EXIT_FAILED} } DEFAULT_SUCCESS_MSG=$(gtxt 'Success') function success() { echo -n "${1:-$DEFAULT_SUCCESS_MSG}" echo -e "\U1F7E2" } ######################## # GENERALIZED SCRIPT: # ######################## function usage() { echo "Usage: installer.sh [options] {supported,install,check,update,uninstall}" echo echo "Available options:" echo " --tool-user USER Set the user of the tool (default: \$USER)" echo exit ${EXIT_INVALID_ARG} } if [ $# -lt 1 ] then usage fi ACTION="" TOOL_USER="$USER" while [[ $# -gt 0 ]] do key="$1" # we have to use command line arguments here as pkexec does not support # setting environment variables case $key in --tool-user) TOOL_USER="$2" shift shift ;; supported|install|check|update|uninstall) if [ -z "$ACTION" ] then ACTION="$1" else echo "Too many actions specified. Please give at most 1." usage fi shift ;; *) echo "Unknown argument $key" usage ;; esac done CFC_DIR="/usr/local/bin" RULE_DIR="/etc/polkit-1/rules.d" if polkit_supports_standalonerule; then RULE_IN="${DIR}/../${POLKIT_DIR}/10-$RULE_BASE.rules" else RULE_IN="${RULE_IN}.legacy" ACTION_IN="${DIR}/../${POLKIT_DIR}/${ACTION_BASE}.policy.in" fi TOOL_IN="${DIR}/$CFC_BASE" TOOL_OUT="${CFC_DIR}/${CFC_BASE}-${TOOL_USER}" RULE_OUT="${RULE_DIR}/10-${RULE_BASE}-${TOOL_USER}.rules" ACTION_ID="${RULE_BASE}.${TOOL_USER}" ACTION_OUT="/usr/share/polkit-1/actions/${ACTION_ID}.policy" function print_policy_xml() { sed -e "s:{{PATH}}:${TOOL_OUT}:g" \ -e "s:{{ACTION_BASE}}:${ACTION_BASE}:g" \ -e "s:{{ACTION_ID}}:${ACTION_ID}:g" "${ACTION_IN}" } function print_rules_javascript() { if [[ "$RULE_IN" == *.legacy ]]; then sed -e "s:{{RULE_BASE}}:${RULE_BASE}:g" "${RULE_IN}" else local tool_out=${TOOL_OUT} if polkit_action_lookup_program_gets_realpath; then tool_out="$(realpath "${TOOL_OUT}")" fi sed -e "s:{{TOOL_OUT}}:${tool_out}:g" \ -e "s:{{TOOL_USER}}:${TOOL_USER}:g" "${RULE_IN}" fi } if [ "$ACTION" = "supported" ] then check_support fi if [ "$ACTION" = "check" ] then require_root NOT_FOUND=0 NEEDS_UPDATE=0 function check_installed() { if [ -f "$1" ]; then echo -n "Found: $1" if cmp --silent "$1" "$2"; then echo " (OK)" else echo " (needs update)" NEEDS_UPDATE=1 fi else echo "Not found: $1" NOT_FOUND=1 fi } check_installed "${TOOL_OUT}" "${TOOL_IN}" check_installed "${RULE_OUT}" <(print_rules_javascript) if [ "$NEEDS_UPDATE" -gt 0 ]; then echo "Your $EXTENSION_NAME installation needs updating!" exit ${EXIT_NEEDS_UPDATE} fi if [ "$NOT_FOUND" -gt 0 ]; then echo "Not installed!" exit ${EXIT_NOT_INSTALLED} fi echo "OK" exit ${EXIT_SUCCESS} fi TOOL_NAME=$(basename ${TOOL_OUT}) if [ "$ACTION" = "install" ] then require_root echo -n "$(gtxt 'Installing') ${TOOL_NAME} $(gtxt 'tool')... " mkdir -p "${CFC_DIR}" install "${TOOL_IN}" "${TOOL_OUT}" || fail success if [ ! -z "$ACTION_IN" ];then echo "$(gtxt 'Using legacy policykit install')..." echo -n "$(gtxt 'Installing') $(gtxt 'policykit action')..." (print_policy_xml > "${ACTION_OUT}" 2>/dev/null && chmod 0644 "${ACTION_OUT}") || fail success fi echo -n "$(gtxt 'Installing') $(gtxt 'policykit rule')..." mkdir -p "${RULE_DIR}" (print_rules_javascript > "${RULE_OUT}" 2>/dev/null && chmod 0644 "${RULE_OUT}") || fail success exit ${EXIT_SUCCESS} fi if [ "$ACTION" = "update" ] then require_root "${BASH_SOURCE[0]}" --tool-user "${TOOL_USER}" uninstall || exit $? "${BASH_SOURCE[0]}" --tool-user "${TOOL_USER}" install || exit $? exit ${EXIT_SUCCESS} fi if [ "$ACTION" = "uninstall" ] then require_root LEG_CFG_OUT="/usr/bin/shutdowntimerctl-$TOOL_USER" if [ -f "$LEG_CFG_OUT" ] then # remove legacy "tool" install echo -n "$(gtxt 'Uninstalling') $(gtxt 'tool')..." rm "${LEG_CFG_OUT}" || fail " - $(gtxt 'cannot remove') ${LEG_CFG_OUT}" && success fi if [ -f "$ACTION_OUT" ] then # remove legacy "policykit action" install echo -n "$(gtxt 'Uninstalling') $(gtxt 'policykit action')..." rm "${ACTION_OUT}" || fail " - $(gtxt 'cannot remove') ${ACTION_OUT}" && success fi LEG_RULE_OUT="/usr/share/polkit-1/rules.d/10-dem.shutdowntimer.settimers.rules" if [ -f "$LEG_RULE_OUT" ] then # remove legacy "policykit action" install echo -n "$(gtxt 'Uninstalling') $(gtxt 'policykit rule')..." rm "${LEG_RULE_OUT}" || fail " - $(gtxt 'cannot remove') ${LEG_RULE_OUT}" && success fi function uninstallFile() { echo -n "$(gtxt 'Uninstalling') $2... " if [ -f "$1" ] then rm "$1" || fail " - $(gtxt 'cannot remove') $1" && success else echo "$2 $(gtxt 'not installed at') $1" fi } uninstallFile "${TOOL_OUT}" "${TOOL_NAME} $(gtxt 'tool')" uninstallFile "${RULE_OUT}" "$(gtxt 'policykit rule')" exit ${EXIT_SUCCESS} fi echo "Unknown parameter." usage